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:
parent
e0776df670
commit
15e0aeb73b
1 changed files with 27 additions and 14 deletions
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue