diff options
author | Linus Nielsen Feltzing <linus@haxx.se> | 2005-08-10 22:59:06 +0000 |
---|---|---|
committer | Linus Nielsen Feltzing <linus@haxx.se> | 2005-08-10 22:59:06 +0000 |
commit | 0da0534d1062feff76f021fd1283fcb55832a7c7 (patch) | |
tree | 4411dd4647a1717551fc6406829157c2324ae058 /apps | |
parent | 315304aef660684e8ff0299f8a2ca1fb240c556f (diff) | |
download | rockbox-0da0534d1062feff76f021fd1283fcb55832a7c7.tar.gz rockbox-0da0534d1062feff76f021fd1283fcb55832a7c7.zip |
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
Diffstat (limited to 'apps')
-rw-r--r-- | apps/codecs/mpa.c | 69 |
1 files changed, 41 insertions, 28 deletions
diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c index 8cfd6eff1c..84d768d543 100644 --- a/apps/codecs/mpa.c +++ b/apps/codecs/mpa.c | |||
@@ -51,20 +51,38 @@ extern char iramstart[]; | |||
51 | extern char iramend[]; | 51 | extern char iramend[]; |
52 | #endif | 52 | #endif |
53 | 53 | ||
54 | struct codec_api *ci; | ||
55 | unsigned int samplecount; | ||
56 | unsigned int samplesdone; | ||
57 | int stop_skip, start_skip; | ||
58 | int current_stereo_mode = -1; | ||
59 | int frequency_divider; | ||
60 | unsigned int current_frequency = 0; | ||
61 | |||
62 | void recalc_samplecount(void) | ||
63 | { | ||
64 | /* NOTE: currently this doesn't work, the below calculated samples_count | ||
65 | seems to be right, but sometimes we just don't have all the data we | ||
66 | need... */ | ||
67 | if (ci->id3->frame_count) { | ||
68 | /* TODO: 1152 is the frame size in samples for MPEG1 layer 2 and layer 3, | ||
69 | it's probably not correct at all for MPEG2 and layer 1 */ | ||
70 | samplecount = ci->id3->frame_count*1152 - (start_skip + stop_skip); | ||
71 | } else { | ||
72 | samplecount = ci->id3->length * frequency_divider / 10; | ||
73 | } | ||
74 | } | ||
75 | |||
54 | /* this is the codec entry point */ | 76 | /* this is the codec entry point */ |
55 | enum codec_status codec_start(struct codec_api* api) | 77 | enum codec_status codec_start(struct codec_api* api) |
56 | { | 78 | { |
57 | struct codec_api *ci = api; | ||
58 | int Status = 0; | 79 | int Status = 0; |
59 | size_t size; | 80 | size_t size; |
60 | int file_end; | 81 | int file_end; |
61 | char *InputBuffer; | 82 | char *InputBuffer; |
62 | unsigned int samplecount; | ||
63 | unsigned int samplesdone; | ||
64 | bool first_frame; | 83 | bool first_frame; |
65 | int stop_skip, start_skip; | 84 | |
66 | int current_stereo_mode = -1; | 85 | ci = api; |
67 | int frequency_divider; | ||
68 | 86 | ||
69 | /* Generic codec inititialisation */ | 87 | /* Generic codec inititialisation */ |
70 | TEST_CODEC_API(api); | 88 | TEST_CODEC_API(api); |
@@ -122,6 +140,7 @@ enum codec_status codec_start(struct codec_api* api) | |||
122 | frequency_divider = 441; | 140 | frequency_divider = 441; |
123 | 141 | ||
124 | ci->configure(DSP_SET_FREQUENCY, (int *)ci->id3->frequency); | 142 | ci->configure(DSP_SET_FREQUENCY, (int *)ci->id3->frequency); |
143 | current_frequency = ci->id3->frequency; | ||
125 | codec_set_replaygain(ci->id3); | 144 | codec_set_replaygain(ci->id3); |
126 | 145 | ||
127 | ci->request_buffer(&size, ci->id3->first_frame_offset); | 146 | ci->request_buffer(&size, ci->id3->first_frame_offset); |
@@ -136,20 +155,9 @@ enum codec_status codec_start(struct codec_api* api) | |||
136 | /* We want to skip this amount anyway */ | 155 | /* We want to skip this amount anyway */ |
137 | start_skip = mpeg_latency[ci->id3->layer]; | 156 | start_skip = mpeg_latency[ci->id3->layer]; |
138 | } | 157 | } |
139 | |||
140 | /* NOTE: currently this doesn't work, the below calculated samples_count | ||
141 | seems to be right, but sometimes libmad just can't supply us with | ||
142 | all the data we need... */ | ||
143 | if (ci->id3->frame_count) { | ||
144 | /* TODO: 1152 is the frame size in samples for MPEG1 layer 2 and layer 3, | ||
145 | it's probably not correct at all for MPEG2 and layer 1 */ | ||
146 | samplecount = ci->id3->frame_count*1152 - (start_skip + stop_skip); | ||
147 | samplesdone = ci->id3->elapsed * frequency_divider / 10; | ||
148 | } else { | ||
149 | samplecount = ci->id3->length * frequency_divider / 10; | ||
150 | samplesdone = ci->id3->elapsed * frequency_divider / 10; | ||
151 | } | ||
152 | 158 | ||
159 | samplesdone = ci->id3->elapsed * frequency_divider / 10; | ||
160 | |||
153 | /* This is the decoding loop. */ | 161 | /* This is the decoding loop. */ |
154 | while (1) { | 162 | while (1) { |
155 | ci->yield(); | 163 | ci->yield(); |
@@ -158,21 +166,19 @@ enum codec_status codec_start(struct codec_api* api) | |||
158 | } | 166 | } |
159 | 167 | ||
160 | if (ci->seek_time) { | 168 | if (ci->seek_time) { |
161 | unsigned int sample_loc; | ||
162 | int newpos; | 169 | int newpos; |
163 | 170 | ||
164 | sample_loc = ci->seek_time * frequency_divider / 10; | 171 | samplesdone = (ci->seek_time-1) * frequency_divider / 10; |
165 | newpos = ci->mp3_get_filepos(ci->seek_time-1); | 172 | newpos = ci->mp3_get_filepos(ci->seek_time-1); |
166 | if (sample_loc >= samplecount + samplesdone) | 173 | |
167 | break ; | 174 | if (!ci->seek_buffer(newpos)) { |
168 | 175 | goto next_track; | |
169 | if (ci->seek_buffer(newpos)) { | ||
170 | samplecount += samplesdone - sample_loc; | ||
171 | samplesdone = sample_loc; | ||
172 | } | 176 | } |
173 | ci->seek_time = 0; | 177 | ci->seek_time = 0; |
174 | } | 178 | } |
175 | 179 | ||
180 | recalc_samplecount(); | ||
181 | |||
176 | /* Lock buffers */ | 182 | /* Lock buffers */ |
177 | if (Stream.error == 0) { | 183 | if (Stream.error == 0) { |
178 | InputBuffer = ci->request_buffer(&size, INPUT_CHUNK_SIZE); | 184 | InputBuffer = ci->request_buffer(&size, INPUT_CHUNK_SIZE); |
@@ -224,6 +230,14 @@ enum codec_status codec_start(struct codec_api* api) | |||
224 | very first frame in the stream. */ | 230 | very first frame in the stream. */ |
225 | /* TODO: possible for start_skip to exceed one frames worth of samples? */ | 231 | /* TODO: possible for start_skip to exceed one frames worth of samples? */ |
226 | 232 | ||
233 | if(Frame.header.samplerate != current_frequency) { | ||
234 | current_frequency = Frame.header.samplerate; | ||
235 | frequency_divider = current_frequency / 100; | ||
236 | ci->configure(DSP_SWITCH_FREQUENCY, | ||
237 | (int *)current_frequency); | ||
238 | recalc_samplecount(); | ||
239 | } | ||
240 | |||
227 | if (MAD_NCHANNELS(&Frame.header) == 2) { | 241 | if (MAD_NCHANNELS(&Frame.header) == 2) { |
228 | if (current_stereo_mode != STEREO_NONINTERLEAVED) { | 242 | if (current_stereo_mode != STEREO_NONINTERLEAVED) { |
229 | ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED); | 243 | ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED); |
@@ -248,7 +262,6 @@ enum codec_status codec_start(struct codec_api* api) | |||
248 | ci->advance_buffer(size); | 262 | ci->advance_buffer(size); |
249 | 263 | ||
250 | samplesdone += Synth.pcm.length; | 264 | samplesdone += Synth.pcm.length; |
251 | samplecount -= Synth.pcm.length; | ||
252 | ci->set_elapsed(samplesdone / (frequency_divider / 10)); | 265 | ci->set_elapsed(samplesdone / (frequency_divider / 10)); |
253 | } | 266 | } |
254 | 267 | ||