aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorPaul Gilbert2016-08-11 20:03:55 -0400
committerPaul Gilbert2016-08-11 20:03:55 -0400
commitb680af7f609594a89dd9acd8227c7d19259f8e6d (patch)
tree6baa83daa6423bb9eb144bbb4380ec6f9f2af6c4 /engines
parente8ea243a1468168d78d4c2d61f5d22a7421f8f2e (diff)
downloadscummvm-rg350-b680af7f609594a89dd9acd8227c7d19259f8e6d.tar.gz
scummvm-rg350-b680af7f609594a89dd9acd8227c7d19259f8e6d.tar.bz2
scummvm-rg350-b680af7f609594a89dd9acd8227c7d19259f8e6d.zip
TITANIC: Fleshing out QSound simulation methods
Diffstat (limited to 'engines')
-rw-r--r--engines/titanic/sound/qmixer.cpp60
-rw-r--r--engines/titanic/sound/qmixer.h21
-rw-r--r--engines/titanic/sound/sound_manager.cpp10
-rw-r--r--engines/titanic/sound/wave_file.cpp26
-rw-r--r--engines/titanic/sound/wave_file.h12
5 files changed, 111 insertions, 18 deletions
diff --git a/engines/titanic/sound/qmixer.cpp b/engines/titanic/sound/qmixer.cpp
index da707c9527..da4f6725a5 100644
--- a/engines/titanic/sound/qmixer.cpp
+++ b/engines/titanic/sound/qmixer.cpp
@@ -28,7 +28,10 @@ QMixer::QMixer(Audio::Mixer *mixer) : _mixer(mixer) {
}
bool QMixer::qsWaveMixInitEx(const QMIXCONFIG &config) {
- // Not currently implemented in ScummVM
+ assert(_channels.empty());
+ assert(config.iChannels > 0 && config.iChannels < 256);
+
+ _channels.resize(config.iChannels);
return true;
}
@@ -48,6 +51,7 @@ int QMixer::qsWaveMixEnableChannel(int iChannel, uint flags, bool enabled) {
void QMixer::qsWaveMixCloseSession() {
_mixer->stopAll();
+ _channels.clear();
}
void QMixer::qsWaveMixFreeWave(Audio::SoundHandle &handle) {
@@ -94,18 +98,62 @@ void QMixer::qsWaveMixSetSourceVelocity(int iChannel, uint flags, const QSVECTOR
// Not currently implemented in ScummVM
}
-int QMixer::qsWaveMixPlayEx(int iChannel, uint flags, CWaveFile *mixWave, int loops, const QMIXPLAYPARAMS &params) {
- // Not currently implemented in ScummVM
+int QMixer::qsWaveMixPlayEx(int iChannel, uint flags, CWaveFile *waveFile, int loops, const QMIXPLAYPARAMS &params) {
+ if (iChannel == -1) {
+ // Find a free channel
+ for (iChannel = 0; iChannel < (int)_channels.size(); ++iChannel) {
+ if (_channels[iChannel]._sounds.empty())
+ break;
+ }
+ assert(iChannel != (int)_channels.size());
+ }
+
+ // If the new sound replaces current ones, then clear the channel
+ ChannelEntry &channel = _channels[iChannel];
+ if (flags & QMIX_CLEARQUEUE) {
+ if (!channel._sounds.empty() && channel._sounds.front()._started)
+ _mixer->stopHandle(channel._sounds.front()._soundHandle);
+
+ channel._sounds.clear();
+ }
+
+ // Add the sound to the channel
+ channel._sounds.push_back(SoundEntry(waveFile, params.callback, params.dwUser));
+ qsWaveMixPump();
+
return 0;
}
bool QMixer::qsWaveMixIsChannelDone(int iChannel) const {
- // Not currently implemented in ScummVM
- return true;
+ return _channels[iChannel]._sounds.empty();
}
void QMixer::qsWaveMixPump() {
- // TODO: Handle checking for done sounds, and calling their end functions
+ // Iterate through each of the channels
+ for (uint iChannel = 0; iChannel < _channels.size(); ++iChannel) {
+ ChannelEntry &channel = _channels[iChannel];
+
+ // If the playing sound on the channel is finished, then call
+ // the callback registered for it, and remove it from the list
+ if (!channel._sounds.empty()) {
+ SoundEntry &sound = channel._sounds.front();
+ if (sound._started && !_mixer->isSoundHandleActive(sound._soundHandle)) {
+ sound._callback(iChannel, sound._waveFile, sound._userData);
+ channel._sounds.erase(channel._sounds.begin());
+ }
+ }
+
+ // If there's an unstarted sound at the front of a channel's
+ // sound list, then start it playing
+ if (!channel._sounds.empty()) {
+ SoundEntry &sound = channel._sounds.front();
+ if (!sound._started) {
+ _mixer->playStream(sound._waveFile->_soundType,
+ &sound._soundHandle, sound._waveFile->_stream);
+ sound._started = true;
+ }
+ }
+ }
}
} // End of namespace Titanic z
diff --git a/engines/titanic/sound/qmixer.h b/engines/titanic/sound/qmixer.h
index fa4604cd2e..32a5e58347 100644
--- a/engines/titanic/sound/qmixer.h
+++ b/engines/titanic/sound/qmixer.h
@@ -152,9 +152,12 @@ struct QMIXPLAYPARAMS {
int lEndLoop;
int lEnd;
const void *lpChannelParams; // initialize with these parameters
+ // Properties introduced by ScummVM
+ Audio::Mixer::SoundType _soundType;
QMIXPLAYPARAMS() : dwSize(36), lpImage(nullptr), hwndNotify(0), callback(nullptr),
- dwUser(nullptr), lStart(0), lStartLoop(0), lEndLoop(0), lEnd(0), lpChannelParams(nullptr) {}
+ dwUser(nullptr), lStart(0), lStartLoop(0), lEndLoop(0), lEnd(0),
+ lpChannelParams(nullptr), _soundType(Audio::Mixer::SoundType::kPlainSoundType) {}
};
/**
@@ -169,8 +172,24 @@ struct QMIXPLAYPARAMS {
* currently ignored, and all sounds play at full volume.
*/
class QMixer {
+ struct SoundEntry {
+ bool _started;
+ CWaveFile *_waveFile;
+ Audio::SoundHandle _soundHandle;
+ LPQMIXDONECALLBACK _callback;
+ void *_userData;
+ SoundEntry() : _started(false), _waveFile(nullptr), _callback(nullptr),
+ _userData(nullptr) {}
+
+ SoundEntry(CWaveFile *waveFile, LPQMIXDONECALLBACK callback, void *userData) :
+ _started(false), _waveFile(waveFile), _callback(callback), _userData(userData) {}
+ };
+ struct ChannelEntry {
+ Common::List<SoundEntry> _sounds;
+ };
private:
Audio::Mixer *_mixer;
+ Common::Array<ChannelEntry> _channels;
public:
QMixer(Audio::Mixer *mixer);
virtual ~QMixer() {}
diff --git a/engines/titanic/sound/sound_manager.cpp b/engines/titanic/sound/sound_manager.cpp
index d466488ceb..8d92e0cf8c 100644
--- a/engines/titanic/sound/sound_manager.cpp
+++ b/engines/titanic/sound/sound_manager.cpp
@@ -143,7 +143,15 @@ CWaveFile *QSoundManager::loadSpeech(CDialogueFile *dialogueFile, int speechId)
}
CWaveFile *QSoundManager::loadMusic(const CString &name) {
- return loadSound(name);
+ CWaveFile *waveFile = new CWaveFile();
+
+ // Try to load the specified sound
+ if (!waveFile->loadMusic(name)) {
+ delete waveFile;
+ return nullptr;
+ }
+
+ return waveFile;
}
int QSoundManager::playSound(CWaveFile &waveFile, CProximity &prox) {
diff --git a/engines/titanic/sound/wave_file.cpp b/engines/titanic/sound/wave_file.cpp
index 7093856217..16bc9deda4 100644
--- a/engines/titanic/sound/wave_file.cpp
+++ b/engines/titanic/sound/wave_file.cpp
@@ -28,11 +28,12 @@
namespace Titanic {
-CWaveFile::CWaveFile() : _owner(nullptr), _stream(nullptr), _soundType(SOUND_SFX) {
+CWaveFile::CWaveFile() : _owner(nullptr), _stream(nullptr),
+ _soundType(Audio::Mixer::SoundType::kPlainSoundType) {
}
CWaveFile::CWaveFile(QSoundManager *owner) : _owner(owner), _stream(nullptr),
- _soundType(SOUND_SFX) {
+ _soundType(Audio::Mixer::SoundType::kPlainSoundType) {
}
CWaveFile::~CWaveFile() {
@@ -57,7 +58,8 @@ bool CWaveFile::loadSound(const CString &name) {
Common::SeekableReadStream *stream = file.readStream();
_size = stream->size();
_stream = Audio::makeWAVStream(stream->readStream(_size), DisposeAfterUse::YES);
- _soundType = SOUND_SFX;
+ _soundType = Audio::Mixer::SoundType::kSFXSoundType;
+
return true;
}
@@ -72,7 +74,23 @@ bool CWaveFile::loadSpeech(CDialogueFile *dialogueFile, int speechIndex) {
_size = res->_size;
_stream = Audio::makeWAVStream(new Common::MemoryReadStream(data, _size, DisposeAfterUse::YES),
DisposeAfterUse::YES);
- _soundType = SOUND_SPEECH;
+ _soundType = Audio::Mixer::SoundType::kSpeechSoundType;
+
+ return true;
+}
+
+bool CWaveFile::loadMusic(const CString &name) {
+ assert(!_stream);
+
+ StdCWadFile file;
+ if (!file.open(name))
+ return false;
+
+ Common::SeekableReadStream *stream = file.readStream();
+ _size = stream->size();
+ _stream = Audio::makeWAVStream(stream->readStream(_size), DisposeAfterUse::YES);
+ _soundType = Audio::Mixer::SoundType::kMusicSoundType;
+
return true;
}
diff --git a/engines/titanic/sound/wave_file.h b/engines/titanic/sound/wave_file.h
index 33b2a8dedf..8c86c509bc 100644
--- a/engines/titanic/sound/wave_file.h
+++ b/engines/titanic/sound/wave_file.h
@@ -32,11 +32,6 @@ namespace Titanic {
class QSoundManager;
-enum SoundType {
- SOUND_SFX = 0,
- SOUND_SPEECH = 1
-};
-
class CWaveFile {
private:
uint _size;
@@ -44,7 +39,7 @@ public:
QSoundManager *_owner;
Audio::AudioStream *_stream;
Audio::SoundHandle _soundHandle;
- SoundType _soundType;
+ Audio::Mixer::SoundType _soundType;
public:
CWaveFile();
CWaveFile(QSoundManager *owner);
@@ -68,6 +63,11 @@ public:
bool loadSpeech(CDialogueFile *dialogueFile, int speechIndex);
/**
+ * Tries to load the specified music wave file
+ */
+ bool loadMusic(const CString &name);
+
+ /**
* Returns true if the wave file has data loaded
*/
bool isLoaded() const { return _stream != nullptr; }