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         } ima_ch[2];
00058     } _status;
00059 
00060     virtual void reset();
00061 
00062 public:
00063     ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign);
00064 
00065     virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos); }
00066     virtual bool isStereo() const { return _channels == 2; }
00067     virtual int getRate() const { return _rate; }
00068 
00069     virtual bool rewind();
00070     virtual bool seek(const Timestamp &where) { return false; }
00071     virtual Timestamp getLength() const { return -1; }
00072 
00080     static const int16 _stepAdjustTable[16];
00081 };
00082 
00083 class Oki_ADPCMStream : public ADPCMStream {
00084 public:
00085     Oki_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
00086         : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) { _decodedSampleCount = 0; }
00087 
00088     virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
00089 
00090     virtual int readBuffer(int16 *buffer, const int numSamples);
00091 
00092 protected:
00093     int16 decodeOKI(byte);
00094 
00095 private:
00096     uint8 _decodedSampleCount;
00097     int16 _decodedSamples[2];
00098 };
00099 
00100 class Ima_ADPCMStream : public ADPCMStream {
00101 protected:
00102     int16 decodeIMA(byte code, int channel = 0); // Default to using the left channel/using one channel
00103 
00104 public:
00105     Ima_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
00106         : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
00107 
00111     static const int16 _imaTable[89];
00112 };
00113 
00114 class DVI_ADPCMStream : public Ima_ADPCMStream {
00115 public:
00116     DVI_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
00117         : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) { _decodedSampleCount = 0; }
00118 
00119     virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
00120 
00121     virtual int readBuffer(int16 *buffer, const int numSamples);
00122 
00123 private:
00124     uint8 _decodedSampleCount;
00125     int16 _decodedSamples[2];
00126 };
00127 
00128 class Apple_ADPCMStream : public Ima_ADPCMStream {
00129 protected:
00130     // Apple QuickTime IMA ADPCM
00131     int32 _streamPos[2];
00132     int16 _buffer[2][2];
00133     uint8 _chunkPos[2];
00134 
00135     void reset() {
00136         Ima_ADPCMStream::reset();
00137         _chunkPos[0] = 0;
00138         _chunkPos[1] = 0;
00139         _streamPos[0] = 0;
00140         _streamPos[1] = _blockAlign;
00141     }
00142 
00143 public:
00144     Apple_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
00145         : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
00146         _chunkPos[0] = 0;
00147         _chunkPos[1] = 0;
00148         _streamPos[0] = 0;
00149         _streamPos[1] = _blockAlign;
00150     }
00151 
00152     virtual int readBuffer(int16 *buffer, const int numSamples);
00153 
00154 };
00155 
00156 class MSIma_ADPCMStream : public Ima_ADPCMStream {
00157 public:
00158     MSIma_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
00159         : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
00160 
00161         if (blockAlign == 0)
00162             error("MSIma_ADPCMStream(): blockAlign isn't specified");
00163 
00164         if (blockAlign % (_channels * 4))
00165             error("MSIma_ADPCMStream(): invalid blockAlign");
00166 
00167         _samplesLeft[0] = 0;
00168         _samplesLeft[1] = 0;
00169     }
00170 
00171     virtual int readBuffer(int16 *buffer, const int numSamples);
00172 
00173     void reset() {
00174         Ima_ADPCMStream::reset();
00175         _samplesLeft[0] = 0;
00176         _samplesLeft[1] = 0;
00177     }
00178 
00179 private:
00180     int16 _buffer[2][8];
00181     int _samplesLeft[2];
00182 };
00183 
00184 class MS_ADPCMStream : public ADPCMStream {
00185 protected:
00186     struct ADPCMChannelStatus {
00187         byte predictor;
00188         int16 delta;
00189         int16 coeff1;
00190         int16 coeff2;
00191         int16 sample1;
00192         int16 sample2;
00193     };
00194 
00195     struct {
00196         // MS ADPCM
00197         ADPCMChannelStatus ch[2];
00198     } _status;
00199 
00200     void reset() {
00201         ADPCMStream::reset();
00202         memset(&_status, 0, sizeof(_status));
00203     }
00204 
00205 public:
00206     MS_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
00207         : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
00208         if (blockAlign == 0)
00209             error("MS_ADPCMStream(): blockAlign isn't specified for MS ADPCM");
00210         memset(&_status, 0, sizeof(_status));
00211         _decodedSampleCount = 0;
00212         _decodedSampleIndex = 0;
00213     }
00214 
00215     virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
00216 
00217     virtual int readBuffer(int16 *buffer, const int numSamples);
00218 
00219 protected:
00220     int16 decodeMS(ADPCMChannelStatus *c, byte);
00221 
00222 private:
00223     uint8 _decodedSampleCount;
00224     uint8 _decodedSampleIndex;
00225     int16 _decodedSamples[4];
00226 };
00227 
00228 // Duck DK3 IMA ADPCM Decoder
00229 // Based on FFmpeg's decoder and http://wiki.multimedia.cx/index.php?title=Duck_DK3_IMA_ADPCM
00230 
00231 class DK3_ADPCMStream : public Ima_ADPCMStream {
00232 public:
00233     DK3_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
00234         : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
00235 
00236         // DK3 only works as a stereo stream
00237         assert(channels == 2);
00238     }
00239 
00240     virtual int readBuffer(int16 *buffer, const int numSamples);
00241 
00242 private:
00243     byte _nibble, _lastByte;
00244     bool _topNibble;
00245 };
00246 
00247 } // End of namespace Audio
00248 
00249 #endif


Generated on Sat Feb 16 2019 05:00:44 for ResidualVM by doxygen 1.7.1
curved edge   curved edge