diff options
author | Lionel Ulmer | 2002-04-26 20:53:48 +0000 |
---|---|---|
committer | Lionel Ulmer | 2002-04-26 20:53:48 +0000 |
commit | 9868f6590deb834fc52ea1738f02bfc455b80fba (patch) | |
tree | 1cd4266b6620d87dfb98f81ffcb6f1b52a07475c /sound | |
parent | d7ce1d2b192adbfe9e78697612d159bcc37dc43e (diff) | |
download | scummvm-rg350-9868f6590deb834fc52ea1738f02bfc455b80fba.tar.gz scummvm-rg350-9868f6590deb834fc52ea1738f02bfc455b80fba.tar.bz2 scummvm-rg350-9868f6590deb834fc52ea1738f02bfc455b80fba.zip |
Fixed race conditions in the sound code (where a sound could be
'freed' while it was mixed at the same time in the sound thread).
Now Monkey1 seems to play well with Valgrind without any memory
warning.
svn-id: r4096
Diffstat (limited to 'sound')
-rw-r--r-- | sound/mixer.cpp | 51 | ||||
-rw-r--r-- | sound/mixer.h | 16 |
2 files changed, 47 insertions, 20 deletions
diff --git a/sound/mixer.cpp b/sound/mixer.cpp index d51393618a..3f2a957911 100644 --- a/sound/mixer.cpp +++ b/sound/mixer.cpp @@ -50,7 +50,7 @@ int SoundMixer::insert(PlayingSoundHandle *handle, Channel *chan) { } warning("SoundMixer::insert out of mixer slots"); - chan->destroy(); + chan->real_destroy(); return -1; } @@ -140,6 +140,7 @@ SoundMixer::Channel_RAW::Channel_RAW(SoundMixer *mixer, void *sound, uint32 size _pos = 0; _fp_pos = 0; _fp_speed = (1 << 16) * rate / mixer->_output_rate; + _to_be_destroyed = false; /* adjust the magnitute to prevent division error */ while (size & 0xFFFF0000) @@ -152,6 +153,11 @@ void SoundMixer::Channel_RAW::mix(int16 *data, uint len) { byte *s, *s_org = NULL; uint32 fp_pos; + if (_to_be_destroyed) { + real_destroy(); + return; + } + if (len > _size) len = _size; _size -= len; @@ -205,11 +211,11 @@ void SoundMixer::Channel_RAW::mix(int16 *data, uint len) { } if (_size < 1) - destroy(); + real_destroy(); } -void SoundMixer::Channel_RAW::destroy() { +void SoundMixer::Channel_RAW::real_destroy() { if (_flags & FLAG_AUTOFREE) free(_ptr); _mixer->uninsert(this); @@ -226,6 +232,7 @@ SoundMixer::Channel_MP3::Channel_MP3(SoundMixer *mixer, void *sound, uint size, _position = 0; _size = size; _ptr = sound; + _to_be_destroyed = false; mad_stream_init(&_stream); #ifdef _WIN32_WCE @@ -266,6 +273,12 @@ static inline int scale_sample(mad_fixed_t sample) void SoundMixer::Channel_MP3::mix(int16 *data, uint len) { mad_fixed_t const *ch; + + if (_to_be_destroyed) { + real_destroy(); + return; + } + while (1) { ch = _synth.pcm.samples[0] + _pos_in_frame; while ((_pos_in_frame < _synth.pcm.length) && (len > 0)) { @@ -281,7 +294,7 @@ void SoundMixer::Channel_MP3::mix(int16 *data, uint len) { return; if (_position >= _size) { - destroy(); + real_destroy(); return; } @@ -290,7 +303,7 @@ void SoundMixer::Channel_MP3::mix(int16 *data, uint len) { if (mad_frame_decode(&_frame, &_stream) == -1) { /* End of audio... */ if (_stream.error == MAD_ERROR_BUFLEN) { - destroy(); + real_destroy(); return; } else if (!MAD_RECOVERABLE(_stream.error)) { error("MAD frame decode error !"); @@ -302,7 +315,7 @@ void SoundMixer::Channel_MP3::mix(int16 *data, uint len) { } } -void SoundMixer::Channel_MP3::destroy() { +void SoundMixer::Channel_MP3::real_destroy() { if (_flags & FLAG_AUTOFREE) free(_ptr); _mixer->uninsert(this); @@ -323,6 +336,8 @@ SoundMixer::Channel_MP3_CDMUSIC::Channel_MP3_CDMUSIC(SoundMixer *mixer, FILE* fi _buffer_size = buffer_size; _ptr = buffer; _flags = 0; + _to_be_destroyed = false; + mad_stream_init(&_stream); #ifdef _WIN32_WCE // 11 kHz on WinCE @@ -330,19 +345,28 @@ SoundMixer::Channel_MP3_CDMUSIC::Channel_MP3_CDMUSIC(SoundMixer *mixer, FILE* fi #endif mad_frame_init(&_frame); mad_synth_init(&_synth); + + debug(1, "CRE %d", getpid()); } void SoundMixer::Channel_MP3_CDMUSIC::mix(int16 *data, uint len) { mad_fixed_t const *ch; mad_timer_t frame_duration; + if (_to_be_destroyed) { + real_destroy(); + return; + } + + debug(1, "MIX %d", getpid()); + if (!_initialized) { int skip_loop; // just skipped memset(_ptr, 0,_buffer_size); _size = fread(_ptr, 1, _buffer_size, _file); if (!_size) { - destroy(); + real_destroy(); return; } // Resync @@ -358,7 +382,7 @@ void SoundMixer::Channel_MP3_CDMUSIC::mix(int16 *data, uint len) { } else { if (!MAD_RECOVERABLE(_stream.error)) { debug(1, "Unrecoverable error while skipping !"); - destroy(); + real_destroy(); return; } } @@ -370,10 +394,9 @@ void SoundMixer::Channel_MP3_CDMUSIC::mix(int16 *data, uint len) { if (mad_frame_decode(&_frame,&_stream) == 0) { _pos_in_frame = 0; _initialized = true; - } - else { + } else { debug(1, "Cannot resume decoding"); - destroy(); + real_destroy(); return; } } @@ -396,7 +419,7 @@ void SoundMixer::Channel_MP3_CDMUSIC::mix(int16 *data, uint len) { mad_timer_negate(&frame_duration); mad_timer_add(&_duration, frame_duration); if (mad_timer_compare(_duration, mad_timer_zero) < 0) { - destroy(); + real_destroy(); return; } if (mad_frame_decode(&_frame, &_stream) == -1) { @@ -427,7 +450,7 @@ void SoundMixer::Channel_MP3_CDMUSIC::mix(int16 *data, uint len) { } } -void SoundMixer::Channel_MP3_CDMUSIC::destroy() { +void SoundMixer::Channel_MP3_CDMUSIC::real_destroy() { if (_flags & FLAG_AUTOFREE) free(_ptr); _mixer->uninsert(this); @@ -435,6 +458,8 @@ void SoundMixer::Channel_MP3_CDMUSIC::destroy() { mad_frame_finish(&_frame); mad_stream_finish(&_stream); + debug(1, "DES %d", getpid()); + delete this; } diff --git a/sound/mixer.h b/sound/mixer.h index d71638b37b..4f7bb6568e 100644 --- a/sound/mixer.h +++ b/sound/mixer.h @@ -32,8 +32,10 @@ class SoundMixer { private: class Channel { public: + bool _to_be_destroyed; virtual void mix(int16 *data, uint len) = 0; - virtual void destroy() = 0; + void destroy() { _to_be_destroyed = true; } + virtual void real_destroy() = 0; }; class Channel_RAW : public Channel { @@ -48,9 +50,8 @@ private: public: void mix(int16 *data, uint len); - void destroy(); - Channel_RAW(SoundMixer *mixer, void *sound, uint32 size, uint rate, byte flags); + void real_destroy(); }; #ifdef COMPRESSED_SOUND_FILE @@ -69,9 +70,9 @@ private: public: void mix(int16 *data, uint len); - void destroy(); - Channel_MP3(SoundMixer *mixer, void *sound, uint size, byte flags); + void real_destroy(); + }; class Channel_MP3_CDMUSIC : public Channel { @@ -89,9 +90,10 @@ private: byte _flags; public: void mix(int16 *data, uint len); - void destroy(); - Channel_MP3_CDMUSIC(SoundMixer *mixer, FILE* file, void *buffer, uint32 buffer_size, mad_timer_t duration); + void real_destroy(); + + }; #endif |