summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libpcm/dvi_adpcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/libpcm/dvi_adpcm.c')
-rw-r--r--lib/rbcodec/codecs/libpcm/dvi_adpcm.c308
1 files changed, 308 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libpcm/dvi_adpcm.c b/lib/rbcodec/codecs/libpcm/dvi_adpcm.c
new file mode 100644
index 0000000000..2e702ca394
--- /dev/null
+++ b/lib/rbcodec/codecs/libpcm/dvi_adpcm.c
@@ -0,0 +1,308 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Dave Chapman
11 * Copyright (C) 2009 Yoshihisa Uchida
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22#include "codeclib.h"
23#include "ima_adpcm_common.h"
24#include "support_formats.h"
25
26/*
27 * Intel DVI ADPCM (IMA ADPCM)
28 *
29 * References
30 * [1] The IMA Digital Audio Focus and Technical Working Groups,
31 * Recommended Practices for Enhancing Digital Audio Compatibility
32 * in Multimedia Systems Revision 3.00, 1992
33 * [2] Microsoft Corporation, New Multimedia Data Types and Data Techniques,
34 * Revision:3.0, 1994
35 * [3] ffmpeg source code, libavcodec/adpcm.c
36 */
37
38static struct pcm_format *fmt;
39
40static bool set_format(struct pcm_format *format)
41{
42 fmt = format;
43
44 if (fmt->bitspersample < 2 || fmt->bitspersample > 5)
45 {
46 DEBUGF("CODEC_ERROR: dvi adpcm must be 2, 3, 4 or 5 bitspersample: %d\n",
47 fmt->bitspersample);
48 return false;
49 }
50
51 fmt->chunksize = fmt->blockalign;
52
53 init_ima_adpcm_decoder(fmt->bitspersample, NULL);
54 return true;
55}
56
57static struct pcm_pos *get_seek_pos(uint32_t seek_val, int seek_mode,
58 uint8_t *(*read_buffer)(size_t *realsize))
59{
60 static struct pcm_pos newpos;
61 uint32_t newblock = (seek_mode == PCM_SEEK_TIME) ?
62 ((uint64_t)seek_val * ci->id3->frequency / 1000LL)
63 / fmt->samplesperblock :
64 seek_val / fmt->blockalign;
65
66 (void)read_buffer;
67 newpos.pos = newblock * fmt->blockalign;
68 newpos.samples = newblock * fmt->samplesperblock;
69 return &newpos;
70}
71
72static inline void decode_2bit(const uint8_t **inbuf, size_t inbufsize,
73 int32_t **outbuf, int *outbufcount)
74{
75 int ch;
76 int i;
77 int32_t *pcmbuf;
78 int samples;
79
80 samples = inbufsize / (4 * fmt->channels) - 1;
81 *outbufcount += (samples << 4);
82 while (samples-- > 0)
83 {
84 for (ch = 0; ch < fmt->channels; ch++)
85 {
86 pcmbuf = *outbuf + ch;
87 for (i = 0; i < 4; i++)
88 {
89 *pcmbuf = create_pcmdata(ch, **inbuf ) << IMA_ADPCM_INC_DEPTH;
90 pcmbuf += fmt->channels;
91 *pcmbuf = create_pcmdata(ch, **inbuf >> 2) << IMA_ADPCM_INC_DEPTH;
92 pcmbuf += fmt->channels;
93 *pcmbuf = create_pcmdata(ch, **inbuf >> 4) << IMA_ADPCM_INC_DEPTH;
94 pcmbuf += fmt->channels;
95 *pcmbuf = create_pcmdata(ch, **inbuf >> 6) << IMA_ADPCM_INC_DEPTH;
96 pcmbuf += fmt->channels;
97 (*inbuf)++;
98 }
99 }
100 *outbuf += 16 * fmt->channels;
101 }
102}
103
104static inline void decode_3bit(const uint8_t **inbuf, size_t inbufsize,
105 int32_t **outbuf, int *outbufcount)
106{
107 const uint8_t *adpcmbuf;
108 uint32_t adpcms;
109 int ch;
110 int i;
111 int32_t *pcmbuf;
112 int samples;
113
114 samples = (inbufsize - 4 * fmt->channels) / (12 * fmt->channels);
115 *outbufcount += (samples << 5);
116 while (samples--)
117 {
118 for (ch = 0; ch < fmt->channels; ch++)
119 {
120 adpcmbuf = *inbuf + ch * 4;
121 pcmbuf = *outbuf + ch;
122 adpcms = *adpcmbuf++;
123 adpcms |= (*adpcmbuf++) << 8;
124 adpcms |= (*adpcmbuf++) << 16;
125 for (i = 0; i < 8; i++)
126 {
127 *pcmbuf = create_pcmdata(ch, adpcms >> (3 * i)) << IMA_ADPCM_INC_DEPTH;
128 pcmbuf += fmt->channels;
129 }
130 adpcms = *adpcmbuf++;
131 adpcmbuf += (fmt->channels - 1) * 4;
132 adpcms |= (*adpcmbuf++) << 8;
133 adpcms |= (*adpcmbuf++) << 16;
134 for (i = 0; i < 8; i++)
135 {
136 *pcmbuf = create_pcmdata(ch, adpcms >> (3 * i)) << IMA_ADPCM_INC_DEPTH;
137 pcmbuf += fmt->channels;
138 }
139 adpcms = *adpcmbuf++;
140 adpcms |= (*adpcmbuf++) << 8;
141 adpcmbuf += (fmt->channels - 1) * 4;
142 adpcms |= (*adpcmbuf++) << 16;
143 for (i = 0; i < 8; i++)
144 {
145 *pcmbuf = create_pcmdata(ch, adpcms >> (3 * i)) << IMA_ADPCM_INC_DEPTH;
146 pcmbuf += fmt->channels;
147 }
148 adpcms = *adpcmbuf++;
149 adpcms |= (*adpcmbuf++) << 8;
150 adpcms |= (*adpcmbuf++) << 16;
151 for (i = 0; i < 8; i++)
152 {
153 *pcmbuf = create_pcmdata(ch, adpcms >> (3 * i)) << IMA_ADPCM_INC_DEPTH;
154 pcmbuf += fmt->channels;
155 }
156 }
157 *outbuf += 32 * fmt->channels;
158 *inbuf += 12 * fmt->channels;
159 }
160}
161
162static inline void decode_4bit(const uint8_t **inbuf, size_t inbufsize,
163 int32_t **outbuf, int *outbufcount)
164{
165 int ch;
166 int i;
167 int32_t *pcmbuf;
168 int samples;
169
170 samples = inbufsize / (4 * fmt->channels) - 1;
171 *outbufcount += (samples << 3);
172 while (samples-- > 0)
173 {
174 for (ch = 0; ch < fmt->channels; ch++)
175 {
176 pcmbuf = *outbuf + ch;
177 for (i = 0; i < 4; i++)
178 {
179 *pcmbuf = create_pcmdata_size4(ch, **inbuf ) << IMA_ADPCM_INC_DEPTH;
180 pcmbuf += fmt->channels;
181 *pcmbuf = create_pcmdata_size4(ch, **inbuf >> 4) << IMA_ADPCM_INC_DEPTH;
182 pcmbuf += fmt->channels;
183 (*inbuf)++;
184 }
185 }
186 *outbuf += 8 * fmt->channels;
187 }
188}
189
190static inline void decode_5bit(const uint8_t **inbuf, size_t inbufsize,
191 int32_t **outbuf, int *outbufcount)
192{
193 const uint8_t *adpcmbuf;
194 uint64_t adpcms;
195 int ch;
196 int i;
197 int32_t *pcmbuf;
198 int samples;
199
200 samples = (inbufsize - 4 * fmt->channels) / (20 * fmt->channels);
201 *outbufcount += (samples << 5);
202 while (samples--)
203 {
204 for (ch = 0; ch < fmt->channels; ch++)
205 {
206 adpcmbuf = *inbuf + ch * 4;
207 pcmbuf = *outbuf + ch;
208 adpcms = *adpcmbuf++;
209 adpcms |= (*adpcmbuf++) << 8;
210 adpcms |= (*adpcmbuf++) << 16;
211 adpcms |= (uint64_t)(*adpcmbuf++) << 24;
212 adpcmbuf += (fmt->channels - 1) * 4;
213 adpcms |= (uint64_t)(*adpcmbuf++) << 32;
214 for (i = 0; i < 8; i++)
215 {
216 *pcmbuf = create_pcmdata(ch, adpcms >> (5 * i)) << IMA_ADPCM_INC_DEPTH;
217 pcmbuf += fmt->channels;
218 }
219 adpcms = *adpcmbuf++;
220 adpcms |= (*adpcmbuf++) << 8;
221 adpcms |= (*adpcmbuf++) << 16;
222 adpcmbuf += (fmt->channels - 1) * 4;
223 adpcms |= (uint64_t)(*adpcmbuf++) << 24;
224 adpcms |= (uint64_t)(*adpcmbuf++) << 32;
225 for (i = 0; i < 8; i++)
226 {
227 *pcmbuf = create_pcmdata(ch, adpcms >> (5 * i)) << IMA_ADPCM_INC_DEPTH;
228 pcmbuf += fmt->channels;
229 }
230 adpcms = *adpcmbuf++;
231 adpcms |= (*adpcmbuf++) << 8;
232 adpcmbuf += (fmt->channels - 1) * 4;
233 adpcms |= (*adpcmbuf++) << 16;
234 adpcms |= (uint64_t)(*adpcmbuf++) << 24;
235 adpcms |= (uint64_t)(*adpcmbuf++) << 32;
236 for (i = 0; i < 8; i++)
237 {
238 *pcmbuf = create_pcmdata(ch, adpcms >> (5 * i)) << IMA_ADPCM_INC_DEPTH;
239 pcmbuf += fmt->channels;
240 }
241 adpcms = *adpcmbuf++;
242 adpcmbuf += (fmt->channels - 1) * 4;
243 adpcms |= (*adpcmbuf++) << 8;
244 adpcms |= (*adpcmbuf++) << 16;
245 adpcms |= (uint64_t)(*adpcmbuf++) << 24;
246 adpcms |= (uint64_t)(*adpcmbuf++) << 32;
247 for (i = 0; i < 8; i++)
248 {
249 *pcmbuf = create_pcmdata(ch, adpcms >> (5 * i)) << IMA_ADPCM_INC_DEPTH;
250 pcmbuf += fmt->channels;
251 }
252 }
253 *outbuf += 32 * fmt->channels;
254 *inbuf += 20 * fmt->channels;
255 }
256}
257
258static int decode(const uint8_t *inbuf, size_t inbufsize,
259 int32_t *outbuf, int *outbufcount)
260{
261 int ch;
262 int32_t init_pcmdata[2];
263 int8_t init_index[2];
264
265 *outbufcount = 0;
266 for (ch = 0; ch < fmt->channels; ch++)
267 {
268 init_pcmdata[ch] = inbuf[0] | (inbuf[1] << 8);
269 if (init_pcmdata[ch] > 32767)
270 init_pcmdata[ch] -= 65536;
271
272 init_index[ch] = inbuf[2];
273 if (init_index[ch] > 88 || init_index[ch] < 0)
274 {
275 DEBUGF("CODEC_ERROR: dvi adpcm illegal step index=%d > 88\n",
276 init_index[ch]);
277 return CODEC_ERROR;
278 }
279 inbuf += 4;
280
281 *outbuf++ = init_pcmdata[ch] << IMA_ADPCM_INC_DEPTH;
282 }
283
284 *outbufcount += 1;
285 set_decode_parameters(fmt->channels, init_pcmdata, init_index);
286
287 if (fmt->bitspersample == 4)
288 decode_4bit(&inbuf, inbufsize, &outbuf, outbufcount);
289 else if (fmt->bitspersample == 3)
290 decode_3bit(&inbuf, inbufsize, &outbuf, outbufcount);
291 else if (fmt->bitspersample == 5)
292 decode_5bit(&inbuf, inbufsize, &outbuf, outbufcount);
293 else /* fmt->bitspersample == 2 */
294 decode_2bit(&inbuf, inbufsize, &outbuf, outbufcount);
295
296 return CODEC_OK;
297}
298
299static const struct pcm_codec codec = {
300 set_format,
301 get_seek_pos,
302 decode,
303 };
304
305const struct pcm_codec *get_dvi_adpcm_codec(void)
306{
307 return &codec;
308}