diff options
-rw-r--r-- | scumm/imuse.cpp | 86 | ||||
-rw-r--r-- | scumm/sound.cpp | 13 | ||||
-rw-r--r-- | scumm/sound.h | 2 | ||||
-rw-r--r-- | sound/mixer.cpp | 57 | ||||
-rw-r--r-- | sound/mixer.h | 1 |
5 files changed, 119 insertions, 40 deletions
diff --git a/scumm/imuse.cpp b/scumm/imuse.cpp index 6217040778..dfb3fa91b3 100644 --- a/scumm/imuse.cpp +++ b/scumm/imuse.cpp @@ -4855,7 +4855,7 @@ IMuseDigital::~IMuseDigital() { void IMuseDigital::handler() { bool new_mixer; - int32 l, idx = 0; + uint32 l, i, idx = 0; for (l = 0; l < MAX_DIGITAL_CHANNELS;l ++) { if (_channel[l]._used) { @@ -4887,6 +4887,29 @@ void IMuseDigital::handler() { memcpy(buf + new_size, _channel[l]._data + _channel[l]._jump[0]._dest, _channel[l]._mixerSize - new_size); } + if (_channel[l]._bits == 12) { + for(i = 0; i < (mixer_size / 4); i++) { + byte sample1 = buf[i * 4 + 0]; + byte sample2 = buf[i * 4 + 1]; + byte sample3 = buf[i * 4 + 2]; + byte sample4 = buf[i * 4 + 3]; + uint16 sample_a = (uint16)(((int16)((sample1 << 8) | sample2) * _channel[l]._volumeLeft) >> 8); + uint16 sample_b = (uint16)(((int16)((sample3 << 8) | sample4) * _channel[l]._volumeRight) >> 8); + buf[i * 4 + 0] = (byte)(sample_a >> 8); + buf[i * 4 + 1] = (byte)(sample_a & 0xff); + buf[i * 4 + 2] = (byte)(sample_b >> 8); + buf[i * 4 + 3] = (byte)(sample_b & 0xff); + } + } else if (_channel[l]._bits == 8) { + for(i = 0; i < (mixer_size / 2); i++) { + byte sample1 = buf[i * 2 + 0]; + byte sample2 = buf[i * 2 + 1]; + uint16 sample_a = (uint16)(((int16)((sample1 << 8) | sample2) * _channel[l]._volumeLeft) >> 8); + buf[i * 2 + 0] = (byte)(sample_a >> 8); + buf[i * 2 + 1] = (byte)(sample_a & 0xff); + } + } + new_mixer = false; if (_channel[l]._mixerTrack == -1) { _scumm->_system->lock_mutex(_scumm->_mixer->_mutex); @@ -4937,6 +4960,8 @@ void IMuseDigital::startSound(int sound) { _channel[l]._offset = 0; _channel[l]._numRegions = 0; _channel[l]._numJumps = 0; + _channel[l]._volumeLeft = 127; + _channel[l]._volumeRight = 127; ptr += 16; uint32 tag, size = 0; @@ -4996,7 +5021,7 @@ void IMuseDigital::startSound(int sound) { if (_channel[l]._bits == 12) { _channel[l]._offsetStop = (_channel[l]._offsetStop / 3) * 4; } - uint32 r; + uint32 r, t; for (r = 0; r < _channel[l]._numRegions; r++) { _channel[l]._region[r]._offset -= header_size; if (_channel[l]._bits == 12) { @@ -5015,23 +5040,29 @@ void IMuseDigital::startSound(int sound) { } } _channel[l]._mixerTrack = -1; - _channel[l]._mixerSize = 22050 / 5; - _channel[l]._mixerFlags = SoundMixer::FLAG_AUTOFREE; + _channel[l]._mixerSize = (22050 / 5) * 2; + _channel[l]._mixerFlags = SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO; if (_channel[l]._bits == 12) { _channel[l]._mixerSize *= 2; _channel[l]._mixerFlags |= SoundMixer::FLAG_16BITS; - _channel[l]._size = _scumm->_sound->decode12BitsSample(ptr, &_channel[l]._data, size); + _channel[l]._size = _scumm->_sound->decode12BitsSample(ptr, &_channel[l]._data, size, (_channel[l]._channels == 1) ? false : true); } if (_channel[l]._bits == 8) { _channel[l]._mixerFlags |= SoundMixer::FLAG_UNSIGNED; - _channel[l]._data = (byte *)malloc(size); - memcpy(_channel[l]._data, ptr, size); + if (_channel[l]._channels == 1) { + size *= 2; + _channel[l]._channels = 2; + _channel[l]._data = (byte *)malloc(size); + for (t = 0; t < size; t++) { + *(_channel[l]._data + l * 2 + 0) = *(ptr + l); + *(_channel[l]._data + l * 2 + 1) = *(ptr + l); + } + } else { + _channel[l]._data = (byte *)malloc(size); + memcpy(_channel[l]._data, ptr, size); + } _channel[l]._size = size; } - if (_channel[l]._channels == 2) { - _channel[l]._mixerSize *= 2; - _channel[l]._mixerFlags |= SoundMixer::FLAG_STEREO; - } if (_channel[l]._freq == 11025) { _channel[l]._mixerSize /= 2; } @@ -5067,6 +5098,7 @@ int32 IMuseDigital::doCommand(int a, int b, int c, int d, int e, int f, int g, i byte param = a >> 8; byte sample = b; byte sub_cmd = c >> 8; + int8 channel = -1, l; if (!(cmd || param)) return 1; @@ -5078,11 +5110,33 @@ int32 IMuseDigital::doCommand(int a, int b, int c, int d, int e, int f, int g, i case 5: // param seems always set 0 (maybe reset) debug(1, "IMuseDigital::doCommand stub cmd=%d,param=%d,sample=%d,sub_cmd=%d,params=(%d,%d,%d)", param, cmd, sample, sub_cmd, d, e, f); return 0; - case 6: // left pan control (0-127) i think - debug(1, "IMuseDigital::doCommand stub cmd=%d,param=%d,sample=%d,sub_cmd=%d,params=(%d,%d,%d)", param, cmd, sample, sub_cmd, d, e, f); + case 6: // right pan control (0-127) i think + debug(1, "IMuseDigital::doCommand setting right sample(%d), volume(%d)", sample, d); + for (l = 0; l < MAX_DIGITAL_CHANNELS; l++) { + if ((_channel[l]._idSound == sample) && (_channel[l]._used == true)) { + channel = l; + break; + } + } + if (channel == -1) { + warning("IMuseDigital::doCommand Sample %d not exist", sample); + return 1; + } + _channel[channel]._volumeRight = d; return 0; - case 7: // right pan control (0-127) i think - debug(1, "IMuseDigital::doCommand stub cmd=%d,param=%d,sample=%d,sub_cmd=%d,params=(%d,%d,%d)", param, cmd, sample, sub_cmd, d, e, f); + case 7: // left pan control (0-127) i think + debug(1, "IMuseDigital::doCommand setting left sample(%d), volume(%d)", sample, d); + for (l = 0; l < MAX_DIGITAL_CHANNELS; l++) { + if ((_channel[l]._idSound == sample) && (_channel[l]._used == true)) { + channel = l; + break; + } + } + if (channel == -1) { + warning("IMuseDigital::doCommand Sample %d not exist", sample); + return 1; + } + _channel[channel]._volumeLeft = d; return 0; default: warning("IMuseDigital::doCommand (param=0, cmd=12) default sub command %d", sub_cmd); @@ -5097,7 +5151,7 @@ int32 IMuseDigital::doCommand(int a, int b, int c, int d, int e, int f, int g, i warning("IMuseDigital::doCommand (param=0) default command %d", cmd); return 1; } - } else if (param == 16) { // unknown commands + } else if (param == 16) { // maybe music related switch (cmd) { case 0: debug(1, "IMuseDigital::doCommand %d,%d(%d,%d,%d,%d,%d)", param, cmd, b, c, d, e, f); diff --git a/scumm/sound.cpp b/scumm/sound.cpp index 59be2d7367..879d8a42e4 100644 --- a/scumm/sound.cpp +++ b/scumm/sound.cpp @@ -847,9 +847,12 @@ bool Sound::isSfxFinished() { return !_scumm->_mixer->hasActiveChannel(); } -uint32 Sound::decode12BitsSample(byte * src, byte ** dst, uint32 size) { +uint32 Sound::decode12BitsSample(byte * src, byte ** dst, uint32 size, bool stereo = false) { uint32 s_size = (size / 3) * 4; uint32 loop_size = s_size / 4; + if (stereo == true) { + s_size *= 2; + } byte *ptr = *dst = (byte*)malloc(s_size); uint32 tmp; @@ -860,9 +863,17 @@ uint32 Sound::decode12BitsSample(byte * src, byte ** dst, uint32 size) { tmp = ((((v2 & 0x0f) << 8) | v1) << 4) - 0x8000; *ptr++ = (byte)((tmp >> 8) & 0xff); *ptr++ = (byte)(tmp & 0xff); + if (stereo == true) { + *ptr++ = (byte)((tmp >> 8) & 0xff); + *ptr++ = (byte)(tmp & 0xff); + } tmp = ((((v2 & 0xf0) << 4) | v3) << 4) - 0x8000; *ptr++ = (byte)((tmp >> 8) & 0xff); *ptr++ = (byte)(tmp & 0xff); + if (stereo == true) { + *ptr++ = (byte)((tmp >> 8) & 0xff); + *ptr++ = (byte)(tmp & 0xff); + } } return s_size; } diff --git a/scumm/sound.h b/scumm/sound.h index 6c206dc3fb..b0986f455a 100644 --- a/scumm/sound.h +++ b/scumm/sound.h @@ -117,7 +117,7 @@ public: File * openSfxFile(); void stopSfxSound(); bool isSfxFinished(); - uint32 decode12BitsSample(byte * src, byte ** dst, uint32 size); + uint32 decode12BitsSample(byte * src, byte ** dst, uint32 size, bool stereo); void playBundleMusic(int32 song); void pauseBundleMusic(bool state); void bundleMusicHandler(Scumm * scumm); diff --git a/sound/mixer.cpp b/sound/mixer.cpp index c19facc3d9..176a5222a0 100644 --- a/sound/mixer.cpp +++ b/sound/mixer.cpp @@ -343,7 +343,7 @@ static inline int clamped_add_16(int a, int b) { } static int16 * mix_signed_mono_8(int16 * data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr, - int fp_speed, const int16 * vol_tab, byte * s_end) { + int fp_speed, const int16 * vol_tab, byte * s_end, bool reverse_stereo) { uint32 fp_pos = *fp_pos_ptr; byte *s = *s_ptr; uint len = *len_ptr; @@ -382,7 +382,7 @@ static int16 * mix_signed_mono_8(int16 * data, uint * len_ptr, byte ** s_ptr, ui } static int16 * mix_unsigned_mono_8(int16 * data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr, - int fp_speed, const int16 * vol_tab, byte * s_end) { + int fp_speed, const int16 * vol_tab, byte * s_end, bool reverse_stereo) { uint32 fp_pos = *fp_pos_ptr; byte *s = *s_ptr; uint len = *len_ptr; @@ -421,13 +421,13 @@ static int16 * mix_unsigned_mono_8(int16 * data, uint * len_ptr, byte ** s_ptr, } static int16 * mix_signed_stereo_8(int16 * data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr, - int fp_speed, const int16 * vol_tab, byte *s_end) { + int fp_speed, const int16 * vol_tab, byte *s_end, bool reverse_stereo) { warning("Mixing stereo signed 8 bit is not supported yet "); return data; } static int16 * mix_unsigned_stereo_8(int16 * data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr, - int fp_speed, const int16 * vol_tab, byte * s_end) { + int fp_speed, const int16 * vol_tab, byte * s_end, bool reverse_stereo) { uint32 fp_pos = *fp_pos_ptr; byte *s = *s_ptr; uint len = *len_ptr; @@ -438,10 +438,17 @@ static int16 * mix_unsigned_stereo_8(int16 * data, uint * len_ptr, byte ** s_ptr do { do { - *data = clamped_add_16(*data, left.interpolate(fp_pos)); - data++; - *data = clamped_add_16(*data, right.interpolate(fp_pos)); - data++; + if (reverse_stereo == false) { + *data = clamped_add_16(*data, left.interpolate(fp_pos)); + data++; + *data = clamped_add_16(*data, right.interpolate(fp_pos)); + data++; + } else { + *data = clamped_add_16(*data, right.interpolate(fp_pos)); + data++; + *data = clamped_add_16(*data, left.interpolate(fp_pos)); + data++; + } fp_pos += fp_speed; inc = (fp_pos >> 16) << 1; @@ -467,7 +474,7 @@ static int16 * mix_unsigned_stereo_8(int16 * data, uint * len_ptr, byte ** s_ptr return data; } static int16 * mix_signed_mono_16(int16 * data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr, - int fp_speed, const int16 * vol_tab, byte * s_end) { + int fp_speed, const int16 * vol_tab, byte * s_end, bool reverse_stereo) { uint32 fp_pos = *fp_pos_ptr; unsigned char volume = ((int)vol_tab[1]) / 8; byte *s = *s_ptr; @@ -492,13 +499,13 @@ static int16 * mix_signed_mono_16(int16 * data, uint * len_ptr, byte ** s_ptr, u return data; } static int16 *mix_unsigned_mono_16(int16 *data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr, - int fp_speed, const int16 * vol_tab, byte * s_end) { + int fp_speed, const int16 * vol_tab, byte * s_end, bool reverse_stereo) { warning("Mixing mono unsigned 16 bit is not supported yet "); return data; } static int16 *mix_signed_stereo_16(int16 * data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr, - int fp_speed, const int16 * vol_tab, byte * s_end) { + int fp_speed, const int16 * vol_tab, byte * s_end, bool reverse_stereo) { uint32 fp_pos = *fp_pos_ptr; unsigned char volume = ((int)vol_tab[1]) / 8; byte *s = *s_ptr; @@ -506,11 +513,17 @@ static int16 *mix_signed_stereo_16(int16 * data, uint * len_ptr, byte ** s_ptr, do { fp_pos += fp_speed; - *data = clamped_add_16(*data, (((int16)(*(s) << 8) | *(s + 1)) * volume) / 32); - data++; - *data = clamped_add_16(*data, (((int16)(*(s + 2) << 8) | *(s + 3)) * volume) / 32); - data++; - + if (reverse_stereo == false) { + *data = clamped_add_16(*data, (((int16)(*(s) << 8) | *(s + 1)) * volume) / 32); + data++; + *data = clamped_add_16(*data, (((int16)(*(s + 2) << 8) | *(s + 3)) * volume) / 32); + data++; + } else { + *data = clamped_add_16(*data, (((int16)(*(s + 2) << 8) | *(s + 3)) * volume) / 32); + data++; + *data = clamped_add_16(*data, (((int16)(*(s) << 8) | *(s + 1)) * volume) / 32); + data++; + } s += (fp_pos >> 16) << 2; fp_pos &= 0x0000FFFF; } while ((--len) && (s < s_end)); @@ -522,7 +535,7 @@ static int16 *mix_signed_stereo_16(int16 * data, uint * len_ptr, byte ** s_ptr, return data; } static int16 * mix_unsigned_stereo_16(int16 * data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr, - int fp_speed, const int16 * vol_tab, byte * s_end) { + int fp_speed, const int16 * vol_tab, byte * s_end, bool reverse_stereo) { warning("Mixing stereo unsigned 16 bit is not supported yet "); return data; @@ -530,7 +543,7 @@ static int16 * mix_unsigned_stereo_16(int16 * data, uint * len_ptr, byte ** s_pt 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) = { + byte * s_end, bool reverse_stereo) = { mix_signed_mono_8, mix_unsigned_mono_8, mix_signed_stereo_8, mix_unsigned_stereo_8, mix_signed_mono_16, mix_unsigned_mono_16, @@ -578,7 +591,7 @@ void SoundMixer::ChannelRaw::mix(int16 * data, uint len) { const uint32 fp_speed = _fpSpeed; const int16 *vol_tab = _mixer->_volumeTable; - mixer_helper_table[_flags & 0x07] (data, &len, &s, &fp_pos, fp_speed, vol_tab, end); + mixer_helper_table[_flags & 0x07] (data, &len, &s, &fp_pos, fp_speed, vol_tab, end, (_flags & FLAG_REVERSE_STEREO) ? true : false); _pos = s - (byte *)_ptr; _fpPos = fp_pos; @@ -667,14 +680,14 @@ void SoundMixer::ChannelStream::mix(int16 * data, uint len) { 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); + mixer_helper_table[_flags & 0x07] (data, &len, &_pos, &fp_pos, fp_speed, vol_tab, end_of_data, (_flags & FLAG_REVERSE_STEREO) ? true : false); } else { - mixer_helper_table[_flags & 0x07] (data, &len, &_pos, &fp_pos, fp_speed, vol_tab, _endOfBuffer); + mixer_helper_table[_flags & 0x07] (data, &len, &_pos, &fp_pos, fp_speed, vol_tab, _endOfBuffer, (_flags & FLAG_REVERSE_STEREO) ? true : false); if (len != 0) { //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); + mixer_helper_table[_flags & 0x07] (data, &len, &_pos, &fp_pos, fp_speed, vol_tab, end_of_data, (_flags & FLAG_REVERSE_STEREO) ? true : false); } } _timeOut = 3; diff --git a/sound/mixer.h b/sound/mixer.h index cdc45a7fee..8182430582 100644 --- a/sound/mixer.h +++ b/sound/mixer.h @@ -177,6 +177,7 @@ public: FLAG_16BITS = 4, /* sound is 16 bits wide */ FLAG_AUTOFREE = 8, /* sound buffer is freed automagically at the end of playing */ FLAG_FILE = 16, /* sound is a FILE * that's read from */ + FLAG_REVERSE_STEREO = 32, /* sound should be reverse stereo */ }; int playRaw(PlayingSoundHandle * handle, void * sound, uint32 size, uint rate, byte flags); int playRaw(PlayingSoundHandle * handle, void * sound, uint32 size, uint rate, byte flags, int id); |