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 /* this is the codec entry point */
62 enum codec_status
codec_main(void)
67 int samples_to_skip
; /* samples to skip in total for this file (at start) */
70 int stop_skip
, start_skip
;
71 int current_stereo_mode
= -1;
72 unsigned long current_frequency
= 0;
74 int padding
= MAD_BUFFER_GUARD
; /* to help mad decode the last frame */
79 /* Create a decoder instance */
81 ci
->configure(DSP_SET_SAMPLE_DEPTH
, MAD_F_FRACBITS
);
86 /* Reinitializing seems to be necessary to avoid playback quircks when seeking. */
90 while (!*ci
->taginfo_ready
&& !ci
->stop_codec
)
93 ci
->configure(DSP_SWITCH_FREQUENCY
, ci
->id3
->frequency
);
94 current_frequency
= ci
->id3
->frequency
;
95 codec_set_replaygain(ci
->id3
);
98 ci
->seek_buffer(ci
->id3
->offset
);
100 ci
->seek_buffer(ci
->id3
->first_frame_offset
);
102 if (ci
->id3
->lead_trim
>= 0 && ci
->id3
->tail_trim
>= 0) {
103 stop_skip
= ci
->id3
->tail_trim
- mpeg_latency
[ci
->id3
->layer
];
104 if (stop_skip
< 0) stop_skip
= 0;
105 start_skip
= ci
->id3
->lead_trim
+ mpeg_latency
[ci
->id3
->layer
];
108 /* We want to skip this amount anyway */
109 start_skip
= mpeg_latency
[ci
->id3
->layer
];
112 /* Libmad will not decode the last frame without 8 bytes of extra padding
113 in the buffer. So, we can trick libmad into not decoding the last frame
114 if we are to skip it entirely and then cut the appropriate samples from
115 final frame that we did decode. Note, if all tags (ID3, APE) are not
116 properly stripped from the end of the file, this trick will not work. */
117 if (stop_skip
>= mpeg_framesize
[ci
->id3
->layer
]) {
119 stop_skip
-= mpeg_framesize
[ci
->id3
->layer
];
121 padding
= MAD_BUFFER_GUARD
;
124 samplesdone
= ((int64_t)ci
->id3
->elapsed
) * current_frequency
/ 1000;
126 /* Don't skip any samples unless we start at the beginning. */
130 samples_to_skip
= start_skip
;
134 /* This is the decoding loop. */
137 if (ci
->stop_codec
|| ci
->new_track
)
143 samplesdone
= ((int64_t)(ci
->seek_time
-1))*current_frequency
/1000;
145 if (ci
->seek_time
-1 == 0) {
146 newpos
= ci
->id3
->first_frame_offset
;
147 samples_to_skip
= start_skip
;
149 newpos
= ci
->mp3_get_filepos(ci
->seek_time
-1);
153 if (!ci
->seek_buffer(newpos
))
161 if (stream
.error
== 0) {
162 inputbuffer
= ci
->request_buffer(&size
, INPUT_CHUNK_SIZE
);
163 if (size
== 0 || inputbuffer
== NULL
)
165 mad_stream_buffer(&stream
, (unsigned char *)inputbuffer
,
169 if (mad_frame_decode(&frame
, &stream
)) {
170 if (stream
.error
== MAD_FLAG_INCOMPLETE
171 || stream
.error
== MAD_ERROR_BUFLEN
) {
172 /* This makes the codec support partially corrupted files */
176 /* Fill the buffer */
177 if (stream
.next_frame
)
178 ci
->advance_buffer_loc((void *)stream
.next_frame
);
180 ci
->advance_buffer(size
);
184 } else if (MAD_RECOVERABLE(stream
.error
)) {
187 /* Some other unrecoverable error */
188 status
= CODEC_ERROR
;
196 /* Do the pcmbuf insert here. Note, this is the PREVIOUS frame's pcm
197 data (not the one just decoded above). When we exit the decoding
198 loop we will need to process the final frame that was decoded. */
199 if (framelength
> 0) {
200 /* In case of a mono file, the second array will be ignored. */
201 ci
->pcmbuf_insert(&synth
.pcm
.samples
[0][samples_to_skip
],
202 &synth
.pcm
.samples
[1][samples_to_skip
],
205 /* Only skip samples for the first frame added. */
209 mad_synth_frame(&synth
, &frame
);
211 /* Check if sample rate and stereo settings changed in this frame. */
212 if (frame
.header
.samplerate
!= current_frequency
) {
213 current_frequency
= frame
.header
.samplerate
;
214 ci
->configure(DSP_SWITCH_FREQUENCY
, current_frequency
);
216 if (MAD_NCHANNELS(&frame
.header
) == 2) {
217 if (current_stereo_mode
!= STEREO_NONINTERLEAVED
) {
218 ci
->configure(DSP_SET_STEREO_MODE
, STEREO_NONINTERLEAVED
);
219 current_stereo_mode
= STEREO_NONINTERLEAVED
;
222 if (current_stereo_mode
!= STEREO_MONO
) {
223 ci
->configure(DSP_SET_STEREO_MODE
, STEREO_MONO
);
224 current_stereo_mode
= STEREO_MONO
;
228 if (stream
.next_frame
)
229 ci
->advance_buffer_loc((void *)stream
.next_frame
);
231 ci
->advance_buffer(size
);
233 framelength
= synth
.pcm
.length
- samples_to_skip
;
234 if (framelength
< 0) {
236 samples_to_skip
-= synth
.pcm
.length
;
239 samplesdone
+= framelength
;
240 ci
->set_elapsed(samplesdone
/ (current_frequency
/ 1000));
243 /* Finish the remaining decoded frame.
244 Cut the required samples from the end. */
245 if (framelength
> stop_skip
)
246 ci
->pcmbuf_insert(synth
.pcm
.samples
[0], synth
.pcm
.samples
[1],
247 framelength
- stop_skip
);
251 if (ci
->request_next_track())