aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Snover2017-01-02 11:13:11 -0600
committerColin Snover2017-01-09 19:34:54 -0600
commit8987d9a889fb908b038e5615baab5403adf3073e (patch)
tree2bbd42d35b19645f090befb1546df2fc7a71f194
parent3e2f4a66f60ecebd2ee2cd42a303b881688bd626 (diff)
downloadscummvm-rg350-8987d9a889fb908b038e5615baab5403adf3073e.tar.gz
scummvm-rg350-8987d9a889fb908b038e5615baab5403adf3073e.tar.bz2
scummvm-rg350-8987d9a889fb908b038e5615baab5403adf3073e.zip
SCI32: Enable playback of stereo audio
-rw-r--r--engines/sci/sound/audio32.cpp10
-rw-r--r--engines/sci/sound/decoders/sol.cpp72
-rw-r--r--engines/sci/sound/decoders/sol.h4
-rw-r--r--engines/sci/video/robot_decoder.cpp4
4 files changed, 56 insertions, 34 deletions
diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp
index d5a7ae14b8..ca2402c859 100644
--- a/engines/sci/sound/audio32.cpp
+++ b/engines/sci/sound/audio32.cpp
@@ -159,9 +159,7 @@ int Audio32::writeAudioInternal(Audio::AudioStream *const sourceStream, Audio::R
// mono, in which case we need to request half
// as many samples from the mono stream and let
// the converter double them for stereo output
- if (!sourceStream->isStereo()) {
- samplesToRead >>= 1;
- }
+ samplesToRead >>= 1;
int samplesWritten = 0;
@@ -182,12 +180,10 @@ int Audio32::writeAudioInternal(Audio::AudioStream *const sourceStream, Audio::R
samplesToRead -= loopSamplesWritten;
samplesWritten += loopSamplesWritten;
- targetBuffer += loopSamplesWritten << 1;
+ targetBuffer += loopSamplesWritten << (sourceStream->isStereo() ? 0 : 1);
} while (loop && samplesToRead > 0);
- if (!sourceStream->isStereo()) {
- samplesWritten <<= 1;
- }
+ samplesWritten <<= 1;
return samplesWritten;
}
diff --git a/engines/sci/sound/decoders/sol.cpp b/engines/sci/sound/decoders/sol.cpp
index ee1ba35406..2dbe98c9e0 100644
--- a/engines/sci/sound/decoders/sol.cpp
+++ b/engines/sci/sound/decoders/sol.cpp
@@ -50,32 +50,42 @@ static const uint16 tableDPCM16[128] = {
static const byte tableDPCM8[8] = { 0, 1, 2, 3, 6, 10, 15, 21 };
/**
+ * Decompresses one channel of 16-bit DPCM compressed audio.
+ */
+static void deDPCM16Channel(int16 *out, int16 &sample, uint8 delta) {
+ if (delta & 0x80) {
+ sample -= tableDPCM16[delta & 0x7f];
+ } else {
+ sample += tableDPCM16[delta];
+ }
+ sample = CLIP<int16>(sample, -32768, 32767);
+ *out = TO_LE_16(sample);
+}
+
+/**
* Decompresses 16-bit DPCM compressed audio. Each byte read
* outputs one sample into the decompression buffer.
*/
-static void deDPCM16(int16 *out, Common::ReadStream &audioStream, const uint32 numBytes, int16 &sample) {
+static void deDPCM16Mono(int16 *out, Common::ReadStream &audioStream, const uint32 numBytes, int16 &sample) {
for (uint32 i = 0; i < numBytes; ++i) {
const uint8 delta = audioStream.readByte();
- if (delta & 0x80) {
- sample -= tableDPCM16[delta & 0x7f];
- } else {
- sample += tableDPCM16[delta];
- }
- sample = CLIP<int16>(sample, -32768, 32767);
- *out++ = TO_LE_16(sample);
+ deDPCM16Channel(out++, sample, delta);
}
}
-void deDPCM16(int16 *out, const byte *in, const uint32 numBytes, int16 &sample) {
+// Used by Robot
+void deDPCM16Mono(int16 *out, const byte *in, const uint32 numBytes, int16 &sample) {
for (uint32 i = 0; i < numBytes; ++i) {
const uint8 delta = *in++;
- if (delta & 0x80) {
- sample -= tableDPCM16[delta & 0x7f];
- } else {
- sample += tableDPCM16[delta];
- }
- sample = CLIP<int16>(sample, -32768, 32767);
- *out++ = TO_LE_16(sample);
+ deDPCM16Channel(out++, sample, delta);
+ }
+}
+
+static void deDPCM16Stereo(int16 *out, Common::ReadStream &audioStream, const uint32 numBytes, int16 &sampleL, int16 &sampleR) {
+ assert((numBytes % 2) == 0);
+ for (uint32 i = 0; i < numBytes / 2; ++i) {
+ deDPCM16Channel(out++, sampleL, audioStream.readByte());
+ deDPCM16Channel(out++, sampleR, audioStream.readByte());
}
}
@@ -98,7 +108,7 @@ static void deDPCM8Nibble(int16 *out, uint8 &sample, uint8 delta) {
* Decompresses 8-bit DPCM compressed audio. Each byte read
* outputs two samples into the decompression buffer.
*/
-static void deDPCM8(int16 *out, Common::ReadStream &audioStream, uint32 numBytes, uint8 &sample) {
+static void deDPCM8Mono(int16 *out, Common::ReadStream &audioStream, uint32 numBytes, uint8 &sample) {
for (uint32 i = 0; i < numBytes; ++i) {
const uint8 delta = audioStream.readByte();
deDPCM8Nibble(out++, sample, delta >> 4);
@@ -106,6 +116,14 @@ static void deDPCM8(int16 *out, Common::ReadStream &audioStream, uint32 numBytes
}
}
+static void deDPCM8Stereo(int16 *out, Common::ReadStream &audioStream, uint32 numBytes, uint8 &sampleL, uint8 &sampleR) {
+ for (uint32 i = 0; i < numBytes; ++i) {
+ const uint8 delta = audioStream.readByte();
+ deDPCM8Nibble(out++, sampleL, delta >> 4);
+ deDPCM8Nibble(out++, sampleR, delta & 0xf);
+ }
+}
+
# pragma mark -
template<bool STEREO, bool S16BIT>
@@ -120,9 +138,9 @@ SOLStream<STEREO, S16BIT>::SOLStream(Common::SeekableReadStream *stream, const D
// carried values for each channel separately. See
// 60900.aud from Lighthouse for an example stereo file
if (S16BIT) {
- _dpcmCarry16 = 0;
+ _dpcmCarry16.l = _dpcmCarry16.r = 0;
} else {
- _dpcmCarry8 = 0x80;
+ _dpcmCarry8.l = _dpcmCarry8.r = 0x80;
}
const uint8 compressionRatio = 2;
@@ -143,9 +161,9 @@ bool SOLStream<STEREO, S16BIT>::seek(const Audio::Timestamp &where) {
}
if (S16BIT) {
- _dpcmCarry16 = 0;
+ _dpcmCarry16.l = _dpcmCarry16.r = 0;
} else {
- _dpcmCarry8 = 0x80;
+ _dpcmCarry8.l = _dpcmCarry8.r = 0x80;
}
return _stream->seek(_dataOffset, SEEK_SET);
@@ -171,9 +189,17 @@ int SOLStream<STEREO, S16BIT>::readBuffer(int16 *buffer, const int numSamples) {
}
if (S16BIT) {
- deDPCM16(buffer, *_stream, bytesToRead, _dpcmCarry16);
+ if (STEREO) {
+ deDPCM16Stereo(buffer, *_stream, bytesToRead, _dpcmCarry16.l, _dpcmCarry16.r);
+ } else {
+ deDPCM16Mono(buffer, *_stream, bytesToRead, _dpcmCarry16.l);
+ }
} else {
- deDPCM8(buffer, *_stream, bytesToRead, _dpcmCarry8);
+ if (STEREO) {
+ deDPCM8Stereo(buffer, *_stream, bytesToRead, _dpcmCarry8.l, _dpcmCarry8.r);
+ } else {
+ deDPCM8Mono(buffer, *_stream, bytesToRead, _dpcmCarry8.l);
+ }
}
const int samplesRead = bytesToRead * samplesPerByte;
diff --git a/engines/sci/sound/decoders/sol.h b/engines/sci/sound/decoders/sol.h
index 1046d0b213..31914c0926 100644
--- a/engines/sci/sound/decoders/sol.h
+++ b/engines/sci/sound/decoders/sol.h
@@ -61,8 +61,8 @@ private:
* The last sample from the previous DPCM decode.
*/
union {
- int16 _dpcmCarry16;
- uint8 _dpcmCarry8;
+ struct { int16 l; int16 r; } _dpcmCarry16;
+ struct { uint8 l; uint8 r; } _dpcmCarry8;
};
/**
diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp
index 446b986581..296fdf8db2 100644
--- a/engines/sci/video/robot_decoder.cpp
+++ b/engines/sci/video/robot_decoder.cpp
@@ -43,7 +43,7 @@ namespace Sci {
#pragma mark RobotAudioStream
-extern void deDPCM16(int16 *out, const byte *in, const uint32 numBytes, int16 &sample);
+extern void deDPCM16Mono(int16 *out, const byte *in, const uint32 numBytes, int16 &sample);
RobotAudioStream::RobotAudioStream(const int32 bufferSize) :
_loopBuffer((byte *)malloc(bufferSize)),
@@ -181,7 +181,7 @@ void RobotAudioStream::fillRobotBuffer(const RobotAudioPacket &packet, const int
}
int16 carry = 0;
- deDPCM16((int16 *)_decompressionBuffer, packet.data, packet.dataSize, carry);
+ deDPCM16Mono((int16 *)_decompressionBuffer, packet.data, packet.dataSize, carry);
_decompressionBufferPosition = packet.position;
}