diff options
Diffstat (limited to 'apps/codecs/libpcm/dvi_adpcm.c')
-rwxr-xr-x | apps/codecs/libpcm/dvi_adpcm.c | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/apps/codecs/libpcm/dvi_adpcm.c b/apps/codecs/libpcm/dvi_adpcm.c new file mode 100755 index 0000000000..9118906a93 --- /dev/null +++ b/apps/codecs/libpcm/dvi_adpcm.c | |||
@@ -0,0 +1,309 @@ | |||
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 "pcm_common.h" | ||
24 | |||
25 | /* | ||
26 | * Intel DVI ADPCM | ||
27 | */ | ||
28 | |||
29 | static const uint16_t dvi_adpcm_steptab[89] ICONST_ATTR = { | ||
30 | 7, 8, 9, 10, 11, 12, 13, 14, | ||
31 | 16, 17, 19, 21, 23, 25, 28, 31, | ||
32 | 34, 37, 41, 45, 50, 55, 60, 66, | ||
33 | 73, 80, 88, 97, 107, 118, 130, 143, | ||
34 | 157, 173, 190, 209, 230, 253, 279, 307, | ||
35 | 337, 371, 408, 449, 494, 544, 598, 658, | ||
36 | 724, 796, 876, 963, 1060, 1166, 1282, 1411, | ||
37 | 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, | ||
38 | 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, | ||
39 | 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, | ||
40 | 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, | ||
41 | 32767 }; | ||
42 | |||
43 | static const int dvi_adpcm_indextab4[8] ICONST_ATTR = { | ||
44 | -1, -1, -1, -1, 2, 4, 6, 8 }; | ||
45 | |||
46 | static const int dvi_adpcm_indextab3[4] ICONST_ATTR = { -1, -1, 1, 2 }; | ||
47 | |||
48 | static struct pcm_format *fmt; | ||
49 | |||
50 | static bool set_format(struct pcm_format *format, const unsigned char *fmtpos) | ||
51 | { | ||
52 | fmt = format; | ||
53 | |||
54 | (void)fmtpos; | ||
55 | |||
56 | if (fmt->bitspersample != 4 && fmt->bitspersample != 3) | ||
57 | { | ||
58 | DEBUGF("CODEC_ERROR: dvi_adpcm must have 3 or 4 bitspersample\n"); | ||
59 | return false; | ||
60 | } | ||
61 | |||
62 | if (fmt->size < 2) { | ||
63 | DEBUGF("CODEC_ERROR: dvi_adpcm is missing SamplesPerBlock value\n"); | ||
64 | return false; | ||
65 | } | ||
66 | |||
67 | /* chunksize is computed so that one chunk is about 1/50s. | ||
68 | * this make 4096 for 44.1kHz 16bits stereo. | ||
69 | * It also has to be a multiple of blockalign */ | ||
70 | fmt->chunksize = (1 + fmt->avgbytespersec / (50*fmt->blockalign))*fmt->blockalign; | ||
71 | |||
72 | /* check that the output buffer is big enough (convert to samplespersec, | ||
73 | then round to the blockalign multiple below) */ | ||
74 | if ((((uint64_t)fmt->chunksize * ci->id3->frequency * fmt->channels * fmt->bitspersample)>>3) | ||
75 | /(uint64_t)fmt->avgbytespersec >= PCM_CHUNK_SIZE) | ||
76 | fmt->chunksize = ((uint64_t)PCM_CHUNK_SIZE * fmt->avgbytespersec | ||
77 | /((uint64_t)ci->id3->frequency * fmt->channels * 2 | ||
78 | * fmt->blockalign)) * fmt->blockalign; | ||
79 | |||
80 | return true; | ||
81 | } | ||
82 | |||
83 | static uint32_t get_seek_pos(long seek_time) | ||
84 | { | ||
85 | uint32_t newpos; | ||
86 | |||
87 | /* use avgbytespersec to round to the closest blockalign multiple, | ||
88 | add firstblockposn. 64-bit casts to avoid overflows. */ | ||
89 | newpos = (((uint64_t)fmt->avgbytespersec*(seek_time - 1)) | ||
90 | / (1000LL*fmt->blockalign))*fmt->blockalign; | ||
91 | return newpos; | ||
92 | } | ||
93 | |||
94 | static int decode_dvi_adpcm(const uint8_t *inbuf, size_t inbufsize, | ||
95 | int32_t *outbuf, size_t *outbufcount) | ||
96 | { | ||
97 | size_t nsamples = 0; | ||
98 | int sample[2]; | ||
99 | int samplecode[32][2]; | ||
100 | int i; | ||
101 | int stepindex[2]; | ||
102 | int c; | ||
103 | int diff; | ||
104 | int step; | ||
105 | int codem; | ||
106 | int code; | ||
107 | |||
108 | if (fmt->bitspersample != 4 && fmt->bitspersample != 3) { | ||
109 | DEBUGF("decode_dvi_adpcm: wrong bitspersample\n"); | ||
110 | return CODEC_ERROR; | ||
111 | } | ||
112 | |||
113 | /* decode block header */ | ||
114 | for (c = 0; c < fmt->channels && inbufsize >= 4; c++) { | ||
115 | /* decode + push first sample */ | ||
116 | sample[c] = (short)(inbuf[0]|(inbuf[1]<<8));/* need cast for sign-extend */ | ||
117 | outbuf[c] = sample[c] << 13; | ||
118 | nsamples++; | ||
119 | stepindex[c] = inbuf[2]; | ||
120 | /* check for step table index overflow */ | ||
121 | if (stepindex[c] > 88) { | ||
122 | DEBUGF("decode_dvi_adpcm: stepindex[%d]=%d>88\n",c,stepindex[c]); | ||
123 | return CODEC_ERROR; | ||
124 | } | ||
125 | |||
126 | inbuf += 4; | ||
127 | inbufsize -= 4; | ||
128 | } | ||
129 | if (fmt->bitspersample == 4) { | ||
130 | while (inbufsize >= (size_t)(fmt->channels*4) && | ||
131 | (nsamples + (fmt->channels*8) <= *outbufcount)) | ||
132 | { | ||
133 | for (c = 0; c < fmt->channels; c++) | ||
134 | { | ||
135 | samplecode[0][c] = inbuf[0]&0xf; | ||
136 | samplecode[1][c] = inbuf[0]>>4; | ||
137 | samplecode[2][c] = inbuf[1]&0xf; | ||
138 | samplecode[3][c] = inbuf[1]>>4; | ||
139 | samplecode[4][c] = inbuf[2]&0xf; | ||
140 | samplecode[5][c] = inbuf[2]>>4; | ||
141 | samplecode[6][c] = inbuf[3]&0xf; | ||
142 | samplecode[7][c] = inbuf[3]>>4; | ||
143 | inbuf += 4; | ||
144 | inbufsize -= 4; | ||
145 | } | ||
146 | for (i = 0; i < 8; i++) | ||
147 | { | ||
148 | for (c = 0; c < fmt->channels; c++) | ||
149 | { | ||
150 | step = dvi_adpcm_steptab[stepindex[c]]; | ||
151 | codem = samplecode[i][c]; | ||
152 | code = codem & 0x07; | ||
153 | |||
154 | /* adjust the step table index */ | ||
155 | stepindex[c] += dvi_adpcm_indextab4[code]; | ||
156 | /* check for step table index overflow and underflow */ | ||
157 | if (stepindex[c] > 88) | ||
158 | stepindex[c] = 88; | ||
159 | else if (stepindex[c] < 0) | ||
160 | stepindex[c] = 0; | ||
161 | /* calculate the difference */ | ||
162 | #ifdef STRICT_IMA | ||
163 | diff = 0; | ||
164 | if (code & 4) | ||
165 | diff += step; | ||
166 | step = step >> 1; | ||
167 | if (code & 2) | ||
168 | diff += step; | ||
169 | step = step >> 1; | ||
170 | if (code & 1) | ||
171 | diff += step; | ||
172 | step = step >> 1; | ||
173 | diff += step; | ||
174 | #else | ||
175 | diff = ((code + code + 1) * step) >> 3; /* faster */ | ||
176 | #endif | ||
177 | /* check the sign bit */ | ||
178 | /* check for overflow and underflow errors */ | ||
179 | if (code != codem) | ||
180 | { | ||
181 | sample[c] -= diff; | ||
182 | if (sample[c] < -32768) | ||
183 | sample[c] = -32768; | ||
184 | } | ||
185 | else | ||
186 | { | ||
187 | sample[c] += diff; | ||
188 | if (sample[c] > 32767) | ||
189 | sample[c] = 32767; | ||
190 | } | ||
191 | /* output the new sample */ | ||
192 | outbuf[nsamples] = sample[c] << 13; | ||
193 | nsamples++; | ||
194 | } | ||
195 | } | ||
196 | } | ||
197 | } else { /* bitspersample == 3 */ | ||
198 | while (inbufsize >= (uint32_t)(fmt->channels*12) && | ||
199 | (nsamples + 32*fmt->channels) <= *outbufcount) { | ||
200 | for (c = 0; c < fmt->channels; c++) { | ||
201 | uint16_t bitstream = 0; | ||
202 | int bitsread = 0; | ||
203 | for (i = 0; i < 32 && inbufsize > 0; i++) { | ||
204 | if (bitsread < 3) { | ||
205 | /* read 8 more bits */ | ||
206 | bitstream |= inbuf[0]<<bitsread; | ||
207 | bitsread += 8; | ||
208 | inbufsize--; | ||
209 | inbuf++; | ||
210 | } | ||
211 | samplecode[i][c] = bitstream & 7; | ||
212 | bitstream = bitstream>>3; | ||
213 | bitsread -= 3; | ||
214 | } | ||
215 | if (bitsread != 0) { | ||
216 | /* 32*3 = 3 words, so we should end with bitsread==0 */ | ||
217 | DEBUGF("decode_dvi_adpcm: error in implementation\n"); | ||
218 | return CODEC_ERROR; | ||
219 | } | ||
220 | } | ||
221 | |||
222 | for (i = 0; i < 32; i++) { | ||
223 | for (c = 0; c < fmt->channels; c++) { | ||
224 | step = dvi_adpcm_steptab[stepindex[c]]; | ||
225 | codem = samplecode[i][c]; | ||
226 | code = codem & 0x03; | ||
227 | |||
228 | /* adjust the step table index */ | ||
229 | stepindex[c] += dvi_adpcm_indextab3[code]; | ||
230 | /* check for step table index overflow and underflow */ | ||
231 | if (stepindex[c] > 88) | ||
232 | stepindex[c] = 88; | ||
233 | else if (stepindex[c] < 0) | ||
234 | stepindex[c] = 0; | ||
235 | /* calculate the difference */ | ||
236 | #ifdef STRICT_IMA | ||
237 | diff = 0; | ||
238 | if (code & 2) | ||
239 | diff += step; | ||
240 | step = step >> 1; | ||
241 | if (code & 1) | ||
242 | diff += step; | ||
243 | step = step >> 1; | ||
244 | diff += step; | ||
245 | #else | ||
246 | diff = ((code + code + 1) * step) >> 3; /* faster */ | ||
247 | #endif | ||
248 | /* check the sign bit */ | ||
249 | /* check for overflow and underflow errors */ | ||
250 | if (code != codem) { | ||
251 | sample[c] -= diff; | ||
252 | if (sample[c] < -32768) | ||
253 | sample[c] = -32768; | ||
254 | } | ||
255 | else { | ||
256 | sample[c] += diff; | ||
257 | if (sample[c] > 32767) | ||
258 | sample[c] = 32767; | ||
259 | } | ||
260 | /* output the new sample */ | ||
261 | outbuf[nsamples] = sample[c] << 13; | ||
262 | nsamples++; | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | } | ||
267 | |||
268 | if (nsamples > *outbufcount) { | ||
269 | DEBUGF("decode_dvi_adpcm: output buffer overflow!\n"); | ||
270 | return CODEC_ERROR; | ||
271 | } | ||
272 | *outbufcount = nsamples; | ||
273 | if (inbufsize != 0) { | ||
274 | DEBUGF("decode_dvi_adpcm: n=%d unprocessed bytes\n", (int)inbufsize); | ||
275 | } | ||
276 | return CODEC_OK; | ||
277 | } | ||
278 | |||
279 | static int decode(const uint8_t *inbuf, size_t inbufsize, | ||
280 | int32_t *outbuf, int *outbufsize) | ||
281 | { | ||
282 | unsigned int i; | ||
283 | unsigned int nblocks = fmt->chunksize / fmt->blockalign; | ||
284 | |||
285 | (void)inbufsize; | ||
286 | |||
287 | for (i = 0; i < nblocks; i++) | ||
288 | { | ||
289 | size_t decodedsize = fmt->samplesperblock * fmt->channels; | ||
290 | if (decode_dvi_adpcm(inbuf + i * fmt->blockalign, fmt->blockalign, | ||
291 | outbuf + i * fmt->samplesperblock * fmt->channels, | ||
292 | &decodedsize) != CODEC_OK) { | ||
293 | return CODEC_ERROR; | ||
294 | } | ||
295 | } | ||
296 | *outbufsize = nblocks * fmt->samplesperblock; | ||
297 | return CODEC_OK; | ||
298 | } | ||
299 | |||
300 | static const struct pcm_codec codec = { | ||
301 | set_format, | ||
302 | get_seek_pos, | ||
303 | decode, | ||
304 | }; | ||
305 | |||
306 | const struct pcm_codec *get_dvi_adpcm_codec(void) | ||
307 | { | ||
308 | return &codec; | ||
309 | } | ||