105 : _stream(stream, disposeAfterUse),
107 _startpos(stream->pos()),
108 _endpos(_startpos + _size),
110 _blockAlign(blockAlign),
112 _length(kInvalidLength) {
138 :
ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
152 assert(numSamples % 2 == 0);
154 for (samples = 0; samples < numSamples && !
_stream->eos() &&
_stream->pos() <
_endpos; samples += 2) {
156 buffer[samples] =
decodeIMA((data >> 4) & 0x0f);
179 :
Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
198 size_t samples[2] = { 0, 0};
201 size_t chanSamples = numSamples /
_channels;
206 while ((samples[i] < chanSamples) &&
217 _status.ima_ch[i].stepIndex = temp & 0x007F;
220 _status.ima_ch[i].stepIndex = CLIP<int32>(
_status.ima_ch[i].stepIndex, 0, 88);
253 return samples[0] + samples[1];
259 :
Ima_ADPCMStream(stream, disposeAfterUse, size - (size % ((blockAlign == 0) ? 1 : blockAlign)),
260 rate, channels, blockAlign) {
263 error(
"MSIma_ADPCMStream(): blockAlign isn't specified");
266 error(
"MSIma_ADPCMStream(): invalid blockAlign");
294 while (samples < numSamples && !_stream->eos() &&
_stream->pos() <
_endpos) {
308 for (
int j = 0; j < 4; j++) {
333 256, 512, 0, 192, 240, 460, 392
337 0, -256, 0, 64, 0, -208, -232
341 230, 230, 230, 230, 307, 409, 512, 614,
342 768, 614, 512, 409, 307, 230, 230, 230
369 :
ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
371 error(
"MS_ADPCMStream(): blockAlign isn't specified for MS ADPCM");
388 predictor += (signed)((code & 0x08) ? (code - 0x10) : (code)) * c->
delta;
390 predictor = CLIP<int32>(predictor, -32768, 32767);
399 return (
int16)predictor;
409 while (samples < numSamples && !_stream->eos() &&
_stream->pos() <
_endpos) {
425 buffer[samples++] =
_status.ch[i].sample2 =
_stream->readSint16LE();
428 buffer[samples++] =
_status.ch[i].sample1;
446 static const int16 adjusts[] = {-1, -1, -1, -1, 2, 4, 6, 8};
448 return adjusts[code & 0x07];
452 7, 8, 9, 10, 11, 12, 13, 14,
453 16, 17, 19, 21, 23, 25, 28, 31,
454 34, 37, 41, 45, 50, 55, 60, 66,
455 73, 80, 88, 97, 107, 118, 130, 143,
456 157, 173, 190, 209, 230, 253, 279, 307,
457 337, 371, 408, 449, 494, 544, 598, 658,
458 724, 796, 876, 963, 1060, 1166, 1282, 1411,
459 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
460 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
461 7132, 7845, 8630, 9493,10442,11487,12635,13899,
462 15289,16818,18500,20350,22385,24623,27086,29794,
468 int32 diff = (code & 0x08) ? -E : E;
469 int32 samp = CLIP<int32>(
_status.ima_ch[channel].last + diff, -32768, 32767);
471 _status.ima_ch[channel].last = samp;
508 :
ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign == 0 ? 36 : blockAlign) {
514 if ((channels != 1) && (channels != 2))
530 if ((overhang % 4) != 0)
533 const bool hasOverhang = overhang > 4;
535 const uint32 blockDataSize = wholeBlocks * (
_blockAlign - 4) + (hasOverhang ? (overhang - 4) : 0);
536 const uint32 blockCount = wholeBlocks + (hasOverhang ? 1 : 0);
538 _length = (blockDataSize / 4) * 8 + blockCount;
571 -1, -1, -1, -1, 2, 4, 6, 8,
572 -1, -1, -1, -1, 2, 4, 6, 8
576 int delta =
status.stepSize >> 3;
581 delta +=
status.stepSize >> 1;
583 delta +=
status.stepSize >> 2;
587 const int16 result = CLIP<int>(
status.predictor + delta, -32768, 32767);
591 status.predictor = result;
598 assert(numSamples % 2 == 0);
602 while (samples < numSamples && !_stream->eos() &&
_stream->pos() <
_endpos) {
611 buffer[samples++] =
_status.ch[c].predictor;
621 for (
size_t j = 0; j < 8; j++) {
643 return new MSIma_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
645 return new MS_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
647 return new Apple_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
649 return new Xbox_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
651 error(
"Unsupported ADPCM encoding");
size_t readBuffer(int16 *buffer, const size_t numSamples)
Fill the given buffer with up to numSamples samples.
PacketizedAudioStream * makePacketizedADPCMStream(ADPCMTypes type, int rate, int channels, uint32 blockAlign)
Creates a PacketizedAudioStream that will automatically queue packets as individual AudioStreams like...
int getRate() const
Sample rate of the stream.
Common::DisposablePtr< Common::SeekableReadStream > _stream
MSIma_ADPCMStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
static const int MSADPCMAdaptationTable[]
virtual int getRate() const
Sample rate of the stream.
Ima_ADPCMStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
struct Sound::Xbox_ADPCMStream::@15 _status
A PacketizedAudioStream that works closer to a QueuingAudioStream.
Low-level macros and functions to handle different endianness portably.
int16 decodeMS(ADPCMChannelStatus *c, byte)
#define ARRAYSIZE(x)
Macro which determines the number of entries in a fixed size array.
PacketizedADPCMStream(ADPCMTypes type, int rate, int channels, uint32 blockAlign)
Exception that provides a stack of explanations.
Decoding ADPCM (Adaptive Differential Pulse Code Modulation).
A rewindable audio stream.
virtual uint64 getLength() const
Estimate the total number of samples per channel in this stream.
virtual int getChannels() const
Return the number channels in this stream.
virtual size_t readBuffer(int16 *buffer, const size_t numSamples)
Fill the given buffer with up to numSamples samples.
int getChannels() const
Return the number channels in this stream.
Xbox_ADPCMStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
int16 decodeIMA(byte code, int channel=0)
RewindableAudioStream * makeADPCMStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 size, ADPCMTypes type, int rate, int channels, uint32 blockAlign)
Takes an input stream containing ADPCM compressed sound data and creates an RewindableAudioStream fro...
An AudioStream designed to work in terms of packets.
struct Sound::MS_ADPCMStream::@14 _status
static const int8 kXboxIndexTable[16]
virtual size_t size() const =0
Obtains the total size of the stream, measured in bytes.
AudioStream * makeStream(Common::SeekableReadStream *data)
Make the AudioStream for a given packet.
ADPCMStream(Common::SeekableReadStream *stream, bool disposeAfterUse, size_t size, int rate, int channels, uint32 blockAlign)
Generic audio input stream.
A smart pointer with a deletion flag.
static const int MSADPCMAdaptCoeff1[]
virtual size_t readBuffer(int16 *buffer, const size_t numSamples)
Fill the given buffer with up to numSamples samples.
virtual size_t readBuffer(int16 *buffer, const size_t numSamples)
Fill the given buffer with up to numSamples samples.
Apple_ADPCMStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
void status(const char *s,...)
virtual size_t readBuffer(int16 *buffer, const size_t numSamples)
Fill the given buffer with up to numSamples samples.
struct Sound::ADPCMStream::@12::@13 ima_ch[2]
struct Sound::ADPCMStream::@12 _status
MS_ADPCMStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
int16 decodeXbox(int code, ADPCMChannelStatus &status)
void NORETURN_PRE error(const char *s,...)
T CLIP(T v, T amin, T amax)
virtual bool rewind()
Rewinds the stream to its start.
Interface for a seekable & readable data stream.
static const uint16 imaStepTable[89]
virtual bool endOfData() const
End of data reached? If this returns true, it means that at this time there is no data available in t...
static const int MSADPCMAdaptCoeff2[]