- Use pointers instead of repeating access to array element
[kugel-rb.git] / apps / codecs / mpa.c
blobf248744c50bd5c4c310146e49e3acfed5bfcb05a
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Dave Chapman
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "codeclib.h"
23 #include <codecs/libmad/mad.h>
24 #include <inttypes.h>
26 CODEC_HEADER
28 #if NUM_CORES > 1 && !defined(MPEGPLAYER)
29 #define MPA_SYNTH_ON_COP
30 #endif
32 struct mad_stream stream IBSS_ATTR;
33 struct mad_frame frame IBSS_ATTR;
34 struct mad_synth synth IBSS_ATTR;
36 #ifdef MPA_SYNTH_ON_COP
37 volatile short die IBSS_ATTR = 0; /*thread should die*/
39 #if (CONFIG_CPU == PP5024) || (CONFIG_CPU == PP5022)
40 mad_fixed_t sbsample_prev[2][36][32] IBSS_ATTR;
41 #else
42 mad_fixed_t sbsample_prev[2][36][32] SHAREDBSS_ATTR;
43 #endif
45 struct semaphore synth_done_sem IBSS_ATTR;
46 struct semaphore synth_pending_sem IBSS_ATTR;
47 #endif
49 #define INPUT_CHUNK_SIZE 8192
51 mad_fixed_t mad_frame_overlap[2][32][18] IBSS_ATTR;
52 mad_fixed_t sbsample[2][36][32] IBSS_ATTR;
54 unsigned char mad_main_data[MAD_BUFFER_MDLEN] IBSS_ATTR;
55 /* TODO: what latency does layer 1 have? */
56 int mpeg_latency[3] = { 0, 481, 529 };
57 int mpeg_framesize[3] = {384, 1152, 1152};
59 static void init_mad(void)
61 ci->memset(&stream, 0, sizeof(struct mad_stream));
62 ci->memset(&frame, 0, sizeof(struct mad_frame));
63 ci->memset(&synth, 0, sizeof(struct mad_synth));
65 ci->memset(&sbsample, 0, sizeof(sbsample));
67 #ifdef MPA_SYNTH_ON_COP
68 frame.sbsample_prev = &sbsample_prev;
69 ci->memset(&sbsample_prev, 0, sizeof(sbsample_prev));
70 #else
71 frame.sbsample_prev = &sbsample;
72 #endif
74 frame.sbsample=&sbsample;
76 mad_stream_init(&stream);
77 mad_frame_init(&frame);
78 mad_synth_init(&synth);
80 /* We do this so libmad doesn't try to call codec_calloc() */
81 ci->memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap));
82 frame.overlap = &mad_frame_overlap;
83 stream.main_data = &mad_main_data;
88 static int get_file_pos(int newtime)
90 int pos = -1;
91 struct mp3entry *id3 = ci->id3;
93 if (id3->vbr) {
94 /* Convert newtime and id3->length to seconds to
95 * avoid overflow */
96 unsigned int newtime_s = newtime/1000;
97 unsigned int length_s = id3->length/1000;
99 if (id3->has_toc) {
100 /* Use the TOC to find the new position */
101 unsigned int percent, remainder;
102 int curtoc, nexttoc, plen;
104 percent = (newtime_s*100) / length_s;
105 if (percent > 99)
106 percent = 99;
108 curtoc = id3->toc[percent];
110 if (percent < 99) {
111 nexttoc = id3->toc[percent+1];
112 } else {
113 nexttoc = 256;
116 pos = (id3->filesize/256)*curtoc;
118 /* Use the remainder to get a more accurate position */
119 remainder = (newtime_s*100) % length_s;
120 remainder = (remainder*100) / length_s;
121 plen = (nexttoc - curtoc)*(id3->filesize/256);
122 pos += (plen/100)*remainder;
123 } else {
124 /* No TOC exists, estimate the new position */
125 pos = (id3->filesize / length_s) * newtime_s;
127 } else if (id3->bitrate) {
128 pos = newtime * (id3->bitrate / 8);
129 } else {
130 return -1;
133 /* Don't seek right to the end of the file so that we can
134 transition properly to the next song */
135 if (pos >= (int)(id3->filesize - id3->id3v1len))
136 pos = id3->filesize - id3->id3v1len - 1;
138 /* id3->filesize excludes id3->first_frame_offset, so add it now */
139 pos += id3->first_frame_offset;
141 return pos;
144 static void set_elapsed(struct mp3entry* id3)
146 unsigned long offset = id3->offset > id3->first_frame_offset ?
147 id3->offset - id3->first_frame_offset : 0;
149 if ( id3->vbr ) {
150 if ( id3->has_toc ) {
151 /* calculate elapsed time using TOC */
152 int i;
153 unsigned int remainder, plen, relpos, nextpos;
155 /* find wich percent we're at */
156 for (i=0; i<100; i++ )
157 if ( offset < id3->toc[i] * (id3->filesize / 256) )
158 break;
160 i--;
161 if (i < 0)
162 i = 0;
164 relpos = id3->toc[i];
166 if (i < 99)
167 nextpos = id3->toc[i+1];
168 else
169 nextpos = 256;
171 remainder = offset - (relpos * (id3->filesize / 256));
173 /* set time for this percent (divide before multiply to prevent
174 overflow on long files. loss of precision is negligible on
175 short files) */
176 id3->elapsed = i * (id3->length / 100);
178 /* calculate remainder time */
179 plen = (nextpos - relpos) * (id3->filesize / 256);
180 id3->elapsed += (((remainder * 100) / plen) *
181 (id3->length / 10000));
183 else {
184 /* no TOC exists. set a rough estimate using average bitrate */
185 int tpk = id3->length /
186 ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
187 1024);
188 id3->elapsed = offset / 1024 * tpk;
191 else
193 /* constant bitrate, use exact calculation */
194 if (id3->bitrate != 0)
195 id3->elapsed = offset / (id3->bitrate / 8);
199 #ifdef MPA_SYNTH_ON_COP
202 * Run the synthesis filter on the COProcessor
205 static int mad_synth_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)/2] IBSS_ATTR;
207 static const unsigned char * const mad_synth_thread_name = "mp3dec";
208 static unsigned int mad_synth_thread_id = 0;
211 static void mad_synth_thread(void)
213 while(1) {
214 ci->semaphore_release(&synth_done_sem);
215 ci->semaphore_wait(&synth_pending_sem);
217 if(die)
218 break;
220 mad_synth_frame(&synth, &frame);
224 /* wait for the synth thread to go idle which indicates a PCM frame has been
225 * synthesized */
226 static inline void mad_synth_thread_wait_pcm(void)
228 ci->semaphore_wait(&synth_done_sem);
231 /* increment the done semaphore - used after a wait for idle to preserve the
232 * semaphore count */
233 static inline void mad_synth_thread_unwait_pcm(void)
235 ci->semaphore_release(&synth_done_sem);
238 /* after synth thread has gone idle - switch decoded frames and commence
239 * synthesis on it */
240 static void mad_synth_thread_ready(void)
242 mad_fixed_t (*temp)[2][36][32];
244 /*circular buffer that holds 2 frames' samples*/
245 temp=frame.sbsample;
246 frame.sbsample = frame.sbsample_prev;
247 frame.sbsample_prev=temp;
249 ci->semaphore_release(&synth_pending_sem);
252 static bool mad_synth_thread_create(void)
254 ci->semaphore_init(&synth_done_sem, 1, 0);
255 ci->semaphore_init(&synth_pending_sem, 1, 0);
257 mad_synth_thread_id = ci->create_thread(mad_synth_thread,
258 mad_synth_thread_stack,
259 sizeof(mad_synth_thread_stack), 0,
260 mad_synth_thread_name
261 IF_PRIO(, PRIORITY_PLAYBACK)
262 IF_COP(, COP));
264 if (mad_synth_thread_id == 0)
265 return false;
267 return true;
270 static void mad_synth_thread_quit(void)
272 /*mop up COP thread*/
273 die=1;
274 ci->semaphore_release(&synth_pending_sem);
275 ci->thread_wait(mad_synth_thread_id);
276 ci->cpucache_invalidate();
278 #else
279 static inline void mad_synth_thread_ready(void)
281 mad_synth_frame(&synth, &frame);
284 static inline bool mad_synth_thread_create(void)
286 return true;
289 static inline void mad_synth_thread_quit(void)
293 static inline void mad_synth_thread_wait_pcm(void)
297 static inline void mad_synth_thread_unwait_pcm(void)
300 #endif /* MPA_SYNTH_ON_COP */
302 /* this is the codec entry point */
303 enum codec_status codec_main(void)
305 int status;
306 size_t size;
307 int file_end;
308 int samples_to_skip; /* samples to skip in total for this file (at start) */
309 char *inputbuffer;
310 int64_t samplesdone;
311 int stop_skip, start_skip;
312 int current_stereo_mode = -1;
313 unsigned long current_frequency = 0;
314 int framelength;
315 int padding = MAD_BUFFER_GUARD; /* to help mad decode the last frame */
317 if (codec_init())
318 return CODEC_ERROR;
320 /* Create a decoder instance */
322 ci->configure(DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS);
324 /*does nothing on 1 processor systems except return true*/
325 if(!mad_synth_thread_create())
326 return CODEC_ERROR;
328 next_track:
330 status = CODEC_OK;
332 /* Reinitializing seems to be necessary to avoid playback quircks when seeking. */
333 init_mad();
335 file_end = 0;
336 while (!*ci->taginfo_ready && !ci->stop_codec)
337 ci->sleep(1);
339 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
340 current_frequency = ci->id3->frequency;
341 codec_set_replaygain(ci->id3);
343 if (ci->id3->offset) {
344 ci->seek_buffer(ci->id3->offset);
345 set_elapsed(ci->id3);
347 else
348 ci->seek_buffer(ci->id3->first_frame_offset);
350 if (ci->id3->lead_trim >= 0 && ci->id3->tail_trim >= 0) {
351 stop_skip = ci->id3->tail_trim - mpeg_latency[ci->id3->layer];
352 if (stop_skip < 0) stop_skip = 0;
353 start_skip = ci->id3->lead_trim + mpeg_latency[ci->id3->layer];
354 } else {
355 stop_skip = 0;
356 /* We want to skip this amount anyway */
357 start_skip = mpeg_latency[ci->id3->layer];
360 /* Libmad will not decode the last frame without 8 bytes of extra padding
361 in the buffer. So, we can trick libmad into not decoding the last frame
362 if we are to skip it entirely and then cut the appropriate samples from
363 final frame that we did decode. Note, if all tags (ID3, APE) are not
364 properly stripped from the end of the file, this trick will not work. */
365 if (stop_skip >= mpeg_framesize[ci->id3->layer]) {
366 padding = 0;
367 stop_skip -= mpeg_framesize[ci->id3->layer];
368 } else {
369 padding = MAD_BUFFER_GUARD;
372 samplesdone = ((int64_t)ci->id3->elapsed) * current_frequency / 1000;
374 /* Don't skip any samples unless we start at the beginning. */
375 if (samplesdone > 0)
376 samples_to_skip = 0;
377 else
378 samples_to_skip = start_skip;
380 framelength = 0;
382 /* This is the decoding loop. */
383 while (1) {
384 ci->yield();
385 if (ci->stop_codec || ci->new_track)
386 break;
388 if (ci->seek_time) {
389 int newpos;
391 /*make sure the synth thread is idle before seeking - MT only*/
392 mad_synth_thread_wait_pcm();
393 mad_synth_thread_unwait_pcm();
395 samplesdone = ((int64_t)(ci->seek_time-1))*current_frequency/1000;
397 if (ci->seek_time-1 == 0) {
398 newpos = ci->id3->first_frame_offset;
399 samples_to_skip = start_skip;
400 } else {
401 newpos = get_file_pos(ci->seek_time-1);
402 samples_to_skip = 0;
405 if (!ci->seek_buffer(newpos))
406 break;
407 ci->seek_complete();
408 init_mad();
409 framelength = 0;
412 /* Lock buffers */
413 if (stream.error == 0) {
414 inputbuffer = ci->request_buffer(&size, INPUT_CHUNK_SIZE);
415 if (size == 0 || inputbuffer == NULL)
416 break;
417 mad_stream_buffer(&stream, (unsigned char *)inputbuffer,
418 size + padding);
421 if (mad_frame_decode(&frame, &stream)) {
422 if (stream.error == MAD_FLAG_INCOMPLETE
423 || stream.error == MAD_ERROR_BUFLEN) {
424 /* This makes the codec support partially corrupted files */
425 if (file_end == 30)
426 break;
428 /* Fill the buffer */
429 if (stream.next_frame)
430 ci->advance_buffer_loc((void *)stream.next_frame);
431 else
432 ci->advance_buffer(size);
433 stream.error = 0;
434 file_end++;
435 continue;
436 } else if (MAD_RECOVERABLE(stream.error)) {
437 continue;
438 } else {
439 /* Some other unrecoverable error */
440 status = CODEC_ERROR;
441 break;
443 break;
446 file_end = 0;
448 /* Do the pcmbuf insert here. Note, this is the PREVIOUS frame's pcm
449 data (not the one just decoded above). When we exit the decoding
450 loop we will need to process the final frame that was decoded. */
451 mad_synth_thread_wait_pcm();
453 if (framelength > 0) {
455 /* In case of a mono file, the second array will be ignored. */
456 ci->pcmbuf_insert(&synth.pcm.samples[0][samples_to_skip],
457 &synth.pcm.samples[1][samples_to_skip],
458 framelength);
460 /* Only skip samples for the first frame added. */
461 samples_to_skip = 0;
464 /* Initiate PCM synthesis on the COP (MT) or perform it here (ST) */
465 mad_synth_thread_ready();
467 /* Check if sample rate and stereo settings changed in this frame. */
468 if (frame.header.samplerate != current_frequency) {
469 current_frequency = frame.header.samplerate;
470 ci->configure(DSP_SWITCH_FREQUENCY, current_frequency);
472 if (MAD_NCHANNELS(&frame.header) == 2) {
473 if (current_stereo_mode != STEREO_NONINTERLEAVED) {
474 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
475 current_stereo_mode = STEREO_NONINTERLEAVED;
477 } else {
478 if (current_stereo_mode != STEREO_MONO) {
479 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
480 current_stereo_mode = STEREO_MONO;
484 if (stream.next_frame)
485 ci->advance_buffer_loc((void *)stream.next_frame);
486 else
487 ci->advance_buffer(size);
489 framelength = synth.pcm.length - samples_to_skip;
490 if (framelength < 0) {
491 framelength = 0;
492 samples_to_skip -= synth.pcm.length;
495 samplesdone += framelength;
496 ci->set_elapsed((samplesdone * 1000) / current_frequency);
499 /* wait for synth idle - MT only*/
500 mad_synth_thread_wait_pcm();
501 mad_synth_thread_unwait_pcm();
503 /* Finish the remaining decoded frame.
504 Cut the required samples from the end. */
505 if (framelength > stop_skip){
506 ci->pcmbuf_insert(synth.pcm.samples[0], synth.pcm.samples[1],
507 framelength - stop_skip);
510 if (ci->request_next_track())
511 goto next_track;
513 /*mop up COP thread - MT only*/
514 mad_synth_thread_quit();
516 return status;