forked from len0rd/rockbox
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
This commit is contained in:
parent
a1df060a93
commit
6b8bd6bc1a
1 changed files with 37 additions and 28 deletions
|
|
@ -74,7 +74,8 @@ enum codec_status codec_start(struct codec_api *api)
|
||||||
int status = 0;
|
int status = 0;
|
||||||
long size;
|
long size;
|
||||||
int file_end;
|
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;
|
char *inputbuffer;
|
||||||
|
|
||||||
ci = api;
|
ci = api;
|
||||||
|
|
@ -106,7 +107,7 @@ enum codec_status codec_start(struct codec_api *api)
|
||||||
mad_synth_init(&synth);
|
mad_synth_init(&synth);
|
||||||
|
|
||||||
/* We do this so libmad doesn't try to call codec_calloc() */
|
/* 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;
|
frame.overlap = &mad_frame_overlap;
|
||||||
stream.main_data = &mad_main_data;
|
stream.main_data = &mad_main_data;
|
||||||
|
|
||||||
|
|
@ -136,7 +137,7 @@ next_track:
|
||||||
}
|
}
|
||||||
|
|
||||||
samplesdone = ((int64_t)ci->id3->elapsed) * current_frequency / 1000;
|
samplesdone = ((int64_t)ci->id3->elapsed) * current_frequency / 1000;
|
||||||
frame_skip = start_skip;
|
samples_to_skip = start_skip;
|
||||||
recalc_samplecount();
|
recalc_samplecount();
|
||||||
|
|
||||||
/* This is the decoding loop. */
|
/* This is the decoding loop. */
|
||||||
|
|
@ -158,7 +159,7 @@ next_track:
|
||||||
if (!ci->seek_buffer(newpos))
|
if (!ci->seek_buffer(newpos))
|
||||||
goto next_track;
|
goto next_track;
|
||||||
if (newpos == 0)
|
if (newpos == 0)
|
||||||
frame_skip = start_skip;
|
samples_to_skip = start_skip;
|
||||||
ci->seek_complete();
|
ci->seek_complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -170,10 +171,9 @@ next_track:
|
||||||
mad_stream_buffer(&stream, inputbuffer, size);
|
mad_stream_buffer(&stream, inputbuffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mad_frame_decode(&frame,&stream)) {
|
if (mad_frame_decode(&frame, &stream)) {
|
||||||
if (stream.error == MAD_FLAG_INCOMPLETE
|
if (stream.error == MAD_FLAG_INCOMPLETE
|
||||||
|| stream.error == MAD_ERROR_BUFLEN) {
|
|| stream.error == MAD_ERROR_BUFLEN) {
|
||||||
// ci->splash(HZ*1, true, "Incomplete");
|
|
||||||
/* This makes the codec support partially corrupted files */
|
/* This makes the codec support partially corrupted files */
|
||||||
if (file_end == 30)
|
if (file_end == 30)
|
||||||
break;
|
break;
|
||||||
|
|
@ -188,57 +188,66 @@ next_track:
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
} else if (stream.error == MAD_ERROR_BUFLEN) {
|
} else if (stream.error == MAD_ERROR_BUFLEN) {
|
||||||
//rb->splash(HZ*1, true, "Buflen error");
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
//rb->splash(HZ*1, true, "Unrecoverable error");
|
/* Some other unrecoverable error */
|
||||||
status = 1;
|
status = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_end = false;
|
file_end = 0;
|
||||||
|
|
||||||
mad_synth_frame(&synth, &frame);
|
mad_synth_frame(&synth, &frame);
|
||||||
framelength = synth.pcm.length - frame_skip;
|
|
||||||
|
/* We need to skip samples_to_skip samples from the start of every file
|
||||||
/* We skip frame_skip number of samples here, this should only happen for
|
to properly support LAME style gapless MP3 files. samples_to_skip
|
||||||
very first frame in the stream. */
|
might be larger than one frame. */
|
||||||
/* TODO: possible for frame_skip to exceed one frames worth of samples? */
|
if (samples_to_skip < synth.pcm.length) {
|
||||||
|
/* skip just part of the frame */
|
||||||
if (frame.header.samplerate != current_frequency) {
|
frame_skip = samples_to_skip;
|
||||||
current_frequency = frame.header.samplerate;
|
samples_to_skip = 0;
|
||||||
ci->configure(DSP_SWITCH_FREQUENCY, (int *)current_frequency);
|
} else {
|
||||||
recalc_samplecount();
|
/* 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) {
|
if (stop_skip > 0) {
|
||||||
int64_t max = samplecount - samplesdone;
|
int64_t max = samplecount - samplesdone;
|
||||||
|
|
||||||
if (max < 0) max = 0;
|
if (max < 0) max = 0;
|
||||||
if (max < framelength) framelength = (int)max;
|
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 (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][frame_skip],
|
|
||||||
&synth.pcm.samples[1][frame_skip],
|
|
||||||
framelength * 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][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)
|
if (stream.next_frame)
|
||||||
ci->advance_buffer_loc((void *)stream.next_frame);
|
ci->advance_buffer_loc((void *)stream.next_frame);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue