diff options
author | Thom Johansen <thomj@rockbox.org> | 2005-11-02 19:02:25 +0000 |
---|---|---|
committer | Thom Johansen <thomj@rockbox.org> | 2005-11-02 19:02:25 +0000 |
commit | 6b8bd6bc1a3f68d74d0bf1a0893d117abb741c2a (patch) | |
tree | f33806f2b036b01b87936957947b7598aa25629b | |
parent | a1df060a933522234ab3064ea904a28e58c70a36 (diff) | |
download | rockbox-6b8bd6bc1a3f68d74d0bf1a0893d117abb741c2a.tar.gz rockbox-6b8bd6bc1a3f68d74d0bf1a0893d117abb741c2a.zip |
Support large delay fields in LAME header, plus some cleanups.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7731 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/codecs/mpa.c | 65 |
1 files changed, 37 insertions, 28 deletions
diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c index 45dff5c486..8c125500c7 100644 --- a/apps/codecs/mpa.c +++ b/apps/codecs/mpa.c @@ -74,7 +74,8 @@ enum codec_status codec_start(struct codec_api *api) int status = 0; long size; int file_end; - int frame_skip; + int frame_skip; /* samples to skip current frame */ + int samples_to_skip; /* samples to skip in total for this file (at start) */ char *inputbuffer; ci = api; @@ -106,7 +107,7 @@ enum codec_status codec_start(struct codec_api *api) mad_synth_init(&synth); /* We do this so libmad doesn't try to call codec_calloc() */ - memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap)); + ci->memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap)); frame.overlap = &mad_frame_overlap; stream.main_data = &mad_main_data; @@ -136,7 +137,7 @@ next_track: } samplesdone = ((int64_t)ci->id3->elapsed) * current_frequency / 1000; - frame_skip = start_skip; + samples_to_skip = start_skip; recalc_samplecount(); /* This is the decoding loop. */ @@ -158,7 +159,7 @@ next_track: if (!ci->seek_buffer(newpos)) goto next_track; if (newpos == 0) - frame_skip = start_skip; + samples_to_skip = start_skip; ci->seek_complete(); } @@ -170,10 +171,9 @@ next_track: mad_stream_buffer(&stream, inputbuffer, size); } - if (mad_frame_decode(&frame,&stream)) { + if (mad_frame_decode(&frame, &stream)) { if (stream.error == MAD_FLAG_INCOMPLETE || stream.error == MAD_ERROR_BUFLEN) { - // ci->splash(HZ*1, true, "Incomplete"); /* This makes the codec support partially corrupted files */ if (file_end == 30) break; @@ -188,57 +188,66 @@ next_track: } continue; } else if (stream.error == MAD_ERROR_BUFLEN) { - //rb->splash(HZ*1, true, "Buflen error"); break; } else { - //rb->splash(HZ*1, true, "Unrecoverable error"); + /* Some other unrecoverable error */ status = 1; break; } break; } - file_end = false; + file_end = 0; mad_synth_frame(&synth, &frame); - framelength = synth.pcm.length - frame_skip; - - /* We skip frame_skip number of samples here, this should only happen for - very first frame in the stream. */ - /* TODO: possible for frame_skip to exceed one frames worth of samples? */ - - if (frame.header.samplerate != current_frequency) { - current_frequency = frame.header.samplerate; - ci->configure(DSP_SWITCH_FREQUENCY, (int *)current_frequency); - recalc_samplecount(); + + /* We need to skip samples_to_skip samples from the start of every file + to properly support LAME style gapless MP3 files. samples_to_skip + might be larger than one frame. */ + if (samples_to_skip < synth.pcm.length) { + /* skip just part of the frame */ + frame_skip = samples_to_skip; + samples_to_skip = 0; + } else { + /* we need to skip an entire frame */ + frame_skip = synth.pcm.length; + samples_to_skip -= synth.pcm.length; } + + framelength = synth.pcm.length - frame_skip; if (stop_skip > 0) { int64_t max = samplecount - samplesdone; if (max < 0) max = 0; if (max < framelength) framelength = (int)max; - if (framelength == 0) break; } - + + /* Check if sample rate and stereo settings changed in this frame. */ + if (frame.header.samplerate != current_frequency) { + current_frequency = frame.header.samplerate; + ci->configure(DSP_SWITCH_FREQUENCY, (int *)current_frequency); + recalc_samplecount(); + } if (MAD_NCHANNELS(&frame.header) == 2) { if (current_stereo_mode != STEREO_NONINTERLEAVED) { ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED); current_stereo_mode = STEREO_NONINTERLEAVED; } - ci->pcmbuf_insert_split(&synth.pcm.samples[0][frame_skip], - &synth.pcm.samples[1][frame_skip], - framelength * 4); } else { if (current_stereo_mode != STEREO_MONO) { ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_MONO); current_stereo_mode = STEREO_MONO; } - ci->pcmbuf_insert((char *)&synth.pcm.samples[0][frame_skip], - framelength * 4); } - - frame_skip = 0; + + /* Check if we can just skip the entire frame. */ + if (frame_skip < synth.pcm.length) { + /* In case of a mono file, the second array will be ignored. */ + ci->pcmbuf_insert_split(&synth.pcm.samples[0][frame_skip], + &synth.pcm.samples[1][frame_skip], + framelength * 4); + } if (stream.next_frame) ci->advance_buffer_loc((void *)stream.next_frame); |