summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2005-08-10 22:59:06 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2005-08-10 22:59:06 +0000
commit0da0534d1062feff76f021fd1283fcb55832a7c7 (patch)
tree4411dd4647a1717551fc6406829157c2324ae058 /apps
parent315304aef660684e8ff0299f8a2ca1fb240c556f (diff)
downloadrockbox-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.c69
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[];
51extern char iramend[]; 51extern char iramend[];
52#endif 52#endif
53 53
54struct codec_api *ci;
55unsigned int samplecount;
56unsigned int samplesdone;
57int stop_skip, start_skip;
58int current_stereo_mode = -1;
59int frequency_divider;
60unsigned int current_frequency = 0;
61
62void 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 */
55enum codec_status codec_start(struct codec_api* api) 77enum 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