ScummVM API documentation
adpcm_intern.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
30 #ifndef AUDIO_ADPCM_INTERN_H
31 #define AUDIO_ADPCM_INTERN_H
32 
33 #include "audio/audiostream.h"
34 #include "common/endian.h"
35 #include "common/ptr.h"
36 #include "common/stream.h"
37 #include "common/textconsole.h"
38 
39 namespace Audio {
40 
42 protected:
44  int32 _startpos;
45  const int32 _endpos;
46  const int _channels;
47  const uint32 _blockAlign;
48  uint32 _blockPos[2];
49  const int _rate;
50 
51  struct ADPCMStatus {
52  // OKI/IMA
53  struct {
54  int32 last;
55  int32 stepIndex;
56  int16 sample[2];
57  } ima_ch[2];
58  } _status;
59 
60  virtual void reset();
61 
62 public:
63  ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign);
64 
65  virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos); }
66  virtual bool isStereo() const { return _channels == 2; }
67  virtual int getRate() const { return _rate; }
68 
69  virtual bool rewind();
70  virtual bool seek(const Timestamp &where) { return false; }
71  virtual Timestamp getLength() const { return Timestamp(); }
72 
80  static const int16 _stepAdjustTable[16];
81 };
82 
83 class Oki_ADPCMStream : public ADPCMStream {
84 public:
85  Oki_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
86  : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) { _decodedSampleCount = 0; }
87 
88  virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
89 
90  virtual int readBuffer(int16 *buffer, const int numSamples);
91 
92 protected:
93  int16 decodeOKI(byte);
94 
95 private:
96  uint8 _decodedSampleCount;
97  int16 _decodedSamples[2];
98 };
99 
100 class XA_ADPCMStream : public ADPCMStream {
101 public:
102  XA_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
103  : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) { _decodedSampleCount = 0; }
104 
105  virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
106 
107  virtual int readBuffer(int16 *buffer, const int numSamples);
108 
109 protected:
110  void decodeXA(const byte *src);
111 
112 private:
113  uint8 _decodedSampleCount;
114  uint8 _decodedSampleIndex;
115  int16 _decodedSamples[28 * 2 * 4];
116 };
117 
118 class Ima_ADPCMStream : public ADPCMStream {
119 protected:
120  int16 decodeIMA(byte code, int channel = 0); // Default to using the left channel/using one channel
121 
122 public:
123  Ima_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
124  : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {}
125 
129  static const int16 _imaTable[89];
130 };
131 
133 public:
134  DVI_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
135  : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) { _decodedSampleCount = 0; }
136 
137  virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
138 
139  virtual int readBuffer(int16 *buffer, const int numSamples);
140 
141 private:
142  uint8 _decodedSampleCount;
143  int16 _decodedSamples[2];
144 };
145 
147 protected:
148  // Apple QuickTime IMA ADPCM
149  int32 _streamPos[2];
150  int16 _buffer[2][2];
151  uint8 _chunkPos[2];
152 
153  void reset() {
154  Ima_ADPCMStream::reset();
155  _chunkPos[0] = 0;
156  _chunkPos[1] = 0;
157  _streamPos[0] = 0;
158  _streamPos[1] = _blockAlign;
159  }
160 
161 public:
162  Apple_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
163  : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
164  _chunkPos[0] = 0;
165  _chunkPos[1] = 0;
166  _streamPos[0] = 0;
167  _streamPos[1] = _blockAlign;
168  }
169 
170  virtual int readBuffer(int16 *buffer, const int numSamples);
171 
172 };
173 
175 public:
176  MSIma_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
177  : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
178 
179  if (blockAlign == 0)
180  error("MSIma_ADPCMStream(): blockAlign isn't specified");
181 
182  if (blockAlign % (_channels * 4))
183  error("MSIma_ADPCMStream(): invalid blockAlign");
184 
185  _samplesLeft[0] = 0;
186  _samplesLeft[1] = 0;
187  }
188 
189  virtual int readBuffer(int16 *buffer, const int numSamples);
190 
191  void reset() {
192  Ima_ADPCMStream::reset();
193  _samplesLeft[0] = 0;
194  _samplesLeft[1] = 0;
195  }
196 
197 private:
198  int16 _buffer[2][8];
199  int _samplesLeft[2];
200 };
201 
202 class MS_ADPCMStream : public ADPCMStream {
203 protected:
205  byte predictor;
206  int16 delta;
207  int16 coeff1;
208  int16 coeff2;
209  int16 sample1;
210  int16 sample2;
211  };
212 
213  struct {
214  // MS ADPCM
215  ADPCMChannelStatus ch[2];
216  } _status;
217 
218  void reset() {
219  ADPCMStream::reset();
220  memset(&_status, 0, sizeof(_status));
221  }
222 
223 public:
224  MS_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
225  : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
226  if (blockAlign == 0)
227  error("MS_ADPCMStream(): blockAlign isn't specified for MS ADPCM");
228  memset(&_status, 0, sizeof(_status));
229  _decodedSampleCount = 0;
230  _decodedSampleIndex = 0;
231  }
232 
233  virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
234 
235  virtual int readBuffer(int16 *buffer, const int numSamples);
236 
237 protected:
238  int16 decodeMS(ADPCMChannelStatus *c, byte);
239 
240 private:
241  uint8 _decodedSampleCount;
242  uint8 _decodedSampleIndex;
243  int16 _decodedSamples[4];
244 };
245 
246 // Duck DK3 IMA ADPCM Decoder
247 // Based on FFmpeg's decoder and http://wiki.multimedia.cx/index.php?title=Duck_DK3_IMA_ADPCM
248 
250 public:
251  DK3_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
252  : Ima_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {
253 
254  // DK3 only works as a stereo stream
255  assert(channels == 2);
256  }
257 
258  virtual int readBuffer(int16 *buffer, const int numSamples);
259 
260 private:
261  byte _nibble, _lastByte;
262  bool _topNibble;
263 };
264 
265 } // End of namespace Audio
266 
267 #endif
virtual bool endOfData() const
Definition: adpcm_intern.h:137
virtual bool rewind()
virtual int64 pos() const =0
virtual int readBuffer(int16 *buffer, const int numSamples)=0
virtual bool endOfData() const
Definition: adpcm_intern.h:88
virtual bool eos() const =0
virtual Timestamp getLength() const
Definition: adpcm_intern.h:71
virtual bool endOfData() const
Definition: adpcm_intern.h:233
Definition: adpcm_intern.h:51
Definition: timestamp.h:83
Definition: stream.h:745
virtual int getRate() const
Definition: adpcm_intern.h:67
Definition: audiostream.h:212
Definition: adpcm_intern.h:174
Definition: adpcm_intern.h:204
Definition: adpcm_intern.h:83
Definition: adpcm_intern.h:146
Definition: adpcm_intern.h:202
static const int16 _stepAdjustTable[16]
Definition: adpcm_intern.h:80
virtual bool seek(const Timestamp &where)
Definition: adpcm_intern.h:70
Definition: adpcm_intern.h:100
virtual bool isStereo() const
Definition: adpcm_intern.h:66
virtual bool endOfData() const
Definition: adpcm_intern.h:65
Definition: adpcm_intern.h:249
void NORETURN_PRE error(MSVC_PRINTF const char *s,...) GCC_PRINTF(1
Definition: adpcm_intern.h:41
Definition: adpcm_intern.h:118
virtual bool endOfData() const
Definition: adpcm_intern.h:105
Definition: adpcm_intern.h:132
Definition: system.h:38