diff options
Diffstat (limited to 'apps/codecs/wav.c')
-rw-r--r-- | apps/codecs/wav.c | 106 |
1 files changed, 46 insertions, 60 deletions
diff --git a/apps/codecs/wav.c b/apps/codecs/wav.c index e179470f27..42bcc7081f 100644 --- a/apps/codecs/wav.c +++ b/apps/codecs/wav.c | |||
@@ -151,9 +151,19 @@ static uint8_t *read_buffer(size_t *realsize) | |||
151 | } | 151 | } |
152 | 152 | ||
153 | /* this is the codec entry point */ | 153 | /* this is the codec entry point */ |
154 | enum codec_status codec_main(void) | 154 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
155 | { | ||
156 | if (reason == CODEC_LOAD) { | ||
157 | /* Generic codec initialisation */ | ||
158 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
159 | } | ||
160 | |||
161 | return CODEC_OK; | ||
162 | } | ||
163 | |||
164 | /* this is called for each file to process */ | ||
165 | enum codec_status codec_run(void) | ||
155 | { | 166 | { |
156 | int status; | ||
157 | uint32_t decodedsamples; | 167 | uint32_t decodedsamples; |
158 | size_t n; | 168 | size_t n; |
159 | int bufcount; | 169 | int bufcount; |
@@ -163,38 +173,28 @@ enum codec_status codec_main(void) | |||
163 | off_t firstblockposn; /* position of the first block in file */ | 173 | off_t firstblockposn; /* position of the first block in file */ |
164 | const struct pcm_codec *codec; | 174 | const struct pcm_codec *codec; |
165 | uint32_t size; | 175 | uint32_t size; |
166 | 176 | intptr_t param; | |
167 | /* Generic codec initialisation */ | ||
168 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
169 | |||
170 | next_track: | ||
171 | status = CODEC_OK; | ||
172 | 177 | ||
173 | if (codec_init()) { | 178 | if (codec_init()) { |
174 | DEBUGF("codec_init() error\n"); | 179 | DEBUGF("codec_init() error\n"); |
175 | status = CODEC_ERROR; | 180 | return CODEC_ERROR; |
176 | goto exit; | ||
177 | } | 181 | } |
178 | 182 | ||
179 | if (codec_wait_taginfo() != 0) | ||
180 | goto done; | ||
181 | |||
182 | codec_set_replaygain(ci->id3); | 183 | codec_set_replaygain(ci->id3); |
183 | 184 | ||
184 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ | 185 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ |
185 | bytesdone = ci->id3->offset; | 186 | bytesdone = ci->id3->offset; |
186 | 187 | ||
187 | /* get RIFF chunk header */ | 188 | /* get RIFF chunk header */ |
189 | ci->seek_buffer(0); | ||
188 | buf = ci->request_buffer(&n, 12); | 190 | buf = ci->request_buffer(&n, 12); |
189 | if (n < 12) { | 191 | if (n < 12) { |
190 | DEBUGF("request_buffer error\n"); | 192 | DEBUGF("request_buffer error\n"); |
191 | status = CODEC_ERROR; | 193 | return CODEC_ERROR; |
192 | goto done; | ||
193 | } | 194 | } |
194 | if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) { | 195 | if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) { |
195 | DEBUGF("CODEC_ERROR: missing riff header\n"); | 196 | DEBUGF("CODEC_ERROR: missing riff header\n"); |
196 | status = CODEC_ERROR; | 197 | return CODEC_ERROR; |
197 | goto done; | ||
198 | } | 198 | } |
199 | 199 | ||
200 | /* advance to first WAVE chunk */ | 200 | /* advance to first WAVE chunk */ |
@@ -215,8 +215,7 @@ next_track: | |||
215 | if (n < 8) { | 215 | if (n < 8) { |
216 | DEBUGF("data chunk request_buffer error\n"); | 216 | DEBUGF("data chunk request_buffer error\n"); |
217 | /* no more chunks, 'data' chunk must not have been found */ | 217 | /* no more chunks, 'data' chunk must not have been found */ |
218 | status = CODEC_ERROR; | 218 | return CODEC_ERROR; |
219 | goto done; | ||
220 | } | 219 | } |
221 | 220 | ||
222 | /* chunkSize */ | 221 | /* chunkSize */ |
@@ -225,8 +224,7 @@ next_track: | |||
225 | if (size < 16) { | 224 | if (size < 16) { |
226 | DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%lu < 16\n", | 225 | DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%lu < 16\n", |
227 | (unsigned long)size); | 226 | (unsigned long)size); |
228 | status = CODEC_ERROR; | 227 | return CODEC_ERROR; |
229 | goto done; | ||
230 | } | 228 | } |
231 | /* wFormatTag */ | 229 | /* wFormatTag */ |
232 | format.formattag=buf[8]|(buf[9]<<8); | 230 | format.formattag=buf[8]|(buf[9]<<8); |
@@ -256,8 +254,7 @@ next_track: | |||
256 | if (format.size < 22) { | 254 | if (format.size < 22) { |
257 | DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " | 255 | DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " |
258 | "missing extension\n"); | 256 | "missing extension\n"); |
259 | status = CODEC_ERROR; | 257 | return CODEC_ERROR; |
260 | goto done; | ||
261 | } | 258 | } |
262 | /* wValidBitsPerSample */ | 259 | /* wValidBitsPerSample */ |
263 | format.bitspersample = buf[26]|(buf[27]<<8); | 260 | format.bitspersample = buf[26]|(buf[27]<<8); |
@@ -273,8 +270,7 @@ next_track: | |||
273 | { | 270 | { |
274 | if (!set_msadpcm_coeffs(buf)) | 271 | if (!set_msadpcm_coeffs(buf)) |
275 | { | 272 | { |
276 | status = CODEC_ERROR; | 273 | return CODEC_ERROR; |
277 | goto done; | ||
278 | } | 274 | } |
279 | } | 275 | } |
280 | 276 | ||
@@ -284,8 +280,7 @@ next_track: | |||
284 | { | 280 | { |
285 | DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", | 281 | DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", |
286 | (unsigned int) format.formattag); | 282 | (unsigned int) format.formattag); |
287 | status = CODEC_ERROR; | 283 | return CODEC_ERROR; |
288 | goto done; | ||
289 | } | 284 | } |
290 | 285 | ||
291 | /* riff 8bit linear pcm is unsigned */ | 286 | /* riff 8bit linear pcm is unsigned */ |
@@ -295,8 +290,7 @@ next_track: | |||
295 | /* set format, parse codec specific tag, check format, and calculate chunk size */ | 290 | /* set format, parse codec specific tag, check format, and calculate chunk size */ |
296 | if (!codec->set_format(&format)) | 291 | if (!codec->set_format(&format)) |
297 | { | 292 | { |
298 | status = CODEC_ERROR; | 293 | return CODEC_ERROR; |
299 | goto done; | ||
300 | } | 294 | } |
301 | } else if (memcmp(buf, "data", 4) == 0) { | 295 | } else if (memcmp(buf, "data", 4) == 0) { |
302 | format.numbytes = size; | 296 | format.numbytes = size; |
@@ -324,31 +318,26 @@ next_track: | |||
324 | if (!codec) | 318 | if (!codec) |
325 | { | 319 | { |
326 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n"); | 320 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n"); |
327 | status = CODEC_ERROR; | 321 | return CODEC_ERROR; |
328 | goto done; | ||
329 | } | 322 | } |
330 | 323 | ||
331 | /* common format check */ | 324 | /* common format check */ |
332 | if (format.channels == 0) { | 325 | if (format.channels == 0) { |
333 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); | 326 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); |
334 | status = CODEC_ERROR; | 327 | return CODEC_ERROR; |
335 | goto done; | ||
336 | } | 328 | } |
337 | if (format.samplesperblock == 0) { | 329 | if (format.samplesperblock == 0) { |
338 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n"); | 330 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n"); |
339 | status = CODEC_ERROR; | 331 | return CODEC_ERROR; |
340 | goto done; | ||
341 | } | 332 | } |
342 | if (format.blockalign == 0) | 333 | if (format.blockalign == 0) |
343 | { | 334 | { |
344 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n"); | 335 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n"); |
345 | status = CODEC_ERROR; | 336 | return CODEC_ERROR; |
346 | goto done; | ||
347 | } | 337 | } |
348 | if (format.numbytes == 0) { | 338 | if (format.numbytes == 0) { |
349 | DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); | 339 | DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); |
350 | status = CODEC_ERROR; | 340 | return CODEC_ERROR; |
351 | goto done; | ||
352 | } | 341 | } |
353 | 342 | ||
354 | /* check chunksize */ | 343 | /* check chunksize */ |
@@ -358,8 +347,7 @@ next_track: | |||
358 | if (format.chunksize == 0) | 347 | if (format.chunksize == 0) |
359 | { | 348 | { |
360 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); | 349 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); |
361 | status = CODEC_ERROR; | 350 | return CODEC_ERROR; |
362 | goto done; | ||
363 | } | 351 | } |
364 | 352 | ||
365 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 353 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
@@ -369,8 +357,7 @@ next_track: | |||
369 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | 357 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); |
370 | } else { | 358 | } else { |
371 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); | 359 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); |
372 | status = CODEC_ERROR; | 360 | return CODEC_ERROR; |
373 | goto done; | ||
374 | } | 361 | } |
375 | 362 | ||
376 | /* make sure we're at the correct offset */ | 363 | /* make sure we're at the correct offset */ |
@@ -380,13 +367,12 @@ next_track: | |||
380 | PCM_SEEK_POS, &read_buffer); | 367 | PCM_SEEK_POS, &read_buffer); |
381 | 368 | ||
382 | if (newpos->pos > format.numbytes) | 369 | if (newpos->pos > format.numbytes) |
383 | goto done; | 370 | return CODEC_OK; |
384 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 371 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
385 | { | 372 | { |
386 | bytesdone = newpos->pos; | 373 | bytesdone = newpos->pos; |
387 | decodedsamples = newpos->samples; | 374 | decodedsamples = newpos->samples; |
388 | } | 375 | } |
389 | ci->seek_complete(); | ||
390 | } else { | 376 | } else { |
391 | /* already where we need to be */ | 377 | /* already where we need to be */ |
392 | bytesdone = 0; | 378 | bytesdone = 0; |
@@ -396,22 +382,28 @@ next_track: | |||
396 | endofstream = 0; | 382 | endofstream = 0; |
397 | 383 | ||
398 | while (!endofstream) { | 384 | while (!endofstream) { |
399 | ci->yield(); | 385 | enum codec_command_action action = ci->get_command(¶m); |
400 | if (ci->stop_codec || ci->new_track) { | 386 | |
387 | if (action == CODEC_ACTION_HALT) | ||
401 | break; | 388 | break; |
402 | } | ||
403 | 389 | ||
404 | if (ci->seek_time) { | 390 | if (action == CODEC_ACTION_SEEK_TIME) { |
405 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, | 391 | struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, |
406 | &read_buffer); | 392 | &read_buffer); |
407 | |||
408 | if (newpos->pos > format.numbytes) | 393 | if (newpos->pos > format.numbytes) |
394 | { | ||
395 | ci->set_elapsed(ci->id3->length); | ||
396 | ci->seek_complete(); | ||
409 | break; | 397 | break; |
398 | } | ||
399 | |||
410 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 400 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
411 | { | 401 | { |
412 | bytesdone = newpos->pos; | 402 | bytesdone = newpos->pos; |
413 | decodedsamples = newpos->samples; | 403 | decodedsamples = newpos->samples; |
414 | } | 404 | } |
405 | |||
406 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | ||
415 | ci->seek_complete(); | 407 | ci->seek_complete(); |
416 | } | 408 | } |
417 | 409 | ||
@@ -423,11 +415,10 @@ next_track: | |||
423 | endofstream = 1; | 415 | endofstream = 1; |
424 | } | 416 | } |
425 | 417 | ||
426 | status = codec->decode(wavbuf, n, samples, &bufcount); | 418 | if (codec->decode(wavbuf, n, samples, &bufcount) == CODEC_ERROR) |
427 | if (status == CODEC_ERROR) | ||
428 | { | 419 | { |
429 | DEBUGF("codec error\n"); | 420 | DEBUGF("codec error\n"); |
430 | goto done; | 421 | return CODEC_ERROR; |
431 | } | 422 | } |
432 | 423 | ||
433 | ci->pcmbuf_insert(samples, NULL, bufcount); | 424 | ci->pcmbuf_insert(samples, NULL, bufcount); |
@@ -440,10 +431,5 @@ next_track: | |||
440 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | 431 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); |
441 | } | 432 | } |
442 | 433 | ||
443 | done: | 434 | return CODEC_OK; |
444 | if (ci->request_next_track()) | ||
445 | goto next_track; | ||
446 | |||
447 | exit: | ||
448 | return status; | ||
449 | } | 435 | } |