aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/mixer.cpp173
-rw-r--r--sound/mixer.h8
2 files changed, 70 insertions, 111 deletions
diff --git a/sound/mixer.cpp b/sound/mixer.cpp
index cdcba77d34..b919ced842 100644
--- a/sound/mixer.cpp
+++ b/sound/mixer.cpp
@@ -39,9 +39,9 @@ class ChannelRaw : public Channel {
public:
ChannelRaw(SoundMixer *mixer, void *sound, uint32 size, uint rate, byte flags, int id);
+ ~ChannelRaw();
void mix(int16 *data, uint len);
- void realDestroy();
};
class ChannelStream : public Channel {
@@ -57,9 +57,9 @@ class ChannelStream : public Channel {
public:
ChannelStream(SoundMixer *mixer, void *sound, uint32 size, uint rate, byte flags, int32 buffer_size);
+ ~ChannelStream();
void mix(int16 *data, uint len);
- void realDestroy();
void append(void *sound, uint32 size);
};
@@ -78,10 +78,9 @@ class ChannelMP3 : public Channel {
public:
ChannelMP3(SoundMixer *mixer, void *sound, uint size, byte flags);
+ ~ChannelMP3();
void mix(int16 *data, uint len);
- void realDestroy();
-
};
class ChannelMP3CDMusic : public Channel {
@@ -99,9 +98,9 @@ class ChannelMP3CDMusic : public Channel {
public:
ChannelMP3CDMusic(SoundMixer *mixer, File *file, mad_timer_t duration);
+ ~ChannelMP3CDMusic();
void mix(int16 *data, uint len);
- void realDestroy();
bool soundFinished();
};
@@ -117,7 +116,6 @@ public:
ChannelVorbis(SoundMixer *mixer, OggVorbis_File *ov_file, int duration, bool is_cd_track);
void mix(int16 *data, uint len);
- void realDestroy();
bool soundFinished();
};
#endif
@@ -138,6 +136,7 @@ SoundMixer::~SoundMixer() {
for (int i = 0; i != NUM_CHANNELS; i++) {
delete _channels[i];
}
+ _syst->delete_mutex(_mutex);
}
int SoundMixer::append(int index, void *sound, uint32 size) {
@@ -154,21 +153,20 @@ int SoundMixer::append(int index, void *sound, uint32 size) {
return 1;
}
-int SoundMixer::insertAt(PlayingSoundHandle *handle, int index, Channel *chan) {
- if(index == -1) {
- for (int i = 0; i != NUM_CHANNELS; i++)
- if (_channels[i] == NULL) {
- index = i;
- break;
- }
- if(index == -1) {
- warning("SoundMixer::out of mixer slots");
- return -1;
+int SoundMixer::insertChannel(PlayingSoundHandle *handle, Channel *chan) {
+ int index = -1;
+ for (int i = 0; i != NUM_CHANNELS; i++) {
+ if (_channels[i] == NULL) {
+ index = i;
+ break;
}
}
- if (_channels[index] != NULL) {
- error("Trying to put a mixer where it cannot go ");
+ if(index == -1) {
+ warning("SoundMixer::out of mixer slots");
+ delete chan;
+ return -1;
}
+
_channels[index] = chan;
_handles[index] = handle;
if (handle)
@@ -177,54 +175,25 @@ int SoundMixer::insertAt(PlayingSoundHandle *handle, int index, Channel *chan) {
}
int SoundMixer::playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id) {
- for (int i = 0; i != NUM_CHANNELS; i++) {
- if (_channels[i] == NULL) {
- return insertAt(handle, i, new ChannelRaw(this, sound, size, rate, flags, id));
- }
- }
-
- warning("SoundMixer::out of mixer slots");
- return -1;
+ return insertChannel(handle, new ChannelRaw(this, sound, size, rate, flags, id));
}
int SoundMixer::playStream(void *sound, uint32 size, uint rate, byte flags, int32 buffer_size) {
- return insertAt(NULL, -1, new ChannelStream(this, sound, size, rate, flags, buffer_size));
+ return insertChannel(NULL, new ChannelStream(this, sound, size, rate, flags, buffer_size));
}
#ifdef USE_MAD
int SoundMixer::playMP3(PlayingSoundHandle *handle, void *sound, uint32 size, byte flags) {
- for (int i = 0; i != NUM_CHANNELS; i++) {
- if (_channels[i] == NULL) {
- return insertAt(handle, i, new ChannelMP3(this, sound, size, flags));
- }
- }
-
- warning("SoundMixer::out of mixer slots");
- return -1;
+ return insertChannel(handle, new ChannelMP3(this, sound, size, flags));
}
int SoundMixer::playMP3CDTrack(PlayingSoundHandle *handle, File *file, mad_timer_t duration) {
- /* Stop the previously playing CD track (if any) */
- for (int i = 0; i != NUM_CHANNELS; i++) {
- if (_channels[i] == NULL) {
- return insertAt(handle, i, new ChannelMP3CDMusic(this, file, duration));
- }
- }
-
- warning("SoundMixer::out of mixer slots");
- return -1;
+ return insertChannel(handle, new ChannelMP3CDMusic(this, file, duration));
}
#endif
#ifdef USE_VORBIS
int SoundMixer::playVorbis(PlayingSoundHandle *handle, OggVorbis_File *ov_file, int duration, bool is_cd_track) {
- for (int i = 0; i != NUM_CHANNELS; i++) {
- if (_channels[i] == NULL) {
- return insertAt(handle, i, new ChannelVorbis(this, ov_file, duration, is_cd_track));
- }
- }
-
- warning("SoundMixer::out of mixer slots");
- return -1;
+ return insertChannel(handle, -1, new ChannelVorbis(this, ov_file, duration, is_cd_track));
}
#endif
@@ -251,7 +220,6 @@ void SoundMixer::mix(int16 *buf, uint len) {
*_handles[i] = 0;
_handles[i] = NULL;
}
- _channels[i]->realDestroy();
delete _channels[i];
_channels[i] = NULL;
} else
@@ -610,9 +578,11 @@ static int16 *mix_unsigned_stereo_16(int16 *data, uint *len_ptr, byte **s_ptr, u
return data;
}
-static int16 *(*mixer_helper_table[8]) (int16 *data, uint *len_ptr, byte **s_ptr,
- uint32 *fp_pos_ptr, int fp_speed, const int16 *vol_tab,
- byte *s_end, bool reverse_stereo) = {
+typedef int16 *MixProc(int16 *data, uint *len_ptr, byte **s_ptr,
+ uint32 *fp_pos_ptr, int fp_speed, const int16 *vol_tab,
+ byte *s_end, bool reverse_stereo);
+
+static MixProc *mixer_helper_table[8] = {
mix_signed_mono_8, mix_unsigned_mono_8,
mix_signed_stereo_8, mix_unsigned_stereo_8,
mix_signed_mono_16, mix_unsigned_mono_16,
@@ -659,6 +629,11 @@ ChannelRaw::ChannelRaw(SoundMixer *mixer, void *sound, uint32 size, uint rate, b
}
}
+ChannelRaw::~ChannelRaw() {
+ if (_flags & SoundMixer::FLAG_AUTOFREE)
+ free(_ptr);
+}
+
void ChannelRaw::mix(int16 *data, uint len) {
byte *s, *end;
@@ -669,10 +644,9 @@ void ChannelRaw::mix(int16 *data, uint len) {
s = _ptr + _pos;
end = _ptr + _realSize;
- const uint32 fp_speed = _fpSpeed;
const int16 *vol_tab = _mixer->_volumeTable;
- mixer_helper_table[_flags & 0x07] (data, &len, &s, &_fpPos, fp_speed, vol_tab, end, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
+ mixer_helper_table[_flags & 0x07] (data, &len, &s, &_fpPos, _fpSpeed, vol_tab, end, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
_pos = s - _ptr;
@@ -683,15 +657,9 @@ void ChannelRaw::mix(int16 *data, uint len) {
_pos = 0;
_fpPos = 0;
} else {
- _toBeDestroyed = true;
+ destroy();
}
}
-
-}
-
-void ChannelRaw::realDestroy() {
- if (_flags & SoundMixer::FLAG_AUTOFREE)
- free(_ptr);
}
#define WARP_WORKAROUND 50000
@@ -716,6 +684,10 @@ ChannelStream::ChannelStream(SoundMixer *mixer, void *sound, uint32 size, uint r
_rate = rate;
}
+ChannelStream::~ChannelStream() {
+ free(_ptr);
+}
+
void ChannelStream::append(void *data, uint32 len) {
byte *new_end = _endOfData + len;
byte *cur_pos = _pos; /* This is just to prevent the variable to move during the tests :-) */
@@ -741,19 +713,14 @@ void ChannelStream::append(void *data, uint32 len) {
}
void ChannelStream::mix(int16 *data, uint len) {
- uint32 fp_pos;
- const uint32 fp_speed = _fpSpeed;
const int16 *vol_tab = _mixer->_volumeTable;
- byte *end_of_data = _endOfData;
- if (_pos == end_of_data) {
+ if (_pos == _endOfData) {
return;
}
- fp_pos = _fpPos;
-
- if (_pos < end_of_data) {
- mixer_helper_table[_flags & 0x07] (data, &len, &_pos, &fp_pos, fp_speed, vol_tab, end_of_data, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
+ if (_pos < _endOfData) {
+ mixer_helper_table[_flags & 0x07] (data, &len, &_pos, &_fpPos, _fpSpeed, vol_tab, _endOfData, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
} else {
int wrap_offset = 0;
@@ -765,7 +732,7 @@ void ChannelStream::mix(int16 *data, uint len) {
}
- mixer_helper_table[_flags & 0x07] (data, &len, &_pos, &fp_pos, fp_speed, vol_tab, _endOfBuffer + wrap_offset, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
+ mixer_helper_table[_flags & 0x07] (data, &len, &_pos, &_fpPos, _fpSpeed, vol_tab, _endOfBuffer + wrap_offset, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
// recover from wrap
if (wrap_offset)
@@ -776,14 +743,9 @@ void ChannelStream::mix(int16 *data, uint len) {
//FIXME: what is wrong ?
warning("bad play sound in stream(wrap around)");
_pos = _ptr;
- mixer_helper_table[_flags & 0x07] (data, &len, &_pos, &fp_pos, fp_speed, vol_tab, end_of_data, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
+ mixer_helper_table[_flags & 0x07] (data, &len, &_pos, &_fpPos, _fpSpeed, vol_tab, _endOfData, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
}
}
- _fpPos = fp_pos;
-}
-
-void ChannelStream::realDestroy() {
- free(_ptr);
}
#ifdef USE_MAD
@@ -818,6 +780,14 @@ ChannelMP3::ChannelMP3(SoundMixer *mixer, void *sound, uint size, byte flags) {
_silenceCut = 576 * 2;
}
+ChannelMP3::~ChannelMP3() {
+ if (_flags & SoundMixer::FLAG_AUTOFREE)
+ free(_ptr);
+ mad_synth_finish(&_synth);
+ mad_frame_finish(&_frame);
+ mad_stream_finish(&_stream);
+}
+
static inline int scale_sample(mad_fixed_t sample) {
/* round */
sample += (1L << (MAD_F_FRACBITS - 16));
@@ -852,20 +822,19 @@ void ChannelMP3::mix(int16 *data, uint len) {
}
while ((_posInFrame < _synth.pcm.length) && (len > 0)) {
- int16 sample = (int16)((scale_sample(*ch) * volume) / 32);
+ int16 sample = (int16)((scale_sample(*ch++) * volume) / 32);
*data = clamped_add_16(*data, sample);
data++;
*data = clamped_add_16(*data, sample);
data++;
len--;
- ch++;
_posInFrame++;
}
if (len == 0)
return;
if (_position >= _size) {
- _toBeDestroyed = true;
+ destroy();
return;
}
@@ -875,7 +844,7 @@ void ChannelMP3::mix(int16 *data, uint len) {
if (mad_frame_decode(&_frame, &_stream) == -1) {
/* End of audio... */
if (_stream.error == MAD_ERROR_BUFLEN) {
- _toBeDestroyed = true;
+ destroy();
return;
} else if (!MAD_RECOVERABLE(_stream.error)) {
error("MAD frame decode error !");
@@ -887,14 +856,6 @@ void ChannelMP3::mix(int16 *data, uint len) {
}
}
-void ChannelMP3::realDestroy() {
- if (_flags & SoundMixer::FLAG_AUTOFREE)
- free(_ptr);
- mad_synth_finish(&_synth);
- mad_frame_finish(&_frame);
- mad_stream_finish(&_stream);
-}
-
#define MP3CD_BUFFERING_SIZE 131072
ChannelMP3CDMusic::ChannelMP3CDMusic(SoundMixer *mixer, File *file,
@@ -916,6 +877,13 @@ ChannelMP3CDMusic::ChannelMP3CDMusic(SoundMixer *mixer, File *file,
mad_synth_init(&_synth);
}
+ChannelMP3CDMusic::~ChannelMP3CDMusic() {
+ free(_ptr);
+ mad_synth_finish(&_synth);
+ mad_frame_finish(&_frame);
+ mad_stream_finish(&_stream);
+}
+
void ChannelMP3CDMusic::mix(int16 *data, uint len) {
mad_fixed_t const *ch;
mad_timer_t frame_duration;
@@ -927,7 +895,7 @@ void ChannelMP3CDMusic::mix(int16 *data, uint len) {
memset(_ptr, 0, _bufferSize);
_size = _file->read(_ptr, _bufferSize);
if (!_size) {
- _toBeDestroyed = true;
+ destroy();
return;
}
// Resync
@@ -943,7 +911,7 @@ void ChannelMP3CDMusic::mix(int16 *data, uint len) {
} else {
if (!MAD_RECOVERABLE(_stream.error)) {
debug(1, "Unrecoverable error while skipping !");
- _toBeDestroyed = true;
+ destroy();
return;
}
}
@@ -957,7 +925,7 @@ void ChannelMP3CDMusic::mix(int16 *data, uint len) {
_initialized = true;
} else {
debug(1, "Cannot resume decoding");
- _toBeDestroyed = true;
+ destroy();
return;
}
}
@@ -1015,13 +983,6 @@ bool ChannelMP3CDMusic::soundFinished() {
return mad_timer_compare(_duration, mad_timer_zero) <= 0;
}
-void ChannelMP3CDMusic::realDestroy() {
- free(_ptr);
- mad_synth_finish(&_synth);
- mad_frame_finish(&_frame);
- mad_stream_finish(&_stream);
-}
-
#endif
#ifdef USE_VORBIS
@@ -1049,8 +1010,7 @@ 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->_musicVolume :
- _mixer->_volumeTable[1];
+ int volume = _is_cd_track ? _mixer->_musicVolume : _mixer->_volumeTable[1];
// Read the samples
while (len_left > 0) {
@@ -1098,10 +1058,7 @@ void ChannelVorbis::mix(int16 *data, uint len) {
delete [] samples;
if (_eof_flag && ! _is_cd_track)
- _toBeDestroyed = true;
-}
-
-void ChannelVorbis::realDestroy() {
+ destroy();
}
bool ChannelVorbis::soundFinished() {
diff --git a/sound/mixer.h b/sound/mixer.h
index afe6560a73..06f22e38fc 100644
--- a/sound/mixer.h
+++ b/sound/mixer.h
@@ -54,11 +54,11 @@ public:
bool _toBeDestroyed;
int _id;
Channel() : _mixer(0), _toBeDestroyed(false), _id(-1) {}
+ virtual ~Channel() {}
virtual void mix(int16 *data, uint len) = 0;
void destroy() {
_toBeDestroyed = true;
}
- virtual void realDestroy() = 0;
virtual bool soundFinished();
};
@@ -141,15 +141,17 @@ public:
* to be generated */
bool bindToSystem(OSystem *syst);
- /** set the volume, 0-256 */
+ /** set the global volume, 0-256 */
void setVolume(int volume);
+
+ /** set the music volume, 0-256 */
void setMusicVolume(int volume);
/** pause - unpause */
void pause(bool paused);
private:
- int insertAt(PlayingSoundHandle *handle, int index, Channel *chan);
+ int insertChannel(PlayingSoundHandle *handle, Channel *chan);
};
#endif