1
0
Fork 0
forked from len0rd/rockbox

mp3 codec: simpler seeking, and now sets the sample frequency dynamically from the mp3 frame headers rather than from the frequency found by the metadata parser

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7299 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Linus Nielsen Feltzing 2005-08-10 22:59:06 +00:00
parent 315304aef6
commit 0da0534d10

View file

@ -51,20 +51,38 @@ extern char iramstart[];
extern char iramend[]; extern char iramend[];
#endif #endif
struct codec_api *ci;
unsigned int samplecount;
unsigned int samplesdone;
int stop_skip, start_skip;
int current_stereo_mode = -1;
int frequency_divider;
unsigned int current_frequency = 0;
void recalc_samplecount(void)
{
/* NOTE: currently this doesn't work, the below calculated samples_count
seems to be right, but sometimes we just don't have all the data we
need... */
if (ci->id3->frame_count) {
/* TODO: 1152 is the frame size in samples for MPEG1 layer 2 and layer 3,
it's probably not correct at all for MPEG2 and layer 1 */
samplecount = ci->id3->frame_count*1152 - (start_skip + stop_skip);
} else {
samplecount = ci->id3->length * frequency_divider / 10;
}
}
/* this is the codec entry point */ /* this is the codec entry point */
enum codec_status codec_start(struct codec_api* api) enum codec_status codec_start(struct codec_api* api)
{ {
struct codec_api *ci = api;
int Status = 0; int Status = 0;
size_t size; size_t size;
int file_end; int file_end;
char *InputBuffer; char *InputBuffer;
unsigned int samplecount;
unsigned int samplesdone;
bool first_frame; bool first_frame;
int stop_skip, start_skip;
int current_stereo_mode = -1; ci = api;
int frequency_divider;
/* Generic codec inititialisation */ /* Generic codec inititialisation */
TEST_CODEC_API(api); TEST_CODEC_API(api);
@ -122,6 +140,7 @@ enum codec_status codec_start(struct codec_api* api)
frequency_divider = 441; frequency_divider = 441;
ci->configure(DSP_SET_FREQUENCY, (int *)ci->id3->frequency); ci->configure(DSP_SET_FREQUENCY, (int *)ci->id3->frequency);
current_frequency = ci->id3->frequency;
codec_set_replaygain(ci->id3); codec_set_replaygain(ci->id3);
ci->request_buffer(&size, ci->id3->first_frame_offset); ci->request_buffer(&size, ci->id3->first_frame_offset);
@ -137,18 +156,7 @@ enum codec_status codec_start(struct codec_api* api)
start_skip = mpeg_latency[ci->id3->layer]; start_skip = mpeg_latency[ci->id3->layer];
} }
/* NOTE: currently this doesn't work, the below calculated samples_count
seems to be right, but sometimes libmad just can't supply us with
all the data we need... */
if (ci->id3->frame_count) {
/* TODO: 1152 is the frame size in samples for MPEG1 layer 2 and layer 3,
it's probably not correct at all for MPEG2 and layer 1 */
samplecount = ci->id3->frame_count*1152 - (start_skip + stop_skip);
samplesdone = ci->id3->elapsed * frequency_divider / 10; samplesdone = ci->id3->elapsed * frequency_divider / 10;
} else {
samplecount = ci->id3->length * frequency_divider / 10;
samplesdone = ci->id3->elapsed * frequency_divider / 10;
}
/* This is the decoding loop. */ /* This is the decoding loop. */
while (1) { while (1) {
@ -158,21 +166,19 @@ enum codec_status codec_start(struct codec_api* api)
} }
if (ci->seek_time) { if (ci->seek_time) {
unsigned int sample_loc;
int newpos; int newpos;
sample_loc = ci->seek_time * frequency_divider / 10; samplesdone = (ci->seek_time-1) * frequency_divider / 10;
newpos = ci->mp3_get_filepos(ci->seek_time-1); newpos = ci->mp3_get_filepos(ci->seek_time-1);
if (sample_loc >= samplecount + samplesdone)
break ;
if (ci->seek_buffer(newpos)) { if (!ci->seek_buffer(newpos)) {
samplecount += samplesdone - sample_loc; goto next_track;
samplesdone = sample_loc;
} }
ci->seek_time = 0; ci->seek_time = 0;
} }
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,6 +230,14 @@ enum codec_status codec_start(struct codec_api* api)
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 start_skip to exceed one frames worth of samples? */
if(Frame.header.samplerate != current_frequency) {
current_frequency = Frame.header.samplerate;
frequency_divider = current_frequency / 100;
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);
@ -248,7 +262,6 @@ enum codec_status codec_start(struct codec_api* api)
ci->advance_buffer(size); ci->advance_buffer(size);
samplesdone += Synth.pcm.length; samplesdone += Synth.pcm.length;
samplecount -= Synth.pcm.length;
ci->set_elapsed(samplesdone / (frequency_divider / 10)); ci->set_elapsed(samplesdone / (frequency_divider / 10));
} }