1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Dave Chapman
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
21 #include <codecs/libmad/mad.h>
26 struct mad_stream stream IBSS_ATTR
;
27 struct mad_frame frame IBSS_ATTR
;
28 struct mad_synth synth IBSS_ATTR
;
30 /* The following function is used inside libmad - let's hope it's never
37 #define INPUT_CHUNK_SIZE 8192
39 mad_fixed_t mad_frame_overlap
[2][32][18] IBSS_ATTR
;
40 unsigned char mad_main_data
[MAD_BUFFER_MDLEN
] IBSS_ATTR
;
41 /* TODO: what latency does layer 1 have? */
42 int mpeg_latency
[3] = { 0, 481, 529 };
43 int mpeg_framesize
[3] = {384, 1152, 1152};
47 ci
->memset(&stream
, 0, sizeof(struct mad_stream
));
48 ci
->memset(&frame
, 0, sizeof(struct mad_frame
));
49 ci
->memset(&synth
, 0, sizeof(struct mad_synth
));
51 mad_stream_init(&stream
);
52 mad_frame_init(&frame
);
53 mad_synth_init(&synth
);
55 /* We do this so libmad doesn't try to call codec_calloc() */
56 ci
->memset(mad_frame_overlap
, 0, sizeof(mad_frame_overlap
));
57 frame
.overlap
= &mad_frame_overlap
;
58 stream
.main_data
= &mad_main_data
;
61 int get_file_pos(int newtime
)
64 struct mp3entry
*id3
= ci
->id3
;
68 /* Use the TOC to find the new position */
69 unsigned int percent
, remainder
;
70 int curtoc
, nexttoc
, plen
;
72 percent
= (newtime
*100) / id3
->length
;
76 curtoc
= id3
->toc
[percent
];
79 nexttoc
= id3
->toc
[percent
+1];
84 pos
= (id3
->filesize
/256)*curtoc
;
86 /* Use the remainder to get a more accurate position */
87 remainder
= (newtime
*100) % id3
->length
;
88 remainder
= (remainder
*100) / id3
->length
;
89 plen
= (nexttoc
- curtoc
)*(id3
->filesize
/256);
90 pos
+= (plen
/100)*remainder
;
92 /* No TOC exists, estimate the new position */
93 pos
= (id3
->filesize
/ (id3
->length
/ 1000)) *
96 } else if (id3
->bitrate
) {
97 pos
= newtime
* (id3
->bitrate
/ 8);
102 pos
+= id3
->first_frame_offset
;
104 /* Don't seek right to the end of the file so that we can
105 transition properly to the next song */
106 if (pos
>= (int)(id3
->filesize
- id3
->id3v1len
))
107 pos
= id3
->filesize
- id3
->id3v1len
- 1;
112 static void set_elapsed(struct mp3entry
* id3
)
114 unsigned long offset
= id3
->offset
> id3
->first_frame_offset
?
115 id3
->offset
- id3
->first_frame_offset
: 0;
118 if ( id3
->has_toc
) {
119 /* calculate elapsed time using TOC */
121 unsigned int remainder
, plen
, relpos
, nextpos
;
123 /* find wich percent we're at */
124 for (i
=0; i
<100; i
++ )
125 if ( offset
< id3
->toc
[i
] * (id3
->filesize
/ 256) )
132 relpos
= id3
->toc
[i
];
135 nextpos
= id3
->toc
[i
+1];
139 remainder
= offset
- (relpos
* (id3
->filesize
/ 256));
141 /* set time for this percent (divide before multiply to prevent
142 overflow on long files. loss of precision is negligible on
144 id3
->elapsed
= i
* (id3
->length
/ 100);
146 /* calculate remainder time */
147 plen
= (nextpos
- relpos
) * (id3
->filesize
/ 256);
148 id3
->elapsed
+= (((remainder
* 100) / plen
) *
149 (id3
->length
/ 10000));
152 /* no TOC exists. set a rough estimate using average bitrate */
153 int tpk
= id3
->length
/
154 ((id3
->filesize
- id3
->first_frame_offset
- id3
->id3v1len
) /
156 id3
->elapsed
= offset
/ 1024 * tpk
;
161 /* constant bitrate, use exact calculation */
162 if (id3
->bitrate
!= 0)
163 id3
->elapsed
= offset
/ (id3
->bitrate
/ 8);
167 /* this is the codec entry point */
168 enum codec_status
codec_main(void)
173 int samples_to_skip
; /* samples to skip in total for this file (at start) */
176 int stop_skip
, start_skip
;
177 int current_stereo_mode
= -1;
178 unsigned long current_frequency
= 0;
180 int padding
= MAD_BUFFER_GUARD
; /* to help mad decode the last frame */
185 /* Create a decoder instance */
187 ci
->configure(DSP_SET_SAMPLE_DEPTH
, MAD_F_FRACBITS
);
192 /* Reinitializing seems to be necessary to avoid playback quircks when seeking. */
196 while (!*ci
->taginfo_ready
&& !ci
->stop_codec
)
199 ci
->configure(DSP_SWITCH_FREQUENCY
, ci
->id3
->frequency
);
200 current_frequency
= ci
->id3
->frequency
;
201 codec_set_replaygain(ci
->id3
);
203 if (ci
->id3
->offset
) {
204 ci
->seek_buffer(ci
->id3
->offset
);
205 set_elapsed(ci
->id3
);
208 ci
->seek_buffer(ci
->id3
->first_frame_offset
);
210 if (ci
->id3
->lead_trim
>= 0 && ci
->id3
->tail_trim
>= 0) {
211 stop_skip
= ci
->id3
->tail_trim
- mpeg_latency
[ci
->id3
->layer
];
212 if (stop_skip
< 0) stop_skip
= 0;
213 start_skip
= ci
->id3
->lead_trim
+ mpeg_latency
[ci
->id3
->layer
];
216 /* We want to skip this amount anyway */
217 start_skip
= mpeg_latency
[ci
->id3
->layer
];
220 /* Libmad will not decode the last frame without 8 bytes of extra padding
221 in the buffer. So, we can trick libmad into not decoding the last frame
222 if we are to skip it entirely and then cut the appropriate samples from
223 final frame that we did decode. Note, if all tags (ID3, APE) are not
224 properly stripped from the end of the file, this trick will not work. */
225 if (stop_skip
>= mpeg_framesize
[ci
->id3
->layer
]) {
227 stop_skip
-= mpeg_framesize
[ci
->id3
->layer
];
229 padding
= MAD_BUFFER_GUARD
;
232 samplesdone
= ((int64_t)ci
->id3
->elapsed
) * current_frequency
/ 1000;
234 /* Don't skip any samples unless we start at the beginning. */
238 samples_to_skip
= start_skip
;
242 /* This is the decoding loop. */
245 if (ci
->stop_codec
|| ci
->new_track
)
251 samplesdone
= ((int64_t)(ci
->seek_time
-1))*current_frequency
/1000;
253 if (ci
->seek_time
-1 == 0) {
254 newpos
= ci
->id3
->first_frame_offset
;
255 samples_to_skip
= start_skip
;
257 newpos
= get_file_pos(ci
->seek_time
-1);
261 if (!ci
->seek_buffer(newpos
))
269 if (stream
.error
== 0) {
270 inputbuffer
= ci
->request_buffer(&size
, INPUT_CHUNK_SIZE
);
271 if (size
== 0 || inputbuffer
== NULL
)
273 mad_stream_buffer(&stream
, (unsigned char *)inputbuffer
,
277 if (mad_frame_decode(&frame
, &stream
)) {
278 if (stream
.error
== MAD_FLAG_INCOMPLETE
279 || stream
.error
== MAD_ERROR_BUFLEN
) {
280 /* This makes the codec support partially corrupted files */
284 /* Fill the buffer */
285 if (stream
.next_frame
)
286 ci
->advance_buffer_loc((void *)stream
.next_frame
);
288 ci
->advance_buffer(size
);
292 } else if (MAD_RECOVERABLE(stream
.error
)) {
295 /* Some other unrecoverable error */
296 status
= CODEC_ERROR
;
304 /* Do the pcmbuf insert here. Note, this is the PREVIOUS frame's pcm
305 data (not the one just decoded above). When we exit the decoding
306 loop we will need to process the final frame that was decoded. */
307 if (framelength
> 0) {
308 /* In case of a mono file, the second array will be ignored. */
309 ci
->pcmbuf_insert(&synth
.pcm
.samples
[0][samples_to_skip
],
310 &synth
.pcm
.samples
[1][samples_to_skip
],
313 /* Only skip samples for the first frame added. */
317 mad_synth_frame(&synth
, &frame
);
319 /* Check if sample rate and stereo settings changed in this frame. */
320 if (frame
.header
.samplerate
!= current_frequency
) {
321 current_frequency
= frame
.header
.samplerate
;
322 ci
->configure(DSP_SWITCH_FREQUENCY
, current_frequency
);
324 if (MAD_NCHANNELS(&frame
.header
) == 2) {
325 if (current_stereo_mode
!= STEREO_NONINTERLEAVED
) {
326 ci
->configure(DSP_SET_STEREO_MODE
, STEREO_NONINTERLEAVED
);
327 current_stereo_mode
= STEREO_NONINTERLEAVED
;
330 if (current_stereo_mode
!= STEREO_MONO
) {
331 ci
->configure(DSP_SET_STEREO_MODE
, STEREO_MONO
);
332 current_stereo_mode
= STEREO_MONO
;
336 if (stream
.next_frame
)
337 ci
->advance_buffer_loc((void *)stream
.next_frame
);
339 ci
->advance_buffer(size
);
341 framelength
= synth
.pcm
.length
- samples_to_skip
;
342 if (framelength
< 0) {
344 samples_to_skip
-= synth
.pcm
.length
;
347 samplesdone
+= framelength
;
348 ci
->set_elapsed(samplesdone
/ (current_frequency
/ 1000));
351 /* Finish the remaining decoded frame.
352 Cut the required samples from the end. */
353 if (framelength
> stop_skip
)
354 ci
->pcmbuf_insert(synth
.pcm
.samples
[0], synth
.pcm
.samples
[1],
355 framelength
- stop_skip
);
359 if (ci
->request_next_track())