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:
parent
2e0235d898
commit
b6c3d440b5
2 changed files with 39 additions and 45 deletions
|
@ -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)
|
||||||
|
|
|
@ -59,8 +59,6 @@ private:
|
||||||
void *_premixParam;
|
void *_premixParam;
|
||||||
PremixProc *_premixProc;
|
PremixProc *_premixProc;
|
||||||
|
|
||||||
PlayingSoundHandle *_handles[NUM_CHANNELS];
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint _outputRate;
|
uint _outputRate;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue