00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "common/debug.h"
00024 #include "common/textconsole.h"
00025 #include "common/stream.h"
00026
00027 #include "audio/audiostream.h"
00028 #include "audio/decoders/wave.h"
00029 #include "audio/decoders/adpcm.h"
00030 #include "audio/decoders/mp3.h"
00031 #include "audio/decoders/raw.h"
00032
00033 namespace Audio {
00034
00035
00036 enum {
00037 kWaveFormatPCM = 1,
00038 kWaveFormatMSADPCM = 2,
00039 kWaveFormatMSIMAADPCM = 17,
00040 kWaveFormatMP3 = 85
00041 };
00042
00043 bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType, int *blockAlign_) {
00044 const int32 initialPos = stream.pos();
00045 byte buf[4+1];
00046
00047 buf[4] = 0;
00048
00049 stream.read(buf, 4);
00050 if (memcmp(buf, "RIFF", 4) != 0) {
00051 warning("getWavInfo: No 'RIFF' header");
00052 return false;
00053 }
00054
00055 int32 wavLength = stream.readUint32LE();
00056
00057 stream.read(buf, 4);
00058 if (memcmp(buf, "WAVE", 4) != 0) {
00059 warning("getWavInfo: No 'WAVE' header");
00060 return false;
00061 }
00062
00063 stream.read(buf, 4);
00064 if (memcmp(buf, "fact", 4) == 0) {
00065
00066 uint32 factLen = stream.readUint32LE();
00067 stream.skip(factLen);
00068 stream.read(buf, 4);
00069 }
00070
00071 if (memcmp(buf, "fmt ", 4) != 0) {
00072 warning("getWavInfo: No 'fmt' header");
00073 return false;
00074 }
00075
00076 uint32 fmtLength = stream.readUint32LE();
00077 if (fmtLength < 16) {
00078
00079 warning("getWavInfo: 'fmt' header is too short");
00080 return false;
00081 }
00082
00083
00084
00085
00086
00087
00088
00089 uint16 type = stream.readUint16LE();
00090 uint16 numChannels = stream.readUint16LE();
00091 uint32 samplesPerSec = stream.readUint32LE();
00092 uint32 avgBytesPerSec = stream.readUint32LE();
00093
00094 uint16 blockAlign = stream.readUint16LE();
00095 uint16 bitsPerSample = stream.readUint16LE();
00096
00097
00098
00099 if (wavType != 0)
00100 *wavType = type;
00101
00102 if (blockAlign_ != 0)
00103 *blockAlign_ = blockAlign;
00104 #if 0
00105 debug("WAVE information:");
00106 debug(" total size: %d", wavLength);
00107 debug(" fmt size: %d", fmtLength);
00108 debug(" type: %d", type);
00109 debug(" numChannels: %d", numChannels);
00110 debug(" samplesPerSec: %d", samplesPerSec);
00111 debug(" avgBytesPerSec: %d", avgBytesPerSec);
00112 debug(" blockAlign: %d", blockAlign);
00113 debug(" bitsPerSample: %d", bitsPerSample);
00114 #endif
00115
00116 #ifdef USE_MAD
00117 if (type == kWaveFormatMP3) {
00118 bitsPerSample = 8;
00119 } else {
00120 #endif
00121 if (type != kWaveFormatPCM && type != kWaveFormatMSADPCM && type != kWaveFormatMSIMAADPCM) {
00122 #ifdef USE_MAD
00123 warning("getWavInfo: only PCM, MS ADPCM, MP3, or IMA ADPCM data is supported (type %d)", type);
00124 #else
00125 warning("getWavInfo: only PCM, MS ADPCM, or IMA ADPCM data is supported (type %d)", type);
00126 #endif
00127
00128 return false;
00129 }
00130
00131 if (blockAlign != numChannels * bitsPerSample / 8 && type != kWaveFormatMSADPCM) {
00132 debug(0, "getWavInfo: blockAlign is invalid");
00133 }
00134
00135 if (avgBytesPerSec != samplesPerSec * blockAlign && type != kWaveFormatMSADPCM) {
00136 debug(0, "getWavInfo: avgBytesPerSec is invalid");
00137 }
00138 #ifdef USE_MAD
00139 }
00140 #endif
00141
00142
00143 rate = samplesPerSec;
00144
00145 flags = 0;
00146 if (bitsPerSample == 8)
00147 flags |= Audio::FLAG_UNSIGNED;
00148 else if (bitsPerSample == 16)
00149 flags |= (Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
00150 else if (bitsPerSample == 4 && (type == kWaveFormatMSADPCM || type == kWaveFormatMSIMAADPCM))
00151 flags |= Audio::FLAG_16BITS;
00152 else {
00153 warning("getWavInfo: unsupported bitsPerSample %d", bitsPerSample);
00154 return false;
00155 }
00156
00157 if (numChannels == 2)
00158 flags |= Audio::FLAG_STEREO;
00159 else if (numChannels != 1) {
00160 warning("getWavInfo: unsupported number of channels %d", numChannels);
00161 return false;
00162 }
00163
00164
00165
00166
00167
00168 int offset = fmtLength - 16;
00169
00170 do {
00171 stream.seek(offset, SEEK_CUR);
00172 if (stream.pos() >= initialPos + wavLength + 8) {
00173 warning("getWavInfo: Can't find 'data' chunk");
00174 return false;
00175 }
00176 stream.read(buf, 4);
00177 offset = stream.readUint32LE();
00178
00179 #if 0
00180 debug(" found a '%s' tag of size %d", buf, offset);
00181 #endif
00182 } while (memcmp(buf, "data", 4) != 0);
00183
00184
00185 size = offset;
00186
00187 return true;
00188 }
00189
00190 SeekableAudioStream *makeWAVStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse) {
00191 int size, rate;
00192 byte flags;
00193 uint16 type;
00194 int blockAlign;
00195
00196 if (!loadWAVFromStream(*stream, size, rate, flags, &type, &blockAlign)) {
00197 if (disposeAfterUse == DisposeAfterUse::YES)
00198 delete stream;
00199 return 0;
00200 }
00201
00202 if (type == kWaveFormatMSIMAADPCM)
00203 return makeADPCMStream(stream, disposeAfterUse, size, Audio::kADPCMMSIma, rate, (flags & Audio::FLAG_STEREO) ? 2 : 1, blockAlign);
00204 else if (type == kWaveFormatMSADPCM)
00205 return makeADPCMStream(stream, disposeAfterUse, size, Audio::kADPCMMS, rate, (flags & Audio::FLAG_STEREO) ? 2 : 1, blockAlign);
00206 #ifdef USE_MAD
00207 else if (type == kWaveFormatMP3)
00208 return makeMP3Stream(stream, disposeAfterUse);
00209 #endif
00210
00211
00212 uint sampleSize = (flags & Audio::FLAG_16BITS ? 2 : 1) * (flags & Audio::FLAG_STEREO ? 2 : 1);
00213 if (size % sampleSize != 0) {
00214 warning("makeWAVStream: Trying to play a WAVE file with an incomplete PCM packet");
00215 size &= ~(sampleSize - 1);
00216 }
00217
00218
00219
00220 byte *data = (byte *)malloc(size);
00221 assert(data);
00222 stream->read(data, size);
00223
00224 if (disposeAfterUse == DisposeAfterUse::YES)
00225 delete stream;
00226
00227 return makeRawStream(data, size, rate, flags);
00228 }
00229
00230 }