diff options
author | Max Horn | 2003-07-31 20:24:10 +0000 |
---|---|---|
committer | Max Horn | 2003-07-31 20:24:10 +0000 |
commit | 0b4e48b59e18865ddd7785594def2aba872a0258 (patch) | |
tree | c805a6ad957aa329de69f3073f65864ee2d6ef5e | |
parent | d8494d658b25d65eee1856d127a8ad5e20155bbe (diff) | |
download | scummvm-rg350-0b4e48b59e18865ddd7785594def2aba872a0258.tar.gz scummvm-rg350-0b4e48b59e18865ddd7785594def2aba872a0258.tar.bz2 scummvm-rg350-0b4e48b59e18865ddd7785594def2aba872a0258.zip |
revamped MP3/Vorbis CD 'emulation' code to use a PlayingSoundHandle -> this allows to finally get rid of the hackish isChannelActive/isChannelUsed methods in SoundMixer
svn-id: r9346
-rw-r--r-- | scumm/sound.cpp | 36 | ||||
-rw-r--r-- | scumm/sound.h | 4 | ||||
-rw-r--r-- | sound/mixer.cpp | 78 | ||||
-rw-r--r-- | sound/mixer.h | 6 |
4 files changed, 34 insertions, 90 deletions
diff --git a/scumm/sound.cpp b/scumm/sound.cpp index d822211928..72ba1f9c1e 100644 --- a/scumm/sound.cpp +++ b/scumm/sound.cpp @@ -46,7 +46,7 @@ enum { class DigitalTrackInfo { public: virtual bool error() = 0; - virtual int play(SoundMixer *mixer, int startFrame, int duration) = 0; + virtual int play(SoundMixer *mixer, PlayingSoundHandle *handle, int startFrame, int duration) = 0; virtual ~DigitalTrackInfo() { } }; @@ -62,7 +62,7 @@ public: MP3TrackInfo(File *file); ~MP3TrackInfo(); bool error() { return _error_flag; } - int play(SoundMixer *mixer, int startFrame, int duration); + int play(SoundMixer *mixer, PlayingSoundHandle *handle, int startFrame, int duration); }; #endif @@ -77,7 +77,7 @@ public: VorbisTrackInfo(File *file); ~VorbisTrackInfo(); bool error() { return _error_flag; } - int play(SoundMixer *mixer, int startFrame, int duration); + int play(SoundMixer *mixer, PlayingSoundHandle *handle, int startFrame, int duration); }; #endif @@ -1653,12 +1653,11 @@ int Sound::playMP3CDTrack(int track, int numLoops, int startFrame, int duration) if (index < 0) return -1; - if (_dig_cd.playing) - _scumm->_mixer->stop(_dig_cd.index); - _dig_cd.index = _track_info[index]->play(_scumm->_mixer, startFrame, duration); + _scumm->_mixer->stopHandle(_dig_cd.handle); + _track_info[index]->play(_scumm->_mixer, &_dig_cd.handle, startFrame, duration); _dig_cd.playing = true; _dig_cd.track = track; - _dig_cd.num_loops = numLoops; + _dig_cd.numLoops = numLoops; _dig_cd.start = startFrame; _dig_cd.duration = duration; return 0; @@ -1666,10 +1665,10 @@ int Sound::playMP3CDTrack(int track, int numLoops, int startFrame, int duration) int Sound::stopMP3CD() { if (_dig_cd.playing) { - _scumm->_mixer->stop(_dig_cd.index); + _scumm->_mixer->stopHandle(_dig_cd.handle); _dig_cd.playing = false; _dig_cd.track = 0; - _dig_cd.num_loops = 0; + _dig_cd.numLoops = 0; _dig_cd.start = 0; _dig_cd.duration = 0; return 0; @@ -1687,14 +1686,9 @@ int Sound::updateMP3CD() { if (!_dig_cd.playing) return -1; - if (!_scumm->_mixer->isChannelUsed(_dig_cd.index)) { - warning("Error in MP3 decoding"); - return -1; - } - - if (!_scumm->_mixer->isChannelActive(_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.duration); + if (!_dig_cd.handle) { + if (_dig_cd.numLoops == -1 || --_dig_cd.numLoops > 0) + playMP3CDTrack(_dig_cd.track, _dig_cd.numLoops, _dig_cd.start, _dig_cd.duration); else stopMP3CD(); } @@ -1774,7 +1768,7 @@ error: delete file; } -int MP3TrackInfo::play(SoundMixer *mixer, int startFrame, int duration) { +int MP3TrackInfo::play(SoundMixer *mixer, PlayingSoundHandle *handle, int startFrame, int duration) { unsigned int offset; mad_timer_t durationTime; @@ -1793,7 +1787,7 @@ int MP3TrackInfo::play(SoundMixer *mixer, int startFrame, int duration) { } // Play it - return mixer->playMP3CDTrack(NULL, _file, durationTime); + return mixer->playMP3CDTrack(handle, _file, durationTime); } MP3TrackInfo::~MP3TrackInfo() { @@ -1894,13 +1888,13 @@ VorbisTrackInfo::VorbisTrackInfo(File *file) { #define VORBIS_TREMOR #endif -int VorbisTrackInfo::play(SoundMixer *mixer, int startFrame, int duration) { +int VorbisTrackInfo::play(SoundMixer *mixer, PlayingSoundHandle *handle, int startFrame, int duration) { #ifdef VORBIS_TREMOR ov_time_seek(&_ov_file, (ogg_int64_t)(startFrame / 75.0 * 1000)); #else ov_time_seek(&_ov_file, startFrame / 75.0); #endif - return mixer->playVorbis(NULL, &_ov_file, + return mixer->playVorbis(handle, &_ov_file, duration * ov_info(&_ov_file, -1)->rate / 75, true); } diff --git a/scumm/sound.h b/scumm/sound.h index 1bb765770c..8e9183659b 100644 --- a/scumm/sound.h +++ b/scumm/sound.h @@ -87,11 +87,11 @@ protected: int _cached_tracks[CACHE_TRACKS]; struct { - int index; + PlayingSoundHandle handle; int track; int start; int duration; - int num_loops; + int numLoops; bool playing; } _dig_cd; diff --git a/sound/mixer.cpp b/sound/mixer.cpp index 6fc7e79df5..326106f6af 100644 --- a/sound/mixer.cpp +++ b/sound/mixer.cpp @@ -59,7 +59,6 @@ public: _mixer->_channels[i] = 0; delete this; } - virtual bool isActive(); virtual bool isMusicChannel() = 0; }; @@ -161,7 +160,6 @@ public: ~ChannelMP3CDMusic(); void mix(int16 *data, uint len); - bool isActive(); bool isMusicChannel() { return true; } }; @@ -175,7 +173,6 @@ class ChannelVorbis : public Channel { #else OggVorbis_File *_ov_file; int _end_pos; - bool _eof_flag; #endif bool _is_cd_track; @@ -184,7 +181,6 @@ public: ~ChannelVorbis(); void mix(int16 *data, uint len); - bool isActive(); bool isMusicChannel() { return _is_cd_track; } @@ -411,18 +407,6 @@ bool SoundMixer::hasActiveSFXChannel() { return false; } -bool SoundMixer::isChannelActive(int index) { - StackLock lock(_mutex); - if (_channels[index]) - return _channels[index]->isActive(); - return false; -} - -bool SoundMixer::isChannelUsed(int index) { - StackLock lock(_mutex); - return (_channels[index] != NULL); -} - void SoundMixer::setupPremix(void *param, PremixProc *proc) { StackLock lock(_mutex); _premixParam = param; @@ -666,11 +650,6 @@ static int16 mixer_element_size[] = { }; #endif -bool Channel::isActive() { - error("isActive should never be called on a non-MP3 mixer "); - return true; -} - /* RAW mixer */ ChannelRaw::ChannelRaw(SoundMixer *mixer, PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id) : Channel(mixer, handle) { @@ -1035,11 +1014,6 @@ void ChannelMP3CDMusic::mix(int16 *data, uint len) { if (_input->eof()) { // TODO: call drain method - - // TODO: we probably shouldn't call destroy() here, this interfers - // with the looping code in scumm/sound.cpp. But then that code - // should be rewritten anyway (which would probably allow us to - // get rid of the isActive() method, too. destroy(); return; } @@ -1121,6 +1095,11 @@ void ChannelMP3CDMusic::mix(int16 *data, uint len) { frame_duration = _frame.header.duration; mad_timer_negate(&frame_duration); mad_timer_add(&_duration, frame_duration); + + if (mad_timer_compare(_duration, mad_timer_zero) <= 0) { + destroy(); + return; + } if (mad_frame_decode(&_frame, &_stream) == -1) { if (_stream.error == MAD_ERROR_BUFLEN) { int not_decoded; @@ -1152,14 +1131,6 @@ void ChannelMP3CDMusic::mix(int16 *data, uint len) { #endif } -bool ChannelMP3CDMusic::isActive() { -#ifdef BUGGY_NEW_MP3_PLAYER - return !_input->eof(); -#else - return mad_timer_compare(_duration, mad_timer_zero) > 0; -#endif -} - #endif #ifdef USE_VORBIS @@ -1182,8 +1153,6 @@ ChannelVorbis::ChannelVorbis(SoundMixer *mixer, PlayingSoundHandle *handle, OggV _end_pos = ov_pcm_tell(ov_file) + duration; else _end_pos = 0; - - _eof_flag = false; #endif _is_cd_track = is_cd_track; } @@ -1205,13 +1174,8 @@ void ChannelVorbis::mix(int16 *data, uint len) { assert(_input); assert(_converter); - if (_input->eof() && !_is_cd_track) { + if (_input->eof()) { // TODO: call drain method - - // TODO: we probably shouldn't call destroy() here, this interfers - // with the looping code in scumm/sound.cpp. But then that code - // should be rewritten anyway (which would probably allow us to - // get rid of the isActive() method, too. destroy(); return; } @@ -1220,7 +1184,8 @@ void ChannelVorbis::mix(int16 *data, uint len) { uint tmpLen = len; _converter->flow(*_input, data, &tmpLen, volume); #else - if (_eof_flag) { + if (_end_pos > 0 && ov_pcm_tell(_ov_file) >= _end_pos) { + destroy(); return; } @@ -1228,7 +1193,8 @@ void ChannelVorbis::mix(int16 *data, uint len) { uint len_left = len * channels * 2; int16 *samples = new int16[len_left / 2]; char *read_pos = (char *) samples; - int volume = _is_cd_track ? _mixer->getMusicVolume() : _mixer->getVolume(); + bool eof_flag = false; + int volume = isMusicChannel() ? _mixer->getMusicVolume() : _mixer->getVolume(); // Read the samples while (len_left > 0) { @@ -1243,19 +1209,17 @@ void ChannelVorbis::mix(int16 *data, uint len) { #endif NULL); if (result == 0) { - _eof_flag = true; + eof_flag = true; memset(read_pos, 0, len_left); - len_left = 0; + break; } else if (result == OV_HOLE) { // Possibly recoverable, just warn about it warning("Corrupted data in Vorbis file"); } else if (result < 0) { debug(1, "Decode error %d in Vorbis file", result); - // Don't delete it yet, that causes problems in - // the CD player emulation code. - _eof_flag = true; + eof_flag = true; memset(read_pos, 0, len_left); - len_left = 0; + break; } else { len_left -= result; read_pos += result; @@ -1264,26 +1228,18 @@ void ChannelVorbis::mix(int16 *data, uint len) { // Mix the samples in for (uint i = 0; i < len; i++) { - int16 sample = (int16) ((int32) samples[i * channels] * volume / 256); + int16 sample = (int16)(samples[i * channels] * volume / 256); clamped_add_16(*data++, sample); if (channels > 1) - sample = (int16) ((int32) samples[i * channels + 1] * volume / 256); + sample = (int16)(samples[i * channels + 1] * volume / 256); clamped_add_16(*data++, sample); } delete [] samples; - if (_eof_flag && !_is_cd_track) + if (eof_flag) destroy(); #endif } -bool ChannelVorbis::isActive() { -#ifdef SOX_HACK - return !_input->eof(); -#else - return !_eof_flag && !(_end_pos > 0 && ov_pcm_tell(_ov_file) >= _end_pos); -#endif -} - #endif diff --git a/sound/mixer.h b/sound/mixer.h index 47acf99d66..2c46f3c8b0 100644 --- a/sound/mixer.h +++ b/sound/mixer.h @@ -118,12 +118,6 @@ public: /** Check whether any SFX channel is active.*/ bool hasActiveSFXChannel(); - /** Check whether the specified channel is active. */ - bool isChannelActive(int index); - - /** Check whether the specified channel is in use. */ - bool isChannelUsed(int index); - /** bind to the OSystem object => mixer will be * invoked automatically when samples need * to be generated */ |