summaryrefslogtreecommitdiff
path: root/apps/codecs/wav.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-04-27 03:08:23 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-04-27 03:08:23 +0000
commitc537d5958e8b421ac4f9bef6c8b9e7425a6cf167 (patch)
tree7ed36518fb6524da7bbd913ba7619b85b5d15d23 /apps/codecs/wav.c
parentdcf0f8de4a37ff1d2ea510aef75fa67977a8bdcc (diff)
downloadrockbox-c537d5958e8b421ac4f9bef6c8b9e7425a6cf167.tar.gz
rockbox-c537d5958e8b421ac4f9bef6c8b9e7425a6cf167.zip
Commit FS#12069 - Playback rework - first stages. Gives as thorough as possible a treatment of codec management, track change and metadata logic as possible while maintaining fairly narrow focus and not rewriting everything all at once. Please see the rockbox-dev mail archive on 2011-04-25 (Playback engine rework) for a more thorough manifest of what was addressed. Plugins and codecs become incompatible.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29785 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/wav.c')
-rw-r--r--apps/codecs/wav.c106
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 */
154enum codec_status codec_main(void) 154enum 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 */
165enum 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
170next_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(&param);
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
443done: 434 return CODEC_OK;
444 if (ci->request_next_track())
445 goto next_track;
446
447exit:
448 return status;
449} 435}