mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-03 23:52:41 +00:00
lots of mixer changes: replaced _volumeTable by _globalVolume (applying volume after resampling is more accurate); made more member vars of SoundMixer protected (and thus added some new getter methods); added (untested) support for a second (stereo) channel when playing MP3
svn-id: r9184
This commit is contained in:
parent
95bb74e2b8
commit
791efd853a
@ -1695,15 +1695,15 @@ int Sound::pollMP3CD() const {
|
||||
}
|
||||
|
||||
int Sound::updateMP3CD() {
|
||||
if (_dig_cd.playing == false)
|
||||
if (!_dig_cd.playing)
|
||||
return -1;
|
||||
|
||||
if (_scumm->_mixer->_channels[_dig_cd.index] == NULL) {
|
||||
if (!_scumm->_mixer->isChannelUsed(_dig_cd.index)) {
|
||||
warning("Error in MP3 decoding");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!_scumm->_mixer->isActiveChannel(_dig_cd.index)) {
|
||||
if (!_scumm->_mixer->isChannelActive(_dig_cd.index)) {
|
||||
if (_dig_cd.num_loops == -1 || --_dig_cd.num_loops > 0)
|
||||
playMP3CDTrack(_dig_cd.track, _dig_cd.num_loops, _dig_cd.start, _dig_cd.duration);
|
||||
else
|
||||
|
146
sound/mixer.cpp
146
sound/mixer.cpp
@ -26,7 +26,6 @@
|
||||
#include "common/file.h"
|
||||
#include "common/util.h"
|
||||
|
||||
|
||||
class Channel {
|
||||
protected:
|
||||
SoundMixer *_mixer;
|
||||
@ -41,6 +40,11 @@ public:
|
||||
if (_handle)
|
||||
*_handle = 0;
|
||||
}
|
||||
|
||||
/* len indicates the number of sample *pairs*. So a value of
|
||||
10 means that the buffer contains twice 10 sample, each
|
||||
16 bits, for a total of 40 bytes.
|
||||
*/
|
||||
virtual void mix(int16 *data, uint len) = 0;
|
||||
void destroy() {
|
||||
for (int i = 0; i != SoundMixer::NUM_CHANNELS; i++)
|
||||
@ -54,12 +58,12 @@ public:
|
||||
|
||||
class ChannelRaw : public Channel {
|
||||
byte *_ptr;
|
||||
byte _flags;
|
||||
uint32 _pos;
|
||||
uint32 _size;
|
||||
uint32 _fpSpeed;
|
||||
uint32 _fpPos;
|
||||
uint32 _realSize, _rate;
|
||||
byte _flags;
|
||||
byte *_loop_ptr;
|
||||
uint32 _loop_size;
|
||||
|
||||
@ -170,7 +174,7 @@ SoundMixer::SoundMixer() {
|
||||
|
||||
_outputRate = 0;
|
||||
|
||||
_volumeTable = (int16 *)calloc(256 * sizeof(int16), 1);
|
||||
_globalVolume = 0;
|
||||
_musicVolume = 0;
|
||||
|
||||
_paused = false;
|
||||
@ -181,13 +185,17 @@ SoundMixer::SoundMixer() {
|
||||
|
||||
SoundMixer::~SoundMixer() {
|
||||
_syst->clear_sound_proc();
|
||||
free(_volumeTable);
|
||||
for (int i = 0; i != NUM_CHANNELS; i++) {
|
||||
delete _channels[i];
|
||||
}
|
||||
_syst->delete_mutex(_mutex);
|
||||
}
|
||||
|
||||
int SoundMixer::newStream(void *sound, uint32 size, uint rate, byte flags, uint32 buffer_size) {
|
||||
StackLock lock(_mutex);
|
||||
return insertChannel(NULL, new ChannelStream(this, 0, sound, size, rate, flags, buffer_size));
|
||||
}
|
||||
|
||||
void SoundMixer::appendStream(int index, void *sound, uint32 size) {
|
||||
StackLock lock(_mutex);
|
||||
|
||||
@ -253,11 +261,6 @@ int SoundMixer::playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, ui
|
||||
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) {
|
||||
StackLock lock(_mutex);
|
||||
return insertChannel(NULL, new ChannelStream(this, 0, sound, size, rate, flags, buffer_size));
|
||||
}
|
||||
|
||||
#ifdef USE_MAD
|
||||
int SoundMixer::playMP3(PlayingSoundHandle *handle, void *sound, uint32 size, byte flags) {
|
||||
StackLock lock(_mutex);
|
||||
@ -298,7 +301,11 @@ void SoundMixer::mix(int16 *buf, uint len) {
|
||||
}
|
||||
}
|
||||
|
||||
void SoundMixer::onGenerateSamples(void *s, byte *samples, int len) {
|
||||
void SoundMixer::mixCallback(void *s, byte *samples, int len) {
|
||||
assert(s);
|
||||
assert(samples);
|
||||
// Len is the number of bytes in the buffer; we divide it by
|
||||
// four to get the number of samples (stereo 16 bit).
|
||||
((SoundMixer *)s)->mix((int16 *)samples, len >> 2);
|
||||
}
|
||||
|
||||
@ -311,7 +318,7 @@ bool SoundMixer::bindToSystem(OSystem *syst) {
|
||||
if (rate == 0)
|
||||
error("OSystem returned invalid sample rate");
|
||||
|
||||
return syst->set_sound_proc(onGenerateSamples, this, OSystem::SOUND_16BIT);
|
||||
return syst->set_sound_proc(mixCallback, this, OSystem::SOUND_16BIT);
|
||||
}
|
||||
|
||||
void SoundMixer::stopAll() {
|
||||
@ -376,13 +383,18 @@ bool SoundMixer::hasActiveSFXChannel() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SoundMixer::isActiveChannel(int index) {
|
||||
bool SoundMixer::isChannelActive(int index) {
|
||||
StackLock lock(_mutex);
|
||||
if (_channels[index])
|
||||
return _channels[index]->isActive();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SoundMixer::isChannelUsed(int index) {
|
||||
StackLock lock(_mutex);
|
||||
return (_channels[index] != NULL);
|
||||
}
|
||||
|
||||
void SoundMixer::setupPremix(void *param, PremixProc *proc) {
|
||||
StackLock lock(_mutex);
|
||||
_premixParam = param;
|
||||
@ -390,20 +402,13 @@ void SoundMixer::setupPremix(void *param, PremixProc *proc) {
|
||||
}
|
||||
|
||||
void SoundMixer::setVolume(int volume) {
|
||||
int i;
|
||||
|
||||
// Check range
|
||||
if (volume > 256)
|
||||
volume = 256;
|
||||
else if (volume < 0)
|
||||
volume = 0;
|
||||
|
||||
// The volume table takes 8 bit unsigned data as index and returns 16 bit signed
|
||||
for (i = 0; i < 128; i++)
|
||||
_volumeTable[i] = i * volume;
|
||||
|
||||
for (i = -128; i < 0; i++)
|
||||
_volumeTable[i + 256] = i * volume;
|
||||
_globalVolume = volume;
|
||||
}
|
||||
|
||||
void SoundMixer::setMusicVolume(int volume) {
|
||||
@ -481,13 +486,13 @@ static inline void clamped_add_16(int16& a, int b) {
|
||||
}
|
||||
|
||||
static void mix_signed_mono_8(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
|
||||
int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
|
||||
int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
|
||||
int inc = 1, result;
|
||||
CubicInterpolator interp(vol_tab[*s], vol_tab[*(s + 1)], vol_tab[*(s + 2)]);
|
||||
CubicInterpolator interp(*s, *(s + 1), *(s + 2));
|
||||
|
||||
do {
|
||||
do {
|
||||
result = interp.interpolate(fp_pos);
|
||||
result = interp.interpolate(fp_pos) * volume / 256;
|
||||
|
||||
clamped_add_16(*data++, result);
|
||||
clamped_add_16(*data++, result);
|
||||
@ -500,7 +505,7 @@ static void mix_signed_mono_8(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
|
||||
} while (!inc && len && (s < s_end));
|
||||
|
||||
if (s + 2 < s_end)
|
||||
interp.feedData(vol_tab[*(s + 2)]);
|
||||
interp.feedData(*(s + 2));
|
||||
else
|
||||
interp.feedData();
|
||||
|
||||
@ -508,13 +513,13 @@ static void mix_signed_mono_8(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
|
||||
}
|
||||
|
||||
static void mix_unsigned_mono_8(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
|
||||
int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
|
||||
int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
|
||||
int inc = 1, result;
|
||||
CubicInterpolator interp(vol_tab[*s ^ 0x80], vol_tab[*(s + 1) ^ 0x80], vol_tab[*(s + 2) ^ 0x80]);
|
||||
CubicInterpolator interp(*s ^ 0x80, *(s + 1) ^ 0x80, *(s + 2) ^ 0x80);
|
||||
|
||||
do {
|
||||
do {
|
||||
result = interp.interpolate(fp_pos);
|
||||
result = interp.interpolate(fp_pos) * volume / 256;
|
||||
|
||||
clamped_add_16(*data++, result);
|
||||
clamped_add_16(*data++, result);
|
||||
@ -527,7 +532,7 @@ static void mix_unsigned_mono_8(int16 *data, uint &len, byte *&s, uint32 &fp_pos
|
||||
} while (!inc && len && (s < s_end));
|
||||
|
||||
if (s + 2 < s_end)
|
||||
interp.feedData(vol_tab[*(s + 2) ^ 0x80]);
|
||||
interp.feedData(*(s + 2) ^ 0x80);
|
||||
else
|
||||
interp.feedData();
|
||||
|
||||
@ -535,23 +540,23 @@ static void mix_unsigned_mono_8(int16 *data, uint &len, byte *&s, uint32 &fp_pos
|
||||
}
|
||||
|
||||
static void mix_signed_stereo_8(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
|
||||
int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
|
||||
int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
|
||||
warning("Mixing stereo signed 8 bit is not supported yet ");
|
||||
}
|
||||
static void mix_unsigned_stereo_8(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
|
||||
int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
|
||||
int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
|
||||
int inc = 1;
|
||||
CubicInterpolator left(vol_tab[*s ^ 0x80], vol_tab[*(s + 2) ^ 0x80], vol_tab[*(s + 4) ^ 0x80]);
|
||||
CubicInterpolator right(vol_tab[*(s + 1) ^ 0x80], vol_tab[*(s + 3) ^ 0x80], vol_tab[*(s + 5) ^ 0x80]);
|
||||
CubicInterpolator left(*s ^ 0x80, *(s + 2) ^ 0x80, *(s + 4) ^ 0x80);
|
||||
CubicInterpolator right(*(s + 1) ^ 0x80, *(s + 3) ^ 0x80, *(s + 5) ^ 0x80);
|
||||
|
||||
do {
|
||||
do {
|
||||
if (!reverse_stereo) {
|
||||
clamped_add_16(*data++, left.interpolate(fp_pos));
|
||||
clamped_add_16(*data++, right.interpolate(fp_pos));
|
||||
clamped_add_16(*data++, left.interpolate(fp_pos) * volume / 256);
|
||||
clamped_add_16(*data++, right.interpolate(fp_pos) * volume / 256);
|
||||
} else {
|
||||
clamped_add_16(*data++, right.interpolate(fp_pos));
|
||||
clamped_add_16(*data++, left.interpolate(fp_pos));
|
||||
clamped_add_16(*data++, right.interpolate(fp_pos) * volume / 256);
|
||||
clamped_add_16(*data++, left.interpolate(fp_pos) * volume / 256);
|
||||
}
|
||||
|
||||
fp_pos += fp_speed;
|
||||
@ -562,8 +567,8 @@ static void mix_unsigned_stereo_8(int16 *data, uint &len, byte *&s, uint32 &fp_p
|
||||
} while (!inc && len && (s < s_end));
|
||||
|
||||
if (s + 5 < s_end) {
|
||||
left.feedData(vol_tab[*(s + 4) ^ 0x80]);
|
||||
right.feedData(vol_tab[*(s + 5) ^ 0x80]);
|
||||
left.feedData(*(s + 4) ^ 0x80);
|
||||
right.feedData(*(s + 5) ^ 0x80);
|
||||
} else {
|
||||
left.feedData();
|
||||
right.feedData();
|
||||
@ -572,8 +577,7 @@ static void mix_unsigned_stereo_8(int16 *data, uint &len, byte *&s, uint32 &fp_p
|
||||
} while (len && (s < s_end));
|
||||
}
|
||||
static void mix_signed_mono_16(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
|
||||
int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
|
||||
unsigned char volume = ((int)vol_tab[1]);
|
||||
int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
|
||||
do {
|
||||
int16 sample = ((int16)READ_BE_UINT16(s) * volume) / 256;
|
||||
fp_pos += fp_speed;
|
||||
@ -586,13 +590,11 @@ static void mix_signed_mono_16(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
|
||||
} while ((--len) && (s < s_end));
|
||||
}
|
||||
static void mix_unsigned_mono_16(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
|
||||
int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
|
||||
int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
|
||||
warning("Mixing mono unsigned 16 bit is not supported yet ");
|
||||
}
|
||||
static void mix_signed_stereo_16(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
|
||||
int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
|
||||
unsigned char volume = (int)vol_tab[1];
|
||||
|
||||
int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
|
||||
do {
|
||||
int16 leftS = ((int16)READ_BE_UINT16(s) * volume) / 256;
|
||||
int16 rightS = ((int16)READ_BE_UINT16(s+2) * volume) / 256;
|
||||
@ -610,12 +612,12 @@ static void mix_signed_stereo_16(int16 *data, uint &len, byte *&s, uint32 &fp_po
|
||||
} while ((--len) && (s < s_end));
|
||||
}
|
||||
static void mix_unsigned_stereo_16(int16 *data, uint &len, byte *&s, uint32 &fp_pos,
|
||||
int fp_speed, const int16 *vol_tab, byte *s_end, bool reverse_stereo) {
|
||||
int fp_speed, int volume, byte *s_end, bool reverse_stereo) {
|
||||
warning("Mixing stereo unsigned 16 bit is not supported yet ");
|
||||
}
|
||||
|
||||
typedef void MixProc(int16 *data, uint &len, byte *&s,
|
||||
uint32 &fp_pos, int fp_speed, const int16 *vol_tab,
|
||||
uint32 &fp_pos, int fp_speed, int volume,
|
||||
byte *s_end, bool reverse_stereo);
|
||||
|
||||
static MixProc *mixer_helper_table[8] = {
|
||||
@ -641,11 +643,12 @@ bool Channel::isActive() {
|
||||
ChannelRaw::ChannelRaw(SoundMixer *mixer, PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id)
|
||||
: Channel(mixer, handle) {
|
||||
_id = id;
|
||||
_flags = flags;
|
||||
_ptr = (byte *)sound;
|
||||
_flags = flags;
|
||||
|
||||
_pos = 0;
|
||||
_fpPos = 0;
|
||||
_fpSpeed = (1 << 16) * rate / mixer->_outputRate;
|
||||
_fpSpeed = (1 << 16) * rate / mixer->getOutputRate();
|
||||
_realSize = size;
|
||||
|
||||
// adjust the magnitude to prevent division error
|
||||
@ -653,7 +656,7 @@ ChannelRaw::ChannelRaw(SoundMixer *mixer, PlayingSoundHandle *handle, void *soun
|
||||
size >>= 1, rate = (rate >> 1) + 1;
|
||||
|
||||
_rate = rate;
|
||||
_size = size * mixer->_outputRate / rate;
|
||||
_size = size * mixer->getOutputRate() / rate;
|
||||
if (_flags & SoundMixer::FLAG_16BITS)
|
||||
_size = _size >> 1;
|
||||
if (_flags & SoundMixer::FLAG_STEREO)
|
||||
@ -680,9 +683,7 @@ void ChannelRaw::mix(int16 *data, uint len) {
|
||||
s = _ptr + _pos;
|
||||
end = _ptr + _realSize;
|
||||
|
||||
const int16 *vol_tab = _mixer->_volumeTable;
|
||||
|
||||
mixer_helper_table[_flags & 0x07] (data, len, s, _fpPos, _fpSpeed, vol_tab, end, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
|
||||
mixer_helper_table[_flags & 0x07] (data, len, s, _fpPos, _fpSpeed, _mixer->getVolume(), end, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
|
||||
|
||||
_pos = s - _ptr;
|
||||
|
||||
@ -712,7 +713,7 @@ ChannelStream::ChannelStream(SoundMixer *mixer, PlayingSoundHandle *handle, void
|
||||
_endOfBuffer = _ptr + _bufferSize;
|
||||
_pos = _ptr;
|
||||
_fpPos = 0;
|
||||
_fpSpeed = (1 << 16) * rate / mixer->_outputRate;
|
||||
_fpSpeed = (1 << 16) * rate / mixer->getOutputRate();
|
||||
_finished = false;
|
||||
|
||||
// adjust the magnitude to prevent division error
|
||||
@ -768,11 +769,10 @@ void ChannelStream::mix(int16 *data, uint len) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int16 *vol_tab = _mixer->_volumeTable;
|
||||
MixProc *mixProc = mixer_helper_table[_flags & 0x07];
|
||||
|
||||
if (_pos < _endOfData) {
|
||||
mixProc(data, len, _pos, _fpPos, _fpSpeed, vol_tab, _endOfData, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
|
||||
mixProc(data, len, _pos, _fpPos, _fpSpeed, _mixer->getVolume(), _endOfData, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
|
||||
} else {
|
||||
int wrapOffset = 0;
|
||||
const uint32 outLen = mixer_element_size[_flags & 0x07] * len;
|
||||
@ -785,7 +785,7 @@ void ChannelStream::mix(int16 *data, uint len) {
|
||||
memcpy(_endOfBuffer, _ptr, wrapOffset);
|
||||
}
|
||||
|
||||
mixProc(data, len, _pos, _fpPos, _fpSpeed, vol_tab, _endOfBuffer + wrapOffset, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
|
||||
mixProc(data, len, _pos, _fpPos, _fpSpeed, _mixer->getVolume(), _endOfBuffer + wrapOffset, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
|
||||
|
||||
// recover from wrap
|
||||
if (wrapOffset)
|
||||
@ -796,7 +796,7 @@ void ChannelStream::mix(int16 *data, uint len) {
|
||||
//FIXME: what is wrong ?
|
||||
warning("bad play sound in stream (wrap around)");
|
||||
_pos = _ptr;
|
||||
mixProc(data, len, _pos, _fpPos, _fpSpeed, vol_tab, _endOfData, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
|
||||
mixProc(data, len, _pos, _fpPos, _fpSpeed, _mixer->getVolume(), _endOfData, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -861,12 +861,9 @@ static inline int scale_sample(mad_fixed_t sample) {
|
||||
}
|
||||
|
||||
void ChannelMP3::mix(int16 *data, uint len) {
|
||||
mad_fixed_t const * ch;
|
||||
const int16 * vol_tab = _mixer->_volumeTable;
|
||||
unsigned char volume = ((int)vol_tab[1]) / 8;
|
||||
const int volume = _mixer->getVolume();
|
||||
|
||||
while (1) {
|
||||
ch = _synth.pcm.samples[0] + _posInFrame;
|
||||
|
||||
/* Skip _silence_cut a the start */
|
||||
if ((_posInFrame < _synth.pcm.length) && (_silenceCut > 0)) {
|
||||
@ -875,13 +872,15 @@ void ChannelMP3::mix(int16 *data, uint len) {
|
||||
if (diff > _silenceCut)
|
||||
diff = _silenceCut;
|
||||
_silenceCut -= diff;
|
||||
ch += diff;
|
||||
_posInFrame += diff;
|
||||
}
|
||||
|
||||
int16 sample;
|
||||
while ((_posInFrame < _synth.pcm.length) && (len > 0)) {
|
||||
int16 sample = (int16)((scale_sample(*ch++) * volume) / 32);
|
||||
sample = (int16)((scale_sample(_synth.pcm.samples[0][_posInFrame]) * volume) / 256);
|
||||
clamped_add_16(*data++, sample);
|
||||
if (_synth.pcm.channels > 1)
|
||||
sample = (int16)((scale_sample(_synth.pcm.samples[1][_posInFrame]) * volume) / 256);
|
||||
clamped_add_16(*data++, sample);
|
||||
len--;
|
||||
_posInFrame++;
|
||||
@ -925,16 +924,15 @@ ChannelMP3CDMusic::ChannelMP3CDMusic(SoundMixer *mixer, PlayingSoundHandle *hand
|
||||
}
|
||||
|
||||
void ChannelMP3CDMusic::mix(int16 *data, uint len) {
|
||||
mad_fixed_t const *ch;
|
||||
mad_timer_t frame_duration;
|
||||
unsigned char volume = _mixer->_musicVolume / 8;
|
||||
int volume = _mixer->getMusicVolume();
|
||||
|
||||
if (!_initialized) {
|
||||
int skip_loop;
|
||||
// just skipped
|
||||
memset(_ptr, 0, _bufferSize);
|
||||
_size = _file->read(_ptr, _bufferSize);
|
||||
if (!_size) {
|
||||
if (_size <= 0) {
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
@ -971,18 +969,24 @@ void ChannelMP3CDMusic::mix(int16 *data, uint len) {
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
||||
// TODO: Check _synth.pcm.samplerate and perform rate conversion of appropriate
|
||||
// TODO: Check _synth.pcm.channels to support stereo
|
||||
|
||||
// Get samples, play samples ...
|
||||
ch = _synth.pcm.samples[0] + _posInFrame;
|
||||
int16 sample;
|
||||
while ((_posInFrame < _synth.pcm.length) && (len > 0)) {
|
||||
int16 sample = (int16)((scale_sample(*ch++) * volume) / 32);
|
||||
sample = (int16)((scale_sample(_synth.pcm.samples[0][_posInFrame]) * volume) / 256);
|
||||
clamped_add_16(*data++, sample);
|
||||
if (_synth.pcm.channels > 1)
|
||||
sample = (int16)((scale_sample(_synth.pcm.samples[1][_posInFrame]) * volume) / 256);
|
||||
clamped_add_16(*data++, sample);
|
||||
len--;
|
||||
_posInFrame++;
|
||||
}
|
||||
if (len == 0) {
|
||||
if (len == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// See if we have finished
|
||||
// May be incorrect to check the size at the end of a frame but I suppose
|
||||
// they are short enough :)
|
||||
@ -1051,7 +1055,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->getMusicVolume() : _mixer->getVolume();
|
||||
|
||||
// Read the samples
|
||||
while (len_left > 0) {
|
||||
|
@ -43,6 +43,7 @@ class Channel;
|
||||
class File;
|
||||
|
||||
class SoundMixer {
|
||||
friend class Channel;
|
||||
public:
|
||||
typedef void PremixProc (void *param, int16 *data, uint len);
|
||||
|
||||
@ -50,6 +51,16 @@ public:
|
||||
NUM_CHANNELS = 16
|
||||
};
|
||||
|
||||
enum {
|
||||
// Do *NOT* change any of these flags without looking at the code in mixer.cpp
|
||||
FLAG_UNSIGNED = 1 << 0, // unsigned samples (default: signed)
|
||||
FLAG_STEREO = 1 << 1, // sound is in stereo (default: mono)
|
||||
FLAG_16BITS = 1 << 2, // sound is 16 bits wide (default: 8bit)
|
||||
FLAG_AUTOFREE = 1 << 3, // sound buffer is freed automagically at the end of playing
|
||||
FLAG_REVERSE_STEREO = 1 << 4, // reverse the left and right stereo channel
|
||||
FLAG_LOOP = 1 << 5 // loop the audio
|
||||
};
|
||||
|
||||
private:
|
||||
OSystem *_syst;
|
||||
OSystem::MutexRef _mutex;
|
||||
@ -57,10 +68,9 @@ private:
|
||||
void *_premixParam;
|
||||
PremixProc *_premixProc;
|
||||
|
||||
public:
|
||||
uint _outputRate;
|
||||
|
||||
int16 *_volumeTable;
|
||||
int _globalVolume;
|
||||
int _musicVolume;
|
||||
|
||||
bool _paused;
|
||||
@ -72,15 +82,6 @@ public:
|
||||
~SoundMixer();
|
||||
|
||||
// start playing a raw sound
|
||||
enum {
|
||||
// Do *NOT* change any of these flags without looking at the code in mixer.cpp
|
||||
FLAG_UNSIGNED = 1 << 0, // unsigned samples
|
||||
FLAG_STEREO = 1 << 1, // sound is in stereo
|
||||
FLAG_16BITS = 1 << 2, // sound is 16 bits wide
|
||||
FLAG_AUTOFREE = 1 << 3, // sound buffer is freed automagically at the end of playing
|
||||
FLAG_REVERSE_STEREO = 1 << 4, // sound should be reverse stereo
|
||||
FLAG_LOOP = 1 << 5 // loop the audio
|
||||
};
|
||||
int playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id = -1);
|
||||
#ifdef USE_MAD
|
||||
int playMP3(PlayingSoundHandle *handle, void *sound, uint32 size, byte flags);
|
||||
@ -118,21 +119,33 @@ public:
|
||||
bool hasActiveSFXChannel();
|
||||
|
||||
/** Check whether the specified channel is active. */
|
||||
bool isActiveChannel(int index);
|
||||
bool isChannelActive(int index);
|
||||
|
||||
/** Check whether the specified channel is in use. */
|
||||
bool isChannelUsed(int index);
|
||||
|
||||
/** bind to the OSystem object => mixer will be
|
||||
* invoked automatically when samples need
|
||||
* to be generated */
|
||||
bool bindToSystem(OSystem *syst);
|
||||
|
||||
/** pause - unpause */
|
||||
void pause(bool paused);
|
||||
|
||||
/** set the global volume, 0-256 */
|
||||
void setVolume(int volume);
|
||||
|
||||
/** query the global volume, 0-256 */
|
||||
int getVolume() const { return _globalVolume; }
|
||||
|
||||
/** set the music volume, 0-256 */
|
||||
void setMusicVolume(int volume);
|
||||
|
||||
/** pause - unpause */
|
||||
void pause(bool paused);
|
||||
|
||||
/** query the music volume, 0-256 */
|
||||
int getMusicVolume() const { return _musicVolume; }
|
||||
|
||||
/** query the output rate in kHz */
|
||||
uint getOutputRate() const { return _outputRate; }
|
||||
|
||||
private:
|
||||
int insertChannel(PlayingSoundHandle *handle, Channel *chan);
|
||||
@ -140,7 +153,7 @@ private:
|
||||
/** mix */
|
||||
void mix(int16 * buf, uint len);
|
||||
|
||||
static void onGenerateSamples(void *s, byte *samples, int len);
|
||||
static void mixCallback(void *s, byte *samples, int len);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user