lcd-common.h hasn't contained code in nearly 6 years.
[kugel-rb.git] / apps / codecs / mpa.c
bloba18a5e8090ec6b2d8f9fa584f231eb463e302d08
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
20 #include "codeclib.h"
21 #include <codecs/libmad/mad.h>
22 #include <inttypes.h>
24 CODEC_HEADER
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
31 called.
34 void abort(void) {
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};
45 void init_mad(void)
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)
63 int pos = -1;
64 struct mp3entry *id3 = ci->id3;
66 if (id3->vbr) {
67 if (id3->has_toc) {
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;
73 if (percent > 99)
74 percent = 99;
76 curtoc = id3->toc[percent];
78 if (percent < 99) {
79 nexttoc = id3->toc[percent+1];
80 } else {
81 nexttoc = 256;
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;
91 } else {
92 /* No TOC exists, estimate the new position */
93 pos = (id3->filesize / (id3->length / 1000)) *
94 (newtime / 1000);
96 } else if (id3->bitrate) {
97 pos = newtime * (id3->bitrate / 8);
98 } else {
99 return -1;
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;
109 return pos;
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;
117 if ( id3->vbr ) {
118 if ( id3->has_toc ) {
119 /* calculate elapsed time using TOC */
120 int i;
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) )
126 break;
128 i--;
129 if (i < 0)
130 i = 0;
132 relpos = id3->toc[i];
134 if (i < 99)
135 nextpos = id3->toc[i+1];
136 else
137 nextpos = 256;
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
143 short files) */
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));
151 else {
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) /
155 1024);
156 id3->elapsed = offset / 1024 * tpk;
159 else
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)
170 int status;
171 size_t size;
172 int file_end;
173 int samples_to_skip; /* samples to skip in total for this file (at start) */
174 char *inputbuffer;
175 int64_t samplesdone;
176 int stop_skip, start_skip;
177 int current_stereo_mode = -1;
178 unsigned long current_frequency = 0;
179 int framelength;
180 int padding = MAD_BUFFER_GUARD; /* to help mad decode the last frame */
182 if (codec_init())
183 return CODEC_ERROR;
185 /* Create a decoder instance */
187 ci->configure(DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS);
189 next_track:
190 status = CODEC_OK;
192 /* Reinitializing seems to be necessary to avoid playback quircks when seeking. */
193 init_mad();
195 file_end = 0;
196 while (!*ci->taginfo_ready && !ci->stop_codec)
197 ci->sleep(1);
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);
207 else
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];
214 } else {
215 stop_skip = 0;
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]) {
226 padding = 0;
227 stop_skip -= mpeg_framesize[ci->id3->layer];
228 } else {
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. */
235 if (samplesdone > 0)
236 samples_to_skip = 0;
237 else
238 samples_to_skip = start_skip;
240 framelength = 0;
242 /* This is the decoding loop. */
243 while (1) {
244 ci->yield();
245 if (ci->stop_codec || ci->new_track)
246 break;
248 if (ci->seek_time) {
249 int newpos;
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;
256 } else {
257 newpos = get_file_pos(ci->seek_time-1);
258 samples_to_skip = 0;
261 if (!ci->seek_buffer(newpos))
262 break;
263 ci->seek_complete();
264 init_mad();
265 framelength = 0;
268 /* Lock buffers */
269 if (stream.error == 0) {
270 inputbuffer = ci->request_buffer(&size, INPUT_CHUNK_SIZE);
271 if (size == 0 || inputbuffer == NULL)
272 break;
273 mad_stream_buffer(&stream, (unsigned char *)inputbuffer,
274 size + padding);
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 */
281 if (file_end == 30)
282 break;
284 /* Fill the buffer */
285 if (stream.next_frame)
286 ci->advance_buffer_loc((void *)stream.next_frame);
287 else
288 ci->advance_buffer(size);
289 stream.error = 0;
290 file_end++;
291 continue;
292 } else if (MAD_RECOVERABLE(stream.error)) {
293 continue;
294 } else {
295 /* Some other unrecoverable error */
296 status = CODEC_ERROR;
297 break;
299 break;
302 file_end = 0;
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],
311 framelength);
313 /* Only skip samples for the first frame added. */
314 samples_to_skip = 0;
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;
329 } else {
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);
338 else
339 ci->advance_buffer(size);
341 framelength = synth.pcm.length - samples_to_skip;
342 if (framelength < 0) {
343 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);
357 stream.error = 0;
359 if (ci->request_next_track())
360 goto next_track;
362 return status;