now that we mutex-protect everything properly, we can get rid of _toBeDestroyed; also, instead of keeping a global _handles array in the mixer, let each Channel manage its own handle

svn-id: r8808
This commit is contained in:
Max Horn 2003-07-06 16:52:09 +00:00
parent 2e0235d898
commit b6c3d440b5
2 changed files with 39 additions and 45 deletions

View file

@ -30,14 +30,23 @@
class Channel { class Channel {
protected: protected:
SoundMixer *_mixer; SoundMixer *_mixer;
PlayingSoundHandle *_handle;
public: public:
bool _toBeDestroyed;
int _id; int _id;
Channel(SoundMixer *mixer) : _mixer(mixer), _toBeDestroyed(false), _id(-1) {} Channel(SoundMixer *mixer, PlayingSoundHandle *handle)
virtual ~Channel() {} : _mixer(mixer), _handle(handle), _id(-1) {
assert(mixer);
}
virtual ~Channel() {
if (_handle)
*_handle = 0;
}
virtual void mix(int16 *data, uint len) = 0; virtual void mix(int16 *data, uint len) = 0;
void destroy() { void destroy() {
_toBeDestroyed = true; for (int i = 0; i != SoundMixer::NUM_CHANNELS; i++)
if (_mixer->_channels[i] == this)
_mixer->_channels[i] = 0;
delete this;
} }
virtual bool isActive(); virtual bool isActive();
virtual bool isMusicChannel() = 0; virtual bool isMusicChannel() = 0;
@ -55,12 +64,12 @@ class ChannelRaw : public Channel {
uint32 _loop_size; uint32 _loop_size;
public: public:
ChannelRaw(SoundMixer *mixer, void *sound, uint32 size, uint rate, byte flags, int id); ChannelRaw(SoundMixer *mixer, PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id);
~ChannelRaw(); ~ChannelRaw();
void mix(int16 *data, uint len); void mix(int16 *data, uint len);
bool isMusicChannel() { bool isMusicChannel() {
return false; // TODO: IS this correct? Or does any Scumm game us this for music? return false; // TODO: Is this correct? Or does anything use ChannelRaw for music?
} }
}; };
@ -77,7 +86,7 @@ class ChannelStream : public Channel {
bool _finished; bool _finished;
public: public:
ChannelStream(SoundMixer *mixer, void *sound, uint32 size, uint rate, byte flags, uint32 buffer_size); ChannelStream(SoundMixer *mixer, PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, uint32 buffer_size);
~ChannelStream(); ~ChannelStream();
void mix(int16 *data, uint len); void mix(int16 *data, uint len);
@ -101,7 +110,7 @@ protected:
uint32 _size; uint32 _size;
public: public:
ChannelMP3Common(SoundMixer *mixer); ChannelMP3Common(SoundMixer *mixer, PlayingSoundHandle *handle);
~ChannelMP3Common(); ~ChannelMP3Common();
}; };
@ -110,7 +119,7 @@ class ChannelMP3 : public ChannelMP3Common {
uint32 _position; uint32 _position;
public: public:
ChannelMP3(SoundMixer *mixer, void *sound, uint size, byte flags); ChannelMP3(SoundMixer *mixer, PlayingSoundHandle *handle, void *sound, uint size, byte flags);
void mix(int16 *data, uint len); void mix(int16 *data, uint len);
bool isMusicChannel() { return false; } bool isMusicChannel() { return false; }
@ -124,7 +133,7 @@ class ChannelMP3CDMusic : public ChannelMP3Common {
public: public:
ChannelMP3CDMusic(SoundMixer *mixer, File *file, mad_timer_t duration); ChannelMP3CDMusic(SoundMixer *mixer, PlayingSoundHandle *handle, File *file, mad_timer_t duration);
void mix(int16 *data, uint len); void mix(int16 *data, uint len);
bool isActive(); bool isActive();
@ -140,7 +149,7 @@ class ChannelVorbis : public Channel {
bool _eof_flag, _is_cd_track; bool _eof_flag, _is_cd_track;
public: public:
ChannelVorbis(SoundMixer *mixer, OggVorbis_File *ov_file, int duration, bool is_cd_track); ChannelVorbis(SoundMixer *mixer, PlayingSoundHandle *handle, OggVorbis_File *ov_file, int duration, bool is_cd_track);
void mix(int16 *data, uint len); void mix(int16 *data, uint len);
bool isActive(); bool isActive();
@ -159,9 +168,6 @@ SoundMixer::SoundMixer() {
_premixProc = 0; _premixProc = 0;
int i = 0; int i = 0;
for (i = 0; i != NUM_CHANNELS; i++)
_handles[i] = NULL;
_outputRate = 0; _outputRate = 0;
_volumeTable = (int16 *)calloc(256 * sizeof(int16), 1); _volumeTable = (int16 *)calloc(256 * sizeof(int16), 1);
@ -219,7 +225,6 @@ int SoundMixer::insertChannel(PlayingSoundHandle *handle, Channel *chan) {
} }
_channels[index] = chan; _channels[index] = chan;
_handles[index] = handle;
if (handle) if (handle)
*handle = index + 1; *handle = index + 1;
return index; return index;
@ -235,29 +240,29 @@ int SoundMixer::playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, ui
return -1; return -1;
} }
return insertChannel(handle, new ChannelRaw(this, sound, size, rate, flags, id)); return insertChannel(handle, new ChannelRaw(this, handle, sound, size, rate, flags, id));
} }
int SoundMixer::newStream(void *sound, uint32 size, uint rate, byte flags, uint32 buffer_size) { int SoundMixer::newStream(void *sound, uint32 size, uint rate, byte flags, uint32 buffer_size) {
StackLock lock(_mutex); StackLock lock(_mutex);
return insertChannel(NULL, new ChannelStream(this, sound, size, rate, flags, buffer_size)); return insertChannel(NULL, new ChannelStream(this, 0, sound, size, rate, flags, buffer_size));
} }
#ifdef USE_MAD #ifdef USE_MAD
int SoundMixer::playMP3(PlayingSoundHandle *handle, void *sound, uint32 size, byte flags) { int SoundMixer::playMP3(PlayingSoundHandle *handle, void *sound, uint32 size, byte flags) {
StackLock lock(_mutex); StackLock lock(_mutex);
return insertChannel(handle, new ChannelMP3(this, sound, size, flags)); return insertChannel(handle, new ChannelMP3(this, handle, sound, size, flags));
} }
int SoundMixer::playMP3CDTrack(PlayingSoundHandle *handle, File *file, mad_timer_t duration) { int SoundMixer::playMP3CDTrack(PlayingSoundHandle *handle, File *file, mad_timer_t duration) {
StackLock lock(_mutex); StackLock lock(_mutex);
return insertChannel(handle, new ChannelMP3CDMusic(this, file, duration)); return insertChannel(handle, new ChannelMP3CDMusic(this, handle, file, duration));
} }
#endif #endif
#ifdef USE_VORBIS #ifdef USE_VORBIS
int SoundMixer::playVorbis(PlayingSoundHandle *handle, OggVorbis_File *ov_file, int duration, bool is_cd_track) { int SoundMixer::playVorbis(PlayingSoundHandle *handle, OggVorbis_File *ov_file, int duration, bool is_cd_track) {
StackLock lock(_mutex); StackLock lock(_mutex);
return insertChannel(handle, new ChannelVorbis(this, ov_file, duration, is_cd_track)); return insertChannel(handle, new ChannelVorbis(this, handle, ov_file, duration, is_cd_track));
} }
#endif #endif
@ -278,17 +283,8 @@ void SoundMixer::mix(int16 *buf, uint len) {
if (!_paused) { if (!_paused) {
// now mix all channels // now mix all channels
for (int i = 0; i != NUM_CHANNELS; i++) for (int i = 0; i != NUM_CHANNELS; i++)
if (_channels[i]) { if (_channels[i])
if (_channels[i]->_toBeDestroyed) { _channels[i]->mix(buf, len);
if (_handles[i]) {
*_handles[i] = 0;
_handles[i] = NULL;
}
delete _channels[i];
_channels[i] = NULL;
} else
_channels[i]->mix(buf, len);
}
} }
} }
@ -627,8 +623,8 @@ bool Channel::isActive() {
} }
/* RAW mixer */ /* RAW mixer */
ChannelRaw::ChannelRaw(SoundMixer *mixer, void *sound, uint32 size, uint rate, byte flags, int id) ChannelRaw::ChannelRaw(SoundMixer *mixer, PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id)
: Channel(mixer) { : Channel(mixer, handle) {
_id = id; _id = id;
_flags = flags; _flags = flags;
_ptr = (byte *)sound; _ptr = (byte *)sound;
@ -689,9 +685,9 @@ void ChannelRaw::mix(int16 *data, uint len) {
#define WARP_WORKAROUND 50000 #define WARP_WORKAROUND 50000
ChannelStream::ChannelStream(SoundMixer *mixer, void *sound, uint32 size, uint rate, ChannelStream::ChannelStream(SoundMixer *mixer, PlayingSoundHandle *handle, void *sound, uint32 size, uint rate,
byte flags, uint32 buffer_size) byte flags, uint32 buffer_size)
: Channel(mixer) { : Channel(mixer, handle) {
assert(size <= buffer_size); assert(size <= buffer_size);
_flags = flags; _flags = flags;
_bufferSize = buffer_size; _bufferSize = buffer_size;
@ -792,8 +788,8 @@ void ChannelStream::mix(int16 *data, uint len) {
#ifdef USE_MAD #ifdef USE_MAD
ChannelMP3Common::ChannelMP3Common(SoundMixer *mixer) ChannelMP3Common::ChannelMP3Common(SoundMixer *mixer, PlayingSoundHandle *handle)
: Channel(mixer) { : Channel(mixer, handle) {
mad_stream_init(&_stream); mad_stream_init(&_stream);
#ifdef _WIN32_WCE #ifdef _WIN32_WCE
// 11 kHz on WinCE if necessary // 11 kHz on WinCE if necessary
@ -812,8 +808,8 @@ ChannelMP3Common::~ChannelMP3Common() {
mad_stream_finish(&_stream); mad_stream_finish(&_stream);
} }
ChannelMP3::ChannelMP3(SoundMixer *mixer, void *sound, uint size, byte flags) ChannelMP3::ChannelMP3(SoundMixer *mixer, PlayingSoundHandle *handle, void *sound, uint size, byte flags)
: ChannelMP3Common(mixer) { : ChannelMP3Common(mixer, handle) {
_posInFrame = 0xFFFFFFFF; _posInFrame = 0xFFFFFFFF;
_position = 0; _position = 0;
_size = size; _size = size;
@ -905,8 +901,8 @@ void ChannelMP3::mix(int16 *data, uint len) {
#define MP3CD_BUFFERING_SIZE 131072 #define MP3CD_BUFFERING_SIZE 131072
ChannelMP3CDMusic::ChannelMP3CDMusic(SoundMixer *mixer, File *file, mad_timer_t duration) ChannelMP3CDMusic::ChannelMP3CDMusic(SoundMixer *mixer, PlayingSoundHandle *handle, File *file, mad_timer_t duration)
: ChannelMP3Common(mixer) { : ChannelMP3Common(mixer, handle) {
_file = file; _file = file;
_duration = duration; _duration = duration;
_initialized = false; _initialized = false;
@ -1017,8 +1013,8 @@ bool ChannelMP3CDMusic::isActive() {
#endif #endif
#ifdef USE_VORBIS #ifdef USE_VORBIS
ChannelVorbis::ChannelVorbis(SoundMixer *mixer, OggVorbis_File *ov_file, int duration, bool is_cd_track) ChannelVorbis::ChannelVorbis(SoundMixer *mixer, PlayingSoundHandle *handle, OggVorbis_File *ov_file, int duration, bool is_cd_track)
: Channel(mixer) { : Channel(mixer, handle) {
_ov_file = ov_file; _ov_file = ov_file;
if (duration) if (duration)

View file

@ -59,8 +59,6 @@ private:
void *_premixParam; void *_premixParam;
PremixProc *_premixProc; PremixProc *_premixProc;
PlayingSoundHandle *_handles[NUM_CHANNELS];
public: public:
uint _outputRate; uint _outputRate;