summaryrefslogtreecommitdiff
path: root/apps/codecs/aiff.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/aiff.c')
-rw-r--r--apps/codecs/aiff.c108
1 files changed, 48 insertions, 60 deletions
diff --git a/apps/codecs/aiff.c b/apps/codecs/aiff.c
index d4cf8660dd..3fc137eaeb 100644
--- a/apps/codecs/aiff.c
+++ b/apps/codecs/aiff.c
@@ -61,9 +61,20 @@ static const struct pcm_codec *get_codec(uint32_t formattag)
61 return NULL; 61 return NULL;
62} 62}
63 63
64enum codec_status codec_main(void) 64/* this is the codec entry point */
65enum codec_status codec_main(enum codec_entry_call_reason reason)
66{
67 if (reason == CODEC_LOAD) {
68 /* Generic codec initialisation */
69 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
70 }
71
72 return CODEC_OK;
73}
74
75/* this is called for each file to process */
76enum codec_status codec_run(void)
65{ 77{
66 int status;
67 struct pcm_format format; 78 struct pcm_format format;
68 uint32_t bytesdone, decodedsamples; 79 uint32_t bytesdone, decodedsamples;
69 uint32_t num_sample_frames = 0; 80 uint32_t num_sample_frames = 0;
@@ -77,38 +88,28 @@ enum codec_status codec_main(void)
77 bool is_aifc = false; 88 bool is_aifc = false;
78 const struct pcm_codec *codec; 89 const struct pcm_codec *codec;
79 uint32_t size; 90 uint32_t size;
80 91 intptr_t param;
81 /* Generic codec initialisation */
82 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
83
84next_track:
85 status = CODEC_OK;
86 92
87 if (codec_init()) { 93 if (codec_init()) {
88 status = CODEC_ERROR; 94 return CODEC_ERROR;
89 goto exit;
90 } 95 }
91 96
92 if (codec_wait_taginfo() != 0)
93 goto done;
94
95 codec_set_replaygain(ci->id3); 97 codec_set_replaygain(ci->id3);
96 98
97 /* Need to save offset for later use (cleared indirectly by advance_buffer) */ 99 /* Need to save offset for later use (cleared indirectly by advance_buffer) */
98 bytesdone = ci->id3->offset; 100 bytesdone = ci->id3->offset;
99 101
100 /* assume the AIFF header is less than 1024 bytes */ 102 /* assume the AIFF header is less than 1024 bytes */
103 ci->seek_buffer(0);
101 buf = ci->request_buffer(&n, 1024); 104 buf = ci->request_buffer(&n, 1024);
102 if (n < 54) { 105 if (n < 54) {
103 status = CODEC_ERROR; 106 return CODEC_ERROR;
104 goto done;
105 } 107 }
106 108
107 if (memcmp(buf, "FORM", 4) != 0) 109 if (memcmp(buf, "FORM", 4) != 0)
108 { 110 {
109 DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[0]); 111 DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[0]);
110 status = CODEC_ERROR; 112 return CODEC_ERROR;
111 goto done;
112 } 113 }
113 if (memcmp(&buf[8], "AIFF", 4) == 0) 114 if (memcmp(&buf[8], "AIFF", 4) == 0)
114 is_aifc = false; 115 is_aifc = false;
@@ -117,8 +118,7 @@ next_track:
117 else 118 else
118 { 119 {
119 DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[8]); 120 DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[8]);
120 status = CODEC_ERROR; 121 return CODEC_ERROR;
121 goto done;
122 } 122 }
123 123
124 buf += 12; 124 buf += 12;
@@ -141,8 +141,7 @@ next_track:
141 { 141 {
142 DEBUGF("CODEC_ERROR: 'COMM' chunk size=%lu < %d\n", 142 DEBUGF("CODEC_ERROR: 'COMM' chunk size=%lu < %d\n",
143 (unsigned long)size, (is_aifc)?22:18); 143 (unsigned long)size, (is_aifc)?22:18);
144 status = CODEC_ERROR; 144 return CODEC_ERROR;
145 goto done;
146 } 145 }
147 /* num_channels */ 146 /* num_channels */
148 format.channels = ((buf[8]<<8)|buf[9]); 147 format.channels = ((buf[8]<<8)|buf[9]);
@@ -154,8 +153,7 @@ next_track:
154 /* sample_rate (don't use last 4 bytes, only integer fs) */ 153 /* sample_rate (don't use last 4 bytes, only integer fs) */
155 if (buf[16] != 0x40) { 154 if (buf[16] != 0x40) {
156 DEBUGF("CODEC_ERROR: weird sampling rate (no @)\n"); 155 DEBUGF("CODEC_ERROR: weird sampling rate (no @)\n");
157 status = CODEC_ERROR; 156 return CODEC_ERROR;
158 goto done;
159 } 157 }
160 format.samplespersec = ((buf[18]<<24)|(buf[19]<<16)|(buf[20]<<8)|buf[21])+1; 158 format.samplespersec = ((buf[18]<<24)|(buf[19]<<16)|(buf[20]<<8)|buf[21])+1;
161 format.samplespersec >>= (16 + 14 - buf[17]); 159 format.samplespersec >>= (16 + 14 - buf[17]);
@@ -181,8 +179,7 @@ next_track:
181 } else if (memcmp(buf, "SSND", 4)==0) { 179 } else if (memcmp(buf, "SSND", 4)==0) {
182 if (format.bitspersample == 0) { 180 if (format.bitspersample == 0) {
183 DEBUGF("CODEC_ERROR: unsupported chunk order\n"); 181 DEBUGF("CODEC_ERROR: unsupported chunk order\n");
184 status = CODEC_ERROR; 182 return CODEC_ERROR;
185 goto done;
186 } 183 }
187 /* offset2snd */ 184 /* offset2snd */
188 offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11]; 185 offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11];
@@ -205,21 +202,18 @@ next_track:
205 buf += size; 202 buf += size;
206 if (n < size) { 203 if (n < size) {
207 DEBUGF("CODEC_ERROR: AIFF header size > 1024\n"); 204 DEBUGF("CODEC_ERROR: AIFF header size > 1024\n");
208 status = CODEC_ERROR; 205 return CODEC_ERROR;
209 goto done;
210 } 206 }
211 n -= size; 207 n -= size;
212 } /* while 'SSND' */ 208 } /* while 'SSND' */
213 209
214 if (format.channels == 0) { 210 if (format.channels == 0) {
215 DEBUGF("CODEC_ERROR: 'COMM' chunk not found or 0-channels file\n"); 211 DEBUGF("CODEC_ERROR: 'COMM' chunk not found or 0-channels file\n");
216 status = CODEC_ERROR; 212 return CODEC_ERROR;
217 goto done;
218 } 213 }
219 if (format.numbytes == 0) { 214 if (format.numbytes == 0) {
220 DEBUGF("CODEC_ERROR: 'SSND' chunk not found or has zero length\n"); 215 DEBUGF("CODEC_ERROR: 'SSND' chunk not found or has zero length\n");
221 status = CODEC_ERROR; 216 return CODEC_ERROR;
222 goto done;
223 } 217 }
224 218
225 codec = get_codec(format.formattag); 219 codec = get_codec(format.formattag);
@@ -227,14 +221,12 @@ next_track:
227 { 221 {
228 DEBUGF("CODEC_ERROR: AIFC does not support compressionType: 0x%x\n", 222 DEBUGF("CODEC_ERROR: AIFC does not support compressionType: 0x%x\n",
229 (unsigned int)format.formattag); 223 (unsigned int)format.formattag);
230 status = CODEC_ERROR; 224 return CODEC_ERROR;
231 goto done;
232 } 225 }
233 226
234 if (!codec->set_format(&format)) 227 if (!codec->set_format(&format))
235 { 228 {
236 status = CODEC_ERROR; 229 return CODEC_ERROR;
237 goto done;
238 } 230 }
239 231
240 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); 232 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
@@ -245,21 +237,18 @@ next_track:
245 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); 237 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
246 } else { 238 } else {
247 DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n"); 239 DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n");
248 status = CODEC_ERROR; 240 return CODEC_ERROR;
249 goto done;
250 } 241 }
251 242
252 if (format.samplesperblock == 0) 243 if (format.samplesperblock == 0)
253 { 244 {
254 DEBUGF("CODEC_ERROR: samplesperblock is 0\n"); 245 DEBUGF("CODEC_ERROR: samplesperblock is 0\n");
255 status = CODEC_ERROR; 246 return CODEC_ERROR;
256 goto done;
257 } 247 }
258 if (format.blockalign == 0) 248 if (format.blockalign == 0)
259 { 249 {
260 DEBUGF("CODEC_ERROR: blockalign is 0\n"); 250 DEBUGF("CODEC_ERROR: blockalign is 0\n");
261 status = CODEC_ERROR; 251 return CODEC_ERROR;
262 goto done;
263 } 252 }
264 253
265 /* check chunksize */ 254 /* check chunksize */
@@ -269,8 +258,7 @@ next_track:
269 if (format.chunksize == 0) 258 if (format.chunksize == 0)
270 { 259 {
271 DEBUGF("CODEC_ERROR: chunksize is 0\n"); 260 DEBUGF("CODEC_ERROR: chunksize is 0\n");
272 status = CODEC_ERROR; 261 return CODEC_ERROR;
273 goto done;
274 } 262 }
275 263
276 firstblockposn = 1024 - n; 264 firstblockposn = 1024 - n;
@@ -283,13 +271,13 @@ next_track:
283 PCM_SEEK_POS, NULL); 271 PCM_SEEK_POS, NULL);
284 272
285 if (newpos->pos > format.numbytes) 273 if (newpos->pos > format.numbytes)
286 goto done; 274 return CODEC_OK;
275
287 if (ci->seek_buffer(firstblockposn + newpos->pos)) 276 if (ci->seek_buffer(firstblockposn + newpos->pos))
288 { 277 {
289 bytesdone = newpos->pos; 278 bytesdone = newpos->pos;
290 decodedsamples = newpos->samples; 279 decodedsamples = newpos->samples;
291 } 280 }
292 ci->seek_complete();
293 } else { 281 } else {
294 /* already where we need to be */ 282 /* already where we need to be */
295 bytesdone = 0; 283 bytesdone = 0;
@@ -299,21 +287,29 @@ next_track:
299 endofstream = 0; 287 endofstream = 0;
300 288
301 while (!endofstream) { 289 while (!endofstream) {
302 ci->yield(); 290 enum codec_command_action action = ci->get_command(&param);
303 if (ci->stop_codec || ci->new_track) 291
292 if (action == CODEC_ACTION_HALT)
304 break; 293 break;
305 294
306 if (ci->seek_time) { 295 if (action == CODEC_ACTION_SEEK_TIME) {
307 /* 3rd args(read_buffer) is unnecessary in the format which AIFF supports. */ 296 /* 3rd args(read_buffer) is unnecessary in the format which AIFF supports. */
308 struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, NULL); 297 struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, NULL);
309 298
310 if (newpos->pos > format.numbytes) 299 if (newpos->pos > format.numbytes)
300 {
301 ci->set_elapsed(ci->id3->length);
302 ci->seek_complete();
311 break; 303 break;
304 }
305
312 if (ci->seek_buffer(firstblockposn + newpos->pos)) 306 if (ci->seek_buffer(firstblockposn + newpos->pos))
313 { 307 {
314 bytesdone = newpos->pos; 308 bytesdone = newpos->pos;
315 decodedsamples = newpos->samples; 309 decodedsamples = newpos->samples;
316 } 310 }
311
312 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
317 ci->seek_complete(); 313 ci->seek_complete();
318 } 314 }
319 aifbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); 315 aifbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize);
@@ -326,11 +322,10 @@ next_track:
326 endofstream = 1; 322 endofstream = 1;
327 } 323 }
328 324
329 status = codec->decode(aifbuf, n, samples, &bufcount); 325 if (codec->decode(aifbuf, n, samples, &bufcount) == CODEC_ERROR)
330 if (status == CODEC_ERROR)
331 { 326 {
332 DEBUGF("codec error\n"); 327 DEBUGF("codec error\n");
333 goto done; 328 return CODEC_ERROR;
334 } 329 }
335 330
336 ci->pcmbuf_insert(samples, NULL, bufcount); 331 ci->pcmbuf_insert(samples, NULL, bufcount);
@@ -343,13 +338,6 @@ next_track:
343 338
344 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); 339 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
345 } 340 }
346 status = CODEC_OK;
347
348done:
349 if (ci->request_next_track())
350 goto next_track;
351 341
352exit: 342 return CODEC_OK;
353 return status;
354} 343}
355