summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus Holmgren <magnushol@gmail.com>2005-08-13 08:02:38 +0000
committerMagnus Holmgren <magnushol@gmail.com>2005-08-13 08:02:38 +0000
commit15e0aeb73b6e4d2a92a71d3ba75da0ce8f78520d (patch)
treec4ab634aee21b8df17ea04ecf3371b843e19b521
parente0776df67088b4562c43f883922bb8eb74a51605 (diff)
downloadrockbox-15e0aeb73b6e4d2a92a71d3ba75da0ce8f78520d.zip
rockbox-15e0aeb73b6e4d2a92a71d3ba75da0ce8f78520d.tar.gz
rockbox-15e0aeb73b6e4d2a92a71d3ba75da0ce8f78520d.tar.bz2
rockbox-15e0aeb73b6e4d2a92a71d3ba75da0ce8f78520d.tar.xz
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
-rw-r--r--apps/codecs/mpa.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c
index 84d768d..e43048f 100644
--- a/apps/codecs/mpa.c
+++ b/apps/codecs/mpa.c
@@ -79,8 +79,8 @@ enum codec_status codec_start(struct codec_api* api)
int Status = 0;
size_t size;
int file_end;
+ int frame_skip;
char *InputBuffer;
- bool first_frame;
ci = api;
@@ -129,7 +129,6 @@ enum codec_status codec_start(struct codec_api* api)
for gapless playback */
next_track:
- first_frame = false;
file_end = 0;
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;
+ frame_skip = start_skip;
+ recalc_samplecount();
/* This is the decoding loop. */
while (1) {
+ int framelength;
+
ci->yield();
if (ci->stop_codec || ci->reload_codec) {
break ;
@@ -175,10 +178,9 @@ enum codec_status codec_start(struct codec_api* api)
goto next_track;
}
ci->seek_time = 0;
+ if (newpos == 0) frame_skip = start_skip;
}
- recalc_samplecount();
-
/* Lock buffers */
if (Stream.error == 0) {
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_synth_frame(&Synth,&Frame);
+ framelength = Synth.pcm.length;
/* 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. */
- /* 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) {
current_frequency = Frame.header.samplerate;
@@ -238,30 +241,40 @@ enum codec_status codec_start(struct codec_api* api)
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 (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][start_skip],
- &Synth.pcm.samples[1][start_skip],
- (Synth.pcm.length - start_skip) * 4);
+ ci->pcmbuf_insert_split(&Synth.pcm.samples[0][frame_skip],
+ &Synth.pcm.samples[1][frame_skip],
+ (framelength - frame_skip) * 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][start_skip],
- (Synth.pcm.length - start_skip) * 4);
+ ci->pcmbuf_insert((char *)&Synth.pcm.samples[0][frame_skip],
+ (framelength - frame_skip) * 4);
}
- start_skip = 0; /* not very elegant, and might want to keep this value */
+
+ frame_skip = 0;
if (Stream.next_frame)
ci->advance_buffer_loc((void *)Stream.next_frame);
else
ci->advance_buffer(size);
-
- samplesdone += Synth.pcm.length;
+
+ samplesdone += framelength;
ci->set_elapsed(samplesdone / (frequency_divider / 10));
}