aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scumm/imuse.cpp86
-rw-r--r--scumm/sound.cpp13
-rw-r--r--scumm/sound.h2
-rw-r--r--sound/mixer.cpp57
-rw-r--r--sound/mixer.h1
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);