mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 21:31:53 +00:00
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
This commit is contained in:
parent
d7ce1d2b19
commit
9868f6590d
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user