1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
23 #include <codecs/libmad/mad.h>
28 struct mad_stream stream IBSS_ATTR
;
29 struct mad_frame frame IBSS_ATTR
;
30 struct mad_synth synth IBSS_ATTR
;
32 /* The following function is used inside libmad - let's hope it's never
39 #define INPUT_CHUNK_SIZE 8192
41 mad_fixed_t mad_frame_overlap
[2][32][18] IBSS_ATTR
;
42 unsigned char mad_main_data
[MAD_BUFFER_MDLEN
] IBSS_ATTR
;
43 /* TODO: what latency does layer 1 have? */
44 int mpeg_latency
[3] = { 0, 481, 529 };
45 int mpeg_framesize
[3] = {384, 1152, 1152};
49 ci
->memset(&stream
, 0, sizeof(struct mad_stream
));
50 ci
->memset(&frame
, 0, sizeof(struct mad_frame
));
51 ci
->memset(&synth
, 0, sizeof(struct mad_synth
));
53 mad_stream_init(&stream
);
54 mad_frame_init(&frame
);
55 mad_synth_init(&synth
);
57 /* We do this so libmad doesn't try to call codec_calloc() */
58 ci
->memset(mad_frame_overlap
, 0, sizeof(mad_frame_overlap
));
59 frame
.overlap
= &mad_frame_overlap
;
60 stream
.main_data
= &mad_main_data
;
63 int get_file_pos(int newtime
)
66 struct mp3entry
*id3
= ci
->id3
;
70 /* Use the TOC to find the new position */
71 unsigned int percent
, remainder
;
72 int curtoc
, nexttoc
, plen
;
74 percent
= (newtime
*100) / id3
->length
;
78 curtoc
= id3
->toc
[percent
];
81 nexttoc
= id3
->toc
[percent
+1];
86 pos
= (id3
->filesize
/256)*curtoc
;
88 /* Use the remainder to get a more accurate position */
89 remainder
= (newtime
*100) % id3
->length
;
90 remainder
= (remainder
*100) / id3
->length
;
91 plen
= (nexttoc
- curtoc
)*(id3
->filesize
/256);
92 pos
+= (plen
/100)*remainder
;
94 /* No TOC exists, estimate the new position */
95 pos
= (id3
->filesize
/ (id3
->length
/ 1000)) *
98 } else if (id3
->bitrate
) {
99 pos
= newtime
* (id3
->bitrate
/ 8);
104 pos
+= id3
->first_frame_offset
;
106 /* Don't seek right to the end of the file so that we can
107 transition properly to the next song */
108 if (pos
>= (int)(id3
->filesize
- id3
->id3v1len
))
109 pos
= id3
->filesize
- id3
->id3v1len
- 1;
114 static void set_elapsed(struct mp3entry
* id3
)
116 unsigned long offset
= id3
->offset
> id3
->first_frame_offset
?
117 id3
->offset
- id3
->first_frame_offset
: 0;
120 if ( id3
->has_toc
) {
121 /* calculate elapsed time using TOC */
123 unsigned int remainder
, plen
, relpos
, nextpos
;
125 /* find wich percent we're at */
126 for (i
=0; i
<100; i
++ )
127 if ( offset
< id3
->toc
[i
] * (id3
->filesize
/ 256) )
134 relpos
= id3
->toc
[i
];
137 nextpos
= id3
->toc
[i
+1];
141 remainder
= offset
- (relpos
* (id3
->filesize
/ 256));
143 /* set time for this percent (divide before multiply to prevent
144 overflow on long files. loss of precision is negligible on
146 id3
->elapsed
= i
* (id3
->length
/ 100);
148 /* calculate remainder time */
149 plen
= (nextpos
- relpos
) * (id3
->filesize
/ 256);
150 id3
->elapsed
+= (((remainder
* 100) / plen
) *
151 (id3
->length
/ 10000));
154 /* no TOC exists. set a rough estimate using average bitrate */
155 int tpk
= id3
->length
/
156 ((id3
->filesize
- id3
->first_frame_offset
- id3
->id3v1len
) /
158 id3
->elapsed
= offset
/ 1024 * tpk
;
163 /* constant bitrate, use exact calculation */
164 if (id3
->bitrate
!= 0)
165 id3
->elapsed
= offset
/ (id3
->bitrate
/ 8);
169 /* this is the codec entry point */
170 enum codec_status
codec_main(void)
175 int samples_to_skip
; /* samples to skip in total for this file (at start) */
178 int stop_skip
, start_skip
;
179 int current_stereo_mode
= -1;
180 unsigned long current_frequency
= 0;
182 int padding
= MAD_BUFFER_GUARD
; /* to help mad decode the last frame */
187 /* Create a decoder instance */
189 ci
->configure(DSP_SET_SAMPLE_DEPTH
, MAD_F_FRACBITS
);
194 /* Reinitializing seems to be necessary to avoid playback quircks when seeking. */
198 while (!*ci
->taginfo_ready
&& !ci
->stop_codec
)
201 ci
->configure(DSP_SWITCH_FREQUENCY
, ci
->id3
->frequency
);
202 current_frequency
= ci
->id3
->frequency
;
203 codec_set_replaygain(ci
->id3
);
205 if (ci
->id3
->offset
) {
206 ci
->seek_buffer(ci
->id3
->offset
);
207 set_elapsed(ci
->id3
);
210 ci
->seek_buffer(ci
->id3
->first_frame_offset
);
212 if (ci
->id3
->lead_trim
>= 0 && ci
->id3
->tail_trim
>= 0) {
213 stop_skip
= ci
->id3
->tail_trim
- mpeg_latency
[ci
->id3
->layer
];
214 if (stop_skip
< 0) stop_skip
= 0;
215 start_skip
= ci
->id3
->lead_trim
+ mpeg_latency
[ci
->id3
->layer
];
218 /* We want to skip this amount anyway */
219 start_skip
= mpeg_latency
[ci
->id3
->layer
];
222 /* Libmad will not decode the last frame without 8 bytes of extra padding
223 in the buffer. So, we can trick libmad into not decoding the last frame
224 if we are to skip it entirely and then cut the appropriate samples from
225 final frame that we did decode. Note, if all tags (ID3, APE) are not
226 properly stripped from the end of the file, this trick will not work. */
227 if (stop_skip
>= mpeg_framesize
[ci
->id3
->layer
]) {
229 stop_skip
-= mpeg_framesize
[ci
->id3
->layer
];
231 padding
= MAD_BUFFER_GUARD
;
234 samplesdone
= ((int64_t)ci
->id3
->elapsed
) * current_frequency
/ 1000;
236 /* Don't skip any samples unless we start at the beginning. */
240 samples_to_skip
= start_skip
;
244 /* This is the decoding loop. */
247 if (ci
->stop_codec
|| ci
->new_track
)
253 samplesdone
= ((int64_t)(ci
->seek_time
-1))*current_frequency
/1000;
255 if (ci
->seek_time
-1 == 0) {
256 newpos
= ci
->id3
->first_frame_offset
;
257 samples_to_skip
= start_skip
;
259 newpos
= get_file_pos(ci
->seek_time
-1);
263 if (!ci
->seek_buffer(newpos
))
271 if (stream
.error
== 0) {
272 inputbuffer
= ci
->request_buffer(&size
, INPUT_CHUNK_SIZE
);
273 if (size
== 0 || inputbuffer
== NULL
)
275 mad_stream_buffer(&stream
, (unsigned char *)inputbuffer
,
279 if (mad_frame_decode(&frame
, &stream
)) {
280 if (stream
.error
== MAD_FLAG_INCOMPLETE
281 || stream
.error
== MAD_ERROR_BUFLEN
) {
282 /* This makes the codec support partially corrupted files */
286 /* Fill the buffer */
287 if (stream
.next_frame
)
288 ci
->advance_buffer_loc((void *)stream
.next_frame
);
290 ci
->advance_buffer(size
);
294 } else if (MAD_RECOVERABLE(stream
.error
)) {
297 /* Some other unrecoverable error */
298 status
= CODEC_ERROR
;
306 /* Do the pcmbuf insert here. Note, this is the PREVIOUS frame's pcm
307 data (not the one just decoded above). When we exit the decoding
308 loop we will need to process the final frame that was decoded. */
309 if (framelength
> 0) {
310 /* In case of a mono file, the second array will be ignored. */
311 ci
->pcmbuf_insert(&synth
.pcm
.samples
[0][samples_to_skip
],
312 &synth
.pcm
.samples
[1][samples_to_skip
],
315 /* Only skip samples for the first frame added. */
319 mad_synth_frame(&synth
, &frame
);
321 /* Check if sample rate and stereo settings changed in this frame. */
322 if (frame
.header
.samplerate
!= current_frequency
) {
323 current_frequency
= frame
.header
.samplerate
;
324 ci
->configure(DSP_SWITCH_FREQUENCY
, current_frequency
);
326 if (MAD_NCHANNELS(&frame
.header
) == 2) {
327 if (current_stereo_mode
!= STEREO_NONINTERLEAVED
) {
328 ci
->configure(DSP_SET_STEREO_MODE
, STEREO_NONINTERLEAVED
);
329 current_stereo_mode
= STEREO_NONINTERLEAVED
;
332 if (current_stereo_mode
!= STEREO_MONO
) {
333 ci
->configure(DSP_SET_STEREO_MODE
, STEREO_MONO
);
334 current_stereo_mode
= STEREO_MONO
;
338 if (stream
.next_frame
)
339 ci
->advance_buffer_loc((void *)stream
.next_frame
);
341 ci
->advance_buffer(size
);
343 framelength
= synth
.pcm
.length
- samples_to_skip
;
344 if (framelength
< 0) {
346 samples_to_skip
-= synth
.pcm
.length
;
349 samplesdone
+= framelength
;
350 ci
->set_elapsed(samplesdone
/ (current_frequency
/ 1000));
353 /* Finish the remaining decoded frame.
354 Cut the required samples from the end. */
355 if (framelength
> stop_skip
)
356 ci
->pcmbuf_insert(synth
.pcm
.samples
[0], synth
.pcm
.samples
[1],
357 framelength
- stop_skip
);
361 if (ci
->request_next_track())