ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

adpcm_intern.h

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00031 #ifndef AUDIO_ADPCM_INTERN_H
00032 #define AUDIO_ADPCM_INTERN_H
00033 
00034 #include "audio/audiostream.h"
00035 #include "common/endian.h"
00036 #include "common/ptr.h"
00037 #include "common/stream.h"
00038 #include "common/textconsole.h"
00039 
00040 namespace Audio {
00041 
00042 class ADPCMStream : public SeekableAudioStream {
00043 protected:
00044     Common::DisposablePtr<Common::SeekableReadStream> _stream;
00045     int32 _startpos;
00046     const int32 _endpos;
00047     const int _channels;
00048     const uint32 _blockAlign;
00049     uint32 _blockPos[2];
00050     const int _rate;
00051 
00052     struct ADPCMStatus {
00053         // OKI/IMA
00054         struct {
00055             int32 last;
00056             int32 stepIndex;
00057             int16 sample[2];
00058         } ima_ch[2];
00059     } _status;
00060 
00061     virtual void reset();
00062 
00063 public:
00064     ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign);
00065 
00066     virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos); }
00067     virtual bool isStereo() const { return _channels == 2; }
00068     virtual int getRate() const { return _rate; }
00069 
00070     virtual bool rewind();
00071     virtual bool seek(const Timestamp &where) { return false; }
00072     virtual Timestamp getLength() const { return Timestamp(); }
00073 
00081     static const int16 _stepAdjustTable[16];
00082 };
00083 
00084 class Oki_ADPCMStream : public ADPCMStream {
00085 public:
00086     Oki_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
00087         : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) { _decodedSampleCount = 0; }
00088 
00089     virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
00090 
00091     virtual int readBuffer(int16 *buffer, const int numSamples);
00092 
00093 protected:
00094     int16 decodeOKI(byte);
00095 
00096 private:
00097     uint8 _decodedSampleCount;
00098     int16 _decodedSamples[2];
00099 };
00100 
00101 class XA_ADPCMStream : public ADPCMStream {
00102 public:
00103     XA_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
00104         : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) { _decodedSampleCount = 0; }
00105 
00106     virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
00107 
00108     virtual int readBuffer(int16 *buffer, const int numSamples);
00109 
00110 protected:
00111     void decodeXA(const byte *src);
00112 
00113 private:
00114     uint8 _decodedSampleCount;
00115     uint8 _decodedSampleIndex;
00116     int16 _decodedSamples[28 * 2 * 4];
00117 };
00118 
00119 class Ima_ADPCMStream : public ADPCMStream {
00120 protected:
00121     int16 decodeIMA(byte code, int channel = 0); // Default to using the left channel/using one channel
00122 
00123 public:
00124     Ima_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
00125         : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
00126 
00130     static const int16 _imaTable[89];
00131 };
00132 
00133 class DVI_ADPCMStream : public Ima_ADPCMStream {
00134 public:
00135     DVI_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
00136         : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) { _decodedSampleCount = 0; }
00137 
00138     virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
00139 
00140     virtual int readBuffer(int16 *buffer, const int numSamples);
00141 
00142 private:
00143     uint8 _decodedSampleCount;
00144     int16 _decodedSamples[2];
00145 };
00146 
00147 class Apple_ADPCMStream : public Ima_ADPCMStream {
00148 protected:
00149     // Apple QuickTime IMA ADPCM
00150     int32 _streamPos[2];
00151     int16 _buffer[2][2];
00152     uint8 _chunkPos[2];
00153 
00154     void reset() {
00155         Ima_ADPCMStream::reset();
00156         _chunkPos[0] = 0;
00157         _chunkPos[1] = 0;
00158         _streamPos[0] = 0;
00159         _streamPos[1] = _blockAlign;
00160     }
00161 
00162 public:
00163     Apple_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
00164         : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
00165         _chunkPos[0] = 0;
00166         _chunkPos[1] = 0;
00167         _streamPos[0] = 0;
00168         _streamPos[1] = _blockAlign;
00169     }
00170 
00171     virtual int readBuffer(int16 *buffer, const int numSamples);
00172 
00173 };
00174 
00175 class MSIma_ADPCMStream : public Ima_ADPCMStream {
00176 public:
00177     MSIma_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
00178         : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
00179 
00180         if (blockAlign == 0)
00181             error("MSIma_ADPCMStream(): blockAlign isn't specified");
00182 
00183         if (blockAlign % (_channels * 4))
00184             error("MSIma_ADPCMStream(): invalid blockAlign");
00185 
00186         _samplesLeft[0] = 0;
00187         _samplesLeft[1] = 0;
00188     }
00189 
00190     virtual int readBuffer(int16 *buffer, const int numSamples);
00191 
00192     void reset() {
00193         Ima_ADPCMStream::reset();
00194         _samplesLeft[0] = 0;
00195         _samplesLeft[1] = 0;
00196     }
00197 
00198 private:
00199     int16 _buffer[2][8];
00200     int _samplesLeft[2];
00201 };
00202 
00203 class MS_ADPCMStream : public ADPCMStream {
00204 protected:
00205     struct ADPCMChannelStatus {
00206         byte predictor;
00207         int16 delta;
00208         int16 coeff1;
00209         int16 coeff2;
00210         int16 sample1;
00211         int16 sample2;
00212     };
00213 
00214     struct {
00215         // MS ADPCM
00216         ADPCMChannelStatus ch[2];
00217     } _status;
00218 
00219     void reset() {
00220         ADPCMStream::reset();
00221         memset(&_status, 0, sizeof(_status));
00222     }
00223 
00224 public:
00225     MS_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
00226         : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
00227         if (blockAlign == 0)
00228             error("MS_ADPCMStream(): blockAlign isn't specified for MS ADPCM");
00229         memset(&_status, 0, sizeof(_status));
00230         _decodedSampleCount = 0;
00231         _decodedSampleIndex = 0;
00232     }
00233 
00234     virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
00235 
00236     virtual int readBuffer(int16 *buffer, const int numSamples);
00237 
00238 protected:
00239     int16 decodeMS(ADPCMChannelStatus *c, byte);
00240 
00241 private:
00242     uint8 _decodedSampleCount;
00243     uint8 _decodedSampleIndex;
00244     int16 _decodedSamples[4];
00245 };
00246 
00247 // Duck DK3 IMA ADPCM Decoder
00248 // Based on FFmpeg's decoder and http://wiki.multimedia.cx/index.php?title=Duck_DK3_IMA_ADPCM
00249 
00250 class DK3_ADPCMStream : public Ima_ADPCMStream {
00251 public:
00252     DK3_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
00253         : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
00254 
00255         // DK3 only works as a stereo stream
00256         assert(channels == 2);
00257     }
00258 
00259     virtual int readBuffer(int16 *buffer, const int numSamples);
00260 
00261 private:
00262     byte _nibble, _lastByte;
00263     bool _topNibble;
00264 };
00265 
00266 } // End of namespace Audio
00267 
00268 #endif


Generated on Sat Sep 19 2020 05:00:53 for ResidualVM by doxygen 1.7.1
curved edge   curved edge