diff options
-rw-r--r-- | scumm/sound.cpp | 4 | ||||
-rw-r--r-- | sound/mixer.cpp | 63 | ||||
-rw-r--r-- | sound/mixer.h | 27 |
3 files changed, 59 insertions, 35 deletions
diff --git a/scumm/sound.cpp b/scumm/sound.cpp index 19f4c74c13..5eaf0beedc 100644 --- a/scumm/sound.cpp +++ b/scumm/sound.cpp @@ -958,7 +958,7 @@ void Sound::stopSfxSound() { } bool Sound::isSfxFinished() { - return !_scumm->_mixer->hasActiveChannel(); + return !_scumm->_mixer->hasActiveSFXChannel(); } uint32 Sound::decode12BitsSample(byte *src, byte **dst, uint32 size, bool stereo = false) { @@ -1577,7 +1577,7 @@ int Sound::updateMP3CD() { return -1; } - if (_scumm->_mixer->_channels[_dig_cd_index]->soundFinished()) { + if (!_scumm->_mixer->isActiveChannel(_dig_cd_index)) { if (_dig_cd_num_loops == -1 || --_dig_cd_num_loops > 0) playMP3CDTrack(_dig_cd_track, _dig_cd_num_loops, _dig_cd_start, _dig_cd_delay); else diff --git a/sound/mixer.cpp b/sound/mixer.cpp index b919ced842..9e1ca4cfc7 100644 --- a/sound/mixer.cpp +++ b/sound/mixer.cpp @@ -26,6 +26,22 @@ #include "common/file.h" +class Channel { +protected: + SoundMixer *_mixer; +public: + bool _toBeDestroyed; + int _id; + Channel() : _mixer(0), _toBeDestroyed(false), _id(-1) {} + virtual ~Channel() {} + virtual void mix(int16 *data, uint len) = 0; + void destroy() { + _toBeDestroyed = true; + } + virtual bool isActive(); + virtual bool isMusicChannel() = 0; +}; + class ChannelRaw : public Channel { byte *_ptr; uint32 _pos; @@ -42,6 +58,9 @@ public: ~ChannelRaw(); void mix(int16 *data, uint len); + bool isMusicChannel() { + return false; // TODO: IS this correct? Or does any Scumm game us this for music? + } }; class ChannelStream : public Channel { @@ -61,6 +80,9 @@ public: void mix(int16 *data, uint len); void append(void *sound, uint32 size); + bool isMusicChannel() { + return true; + } }; #ifdef USE_MAD @@ -81,6 +103,9 @@ public: ~ChannelMP3(); void mix(int16 *data, uint len); + bool isMusicChannel() { + return false; + } }; class ChannelMP3CDMusic : public Channel { @@ -101,7 +126,10 @@ public: ~ChannelMP3CDMusic(); void mix(int16 *data, uint len); - bool soundFinished(); + bool isActive(); + bool isMusicChannel() { + return true; + } }; #endif @@ -116,7 +144,10 @@ public: ChannelVorbis(SoundMixer *mixer, OggVorbis_File *ov_file, int duration, bool is_cd_track); void mix(int16 *data, uint len); - bool soundFinished(); + bool isActive(); + bool isMusicChannel() { + return _is_cd_track; + } }; #endif @@ -276,13 +307,23 @@ void SoundMixer::pause(bool paused) { _paused = paused; } -bool SoundMixer::hasActiveChannel() { +bool SoundMixer::hasActiveSFXChannel() { + // FIXME/TODO: We need to distinguish between SFX and music channels + // (and maybe also voice) here to work properly in iMuseDigital + // games. In the past that was achieve using the _beginSlots hack. + // Since we don't have that anymore, it's not that simple anymore. for (int i = 0; i != NUM_CHANNELS; i++) - if (_channels[i]) + if (_channels[i] && !_channels[i]->isMusicChannel()) return true; return false; } +bool SoundMixer::isActiveChannel(int index) { + if (_channels[index]) + return _channels[index]->isActive(); + return false; +} + void SoundMixer::setupPremix(void *param, PremixProc *proc) { _premixParam = param; _premixProc = proc; @@ -596,9 +637,9 @@ static int16 mixer_element_size[] = { 4, 4 }; -bool Channel::soundFinished() { - warning("sound_finished should never be called on a non-MP3 mixer "); - return false; +bool Channel::isActive() { + error("isActive should never be called on a non-MP3 mixer "); + return true; } /* RAW mixer */ @@ -979,8 +1020,8 @@ void ChannelMP3CDMusic::mix(int16 *data, uint len) { } } -bool ChannelMP3CDMusic::soundFinished() { - return mad_timer_compare(_duration, mad_timer_zero) <= 0; +bool ChannelMP3CDMusic::isActive() { + return mad_timer_compare(_duration, mad_timer_zero) > 0; } #endif @@ -1061,8 +1102,8 @@ void ChannelVorbis::mix(int16 *data, uint len) { destroy(); } -bool ChannelVorbis::soundFinished() { - return _eof_flag || (_end_pos > 0 && ov_pcm_tell(_ov_file) >= _end_pos); +bool ChannelVorbis::isActive() { + return !_eof_flag && (_end_pos <= 0 && ov_pcm_tell(_ov_file) >= _end_pos); } #endif diff --git a/sound/mixer.h b/sound/mixer.h index 06f22e38fc..bced868538 100644 --- a/sound/mixer.h +++ b/sound/mixer.h @@ -41,26 +41,6 @@ typedef uint32 PlayingSoundHandle; class Channel; class File; -class SoundMixer; - -// TODO: class Channel should really be declared non-public, inside mixer.cpp -// However, right now Sound::updateMP3CD directly calls soundFinished. That -// should be changed, by adding proper API abstraction to SoundMixer for -// MP3/Vorbis "CD" playback. -class Channel { -protected: - SoundMixer *_mixer; -public: - bool _toBeDestroyed; - int _id; - Channel() : _mixer(0), _toBeDestroyed(false), _id(-1) {} - virtual ~Channel() {} - virtual void mix(int16 *data, uint len) = 0; - void destroy() { - _toBeDestroyed = true; - } - virtual bool soundFinished(); -}; class SoundMixer { public: @@ -133,8 +113,11 @@ public: /** append to existing sound */ int append(int index, void * sound, uint32 size); - /** is any channel active? */ - bool hasActiveChannel(); + /** Check whether any SFX channel is active.*/ + bool hasActiveSFXChannel(); + + /** Check whether the specified channel si active. */ + bool isActiveChannel(int index); /** bind to the OSystem object => mixer will be * invoked automatically when samples need |