diff options
Diffstat (limited to 'audio/decoders/wave.cpp')
-rw-r--r-- | audio/decoders/wave.cpp | 59 |
1 files changed, 46 insertions, 13 deletions
diff --git a/audio/decoders/wave.cpp b/audio/decoders/wave.cpp index adee749b37..55c7034df6 100644 --- a/audio/decoders/wave.cpp +++ b/audio/decoders/wave.cpp @@ -27,10 +27,19 @@ #include "audio/audiostream.h" #include "audio/decoders/wave.h" #include "audio/decoders/adpcm.h" +#include "audio/decoders/mp3.h" #include "audio/decoders/raw.h" namespace Audio { +// Audio Codecs +enum { + kWaveFormatPCM = 1, + kWaveFormatMSADPCM = 2, + kWaveFormatMSIMAADPCM = 17, + kWaveFormatMP3 = 85 +}; + bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType, int *blockAlign_) { const int32 initialPos = stream.pos(); byte buf[4+1]; @@ -52,6 +61,13 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, } stream.read(buf, 4); + if (memcmp(buf, "fact", 4) == 0) { + // Initial fact chunk, so skip over it + uint32 factLen = stream.readUint32LE(); + stream.skip(factLen); + stream.read(buf, 4); + } + if (memcmp(buf, "fmt ", 4) != 0) { warning("getWavInfo: No 'fmt' header"); return false; @@ -97,18 +113,31 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, debug(" bitsPerSample: %d", bitsPerSample); #endif - if (type != 1 && type != 2 && type != 17) { - warning("getWavInfo: only PCM, MS ADPCM or IMA ADPCM data is supported (type %d)", type); - return false; - } + #ifdef USE_MAD + if (type == kWaveFormatMP3) { + bitsPerSample = 8; + } else { + #endif + if (type != kWaveFormatPCM && type != kWaveFormatMSADPCM && type != kWaveFormatMSIMAADPCM) { + #ifdef USE_MAD + warning("getWavInfo: only PCM, MS ADPCM, MP3, or IMA ADPCM data is supported (type %d)", type); + #else + warning("getWavInfo: only PCM, MS ADPCM, or IMA ADPCM data is supported (type %d)", type); + #endif - if (blockAlign != numChannels * bitsPerSample / 8 && type != 2) { - debug(0, "getWavInfo: blockAlign is invalid"); - } + return false; + } - if (avgBytesPerSec != samplesPerSec * blockAlign && type != 2) { - debug(0, "getWavInfo: avgBytesPerSec is invalid"); + if (blockAlign != numChannels * bitsPerSample / 8 && type != kWaveFormatMSADPCM) { + debug(0, "getWavInfo: blockAlign is invalid"); + } + + if (avgBytesPerSec != samplesPerSec * blockAlign && type != kWaveFormatMSADPCM) { + debug(0, "getWavInfo: avgBytesPerSec is invalid"); + } + #ifdef USE_MAD } + #endif // Prepare the return values. rate = samplesPerSec; @@ -118,7 +147,7 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, flags |= Audio::FLAG_UNSIGNED; else if (bitsPerSample == 16) // 16 bit data is signed little endian flags |= (Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN); - else if (bitsPerSample == 4 && (type == 2 || type == 17)) + else if (bitsPerSample == 4 && (type == kWaveFormatMSADPCM || type == kWaveFormatMSIMAADPCM)) flags |= Audio::FLAG_16BITS; else { warning("getWavInfo: unsupported bitsPerSample %d", bitsPerSample); @@ -158,7 +187,7 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, return true; } -RewindableAudioStream *makeWAVStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse) { +SeekableAudioStream *makeWAVStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse) { int size, rate; byte flags; uint16 type; @@ -170,10 +199,14 @@ RewindableAudioStream *makeWAVStream(Common::SeekableReadStream *stream, Dispose return 0; } - if (type == 17) // MS IMA ADPCM + if (type == kWaveFormatMSIMAADPCM) // MS IMA ADPCM return makeADPCMStream(stream, disposeAfterUse, size, Audio::kADPCMMSIma, rate, (flags & Audio::FLAG_STEREO) ? 2 : 1, blockAlign); - else if (type == 2) // MS ADPCM + else if (type == kWaveFormatMSADPCM) // MS ADPCM return makeADPCMStream(stream, disposeAfterUse, size, Audio::kADPCMMS, rate, (flags & Audio::FLAG_STEREO) ? 2 : 1, blockAlign); + #ifdef USE_MAD + else if (type == kWaveFormatMP3) + return makeMP3Stream(stream, disposeAfterUse); + #endif // Raw PCM, make sure the last packet is complete uint sampleSize = (flags & Audio::FLAG_16BITS ? 2 : 1) * (flags & Audio::FLAG_STEREO ? 2 : 1); |