diff options
author | Michael Giacomelli <giac2000@hotmail.com> | 2010-01-27 17:25:10 +0000 |
---|---|---|
committer | Michael Giacomelli <giac2000@hotmail.com> | 2010-01-27 17:25:10 +0000 |
commit | c9183bf15e56bbc795f9fb08027ee6285b2ebed4 (patch) | |
tree | e355d4ebbdb9b06e7da5260ec58679aa96da15f1 | |
parent | 7a50f6f2740b84d10cbb021fd59a870c09688b88 (diff) | |
download | rockbox-c9183bf15e56bbc795f9fb08027ee6285b2ebed4.tar.gz rockbox-c9183bf15e56bbc795f9fb08027ee6285b2ebed4.zip |
Commit FS#10422 by Yoshihisa Uchida. Seperates WAV and AIFF parsing from PCM decoding by introducing libpcm, a library for decoding linear and non-uniform PCM independently of the container format.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24346 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/codecs/aiff.c | 213 | ||||
-rw-r--r-- | apps/codecs/codecs.make | 3 | ||||
-rw-r--r-- | apps/codecs/libpcm/SOURCES | 3 | ||||
-rwxr-xr-x | apps/codecs/libpcm/dvi_adpcm.c | 309 | ||||
-rw-r--r-- | apps/codecs/libpcm/itut_g711.c | 203 | ||||
-rw-r--r-- | apps/codecs/libpcm/libpcm.make | 25 | ||||
-rw-r--r-- | apps/codecs/libpcm/linear_pcm.c | 163 | ||||
-rw-r--r-- | apps/codecs/libpcm/pcm_common.h | 120 | ||||
-rw-r--r-- | apps/codecs/libpcm/support_formats.h | 37 | ||||
-rw-r--r-- | apps/codecs/wav.c | 648 | ||||
-rw-r--r-- | apps/metadata/aiff.c | 2 |
11 files changed, 1114 insertions, 612 deletions
diff --git a/apps/codecs/aiff.c b/apps/codecs/aiff.c index 9a675415e2..1b8c2da920 100644 --- a/apps/codecs/aiff.c +++ b/apps/codecs/aiff.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (c) 2005 Jvo Studer | 10 | * Copyright (c) 2005 Jvo Studer |
11 | * Copyright (c) 2009 Yoshihisa Uchida | ||
11 | * | 12 | * |
12 | * This program is free software; you can redistribute it and/or | 13 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 14 | * modify it under the terms of the GNU General Public License |
@@ -21,48 +22,62 @@ | |||
21 | 22 | ||
22 | #include "codeclib.h" | 23 | #include "codeclib.h" |
23 | #include <inttypes.h> | 24 | #include <inttypes.h> |
25 | #include "codecs/libpcm/support_formats.h" | ||
24 | 26 | ||
25 | CODEC_HEADER | 27 | CODEC_HEADER |
26 | 28 | ||
27 | /* Macro that sign extends an unsigned byte */ | 29 | #define FOURCC(c1, c2, c3, c4) \ |
28 | #define SE(x) ((int32_t)((int8_t)(x))) | 30 | ((((uint32_t)c1)<<24)|(((uint32_t)c2)<<16)|(((uint32_t)c3)<<8)|((uint32_t)c4)) |
29 | 31 | ||
30 | /* This codec supports AIFF files with the following formats: | 32 | /* This codec supports the following AIFC compressionType formats */ |
31 | * - PCM, 8, 16 and 24 bits, mono or stereo | 33 | enum { |
32 | */ | 34 | AIFC_FORMAT_PCM = FOURCC('N', 'O', 'N', 'E'), /* AIFC PCM Format (big endian) */ |
35 | AIFC_FORMAT_ALAW = FOURCC('a', 'l', 'a', 'w'), /* AIFC ALaw compressed */ | ||
36 | AIFC_FORMAT_MULAW = FOURCC('u', 'l', 'a', 'w'), /* AIFC uLaw compressed */ | ||
37 | }; | ||
33 | 38 | ||
34 | enum | 39 | static const struct pcm_entry pcm_codecs[] = { |
35 | { | 40 | { AIFC_FORMAT_PCM, get_linear_pcm_codec }, |
36 | AIFF_FORMAT_PCM = 0x0001, /* AIFF PCM Format (big endian) */ | 41 | { AIFC_FORMAT_ALAW, get_itut_g711_alaw_codec }, |
37 | IEEE_FORMAT_FLOAT = 0x0003, /* IEEE Float */ | 42 | { AIFC_FORMAT_MULAW, get_itut_g711_mulaw_codec }, |
38 | AIFF_FORMAT_ALAW = 0x0004, /* AIFC ALaw compressed */ | ||
39 | AIFF_FORMAT_ULAW = 0x0005 /* AIFC uLaw compressed */ | ||
40 | }; | 43 | }; |
41 | 44 | ||
42 | /* Maximum number of bytes to process in one iteration */ | 45 | #define NUM_FORMATS 3 |
43 | /* for 44.1kHz stereo 16bits, this represents 0.023s ~= 1/50s */ | ||
44 | #define AIF_CHUNK_SIZE (1024*2) | ||
45 | 46 | ||
46 | static int32_t samples[AIF_CHUNK_SIZE] IBSS_ATTR; | 47 | static int32_t samples[PCM_CHUNK_SIZE] IBSS_ATTR; |
48 | |||
49 | static const struct pcm_codec *get_codec(uint32_t formattag) | ||
50 | { | ||
51 | int i; | ||
52 | |||
53 | for (i = 0; i < NUM_FORMATS; i++) | ||
54 | { | ||
55 | if (pcm_codecs[i].format_tag == formattag) | ||
56 | { | ||
57 | if (pcm_codecs[i].get_codec) | ||
58 | return pcm_codecs[i].get_codec(); | ||
59 | return 0; | ||
60 | } | ||
61 | } | ||
62 | return 0; | ||
63 | } | ||
47 | 64 | ||
48 | enum codec_status codec_main(void) | 65 | enum codec_status codec_main(void) |
49 | { | 66 | { |
50 | uint32_t numbytes, bytesdone; | 67 | int status = CODEC_OK; |
51 | uint16_t num_channels = 0; | 68 | struct pcm_format format; |
69 | uint32_t bytesdone, decodedbytes; | ||
52 | uint32_t num_sample_frames = 0; | 70 | uint32_t num_sample_frames = 0; |
53 | uint16_t sample_size = 0; | 71 | uint32_t i = CODEC_OK; |
54 | uint32_t sample_rate = 0; | ||
55 | uint32_t i; | ||
56 | size_t n; | 72 | size_t n; |
57 | int bufcount; | 73 | int bufcount; |
58 | int endofstream; | 74 | int endofstream; |
59 | unsigned char *buf; | 75 | unsigned char *buf; |
60 | uint8_t *aifbuf; | 76 | uint8_t *aifbuf; |
61 | long chunksize; | ||
62 | uint32_t offset2snd = 0; | 77 | uint32_t offset2snd = 0; |
63 | uint16_t block_size = 0; | ||
64 | uint32_t avgbytespersec = 0; | ||
65 | off_t firstblockposn; /* position of the first block in file */ | 78 | off_t firstblockposn; /* position of the first block in file */ |
79 | bool is_aifc = false; | ||
80 | const struct pcm_codec *codec; | ||
66 | 81 | ||
67 | /* Generic codec initialisation */ | 82 | /* Generic codec initialisation */ |
68 | ci->configure(DSP_SET_SAMPLE_DEPTH, 28); | 83 | ci->configure(DSP_SET_SAMPLE_DEPTH, 28); |
@@ -84,45 +99,80 @@ next_track: | |||
84 | i = CODEC_ERROR; | 99 | i = CODEC_ERROR; |
85 | goto done; | 100 | goto done; |
86 | } | 101 | } |
87 | if ((memcmp(buf, "FORM", 4) != 0) || (memcmp(&buf[8], "AIFF", 4) != 0)) { | 102 | |
103 | if (memcmp(buf, "FORM", 4) != 0) | ||
104 | { | ||
105 | DEBUGF("CODEC_ERROR: does not aiff format %c%c%c%c\n", buf[0], buf[1], buf[2], buf[3]); | ||
106 | i = CODEC_ERROR; | ||
107 | goto done; | ||
108 | } | ||
109 | if (memcmp(&buf[8], "AIFF", 4) == 0) | ||
110 | is_aifc = false; | ||
111 | else if (memcmp(&buf[8], "AIFC", 4) == 0) | ||
112 | is_aifc = true; | ||
113 | else | ||
114 | { | ||
115 | DEBUGF("CODEC_ERROR: does not aiff format %c%c%c%c\n", buf[8], buf[9], buf[10], buf[11]); | ||
88 | i = CODEC_ERROR; | 116 | i = CODEC_ERROR; |
89 | goto done; | 117 | goto done; |
90 | } | 118 | } |
91 | 119 | ||
92 | buf += 12; | 120 | buf += 12; |
93 | n -= 12; | 121 | n -= 12; |
94 | numbytes = 0; | 122 | |
123 | ci->memset(&format, 0, sizeof(struct pcm_format)); | ||
124 | format.is_signed = true; | ||
125 | format.is_little_endian = false; | ||
126 | |||
127 | decodedbytes = 0; | ||
128 | codec = 0; | ||
95 | 129 | ||
96 | /* read until 'SSND' chunk, which typically is last */ | 130 | /* read until 'SSND' chunk, which typically is last */ |
97 | while (numbytes == 0 && n >= 8) { | 131 | while (format.numbytes == 0 && n >= 8) |
132 | { | ||
98 | /* chunkSize */ | 133 | /* chunkSize */ |
99 | i = ((buf[4]<<24)|(buf[5]<<16)|(buf[6]<<8)|buf[7]); | 134 | i = ((buf[4]<<24)|(buf[5]<<16)|(buf[6]<<8)|buf[7]); |
100 | if (memcmp(buf, "COMM", 4) == 0) { | 135 | if (memcmp(buf, "COMM", 4) == 0) { |
101 | if (i < 18) { | 136 | if ((!is_aifc && i < 18) || (is_aifc && i < 22)) |
102 | DEBUGF("CODEC_ERROR: 'COMM' chunk size=%lu < 18\n", | 137 | { |
103 | (unsigned long)i); | 138 | DEBUGF("CODEC_ERROR: 'COMM' chunk size=%lu < %d\n", |
139 | (unsigned long)i, (is_aifc)?22:18); | ||
104 | i = CODEC_ERROR; | 140 | i = CODEC_ERROR; |
105 | goto done; | 141 | goto done; |
106 | } | 142 | } |
107 | /* num_channels */ | 143 | /* num_channels */ |
108 | num_channels = ((buf[8]<<8)|buf[9]); | 144 | format.channels = ((buf[8]<<8)|buf[9]); |
109 | /* num_sample_frames */ | 145 | /* num_sample_frames */ |
110 | num_sample_frames = ((buf[10]<<24)|(buf[11]<<16)|(buf[12]<<8) | 146 | num_sample_frames = ((buf[10]<<24)|(buf[11]<<16)|(buf[12]<<8) |
111 | |buf[13]); | 147 | |buf[13]); |
112 | /* sample_size */ | 148 | /* sample_size */ |
113 | sample_size = ((buf[14]<<8)|buf[15]); | 149 | format.bitspersample = ((buf[14]<<8)|buf[15]); |
114 | /* sample_rate (don't use last 4 bytes, only integer fs) */ | 150 | /* sample_rate (don't use last 4 bytes, only integer fs) */ |
115 | if (buf[16] != 0x40) { | 151 | if (buf[16] != 0x40) { |
116 | DEBUGF("CODEC_ERROR: weird sampling rate (no @)\n"); | 152 | DEBUGF("CODEC_ERROR: weird sampling rate (no @)\n"); |
117 | i = CODEC_ERROR; | 153 | i = CODEC_ERROR; |
118 | goto done; | 154 | goto done; |
119 | } | 155 | } |
120 | sample_rate = ((buf[18]<<24)|(buf[19]<<16)|(buf[20]<<8)|buf[21])+1; | 156 | format.samplespersec = ((buf[18]<<24)|(buf[19]<<16)|(buf[20]<<8)|buf[21])+1; |
121 | sample_rate = sample_rate >> (16 + 14 - buf[17]); | 157 | format.samplespersec >>= (16 + 14 - buf[17]); |
158 | /* compressionType (AIFC only) */ | ||
159 | if (is_aifc) | ||
160 | { | ||
161 | format.formattag = (buf[26]<<24)|(buf[27]<<16)|(buf[28]<<8)|buf[29]; | ||
162 | |||
163 | /* | ||
164 | * aiff's sample_size is uncompressed sound data size. | ||
165 | * But format.bitspersample is compressed sound data size. | ||
166 | */ | ||
167 | if (format.formattag == AIFC_FORMAT_ALAW || format.formattag == AIFC_FORMAT_MULAW) | ||
168 | format.bitspersample = 8; | ||
169 | } | ||
170 | else | ||
171 | format.formattag = AIFC_FORMAT_PCM; | ||
122 | /* calc average bytes per second */ | 172 | /* calc average bytes per second */ |
123 | avgbytespersec = sample_rate*num_channels*sample_size/8; | 173 | format.avgbytespersec = format.samplespersec*format.channels*format.bitspersample/8; |
124 | } else if (memcmp(buf, "SSND", 4)==0) { | 174 | } else if (memcmp(buf, "SSND", 4)==0) { |
125 | if (sample_size == 0) { | 175 | if (format.bitspersample == 0) { |
126 | DEBUGF("CODEC_ERROR: unsupported chunk order\n"); | 176 | DEBUGF("CODEC_ERROR: unsupported chunk order\n"); |
127 | i = CODEC_ERROR; | 177 | i = CODEC_ERROR; |
128 | goto done; | 178 | goto done; |
@@ -130,11 +180,14 @@ next_track: | |||
130 | /* offset2snd */ | 180 | /* offset2snd */ |
131 | offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11]; | 181 | offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11]; |
132 | /* block_size */ | 182 | /* block_size */ |
133 | block_size = (buf[12]<<24)|(buf[13]<<16)|(buf[14]<<8)|buf[15]; | 183 | format.blockalign = (buf[12]<<24)|(buf[13]<<16)|(buf[14]<<8)|buf[15]; |
134 | if (block_size == 0) | 184 | if (format.blockalign == 0) |
135 | block_size = num_channels*sample_size; | 185 | format.blockalign = format.channels*format.bitspersample; |
136 | numbytes = i - 8 - offset2snd; | 186 | format.numbytes = i - 8 - offset2snd; |
137 | i = 8 + offset2snd; /* advance to the beginning of data */ | 187 | i = 8 + offset2snd; /* advance to the beginning of data */ |
188 | } else if (is_aifc && (memcmp(buf, "FVER", 4)==0)) { | ||
189 | /* Format Version Chunk (AIFC only chunk) */ | ||
190 | /* skip this chunk */ | ||
138 | } else { | 191 | } else { |
139 | DEBUGF("unsupported AIFF chunk: '%c%c%c%c', size=%lu\n", | 192 | DEBUGF("unsupported AIFF chunk: '%c%c%c%c', size=%lu\n", |
140 | buf[0], buf[1], buf[2], buf[3], (unsigned long)i); | 193 | buf[0], buf[1], buf[2], buf[3], (unsigned long)i); |
@@ -151,28 +204,36 @@ next_track: | |||
151 | n -= i + 8; | 204 | n -= i + 8; |
152 | } /* while 'SSND' */ | 205 | } /* while 'SSND' */ |
153 | 206 | ||
154 | if (num_channels == 0) { | 207 | if (format.channels == 0) { |
155 | DEBUGF("CODEC_ERROR: 'COMM' chunk not found or 0-channels file\n"); | 208 | DEBUGF("CODEC_ERROR: 'COMM' chunk not found or 0-channels file\n"); |
156 | i = CODEC_ERROR; | 209 | i = CODEC_ERROR; |
157 | goto done; | 210 | goto done; |
158 | } | 211 | } |
159 | if (numbytes == 0) { | 212 | if (format.numbytes == 0) { |
160 | DEBUGF("CODEC_ERROR: 'SSND' chunk not found or has zero length\n"); | 213 | DEBUGF("CODEC_ERROR: 'SSND' chunk not found or has zero length\n"); |
161 | i = CODEC_ERROR; | 214 | i = CODEC_ERROR; |
162 | goto done; | 215 | goto done; |
163 | } | 216 | } |
164 | if (sample_size > 24) { | 217 | |
165 | DEBUGF("CODEC_ERROR: PCM with more than 24 bits per sample " | 218 | codec = get_codec(format.formattag); |
166 | "is unsupported\n"); | 219 | if (codec == 0) |
220 | { | ||
221 | DEBUGF("CODEC_ERROR: AIFC does not support compressionType: 0x%x\n", format.formattag); | ||
222 | i = CODEC_ERROR; | ||
223 | goto done; | ||
224 | } | ||
225 | |||
226 | if (!codec->set_format(&format, 0)) | ||
227 | { | ||
167 | i = CODEC_ERROR; | 228 | i = CODEC_ERROR; |
168 | goto done; | 229 | goto done; |
169 | } | 230 | } |
170 | 231 | ||
171 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 232 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
172 | 233 | ||
173 | if (num_channels == 2) { | 234 | if (format.channels == 2) { |
174 | ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); | 235 | ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); |
175 | } else if (num_channels == 1) { | 236 | } else if (format.channels == 1) { |
176 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | 237 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); |
177 | } else { | 238 | } else { |
178 | DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n"); | 239 | DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n"); |
@@ -187,18 +248,6 @@ next_track: | |||
187 | bytesdone = 0; | 248 | bytesdone = 0; |
188 | ci->set_elapsed(0); | 249 | ci->set_elapsed(0); |
189 | endofstream = 0; | 250 | endofstream = 0; |
190 | /* chunksize is computed so that one chunk is about 1/50s. | ||
191 | * this make 4096 for 44.1kHz 16bits stereo. | ||
192 | * It also has to be a multiple of blockalign */ | ||
193 | chunksize = (1 + avgbytespersec/(50*block_size))*block_size; | ||
194 | /* check that the output buffer is big enough (convert to samplespersec, | ||
195 | then round to the block_size multiple below) */ | ||
196 | if (((uint64_t)chunksize*ci->id3->frequency*num_channels*2) | ||
197 | /(uint64_t)avgbytespersec >= AIF_CHUNK_SIZE) { | ||
198 | chunksize = ((uint64_t)AIF_CHUNK_SIZE*avgbytespersec | ||
199 | /((uint64_t)ci->id3->frequency*num_channels*2 | ||
200 | *block_size))*block_size; | ||
201 | } | ||
202 | 251 | ||
203 | while (!endofstream) { | 252 | while (!endofstream) { |
204 | ci->yield(); | 253 | ci->yield(); |
@@ -206,61 +255,39 @@ next_track: | |||
206 | break; | 255 | break; |
207 | 256 | ||
208 | if (ci->seek_time) { | 257 | if (ci->seek_time) { |
209 | uint32_t newpos; | 258 | uint32_t newpos = codec->get_seek_pos(ci->seek_time); |
210 | 259 | if (newpos > format.numbytes) | |
211 | /* use avgbytespersec to round to the closest blockalign multiple, | ||
212 | add firstblockposn. 64-bit casts to avoid overflows. */ | ||
213 | newpos = (((uint64_t)avgbytespersec*(ci->seek_time - 1)) | ||
214 | /(1000LL*block_size))*block_size; | ||
215 | if (newpos > numbytes) | ||
216 | break; | 260 | break; |
217 | if (ci->seek_buffer(firstblockposn + newpos)) | 261 | if (ci->seek_buffer(firstblockposn + newpos)) |
218 | bytesdone = newpos; | 262 | bytesdone = newpos; |
219 | ci->seek_complete(); | 263 | ci->seek_complete(); |
220 | } | 264 | } |
221 | aifbuf = (uint8_t *)ci->request_buffer(&n, chunksize); | 265 | aifbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); |
222 | 266 | ||
223 | if (n == 0) | 267 | if (n == 0) |
224 | break; /* End of stream */ | 268 | break; /* End of stream */ |
225 | 269 | ||
226 | if (bytesdone + n > numbytes) { | 270 | if (bytesdone + n > format.numbytes) { |
227 | n = numbytes - bytesdone; | 271 | n = format.numbytes - bytesdone; |
228 | endofstream = 1; | 272 | endofstream = 1; |
229 | } | 273 | } |
230 | 274 | ||
231 | if (sample_size > 24) { | 275 | status = codec->decode(aifbuf, n, samples, &bufcount); |
232 | for (i = 0; i < n; i += 4) { | 276 | if (status == CODEC_ERROR) |
233 | samples[i/4] = (SE(aifbuf[i])<<21)|(aifbuf[i + 1]<<13) | 277 | { |
234 | |(aifbuf[i + 2]<<5)|(aifbuf[i + 3]>>3); | 278 | DEBUGF("codec error\n"); |
235 | } | 279 | goto done; |
236 | bufcount = n >> 2; | ||
237 | } else if (sample_size > 16) { | ||
238 | for (i = 0; i < n; i += 3) { | ||
239 | samples[i/3] = (SE(aifbuf[i])<<21)|(aifbuf[i + 1]<<13) | ||
240 | |(aifbuf[i + 2]<<5); | ||
241 | } | ||
242 | bufcount = n/3; | ||
243 | } else if (sample_size > 8) { | ||
244 | for (i = 0; i < n; i += 2) | ||
245 | samples[i/2] = (SE(aifbuf[i])<<21)|(aifbuf[i + 1]<<13); | ||
246 | bufcount = n >> 1; | ||
247 | } else { | ||
248 | for (i = 0; i < n; i++) | ||
249 | samples[i] = SE(aifbuf[i]) << 21; | ||
250 | bufcount = n; | ||
251 | } | 280 | } |
252 | 281 | ||
253 | if (num_channels == 2) | ||
254 | bufcount >>= 1; | ||
255 | |||
256 | ci->pcmbuf_insert(samples, NULL, bufcount); | 282 | ci->pcmbuf_insert(samples, NULL, bufcount); |
257 | 283 | ||
258 | ci->advance_buffer(n); | 284 | ci->advance_buffer(n); |
259 | bytesdone += n; | 285 | bytesdone += n; |
260 | if (bytesdone >= numbytes) | 286 | decodedbytes += bufcount; |
287 | if (bytesdone >= format.numbytes) | ||
261 | endofstream = 1; | 288 | endofstream = 1; |
262 | 289 | ||
263 | ci->set_elapsed(bytesdone*1000LL/avgbytespersec); | 290 | ci->set_elapsed(decodedbytes*1000LL/ci->id3->frequency); |
264 | } | 291 | } |
265 | i = CODEC_OK; | 292 | i = CODEC_OK; |
266 | 293 | ||
diff --git a/apps/codecs/codecs.make b/apps/codecs/codecs.make index 391975d73c..9e1f909462 100644 --- a/apps/codecs/codecs.make +++ b/apps/codecs/codecs.make | |||
@@ -39,6 +39,7 @@ include $(APPSDIR)/codecs/libwma/libwma.make | |||
39 | include $(APPSDIR)/codecs/libcook/libcook.make | 39 | include $(APPSDIR)/codecs/libcook/libcook.make |
40 | include $(APPSDIR)/codecs/librm/librm.make | 40 | include $(APPSDIR)/codecs/librm/librm.make |
41 | include $(APPSDIR)/codecs/libatrac/libatrac.make | 41 | include $(APPSDIR)/codecs/libatrac/libatrac.make |
42 | include $(APPSDIR)/codecs/libpcm/libpcm.make | ||
42 | 43 | ||
43 | # compile flags for codecs | 44 | # compile flags for codecs |
44 | CODECFLAGS = $(filter-out -fno-strict-aliasing,$(CFLAGS)) -fstrict-aliasing \ | 45 | CODECFLAGS = $(filter-out -fno-strict-aliasing,$(CFLAGS)) -fstrict-aliasing \ |
@@ -85,6 +86,8 @@ $(CODECDIR)/cook.codec : $(CODECDIR)/libcook.a $(CODECDIR)/librm.a | |||
85 | $(CODECDIR)/raac.codec : $(CODECDIR)/libfaad.a $(CODECDIR)/librm.a | 86 | $(CODECDIR)/raac.codec : $(CODECDIR)/libfaad.a $(CODECDIR)/librm.a |
86 | $(CODECDIR)/a52_rm.codec : $(CODECDIR)/liba52.a $(CODECDIR)/librm.a | 87 | $(CODECDIR)/a52_rm.codec : $(CODECDIR)/liba52.a $(CODECDIR)/librm.a |
87 | $(CODECDIR)/atrac3_rm.codec : $(CODECDIR)/libatrac.a $(CODECDIR)/librm.a | 88 | $(CODECDIR)/atrac3_rm.codec : $(CODECDIR)/libatrac.a $(CODECDIR)/librm.a |
89 | $(CODECDIR)/aiff.codec : $(CODECDIR)/libpcm.a | ||
90 | $(CODECDIR)/wav.codec : $(CODECDIR)/libpcm.a | ||
88 | 91 | ||
89 | $(CODECS): $(CODECLIB) # this must be last in codec dependency list | 92 | $(CODECS): $(CODECLIB) # this must be last in codec dependency list |
90 | 93 | ||
diff --git a/apps/codecs/libpcm/SOURCES b/apps/codecs/libpcm/SOURCES new file mode 100644 index 0000000000..e921584f7c --- /dev/null +++ b/apps/codecs/libpcm/SOURCES | |||
@@ -0,0 +1,3 @@ | |||
1 | linear_pcm.c | ||
2 | itut_g711.c | ||
3 | dvi_adpcm.c | ||
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 | } | ||
diff --git a/apps/codecs/libpcm/itut_g711.c b/apps/codecs/libpcm/itut_g711.c new file mode 100644 index 0000000000..1f235943ad --- /dev/null +++ b/apps/codecs/libpcm/itut_g711.c | |||
@@ -0,0 +1,203 @@ | |||
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 | * ITU-T G.711 A-law mu-law | ||
27 | */ | ||
28 | |||
29 | static const int16_t alaw2linear16[256] ICONST_ATTR = { | ||
30 | -5504, -5248, -6016, -5760, -4480, -4224, -4992, | ||
31 | -4736, -7552, -7296, -8064, -7808, -6528, -6272, | ||
32 | -7040, -6784, -2752, -2624, -3008, -2880, -2240, | ||
33 | -2112, -2496, -2368, -3776, -3648, -4032, -3904, | ||
34 | -3264, -3136, -3520, -3392, -22016, -20992, -24064, | ||
35 | -23040, -17920, -16896, -19968, -18944, -30208, -29184, | ||
36 | -32256, -31232, -26112, -25088, -28160, -27136, -11008, | ||
37 | -10496, -12032, -11520, -8960, -8448, -9984, -9472, | ||
38 | -15104, -14592, -16128, -15616, -13056, -12544, -14080, | ||
39 | -13568, -344, -328, -376, -360, -280, -264, | ||
40 | -312, -296, -472, -456, -504, -488, -408, | ||
41 | -392, -440, -424, -88, -72, -120, -104, | ||
42 | -24, -8, -56, -40, -216, -200, -248, | ||
43 | -232, -152, -136, -184, -168, -1376, -1312, | ||
44 | -1504, -1440, -1120, -1056, -1248, -1184, -1888, | ||
45 | -1824, -2016, -1952, -1632, -1568, -1760, -1696, | ||
46 | -688, -656, -752, -720, -560, -528, -624, | ||
47 | -592, -944, -912, -1008, -976, -816, -784, | ||
48 | -880, -848, 5504, 5248, 6016, 5760, 4480, | ||
49 | 4224, 4992, 4736, 7552, 7296, 8064, 7808, | ||
50 | 6528, 6272, 7040, 6784, 2752, 2624, 3008, | ||
51 | 2880, 2240, 2112, 2496, 2368, 3776, 3648, | ||
52 | 4032, 3904, 3264, 3136, 3520, 3392, 22016, | ||
53 | 20992, 24064, 23040, 17920, 16896, 19968, 18944, | ||
54 | 30208, 29184, 32256, 31232, 26112, 25088, 28160, | ||
55 | 27136, 11008, 10496, 12032, 11520, 8960, 8448, | ||
56 | 9984, 9472, 15104, 14592, 16128, 15616, 13056, | ||
57 | 12544, 14080, 13568, 344, 328, 376, 360, | ||
58 | 280, 264, 312, 296, 472, 456, 504, | ||
59 | 488, 408, 392, 440, 424, 88, 72, | ||
60 | 120, 104, 24, 8, 56, 40, 216, | ||
61 | 200, 248, 232, 152, 136, 184, 168, | ||
62 | 1376, 1312, 1504, 1440, 1120, 1056, 1248, | ||
63 | 1184, 1888, 1824, 2016, 1952, 1632, 1568, | ||
64 | 1760, 1696, 688, 656, 752, 720, 560, | ||
65 | 528, 624, 592, 944, 912, 1008, 976, | ||
66 | 816, 784, 880, 848 | ||
67 | }; | ||
68 | |||
69 | static const int16_t ulaw2linear16[256] ICONST_ATTR = { | ||
70 | -32124, -31100, -30076, -29052, -28028, -27004, -25980, | ||
71 | -24956, -23932, -22908, -21884, -20860, -19836, -18812, | ||
72 | -17788, -16764, -15996, -15484, -14972, -14460, -13948, | ||
73 | -13436, -12924, -12412, -11900, -11388, -10876, -10364, | ||
74 | -9852, -9340, -8828, -8316, -7932, -7676, -7420, | ||
75 | -7164, -6908, -6652, -6396, -6140, -5884, -5628, | ||
76 | -5372, -5116, -4860, -4604, -4348, -4092, -3900, | ||
77 | -3772, -3644, -3516, -3388, -3260, -3132, -3004, | ||
78 | -2876, -2748, -2620, -2492, -2364, -2236, -2108, | ||
79 | -1980, -1884, -1820, -1756, -1692, -1628, -1564, | ||
80 | -1500, -1436, -1372, -1308, -1244, -1180, -1116, | ||
81 | -1052, -988, -924, -876, -844, -812, -780, | ||
82 | -748, -716, -684, -652, -620, -588, -556, | ||
83 | -524, -492, -460, -428, -396, -372, -356, | ||
84 | -340, -324, -308, -292, -276, -260, -244, | ||
85 | -228, -212, -196, -180, -164, -148, -132, | ||
86 | -120, -112, -104, -96, -88, -80, -72, | ||
87 | -64, -56, -48, -40, -32, -24, -16, | ||
88 | -8, 0, 32124, 31100, 30076, 29052, 28028, | ||
89 | 27004, 25980, 24956, 23932, 22908, 21884, 20860, | ||
90 | 19836, 18812, 17788, 16764, 15996, 15484, 14972, | ||
91 | 14460, 13948, 13436, 12924, 12412, 11900, 11388, | ||
92 | 10876, 10364, 9852, 9340, 8828, 8316, 7932, | ||
93 | 7676, 7420, 7164, 6908, 6652, 6396, 6140, | ||
94 | 5884, 5628, 5372, 5116, 4860, 4604, 4348, | ||
95 | 4092, 3900, 3772, 3644, 3516, 3388, 3260, | ||
96 | 3132, 3004, 2876, 2748, 2620, 2492, 2364, | ||
97 | 2236, 2108, 1980, 1884, 1820, 1756, 1692, | ||
98 | 1628, 1564, 1500, 1436, 1372, 1308, 1244, | ||
99 | 1180, 1116, 1052, 988, 924, 876, 844, | ||
100 | 812, 780, 748, 716, 684, 652, 620, | ||
101 | 588, 556, 524, 492, 460, 428, 396, | ||
102 | 372, 356, 340, 324, 308, 292, 276, | ||
103 | 260, 244, 228, 212, 196, 180, 164, | ||
104 | 148, 132, 120, 112, 104, 96, 88, | ||
105 | 80, 72, 64, 56, 48, 40, 32, | ||
106 | 24, 16, 8, 0 | ||
107 | }; | ||
108 | |||
109 | static struct pcm_format *fmt; | ||
110 | |||
111 | static bool set_format(struct pcm_format *format, const unsigned char *fmtpos) | ||
112 | { | ||
113 | fmt = format; | ||
114 | |||
115 | (void)fmtpos; | ||
116 | |||
117 | if (fmt->bitspersample != 8) | ||
118 | { | ||
119 | DEBUGF("CODEC_ERROR: alaw and mulaw must have 8 bitspersample\n"); | ||
120 | return false; | ||
121 | } | ||
122 | |||
123 | if (fmt->totalsamples == 0) | ||
124 | { | ||
125 | fmt->bytespersample = fmt->channels; | ||
126 | fmt->totalsamples = fmt->numbytes/fmt->bytespersample; | ||
127 | } | ||
128 | |||
129 | /* chunksize is computed so that one chunk is about 1/50s. | ||
130 | * this make 4096 for 44.1kHz 16bits stereo. | ||
131 | * It also has to be a multiple of blockalign */ | ||
132 | fmt->chunksize = (1 + fmt->avgbytespersec / (50*fmt->blockalign))*fmt->blockalign; | ||
133 | |||
134 | /* check that the output buffer is big enough (convert to samplespersec, | ||
135 | then round to the blockalign multiple below) */ | ||
136 | if ((((uint64_t)fmt->chunksize * ci->id3->frequency * fmt->channels * fmt->bitspersample)>>3) | ||
137 | /(uint64_t)fmt->avgbytespersec >= PCM_CHUNK_SIZE) | ||
138 | fmt->chunksize = ((uint64_t)PCM_CHUNK_SIZE * fmt->avgbytespersec | ||
139 | /((uint64_t)ci->id3->frequency * fmt->channels * 2 | ||
140 | * fmt->blockalign)) * fmt->blockalign; | ||
141 | |||
142 | return true; | ||
143 | } | ||
144 | |||
145 | static uint32_t get_seek_pos(long seek_time) | ||
146 | { | ||
147 | uint32_t newpos; | ||
148 | |||
149 | /* use avgbytespersec to round to the closest blockalign multiple, | ||
150 | add firstblockposn. 64-bit casts to avoid overflows. */ | ||
151 | newpos = (((uint64_t)fmt->avgbytespersec*(seek_time - 1)) | ||
152 | / (1000LL*fmt->blockalign))*fmt->blockalign; | ||
153 | return newpos; | ||
154 | } | ||
155 | |||
156 | static int decode_alaw(const uint8_t *inbuf, size_t inbufsize, | ||
157 | int32_t *outbuf, int *outbufsize) | ||
158 | { | ||
159 | uint32_t i; | ||
160 | |||
161 | for (i = 0; i < inbufsize; i++) | ||
162 | outbuf[i] = alaw2linear16[inbuf[i]] << 13; | ||
163 | |||
164 | *outbufsize = (fmt->channels == 2) ? (inbufsize >> 1) : inbufsize; | ||
165 | |||
166 | return CODEC_OK; | ||
167 | } | ||
168 | |||
169 | static int decode_mulaw(const uint8_t *inbuf, size_t inbufsize, | ||
170 | int32_t *outbuf, int *outbufsize) | ||
171 | { | ||
172 | uint32_t i; | ||
173 | |||
174 | for (i = 0; i < inbufsize; i++) | ||
175 | outbuf[i] = ulaw2linear16[inbuf[i]] << 13; | ||
176 | |||
177 | *outbufsize = (fmt->channels == 2) ? (inbufsize >> 1) : inbufsize; | ||
178 | |||
179 | return CODEC_OK; | ||
180 | } | ||
181 | |||
182 | static const struct pcm_codec alaw_codec = { | ||
183 | set_format, | ||
184 | get_seek_pos, | ||
185 | decode_alaw, | ||
186 | }; | ||
187 | |||
188 | static const struct pcm_codec mulaw_codec = { | ||
189 | set_format, | ||
190 | get_seek_pos, | ||
191 | decode_mulaw, | ||
192 | }; | ||
193 | |||
194 | const struct pcm_codec *get_itut_g711_alaw_codec(void) | ||
195 | { | ||
196 | return &alaw_codec; | ||
197 | } | ||
198 | |||
199 | const struct pcm_codec *get_itut_g711_mulaw_codec(void) | ||
200 | { | ||
201 | return &mulaw_codec; | ||
202 | } | ||
203 | |||
diff --git a/apps/codecs/libpcm/libpcm.make b/apps/codecs/libpcm/libpcm.make new file mode 100644 index 0000000000..ce7b6b5083 --- /dev/null +++ b/apps/codecs/libpcm/libpcm.make | |||
@@ -0,0 +1,25 @@ | |||
1 | # __________ __ ___. | ||
2 | # Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
3 | # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
4 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
5 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
6 | # \/ \/ \/ \/ \/ | ||
7 | # $Id$ | ||
8 | # | ||
9 | |||
10 | # libpcm | ||
11 | PCMSLIB := $(CODECDIR)/libpcm.a | ||
12 | PCMSLIB_SRC := $(call preprocess, $(APPSDIR)/codecs/libpcm/SOURCES) | ||
13 | PCMSLIB_OBJ := $(call c2obj, $(PCMSLIB_SRC)) | ||
14 | OTHER_SRC += $(PCMSLIB_SRC) | ||
15 | |||
16 | $(PCMSLIB): $(PCMSLIB_OBJ) | ||
17 | $(SILENT)$(shell rm -f $@) | ||
18 | $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null | ||
19 | |||
20 | PCMSFLAGS = $(filter-out -O%,$(CODECFLAGS)) | ||
21 | PCMSFLAGS += -O1 | ||
22 | |||
23 | $(CODECDIR)/libpcm/%.o: $(ROOTDIR)/apps/codecs/libpcm/%.c | ||
24 | $(SILENT)mkdir -p $(dir $@) | ||
25 | $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) $(PCMSFLAGS) -c $< -o $@ | ||
diff --git a/apps/codecs/libpcm/linear_pcm.c b/apps/codecs/libpcm/linear_pcm.c new file mode 100644 index 0000000000..2c766bd741 --- /dev/null +++ b/apps/codecs/libpcm/linear_pcm.c | |||
@@ -0,0 +1,163 @@ | |||
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 | * Linear PCM | ||
27 | */ | ||
28 | |||
29 | static struct pcm_format *fmt; | ||
30 | |||
31 | static bool set_format(struct pcm_format *format, const unsigned char *fmtpos) | ||
32 | { | ||
33 | fmt = format; | ||
34 | |||
35 | (void)fmtpos; | ||
36 | |||
37 | if (fmt->bitspersample > 32) | ||
38 | { | ||
39 | DEBUGF("CODEC_ERROR: pcm with more than 32 bitspersample " | ||
40 | "is unsupported\n"); | ||
41 | return false; | ||
42 | } | ||
43 | |||
44 | if (fmt->totalsamples == 0) | ||
45 | { | ||
46 | fmt->bytespersample = (((fmt->bitspersample - 1)/8 + 1)*fmt->channels); | ||
47 | fmt->totalsamples = fmt->numbytes/fmt->bytespersample; | ||
48 | } | ||
49 | |||
50 | /* chunksize is computed so that one chunk is about 1/50s. | ||
51 | * this make 4096 for 44.1kHz 16bits stereo. | ||
52 | * It also has to be a multiple of blockalign */ | ||
53 | fmt->chunksize = (1 + fmt->avgbytespersec / (50*fmt->blockalign))*fmt->blockalign; | ||
54 | |||
55 | return true; | ||
56 | } | ||
57 | |||
58 | static uint32_t get_seek_pos(long seek_time) | ||
59 | { | ||
60 | uint32_t newpos; | ||
61 | |||
62 | /* use avgbytespersec to round to the closest blockalign multiple, | ||
63 | add firstblockposn. 64-bit casts to avoid overflows. */ | ||
64 | newpos = (((uint64_t)fmt->avgbytespersec*(seek_time - 1)) | ||
65 | / (1000LL*fmt->blockalign))*fmt->blockalign; | ||
66 | return newpos; | ||
67 | } | ||
68 | |||
69 | static int decode(const uint8_t *inbuf, size_t inbufsize, | ||
70 | int32_t *outbuf, int *outbufsize) | ||
71 | { | ||
72 | uint32_t i; | ||
73 | |||
74 | if (fmt->bitspersample > 24) | ||
75 | { | ||
76 | for (i = 0; i < inbufsize; i += 4) | ||
77 | { | ||
78 | if (fmt->is_little_endian) | ||
79 | { | ||
80 | if (fmt->is_signed) | ||
81 | outbuf[i/4] = (inbuf[i]>>3)|(inbuf[i+1]<<5)|(inbuf[i+2]<<13)|(SE(inbuf[i+3])<<21); | ||
82 | else | ||
83 | outbuf[i/4] = (inbuf[i]>>3)|(inbuf[i+1]<<5)|(inbuf[i+2]<<13)|(SFT(inbuf[i+3])<<21); | ||
84 | } | ||
85 | else | ||
86 | { | ||
87 | if (fmt->is_signed) | ||
88 | outbuf[i/4] = (inbuf[i+3]>>3)|(inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SE(inbuf[i])<<21); | ||
89 | else | ||
90 | outbuf[i/4] = (inbuf[i+3]>>3)|(inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SFT(inbuf[i])<<21); | ||
91 | } | ||
92 | } | ||
93 | *outbufsize = inbufsize >> 2; | ||
94 | } | ||
95 | else if (fmt->bitspersample > 16) | ||
96 | { | ||
97 | for (i = 0; i < inbufsize; i += 3) | ||
98 | { | ||
99 | if (fmt->is_little_endian) | ||
100 | { | ||
101 | if (fmt->is_signed) | ||
102 | outbuf[i/3] = (inbuf[i]<<5)|(inbuf[i+1]<<13)|(SE(inbuf[i+2])<<21); | ||
103 | else | ||
104 | outbuf[i/3] = (inbuf[i]<<5)|(inbuf[i+1]<<13)|(SFT(inbuf[i+2])<<21); | ||
105 | } | ||
106 | else | ||
107 | { | ||
108 | if (fmt->is_signed) | ||
109 | outbuf[i/3] = (inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SE(inbuf[i])<<21); | ||
110 | else | ||
111 | outbuf[i/3] = (inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SFT(inbuf[i])<<21); | ||
112 | } | ||
113 | } | ||
114 | *outbufsize = inbufsize/3; | ||
115 | } | ||
116 | else if (fmt->bitspersample > 8) | ||
117 | { | ||
118 | for (i = 0; i < inbufsize; i += 2) | ||
119 | { | ||
120 | if (fmt->is_little_endian) | ||
121 | { | ||
122 | if (fmt->is_signed) | ||
123 | outbuf[i/2] = (inbuf[i]<<13)|(SE(inbuf[i+1])<<21); | ||
124 | else | ||
125 | outbuf[i/2] = (inbuf[i]<<13)|(SFT(inbuf[i+1])<<21); | ||
126 | } | ||
127 | else | ||
128 | { | ||
129 | if (fmt->is_signed) | ||
130 | outbuf[i/2] = (inbuf[i+1]<<13)|(SE(inbuf[i])<<21); | ||
131 | else | ||
132 | outbuf[i/2] = (inbuf[i+1]<<13)|(SFT(inbuf[i])<<21); | ||
133 | } | ||
134 | } | ||
135 | *outbufsize = inbufsize >> 1; | ||
136 | } | ||
137 | else | ||
138 | { | ||
139 | for (i = 0; i < inbufsize; i++) { | ||
140 | if (fmt->is_signed) | ||
141 | outbuf[i] = SE(inbuf[i])<<21; | ||
142 | else | ||
143 | outbuf[i] = SFT(inbuf[i])<<21; | ||
144 | } | ||
145 | *outbufsize = inbufsize; | ||
146 | } | ||
147 | |||
148 | if (fmt->channels == 2) | ||
149 | *outbufsize >>= 1; | ||
150 | |||
151 | return CODEC_OK; | ||
152 | } | ||
153 | |||
154 | static const struct pcm_codec codec = { | ||
155 | set_format, | ||
156 | get_seek_pos, | ||
157 | decode, | ||
158 | }; | ||
159 | |||
160 | const struct pcm_codec *get_linear_pcm_codec(void) | ||
161 | { | ||
162 | return &codec; | ||
163 | } | ||
diff --git a/apps/codecs/libpcm/pcm_common.h b/apps/codecs/libpcm/pcm_common.h new file mode 100644 index 0000000000..757d0ad5d9 --- /dev/null +++ b/apps/codecs/libpcm/pcm_common.h | |||
@@ -0,0 +1,120 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2009 Yoshihisa Uchida | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef CODEC_LIBPCMS_PCM_COMMON_H | ||
22 | #define CODEC_LIBPCMS_PCM_COMMON_H | ||
23 | |||
24 | #include <sys/types.h> | ||
25 | #include <stdbool.h> | ||
26 | #include <inttypes.h> | ||
27 | |||
28 | /* | ||
29 | * PCM_CHUNK_SIZE has the size only of storing the sample at 1/50 seconds. | ||
30 | * But it might not be 1/50 seconds according to the format. | ||
31 | * Please confirm the source file of each format. | ||
32 | */ | ||
33 | #define PCM_CHUNK_SIZE (4096*2) | ||
34 | |||
35 | /* Macro that sign extends an unsigned byte */ | ||
36 | #define SE(x) ((int32_t)((int8_t)(x))) | ||
37 | |||
38 | /* Macro that shift to -0x80. (0 .. 127 to -128 .. -1, 128 .. 255 to 0 .. 127) */ | ||
39 | #define SFT(x) ((int32_t)x-0x80) | ||
40 | |||
41 | struct pcm_format { | ||
42 | /* | ||
43 | * RIFF: wFormatTag (in 'fmt ' chunk) | ||
44 | * AIFF: compressionType (in 'COMM' chunk) | ||
45 | */ | ||
46 | uint32_t formattag; | ||
47 | |||
48 | /* | ||
49 | * RIFF: wChannels (in 'fmt ' chunk) | ||
50 | * AIFF: numChannels (in 'COMM' chunk) | ||
51 | */ | ||
52 | uint16_t channels; | ||
53 | |||
54 | /* | ||
55 | * RIFF: dwSamplesPerSec (in 'fmt ' chunk) | ||
56 | * AIFF: sampleRate (in 'COMM' chunk) | ||
57 | */ | ||
58 | uint32_t samplespersec; | ||
59 | |||
60 | /* RIFF: dwAvgBytesPerSec (in 'fmt ' chunk) */ | ||
61 | uint32_t avgbytespersec; | ||
62 | |||
63 | /* | ||
64 | * RIFF: wBlockAlign (in 'fmt ' chunk) | ||
65 | * AIFF: blockSize (in 'SSND' chunk) | ||
66 | */ | ||
67 | uint16_t blockalign; | ||
68 | |||
69 | /* | ||
70 | * RIFF: wBitsPerSample (in 'fmt ' chunk) | ||
71 | * AIFF: sampleSize (in 'COMM' chunk) | ||
72 | */ | ||
73 | uint16_t bitspersample; | ||
74 | |||
75 | /* RIFF: wSize (in 'fmt ' chunk) */ | ||
76 | uint16_t size; | ||
77 | |||
78 | /* RIFF: dSamplesPerBlock (in 'fmt ' chunk) */ | ||
79 | uint16_t samplesperblock; | ||
80 | |||
81 | /* RIFF: wTotalSamples (in 'fact' chunk) */ | ||
82 | uint16_t totalsamples; | ||
83 | |||
84 | /* the following values are not RIFF/AIFF chunk values */ | ||
85 | |||
86 | /* bytes per sample */ | ||
87 | int bytespersample; | ||
88 | |||
89 | /* chunk size */ | ||
90 | long chunksize; | ||
91 | |||
92 | /* data size */ | ||
93 | uint32_t numbytes; | ||
94 | |||
95 | /* | ||
96 | * data endian | ||
97 | * true: little endian, false: big endian | ||
98 | */ | ||
99 | bool is_little_endian; | ||
100 | |||
101 | /* | ||
102 | * data signess | ||
103 | * true: signed, false: unsigned | ||
104 | */ | ||
105 | bool is_signed; | ||
106 | }; | ||
107 | |||
108 | struct pcm_codec { | ||
109 | bool (*set_format)(struct pcm_format *format, const unsigned char *fmtpos); | ||
110 | uint32_t (*get_seek_pos)(long seek_time); | ||
111 | int (*decode)(const uint8_t *inbuf, size_t inbufsize, | ||
112 | int32_t *outbuf, int *outbufsize); | ||
113 | }; | ||
114 | |||
115 | struct pcm_entry { | ||
116 | uint32_t format_tag; | ||
117 | const struct pcm_codec *(*get_codec)(void); | ||
118 | }; | ||
119 | |||
120 | #endif | ||
diff --git a/apps/codecs/libpcm/support_formats.h b/apps/codecs/libpcm/support_formats.h new file mode 100644 index 0000000000..9a1f4f764d --- /dev/null +++ b/apps/codecs/libpcm/support_formats.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2009 Yoshihisa Uchida | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef CODEC_LIBPCMS_SUPPORT_FORMATS_H | ||
22 | #define CODEC_LIBPCMS_SUPPORT_FORMATS_H | ||
23 | |||
24 | #include "pcm_common.h" | ||
25 | |||
26 | /* Linear PCM */ | ||
27 | const struct pcm_codec *get_linear_pcm_codec(void); | ||
28 | |||
29 | /* ITU-T G.711 A-law */ | ||
30 | const struct pcm_codec *get_itut_g711_alaw_codec(void); | ||
31 | |||
32 | /* ITU-T G.711 mu-law */ | ||
33 | const struct pcm_codec *get_itut_g711_mulaw_codec(void); | ||
34 | |||
35 | /* Intel DVI ADPCM */ | ||
36 | const struct pcm_codec *get_dvi_adpcm_codec(void); | ||
37 | #endif | ||
diff --git a/apps/codecs/wav.c b/apps/codecs/wav.c index b3efbc10ce..1f210a99bf 100644 --- a/apps/codecs/wav.c +++ b/apps/codecs/wav.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2005 Dave Chapman | 10 | * Copyright (C) 2005 Dave Chapman |
11 | * Copyright (C) 2009 Yoshihisa Uchida | ||
11 | * | 12 | * |
12 | * This program is free software; you can redistribute it and/or | 13 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 14 | * modify it under the terms of the GNU General Public License |
@@ -21,16 +22,11 @@ | |||
21 | 22 | ||
22 | #include "codeclib.h" | 23 | #include "codeclib.h" |
23 | #include "inttypes.h" | 24 | #include "inttypes.h" |
25 | #include "codecs/libpcm/support_formats.h" | ||
24 | 26 | ||
25 | CODEC_HEADER | 27 | CODEC_HEADER |
26 | 28 | ||
27 | /* Macro that sign extends an unsigned byte */ | 29 | /* WAVE (RIFF) codec: |
28 | #define SE(x) ((int32_t)((int8_t)(x))) | ||
29 | |||
30 | /* This codec support WAVE files with the following formats: | ||
31 | * - PCM, up to 32 bits, supporting 32 bits playback when useful. | ||
32 | * - ALAW and MULAW (16 bits compressed on 8 bits). | ||
33 | * - DVI_ADPCM (16 bits compressed on 3 or 4 bits). | ||
34 | * | 30 | * |
35 | * For a good documentation on WAVE files, see: | 31 | * For a good documentation on WAVE files, see: |
36 | * http://www.tsp.ece.mcgill.ca/MMSP/Documents/AudioFormats/WAVE/WAVE.html | 32 | * http://www.tsp.ece.mcgill.ca/MMSP/Documents/AudioFormats/WAVE/WAVE.html |
@@ -40,198 +36,74 @@ CODEC_HEADER | |||
40 | * For sample WAV files, see: | 36 | * For sample WAV files, see: |
41 | * http://www.tsp.ece.mcgill.ca/MMSP/Documents/AudioFormats/WAVE/Samples.html | 37 | * http://www.tsp.ece.mcgill.ca/MMSP/Documents/AudioFormats/WAVE/Samples.html |
42 | * | 38 | * |
43 | * The most common formats seem to be PCM, ADPCM, DVI_ADPCM, IEEE_FLOAT, | ||
44 | * ALAW and MULAW | ||
45 | */ | 39 | */ |
46 | 40 | ||
47 | /* These constants are from RFC 2361. */ | 41 | static int32_t samples[PCM_CHUNK_SIZE] IBSS_ATTR; |
42 | |||
43 | /* This codec support WAVE files with the following formats: */ | ||
48 | enum | 44 | enum |
49 | { | 45 | { |
50 | WAVE_FORMAT_UNKNOWN = 0x0000, /* Microsoft Unknown Wave Format */ | 46 | WAVE_FORMAT_UNKNOWN = 0x0000, /* Microsoft Unknown Wave Format */ |
51 | WAVE_FORMAT_PCM = 0x0001, /* Microsoft PCM Format */ | 47 | WAVE_FORMAT_PCM = 0x0001, /* Microsoft PCM Format */ |
52 | WAVE_FORMAT_ADPCM = 0x0002, /* Microsoft ADPCM Format */ | ||
53 | WAVE_FORMAT_IEEE_FLOAT = 0x0003, /* IEEE Float */ | ||
54 | WAVE_FORMAT_VSELP = 0x0004, /* Compaq Computer's VSELP */ | ||
55 | WAVE_FORMAT_IBM_CVSD = 0x0005, /* IBM CVSD */ | ||
56 | WAVE_FORMAT_ALAW = 0x0006, /* Microsoft ALAW */ | 48 | WAVE_FORMAT_ALAW = 0x0006, /* Microsoft ALAW */ |
57 | WAVE_FORMAT_MULAW = 0x0007, /* Microsoft MULAW */ | 49 | WAVE_FORMAT_MULAW = 0x0007, /* Microsoft MULAW */ |
58 | WAVE_FORMAT_OKI_ADPCM = 0x0010, /* OKI ADPCM */ | ||
59 | WAVE_FORMAT_DVI_ADPCM = 0x0011, /* Intel's DVI ADPCM */ | 50 | WAVE_FORMAT_DVI_ADPCM = 0x0011, /* Intel's DVI ADPCM */ |
60 | WAVE_FORMAT_MEDIASPACE_ADPCM = 0x0012, /* Videologic's MediaSpace ADPCM */ | ||
61 | WAVE_FORMAT_SIERRA_ADPCM = 0x0013, /* Sierra ADPCM */ | ||
62 | WAVE_FORMAT_G723_ADPCM = 0x0014, /* G.723 ADPCM */ | ||
63 | WAVE_FORMAT_DIGISTD = 0x0015, /* DSP Solutions' DIGISTD */ | ||
64 | WAVE_FORMAT_DIGIFIX = 0x0016, /* DSP Solutions' DIGIFIX */ | ||
65 | WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 0x0017, /* Dialogic OKI ADPCM */ | ||
66 | WAVE_FORMAT_MEDIAVISION_ADPCM = 0x0018, /* MediaVision ADPCM */ | ||
67 | WAVE_FORMAT_CU_CODEC = 0x0019, /* HP CU */ | ||
68 | WAVE_FORMAT_YAMAHA_ADPCM = 0x0020, /* Yamaha ADPCM */ | ||
69 | WAVE_FORMAT_SONARC = 0x0021, /* Speech Compression's Sonarc */ | ||
70 | WAVE_FORMAT_DSP_TRUESPEECH = 0x0022, /* DSP Group's True Speech */ | ||
71 | WAVE_FORMAT_ECHOSC1 = 0x0023, /* Echo Speech's EchoSC1 */ | ||
72 | WAVE_FORMAT_AUDIOFILE_AF36 = 0x0024, /* Audiofile AF36 */ | ||
73 | WAVE_FORMAT_APTX = 0x0025, /* APTX */ | ||
74 | WAVE_FORMAT_DOLBY_AC2 = 0x0030, /* Dolby AC2 */ | ||
75 | WAVE_FORMAT_GSM610 = 0x0031, /* GSM610 */ | ||
76 | WAVE_FORMAT_MSNAUDIO = 0x0032, /* MSNAudio */ | ||
77 | WAVE_FORMAT_ANTEX_ADPCME = 0x0033, /* Antex ADPCME */ | ||
78 | |||
79 | WAVE_FORMAT_MPEG = 0x0050, /* MPEG */ | ||
80 | WAVE_FORMAT_MPEGLAYER3 = 0x0055, /* MPEG layer 3 */ | ||
81 | WAVE_FORMAT_LUCENT_G723 = 0x0059, /* Lucent G.723 */ | ||
82 | WAVE_FORMAT_G726_ADPCM = 0x0064, /* G.726 ADPCM */ | ||
83 | WAVE_FORMAT_G722_ADPCM = 0x0065, /* G.722 ADPCM */ | ||
84 | |||
85 | IBM_FORMAT_MULAW = 0x0101, /* same as WAVE_FORMAT_MULAW */ | 51 | IBM_FORMAT_MULAW = 0x0101, /* same as WAVE_FORMAT_MULAW */ |
86 | IBM_FORMAT_ALAW = 0x0102, /* same as WAVE_FORMAT_ALAW */ | 52 | IBM_FORMAT_ALAW = 0x0102, /* same as WAVE_FORMAT_ALAW */ |
87 | IBM_FORMAT_ADPCM = 0x0103, | ||
88 | |||
89 | WAVE_FORMAT_CREATIVE_ADPCM = 0x0200, | ||
90 | |||
91 | WAVE_FORMAT_EXTENSIBLE = 0xFFFE | 53 | WAVE_FORMAT_EXTENSIBLE = 0xFFFE |
92 | }; | 54 | }; |
93 | 55 | ||
94 | /* Maximum number of bytes to process in one iteration */ | 56 | const struct pcm_entry wave_codecs[] = { |
95 | /* for 44.1kHz stereo 16bits, this represents 0.023s ~= 1/50s */ | 57 | { WAVE_FORMAT_UNKNOWN, 0 }, |
96 | #define WAV_CHUNK_SIZE (1024*2) | 58 | { WAVE_FORMAT_PCM, get_linear_pcm_codec }, |
97 | 59 | { WAVE_FORMAT_ALAW, get_itut_g711_alaw_codec }, | |
98 | static const int16_t alaw2linear16[256] ICONST_ATTR = { | 60 | { WAVE_FORMAT_MULAW, get_itut_g711_mulaw_codec }, |
99 | -5504, -5248, -6016, -5760, -4480, -4224, -4992, | 61 | { WAVE_FORMAT_DVI_ADPCM, get_dvi_adpcm_codec }, |
100 | -4736, -7552, -7296, -8064, -7808, -6528, -6272, | 62 | { IBM_FORMAT_MULAW, get_itut_g711_mulaw_codec }, |
101 | -7040, -6784, -2752, -2624, -3008, -2880, -2240, | 63 | { IBM_FORMAT_ALAW, get_itut_g711_alaw_codec }, |
102 | -2112, -2496, -2368, -3776, -3648, -4032, -3904, | ||
103 | -3264, -3136, -3520, -3392, -22016, -20992, -24064, | ||
104 | -23040, -17920, -16896, -19968, -18944, -30208, -29184, | ||
105 | -32256, -31232, -26112, -25088, -28160, -27136, -11008, | ||
106 | -10496, -12032, -11520, -8960, -8448, -9984, -9472, | ||
107 | -15104, -14592, -16128, -15616, -13056, -12544, -14080, | ||
108 | -13568, -344, -328, -376, -360, -280, -264, | ||
109 | -312, -296, -472, -456, -504, -488, -408, | ||
110 | -392, -440, -424, -88, -72, -120, -104, | ||
111 | -24, -8, -56, -40, -216, -200, -248, | ||
112 | -232, -152, -136, -184, -168, -1376, -1312, | ||
113 | -1504, -1440, -1120, -1056, -1248, -1184, -1888, | ||
114 | -1824, -2016, -1952, -1632, -1568, -1760, -1696, | ||
115 | -688, -656, -752, -720, -560, -528, -624, | ||
116 | -592, -944, -912, -1008, -976, -816, -784, | ||
117 | -880, -848, 5504, 5248, 6016, 5760, 4480, | ||
118 | 4224, 4992, 4736, 7552, 7296, 8064, 7808, | ||
119 | 6528, 6272, 7040, 6784, 2752, 2624, 3008, | ||
120 | 2880, 2240, 2112, 2496, 2368, 3776, 3648, | ||
121 | 4032, 3904, 3264, 3136, 3520, 3392, 22016, | ||
122 | 20992, 24064, 23040, 17920, 16896, 19968, 18944, | ||
123 | 30208, 29184, 32256, 31232, 26112, 25088, 28160, | ||
124 | 27136, 11008, 10496, 12032, 11520, 8960, 8448, | ||
125 | 9984, 9472, 15104, 14592, 16128, 15616, 13056, | ||
126 | 12544, 14080, 13568, 344, 328, 376, 360, | ||
127 | 280, 264, 312, 296, 472, 456, 504, | ||
128 | 488, 408, 392, 440, 424, 88, 72, | ||
129 | 120, 104, 24, 8, 56, 40, 216, | ||
130 | 200, 248, 232, 152, 136, 184, 168, | ||
131 | 1376, 1312, 1504, 1440, 1120, 1056, 1248, | ||
132 | 1184, 1888, 1824, 2016, 1952, 1632, 1568, | ||
133 | 1760, 1696, 688, 656, 752, 720, 560, | ||
134 | 528, 624, 592, 944, 912, 1008, 976, | ||
135 | 816, 784, 880, 848 | ||
136 | }; | 64 | }; |
137 | 65 | ||
138 | static const int16_t ulaw2linear16[256] ICONST_ATTR = { | 66 | #define NUM_FORMATS 7 |
139 | -32124, -31100, -30076, -29052, -28028, -27004, -25980, | 67 | |
140 | -24956, -23932, -22908, -21884, -20860, -19836, -18812, | 68 | static const struct pcm_codec *get_wave_codec(uint32_t formattag) |
141 | -17788, -16764, -15996, -15484, -14972, -14460, -13948, | 69 | { |
142 | -13436, -12924, -12412, -11900, -11388, -10876, -10364, | 70 | int i; |
143 | -9852, -9340, -8828, -8316, -7932, -7676, -7420, | 71 | |
144 | -7164, -6908, -6652, -6396, -6140, -5884, -5628, | 72 | for (i = 0; i < NUM_FORMATS; i++) |
145 | -5372, -5116, -4860, -4604, -4348, -4092, -3900, | 73 | { |
146 | -3772, -3644, -3516, -3388, -3260, -3132, -3004, | 74 | if (wave_codecs[i].format_tag == formattag) |
147 | -2876, -2748, -2620, -2492, -2364, -2236, -2108, | 75 | { |
148 | -1980, -1884, -1820, -1756, -1692, -1628, -1564, | 76 | if (wave_codecs[i].get_codec) |
149 | -1500, -1436, -1372, -1308, -1244, -1180, -1116, | 77 | return wave_codecs[i].get_codec(); |
150 | -1052, -988, -924, -876, -844, -812, -780, | 78 | return 0; |
151 | -748, -716, -684, -652, -620, -588, -556, | 79 | } |
152 | -524, -492, -460, -428, -396, -372, -356, | 80 | } |
153 | -340, -324, -308, -292, -276, -260, -244, | 81 | return 0; |
154 | -228, -212, -196, -180, -164, -148, -132, | 82 | } |
155 | -120, -112, -104, -96, -88, -80, -72, | ||
156 | -64, -56, -48, -40, -32, -24, -16, | ||
157 | -8, 0, 32124, 31100, 30076, 29052, 28028, | ||
158 | 27004, 25980, 24956, 23932, 22908, 21884, 20860, | ||
159 | 19836, 18812, 17788, 16764, 15996, 15484, 14972, | ||
160 | 14460, 13948, 13436, 12924, 12412, 11900, 11388, | ||
161 | 10876, 10364, 9852, 9340, 8828, 8316, 7932, | ||
162 | 7676, 7420, 7164, 6908, 6652, 6396, 6140, | ||
163 | 5884, 5628, 5372, 5116, 4860, 4604, 4348, | ||
164 | 4092, 3900, 3772, 3644, 3516, 3388, 3260, | ||
165 | 3132, 3004, 2876, 2748, 2620, 2492, 2364, | ||
166 | 2236, 2108, 1980, 1884, 1820, 1756, 1692, | ||
167 | 1628, 1564, 1500, 1436, 1372, 1308, 1244, | ||
168 | 1180, 1116, 1052, 988, 924, 876, 844, | ||
169 | 812, 780, 748, 716, 684, 652, 620, | ||
170 | 588, 556, 524, 492, 460, 428, 396, | ||
171 | 372, 356, 340, 324, 308, 292, 276, | ||
172 | 260, 244, 228, 212, 196, 180, 164, | ||
173 | 148, 132, 120, 112, 104, 96, 88, | ||
174 | 80, 72, 64, 56, 48, 40, 32, | ||
175 | 24, 16, 8, 0 | ||
176 | }; | ||
177 | 83 | ||
178 | static const uint16_t dvi_adpcm_steptab[89] ICONST_ATTR = { | ||
179 | 7, 8, 9, 10, 11, 12, 13, 14, | ||
180 | 16, 17, 19, 21, 23, 25, 28, 31, | ||
181 | 34, 37, 41, 45, 50, 55, 60, 66, | ||
182 | 73, 80, 88, 97, 107, 118, 130, 143, | ||
183 | 157, 173, 190, 209, 230, 253, 279, 307, | ||
184 | 337, 371, 408, 449, 494, 544, 598, 658, | ||
185 | 724, 796, 876, 963, 1060, 1166, 1282, 1411, | ||
186 | 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, | ||
187 | 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, | ||
188 | 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, | ||
189 | 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, | ||
190 | 32767 }; | ||
191 | |||
192 | static const int dvi_adpcm_indextab4[8] ICONST_ATTR = { | ||
193 | -1, -1, -1, -1, 2, 4, 6, 8 }; | ||
194 | |||
195 | static const int dvi_adpcm_indextab3[4] ICONST_ATTR = { -1, -1, 1, 2 }; | ||
196 | |||
197 | static int32_t samples[WAV_CHUNK_SIZE] IBSS_ATTR; | ||
198 | |||
199 | static enum codec_status | ||
200 | decode_dvi_adpcm(struct codec_api *ci, | ||
201 | const uint8_t *buf, | ||
202 | int n, | ||
203 | uint16_t channels, uint16_t bitspersample, | ||
204 | int32_t *pcmout, | ||
205 | size_t *pcmoutsize); | ||
206 | 84 | ||
207 | /* this is the codec entry point */ | 85 | /* this is the codec entry point */ |
208 | enum codec_status codec_main(void) | 86 | enum codec_status codec_main(void) |
209 | { | 87 | { |
210 | uint32_t numbytes, bytesdone; | 88 | int status = CODEC_OK; |
211 | uint32_t totalsamples = 0; | 89 | struct pcm_format format; |
212 | uint16_t channels = 0; | 90 | uint32_t bytesdone, decodedbytes; |
213 | uint16_t samplesperblock = 0; | ||
214 | int bytespersample = 0; | ||
215 | uint16_t bitspersample; | ||
216 | uint32_t i; | 91 | uint32_t i; |
217 | size_t n; | 92 | size_t n; |
218 | int bufcount; | 93 | int bufcount; |
219 | int endofstream; | 94 | int endofstream; |
220 | unsigned char *buf; | 95 | unsigned char *buf; |
221 | uint8_t *wavbuf; | 96 | uint8_t *wavbuf; |
222 | long chunksize; | ||
223 | uint16_t formattag = 0; | ||
224 | uint16_t blockalign = 0; | ||
225 | uint32_t avgbytespersec = 0; | ||
226 | off_t firstblockposn; /* position of the first block in file */ | 97 | off_t firstblockposn; /* position of the first block in file */ |
227 | 98 | const struct pcm_codec *codec; | |
228 | 99 | ||
229 | /* Generic codec initialisation */ | 100 | /* Generic codec initialisation */ |
230 | ci->configure(DSP_SET_SAMPLE_DEPTH, 28); | 101 | ci->configure(DSP_SET_SAMPLE_DEPTH, 28); |
231 | 102 | ||
232 | next_track: | 103 | next_track: |
233 | if (codec_init()) { | 104 | if (codec_init()) { |
234 | i = CODEC_ERROR; | 105 | DEBUGF("codec_init() error\n"); |
106 | status = CODEC_ERROR; | ||
235 | goto exit; | 107 | goto exit; |
236 | } | 108 | } |
237 | 109 | ||
@@ -246,11 +118,12 @@ next_track: | |||
246 | /* get RIFF chunk header */ | 118 | /* get RIFF chunk header */ |
247 | buf = ci->request_buffer(&n, 12); | 119 | buf = ci->request_buffer(&n, 12); |
248 | if (n < 12) { | 120 | if (n < 12) { |
249 | i = CODEC_ERROR; | 121 | DEBUGF("request_buffer error\n"); |
122 | status = CODEC_ERROR; | ||
250 | goto done; | 123 | goto done; |
251 | } | 124 | } |
252 | if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) { | 125 | if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) { |
253 | i = CODEC_ERROR; | 126 | status = CODEC_ERROR; |
254 | goto done; | 127 | goto done; |
255 | } | 128 | } |
256 | 129 | ||
@@ -258,17 +131,21 @@ next_track: | |||
258 | ci->advance_buffer(12); | 131 | ci->advance_buffer(12); |
259 | 132 | ||
260 | firstblockposn = 12; | 133 | firstblockposn = 12; |
261 | bitspersample = 0; | 134 | ci->memset(&format, 0, sizeof(struct pcm_format)); |
262 | numbytes = 0; | 135 | format.is_signed = true; |
263 | totalsamples = 0; | 136 | format.is_little_endian = true; |
137 | |||
138 | decodedbytes = 0; | ||
139 | codec = 0; | ||
264 | 140 | ||
265 | /* iterate over WAVE chunks until the 'data' chunk, which should be after the 'fmt ' chunk */ | 141 | /* iterate over WAVE chunks until the 'data' chunk, which should be after the 'fmt ' chunk */ |
266 | while (true) { | 142 | while (true) { |
267 | /* get WAVE chunk header */ | 143 | /* get WAVE chunk header */ |
268 | buf = ci->request_buffer(&n, 1024); | 144 | buf = ci->request_buffer(&n, 1024); |
269 | if (n < 8) { | 145 | if (n < 8) { |
146 | DEBUGF("data chunk request_buffer error\n"); | ||
270 | /* no more chunks, 'data' chunk must not have been found */ | 147 | /* no more chunks, 'data' chunk must not have been found */ |
271 | i = CODEC_ERROR; | 148 | status = CODEC_ERROR; |
272 | goto done; | 149 | goto done; |
273 | } | 150 | } |
274 | 151 | ||
@@ -278,54 +155,70 @@ next_track: | |||
278 | if (i < 16) { | 155 | if (i < 16) { |
279 | DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%lu < 16\n", | 156 | DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%lu < 16\n", |
280 | (unsigned long)i); | 157 | (unsigned long)i); |
281 | i = CODEC_ERROR; | 158 | status = CODEC_ERROR; |
282 | goto done; | 159 | goto done; |
283 | } | 160 | } |
284 | /* wFormatTag */ | 161 | /* wFormatTag */ |
285 | formattag=buf[8]|(buf[9]<<8); | 162 | format.formattag=buf[8]|(buf[9]<<8); |
286 | /* wChannels */ | 163 | /* wChannels */ |
287 | channels=buf[10]|(buf[11]<<8); | 164 | format.channels=buf[10]|(buf[11]<<8); |
288 | /* skipping dwSamplesPerSec */ | 165 | /* skipping dwSamplesPerSec */ |
289 | /* dwAvgBytesPerSec */ | 166 | /* dwAvgBytesPerSec */ |
290 | avgbytespersec = buf[16]|(buf[17]<<8)|(buf[18]<<16)|(buf[19]<<24); | 167 | format.avgbytespersec = buf[16]|(buf[17]<<8)|(buf[18]<<16)|(buf[19]<<24); |
291 | /* wBlockAlign */ | 168 | /* wBlockAlign */ |
292 | blockalign=buf[20]|(buf[21]<<8); | 169 | format.blockalign=buf[20]|(buf[21]<<8); |
293 | /* wBitsPerSample */ | 170 | /* wBitsPerSample */ |
294 | bitspersample=buf[22]|(buf[23]<<8); | 171 | format.bitspersample=buf[22]|(buf[23]<<8); |
295 | if (formattag != WAVE_FORMAT_PCM) { | 172 | if (format.formattag != WAVE_FORMAT_PCM) { |
296 | uint16_t size; | ||
297 | if (i < 18) { | 173 | if (i < 18) { |
298 | /* this is not a fatal error with some formats, | 174 | /* this is not a fatal error with some formats, |
299 | * we'll see later if we can't decode it */ | 175 | * we'll see later if we can't decode it */ |
300 | DEBUGF("CODEC_WARNING: non-PCM WAVE (formattag=0x%x) " | 176 | DEBUGF("CODEC_WARNING: non-PCM WAVE (formattag=0x%x) " |
301 | "doesn't have ext. fmt descr (chunksize=%ld<18).\n", | 177 | "doesn't have ext. fmt descr (chunksize=%ld<18).\n", |
302 | formattag, (long)i); | 178 | format.formattag, (long)i); |
303 | } | 179 | } |
304 | size = buf[24]|(buf[25]<<8); | 180 | else |
305 | if (formattag == WAVE_FORMAT_DVI_ADPCM) { | 181 | { |
306 | if (size < 2) { | 182 | format.size = buf[24]|(buf[25]<<8); |
307 | DEBUGF("CODEC_ERROR: dvi_adpcm is missing " | 183 | if (format.formattag != WAVE_FORMAT_EXTENSIBLE) |
308 | "SamplesPerBlock value\n"); | 184 | format.samplesperblock = buf[26]|(buf[27]<<8); |
309 | i = CODEC_ERROR; | 185 | else { |
310 | goto done; | 186 | if (format.size < 22) { |
311 | } | 187 | DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " |
312 | samplesperblock = buf[26]|(buf[27]<<8); | 188 | "missing extension\n"); |
313 | } else if (formattag == WAVE_FORMAT_EXTENSIBLE) { | 189 | status = CODEC_ERROR; |
314 | if (size < 22) { | 190 | goto done; |
315 | DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " | 191 | } |
316 | "missing extension\n"); | 192 | /* wValidBitsPerSample */ |
317 | i = CODEC_ERROR; | 193 | format.bitspersample = buf[26]|(buf[27]<<8); |
318 | goto done; | 194 | /* skipping dwChannelMask (4bytes) */ |
195 | /* SubFormat (only get the first two bytes) */ | ||
196 | format.formattag = buf[32]|(buf[33]<<8); | ||
319 | } | 197 | } |
320 | /* wValidBitsPerSample */ | ||
321 | bitspersample = buf[26]|(buf[27]<<8); | ||
322 | /* skipping dwChannelMask (4bytes) */ | ||
323 | /* SubFormat (only get the first two bytes) */ | ||
324 | formattag = buf[32]|(buf[33]<<8); | ||
325 | } | 198 | } |
326 | } | 199 | } |
200 | |||
201 | /* get codec */ | ||
202 | codec = get_wave_codec(format.formattag); | ||
203 | if (!codec) | ||
204 | { | ||
205 | DEBUGF("CODEC_ERROR: unsupport wave format %x\n", format.formattag); | ||
206 | status = CODEC_ERROR; | ||
207 | goto done; | ||
208 | } | ||
209 | |||
210 | /* riff 8bit linear pcm is unsigned */ | ||
211 | if (format.formattag == WAVE_FORMAT_PCM && format.bitspersample == 8) | ||
212 | format.is_signed = false; | ||
213 | |||
214 | /* set format, parse codec specific tag, check format, and calculate chunk size */ | ||
215 | if (!codec->set_format(&format, buf)) | ||
216 | { | ||
217 | status = CODEC_ERROR; | ||
218 | goto done; | ||
219 | } | ||
327 | } else if (memcmp(buf, "data", 4) == 0) { | 220 | } else if (memcmp(buf, "data", 4) == 0) { |
328 | numbytes = i; | 221 | format.numbytes = i; |
329 | /* advance to start of data */ | 222 | /* advance to start of data */ |
330 | ci->advance_buffer(8); | 223 | ci->advance_buffer(8); |
331 | firstblockposn += 8; | 224 | firstblockposn += 8; |
@@ -333,7 +226,8 @@ next_track: | |||
333 | } else if (memcmp(buf, "fact", 4) == 0) { | 226 | } else if (memcmp(buf, "fact", 4) == 0) { |
334 | /* dwSampleLength */ | 227 | /* dwSampleLength */ |
335 | if (i >= 4) | 228 | if (i >= 4) |
336 | totalsamples = (buf[8]|(buf[9]<<8)|(buf[10]<<16)|(buf[11]<<24)); | 229 | format.totalsamples = |
230 | (buf[8]|(buf[9]<<8)|(buf[10]<<16)|(buf[11]<<24)); | ||
337 | } else { | 231 | } else { |
338 | DEBUGF("unknown WAVE chunk: '%c%c%c%c', size=%lu\n", | 232 | DEBUGF("unknown WAVE chunk: '%c%c%c%c', size=%lu\n", |
339 | buf[0], buf[1], buf[2], buf[3], (unsigned long)i); | 233 | buf[0], buf[1], buf[2], buf[3], (unsigned long)i); |
@@ -346,71 +240,40 @@ next_track: | |||
346 | firstblockposn += i + 8; | 240 | firstblockposn += i + 8; |
347 | } | 241 | } |
348 | 242 | ||
349 | if (channels == 0) { | 243 | if (!codec) |
350 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); | 244 | { |
351 | i = CODEC_ERROR; | 245 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n"); |
246 | status = CODEC_ERROR; | ||
352 | goto done; | 247 | goto done; |
353 | } | 248 | } |
354 | if (numbytes == 0) { | 249 | |
355 | DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); | 250 | /* common format check */ |
356 | i = CODEC_ERROR; | 251 | if (format.channels == 0) { |
357 | goto done; | 252 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); |
358 | } | 253 | status = CODEC_ERROR; |
359 | if (formattag != WAVE_FORMAT_PCM && totalsamples == 0) { | ||
360 | /* This is non-fatal for some formats */ | ||
361 | DEBUGF("CODEC_WARNING: non-PCM WAVE doesn't have a 'fact' chunk\n"); | ||
362 | } | ||
363 | if (formattag == WAVE_FORMAT_ALAW || formattag == WAVE_FORMAT_MULAW || | ||
364 | formattag == IBM_FORMAT_ALAW || formattag == IBM_FORMAT_MULAW) { | ||
365 | if (bitspersample != 8) { | ||
366 | DEBUGF("CODEC_ERROR: alaw and mulaw must have 8 bitspersample\n"); | ||
367 | i = CODEC_ERROR; | ||
368 | goto done; | ||
369 | } | ||
370 | bytespersample = channels; | ||
371 | } | ||
372 | if (formattag == WAVE_FORMAT_DVI_ADPCM | ||
373 | && bitspersample != 4 && bitspersample != 3) { | ||
374 | DEBUGF("CODEC_ERROR: dvi_adpcm must have 3 or 4 bitspersample\n"); | ||
375 | i = CODEC_ERROR; | ||
376 | goto done; | 254 | goto done; |
377 | } | 255 | } |
378 | if (formattag == WAVE_FORMAT_PCM && bitspersample > 32) { | 256 | if (format.numbytes == 0) { |
379 | DEBUGF("CODEC_ERROR: pcm with more than 32 bitspersample " | 257 | DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); |
380 | "is unsupported\n"); | 258 | status = CODEC_ERROR; |
381 | i = CODEC_ERROR; | ||
382 | goto done; | 259 | goto done; |
383 | } | 260 | } |
384 | 261 | ||
385 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 262 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
386 | if (channels == 2) { | 263 | if (format.channels == 2) { |
387 | ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); | 264 | ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); |
388 | } else if (channels == 1) { | 265 | } else if (format.channels == 1) { |
389 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | 266 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); |
390 | } else { | 267 | } else { |
391 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); | 268 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); |
392 | i = CODEC_ERROR; | 269 | status = CODEC_ERROR; |
393 | goto done; | 270 | goto done; |
394 | } | 271 | } |
395 | 272 | ||
396 | if (totalsamples == 0) { | ||
397 | if (formattag == WAVE_FORMAT_PCM || | ||
398 | formattag == WAVE_FORMAT_ALAW || formattag == WAVE_FORMAT_MULAW || | ||
399 | formattag == IBM_FORMAT_ALAW || formattag == IBM_FORMAT_MULAW) { | ||
400 | /* for PCM and derived formats only */ | ||
401 | bytespersample = (((bitspersample - 1)/8 + 1)*channels); | ||
402 | totalsamples = numbytes/bytespersample; | ||
403 | } else { | ||
404 | DEBUGF("CODEC_ERROR: cannot compute totalsamples\n"); | ||
405 | i = CODEC_ERROR; | ||
406 | goto done; | ||
407 | } | ||
408 | } | ||
409 | |||
410 | /* make sure we're at the correct offset */ | 273 | /* make sure we're at the correct offset */ |
411 | if (bytesdone > (uint32_t) firstblockposn) { | 274 | if (bytesdone > (uint32_t) firstblockposn) { |
412 | /* Round down to previous block */ | 275 | /* Round down to previous block */ |
413 | uint32_t offset = bytesdone - bytesdone % blockalign; | 276 | uint32_t offset = bytesdone - bytesdone % format.blockalign; |
414 | 277 | ||
415 | ci->advance_buffer(offset-firstblockposn); | 278 | ci->advance_buffer(offset-firstblockposn); |
416 | bytesdone = offset - firstblockposn; | 279 | bytesdone = offset - firstblockposn; |
@@ -421,18 +284,6 @@ next_track: | |||
421 | 284 | ||
422 | /* The main decoder loop */ | 285 | /* The main decoder loop */ |
423 | endofstream = 0; | 286 | endofstream = 0; |
424 | /* chunksize is computed so that one chunk is about 1/50s. | ||
425 | * this make 4096 for 44.1kHz 16bits stereo. | ||
426 | * It also has to be a multiple of blockalign */ | ||
427 | chunksize = (1 + avgbytespersec / (50*blockalign))*blockalign; | ||
428 | /* check that the output buffer is big enough (convert to samplespersec, | ||
429 | then round to the blockalign multiple below) */ | ||
430 | if (((uint64_t)chunksize*ci->id3->frequency*channels*2) | ||
431 | /(uint64_t)avgbytespersec >= WAV_CHUNK_SIZE) { | ||
432 | chunksize = ((uint64_t)WAV_CHUNK_SIZE*avgbytespersec | ||
433 | /((uint64_t)ci->id3->frequency*channels*2 | ||
434 | *blockalign))*blockalign; | ||
435 | } | ||
436 | 287 | ||
437 | while (!endofstream) { | 288 | while (!endofstream) { |
438 | ci->yield(); | 289 | ci->yield(); |
@@ -441,286 +292,47 @@ next_track: | |||
441 | } | 292 | } |
442 | 293 | ||
443 | if (ci->seek_time) { | 294 | if (ci->seek_time) { |
444 | uint32_t newpos; | 295 | uint32_t newpos = codec->get_seek_pos(ci->seek_time); |
445 | 296 | ||
446 | /* use avgbytespersec to round to the closest blockalign multiple, | 297 | if (newpos > format.numbytes) |
447 | add firstblockposn. 64-bit casts to avoid overflows. */ | ||
448 | newpos = (((uint64_t)avgbytespersec*(ci->seek_time - 1)) | ||
449 | / (1000LL*blockalign))*blockalign; | ||
450 | if (newpos > numbytes) | ||
451 | break; | 298 | break; |
452 | if (ci->seek_buffer(firstblockposn + newpos)) | 299 | if (ci->seek_buffer(firstblockposn + newpos)) |
300 | { | ||
453 | bytesdone = newpos; | 301 | bytesdone = newpos; |
302 | } | ||
454 | ci->seek_complete(); | 303 | ci->seek_complete(); |
455 | } | 304 | } |
456 | wavbuf = (uint8_t *)ci->request_buffer(&n, chunksize); | ||
457 | 305 | ||
306 | wavbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); | ||
458 | if (n == 0) | 307 | if (n == 0) |
459 | break; /* End of stream */ | 308 | break; /* End of stream */ |
460 | 309 | if (bytesdone + n > format.numbytes) { | |
461 | if (bytesdone + n > numbytes) { | 310 | n = format.numbytes - bytesdone; |
462 | n = numbytes - bytesdone; | ||
463 | endofstream = 1; | 311 | endofstream = 1; |
464 | } | 312 | } |
465 | 313 | ||
466 | if (formattag == WAVE_FORMAT_PCM) { | 314 | status = codec->decode(wavbuf, n, samples, &bufcount); |
467 | if (bitspersample > 24) { | 315 | if (status == CODEC_ERROR) |
468 | for (i = 0; i < n; i += 4) { | 316 | { |
469 | samples[i/4] = (wavbuf[i] >> 3)| | 317 | DEBUGF("codec error\n"); |
470 | (wavbuf[i + 1]<<5)|(wavbuf[i + 2]<<13)| | ||
471 | (SE(wavbuf[i + 3])<<21); | ||
472 | } | ||
473 | bufcount = n >> 2; | ||
474 | } else if (bitspersample > 16) { | ||
475 | for (i = 0; i < n; i += 3) { | ||
476 | samples[i/3] = (wavbuf[i]<<5)| | ||
477 | (wavbuf[i + 1]<<13)|(SE(wavbuf[i + 2])<<21); | ||
478 | } | ||
479 | bufcount = n/3; | ||
480 | } else if (bitspersample > 8) { | ||
481 | for (i = 0; i < n; i += 2) { | ||
482 | samples[i/2] = (wavbuf[i]<<13)|(SE(wavbuf[i + 1])<<21); | ||
483 | } | ||
484 | bufcount = n >> 1; | ||
485 | } else { | ||
486 | for (i = 0; i < n; i++) { | ||
487 | samples[i] = (wavbuf[i] - 0x80)<<21; | ||
488 | } | ||
489 | bufcount = n; | ||
490 | } | ||
491 | |||
492 | if (channels == 2) | ||
493 | bufcount >>= 1; | ||
494 | } else if (formattag == WAVE_FORMAT_ALAW | ||
495 | || formattag == IBM_FORMAT_ALAW) { | ||
496 | for (i = 0; i < n; i++) | ||
497 | samples[i] = alaw2linear16[wavbuf[i]] << 13; | ||
498 | |||
499 | bufcount = (channels == 2) ? (n >> 1) : n; | ||
500 | } else if (formattag == WAVE_FORMAT_MULAW | ||
501 | || formattag == IBM_FORMAT_MULAW) { | ||
502 | for (i = 0; i < n; i++) | ||
503 | samples[i] = ulaw2linear16[wavbuf[i]] << 13; | ||
504 | |||
505 | bufcount = (channels == 2) ? (n >> 1) : n; | ||
506 | } | ||
507 | else if (formattag == WAVE_FORMAT_DVI_ADPCM) { | ||
508 | unsigned int nblocks = chunksize/blockalign; | ||
509 | |||
510 | for (i = 0; i < nblocks; i++) { | ||
511 | size_t decodedsize = samplesperblock*channels; | ||
512 | if (decode_dvi_adpcm(ci, wavbuf + i*blockalign, | ||
513 | blockalign, channels, bitspersample, | ||
514 | samples + i*samplesperblock*channels, | ||
515 | &decodedsize) != CODEC_OK) { | ||
516 | i = CODEC_ERROR; | ||
517 | goto done; | ||
518 | } | ||
519 | } | ||
520 | bufcount = nblocks*samplesperblock; | ||
521 | } else { | ||
522 | DEBUGF("CODEC_ERROR: unsupported format %x\n", formattag); | ||
523 | i = CODEC_ERROR; | ||
524 | goto done; | 318 | goto done; |
525 | } | 319 | } |
526 | 320 | ||
527 | ci->pcmbuf_insert(samples, NULL, bufcount); | 321 | ci->pcmbuf_insert(samples, NULL, bufcount); |
528 | |||
529 | ci->advance_buffer(n); | 322 | ci->advance_buffer(n); |
530 | bytesdone += n; | 323 | bytesdone += n; |
531 | if (bytesdone >= numbytes) | 324 | decodedbytes += bufcount; |
325 | |||
326 | if (bytesdone >= format.numbytes) | ||
532 | endofstream = 1; | 327 | endofstream = 1; |
533 | ci->set_elapsed(bytesdone*1000LL/avgbytespersec); | 328 | ci->set_elapsed(decodedbytes*1000LL/ci->id3->frequency); |
534 | } | 329 | } |
535 | i = CODEC_OK; | 330 | status = CODEC_OK; |
536 | 331 | ||
537 | done: | 332 | done: |
538 | if (ci->request_next_track()) | 333 | if (ci->request_next_track()) |
539 | goto next_track; | 334 | goto next_track; |
540 | 335 | ||
541 | exit: | 336 | exit: |
542 | return i; | 337 | return status; |
543 | } | 338 | } |
544 | |||
545 | static enum codec_status | ||
546 | decode_dvi_adpcm(struct codec_api *ci, | ||
547 | const uint8_t *buf, | ||
548 | int n, | ||
549 | uint16_t channels, uint16_t bitspersample, | ||
550 | int32_t *pcmout, | ||
551 | size_t *pcmoutsize) | ||
552 | { | ||
553 | size_t nsamples = 0; | ||
554 | int sample[2]; | ||
555 | int samplecode[32][2]; | ||
556 | int i; | ||
557 | int stepindex[2]; | ||
558 | int c; | ||
559 | int diff; | ||
560 | int step; | ||
561 | int codem; | ||
562 | int code; | ||
563 | |||
564 | (void)ci; | ||
565 | if (bitspersample != 4 && bitspersample != 3) { | ||
566 | DEBUGF("decode_dvi_adpcm: wrong bitspersample\n"); | ||
567 | return CODEC_ERROR; | ||
568 | } | ||
569 | |||
570 | /* decode block header */ | ||
571 | for (c = 0; c < channels && n >= 4; c++) { | ||
572 | /* decode + push first sample */ | ||
573 | sample[c] = (short)(buf[0]|(buf[1]<<8));/* need cast for sign-extend */ | ||
574 | pcmout[c] = sample[c] << 13; | ||
575 | nsamples++; | ||
576 | stepindex[c] = buf[2]; | ||
577 | /* check for step table index overflow */ | ||
578 | if (stepindex[c] > 88) { | ||
579 | DEBUGF("decode_dvi_adpcm: stepindex[%d]=%d>88\n",c,stepindex[c]); | ||
580 | return CODEC_ERROR; | ||
581 | } | ||
582 | |||
583 | buf += 4; | ||
584 | n -= 4; | ||
585 | } | ||
586 | if (bitspersample == 4) { | ||
587 | while (n>= channels*4 && (nsamples + 8*channels) <= *pcmoutsize) { | ||
588 | for (c = 0; c < channels; c++) { | ||
589 | samplecode[0][c] = buf[0]&0xf; | ||
590 | samplecode[1][c] = buf[0]>>4; | ||
591 | samplecode[2][c] = buf[1]&0xf; | ||
592 | samplecode[3][c] = buf[1]>>4; | ||
593 | samplecode[4][c] = buf[2]&0xf; | ||
594 | samplecode[5][c] = buf[2]>>4; | ||
595 | samplecode[6][c] = buf[3]&0xf; | ||
596 | samplecode[7][c] = buf[3]>>4; | ||
597 | buf += 4; | ||
598 | n -= 4; | ||
599 | } | ||
600 | for (i = 0; i < 8; i++) { | ||
601 | for (c = 0; c < channels; c++) { | ||
602 | step = dvi_adpcm_steptab[stepindex[c]]; | ||
603 | codem = samplecode[i][c]; | ||
604 | code = codem & 0x07; | ||
605 | |||
606 | /* adjust the step table index */ | ||
607 | stepindex[c] += dvi_adpcm_indextab4[code]; | ||
608 | /* check for step table index overflow and underflow */ | ||
609 | if (stepindex[c] > 88) | ||
610 | stepindex[c] = 88; | ||
611 | else if (stepindex[c] < 0) | ||
612 | stepindex[c] = 0; | ||
613 | /* calculate the difference */ | ||
614 | #ifdef STRICT_IMA | ||
615 | diff = 0; | ||
616 | if (code & 4) | ||
617 | diff += step; | ||
618 | step = step >> 1; | ||
619 | if (code & 2) | ||
620 | diff += step; | ||
621 | step = step >> 1; | ||
622 | if (code & 1) | ||
623 | diff += step; | ||
624 | step = step >> 1; | ||
625 | diff += step; | ||
626 | #else | ||
627 | diff = ((code + code + 1) * step) >> 3; /* faster */ | ||
628 | #endif | ||
629 | /* check the sign bit */ | ||
630 | /* check for overflow and underflow errors */ | ||
631 | if (code != codem) { | ||
632 | sample[c] -= diff; | ||
633 | if (sample[c] < -32768) | ||
634 | sample[c] = -32768; | ||
635 | } else { | ||
636 | sample[c] += diff; | ||
637 | if (sample[c] > 32767) | ||
638 | sample[c] = 32767; | ||
639 | } | ||
640 | /* output the new sample */ | ||
641 | pcmout[nsamples] = sample[c] << 13; | ||
642 | nsamples++; | ||
643 | } | ||
644 | } | ||
645 | } | ||
646 | } else { /* bitspersample == 3 */ | ||
647 | while (n >= channels*12 && (nsamples + 32*channels) <= *pcmoutsize) { | ||
648 | for (c = 0; c < channels; c++) { | ||
649 | uint16_t bitstream = 0; | ||
650 | int bitsread = 0; | ||
651 | for (i = 0; i < 32 && n > 0; i++) { | ||
652 | if (bitsread < 3) { | ||
653 | /* read 8 more bits */ | ||
654 | bitstream |= buf[0]<<bitsread; | ||
655 | bitsread += 8; | ||
656 | n--; | ||
657 | buf++; | ||
658 | } | ||
659 | samplecode[i][c] = bitstream & 7; | ||
660 | bitstream = bitstream>>3; | ||
661 | bitsread -= 3; | ||
662 | } | ||
663 | if (bitsread != 0) { | ||
664 | /* 32*3 = 3 words, so we should end with bitsread==0 */ | ||
665 | DEBUGF("decode_dvi_adpcm: error in implementation\n"); | ||
666 | return CODEC_ERROR; | ||
667 | } | ||
668 | } | ||
669 | |||
670 | for (i = 0; i < 32; i++) { | ||
671 | for (c = 0; c < channels; c++) { | ||
672 | step = dvi_adpcm_steptab[stepindex[c]]; | ||
673 | codem = samplecode[i][c]; | ||
674 | code = codem & 0x03; | ||
675 | |||
676 | /* adjust the step table index */ | ||
677 | stepindex[c] += dvi_adpcm_indextab3[code]; | ||
678 | /* check for step table index overflow and underflow */ | ||
679 | if (stepindex[c] > 88) | ||
680 | stepindex[c] = 88; | ||
681 | else if (stepindex[c] < 0) | ||
682 | stepindex[c] = 0; | ||
683 | /* calculate the difference */ | ||
684 | #ifdef STRICT_IMA | ||
685 | diff = 0; | ||
686 | if (code & 2) | ||
687 | diff += step; | ||
688 | step = step >> 1; | ||
689 | if (code & 1) | ||
690 | diff += step; | ||
691 | step = step >> 1; | ||
692 | diff += step; | ||
693 | #else | ||
694 | diff = ((code + code + 1) * step) >> 3; /* faster */ | ||
695 | #endif | ||
696 | /* check the sign bit */ | ||
697 | /* check for overflow and underflow errors */ | ||
698 | if (code != codem) { | ||
699 | sample[c] -= diff; | ||
700 | if (sample[c] < -32768) | ||
701 | sample[c] = -32768; | ||
702 | } | ||
703 | else { | ||
704 | sample[c] += diff; | ||
705 | if (sample[c] > 32767) | ||
706 | sample[c] = 32767; | ||
707 | } | ||
708 | /* output the new sample */ | ||
709 | pcmout[nsamples] = sample[c] << 13; | ||
710 | nsamples++; | ||
711 | } | ||
712 | } | ||
713 | } | ||
714 | } | ||
715 | |||
716 | if (nsamples > *pcmoutsize) { | ||
717 | DEBUGF("decode_dvi_adpcm: output buffer overflow!\n"); | ||
718 | return CODEC_ERROR; | ||
719 | } | ||
720 | *pcmoutsize = nsamples; | ||
721 | if (n != 0) { | ||
722 | DEBUGF("decode_dvi_adpcm: n=%d unprocessed bytes\n", n); | ||
723 | } | ||
724 | return CODEC_OK; | ||
725 | } | ||
726 | |||
diff --git a/apps/metadata/aiff.c b/apps/metadata/aiff.c index cb18e9249a..67fb43b8c6 100644 --- a/apps/metadata/aiff.c +++ b/apps/metadata/aiff.c | |||
@@ -48,7 +48,7 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3) | |||
48 | } | 48 | } |
49 | 49 | ||
50 | if ((memcmp(buf, "FORM",4) != 0) | 50 | if ((memcmp(buf, "FORM",4) != 0) |
51 | || (memcmp(&buf[8], "AIFF", 4) !=0 )) | 51 | || ((memcmp(&buf[8], "AIFF", 4) !=0) && (memcmp(&buf[8], "AIFC", 4) !=0))) |
52 | { | 52 | { |
53 | return false; | 53 | return false; |
54 | } | 54 | } |