1
0
Fork 0
forked from len0rd/rockbox

More complete gapless playback implementation in the MP3 codec (using LAME header values). Some cleanups as well.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7312 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Magnus Holmgren 2005-08-13 08:02:38 +00:00
parent e0776df670
commit 15e0aeb73b

View file

@ -79,8 +79,8 @@ enum codec_status codec_start(struct codec_api* api)
int Status = 0; int Status = 0;
size_t size; size_t size;
int file_end; int file_end;
int frame_skip;
char *InputBuffer; char *InputBuffer;
bool first_frame;
ci = api; ci = api;
@ -129,7 +129,6 @@ enum codec_status codec_start(struct codec_api* api)
for gapless playback */ for gapless playback */
next_track: next_track:
first_frame = false;
file_end = 0; file_end = 0;
while (!*ci->taginfo_ready && !ci->stop_codec) while (!*ci->taginfo_ready && !ci->stop_codec)
@ -157,9 +156,13 @@ enum codec_status codec_start(struct codec_api* api)
} }
samplesdone = ci->id3->elapsed * frequency_divider / 10; samplesdone = ci->id3->elapsed * frequency_divider / 10;
frame_skip = start_skip;
recalc_samplecount();
/* This is the decoding loop. */ /* This is the decoding loop. */
while (1) { while (1) {
int framelength;
ci->yield(); ci->yield();
if (ci->stop_codec || ci->reload_codec) { if (ci->stop_codec || ci->reload_codec) {
break ; break ;
@ -175,10 +178,9 @@ enum codec_status codec_start(struct codec_api* api)
goto next_track; goto next_track;
} }
ci->seek_time = 0; ci->seek_time = 0;
if (newpos == 0) frame_skip = start_skip;
} }
recalc_samplecount();
/* Lock buffers */ /* Lock buffers */
if (Stream.error == 0) { if (Stream.error == 0) {
InputBuffer = ci->request_buffer(&size, INPUT_CHUNK_SIZE); InputBuffer = ci->request_buffer(&size, INPUT_CHUNK_SIZE);
@ -224,11 +226,12 @@ enum codec_status codec_start(struct codec_api* api)
// mad_timer_add(&Timer,Frame.header.duration); // mad_timer_add(&Timer,Frame.header.duration);
mad_synth_frame(&Synth,&Frame); mad_synth_frame(&Synth,&Frame);
framelength = Synth.pcm.length;
/* Convert MAD's numbers to an array of 16-bit LE signed integers */ /* Convert MAD's numbers to an array of 16-bit LE signed integers */
/* We skip start_skip number of samples here, this should only happen for /* We skip frame_skip number of samples here, this should only happen for
very first frame in the stream. */ very first frame in the stream. */
/* TODO: possible for start_skip to exceed one frames worth of samples? */ /* TODO: possible for frame_skip to exceed one frames worth of samples? */
if(Frame.header.samplerate != current_frequency) { if(Frame.header.samplerate != current_frequency) {
current_frequency = Frame.header.samplerate; current_frequency = Frame.header.samplerate;
@ -238,30 +241,40 @@ enum codec_status codec_start(struct codec_api* api)
recalc_samplecount(); recalc_samplecount();
} }
if (stop_skip > 0)
{
long max = samplecount - samplesdone;
if (max < 0) max = 0;
if (max < framelength) framelength = max;
if (framelength == 0) break;
}
if (MAD_NCHANNELS(&Frame.header) == 2) { if (MAD_NCHANNELS(&Frame.header) == 2) {
if (current_stereo_mode != STEREO_NONINTERLEAVED) { if (current_stereo_mode != STEREO_NONINTERLEAVED) {
ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED); ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED);
current_stereo_mode = STEREO_NONINTERLEAVED; current_stereo_mode = STEREO_NONINTERLEAVED;
} }
ci->pcmbuf_insert_split(&Synth.pcm.samples[0][start_skip], ci->pcmbuf_insert_split(&Synth.pcm.samples[0][frame_skip],
&Synth.pcm.samples[1][start_skip], &Synth.pcm.samples[1][frame_skip],
(Synth.pcm.length - start_skip) * 4); (framelength - frame_skip) * 4);
} else { } else {
if (current_stereo_mode != STEREO_MONO) { if (current_stereo_mode != STEREO_MONO) {
ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_MONO); ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_MONO);
current_stereo_mode = STEREO_MONO; current_stereo_mode = STEREO_MONO;
} }
ci->pcmbuf_insert((char *)&Synth.pcm.samples[0][start_skip], ci->pcmbuf_insert((char *)&Synth.pcm.samples[0][frame_skip],
(Synth.pcm.length - start_skip) * 4); (framelength - frame_skip) * 4);
} }
start_skip = 0; /* not very elegant, and might want to keep this value */
frame_skip = 0;
if (Stream.next_frame) if (Stream.next_frame)
ci->advance_buffer_loc((void *)Stream.next_frame); ci->advance_buffer_loc((void *)Stream.next_frame);
else else
ci->advance_buffer(size); ci->advance_buffer(size);
samplesdone += Synth.pcm.length; samplesdone += framelength;
ci->set_elapsed(samplesdone / (frequency_divider / 10)); ci->set_elapsed(samplesdone / (frequency_divider / 10));
} }