summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorThom Johansen <thomj@rockbox.org>2005-06-12 14:38:36 +0000
committerThom Johansen <thomj@rockbox.org>2005-06-12 14:38:36 +0000
commit7cdae1ac657e3fe6ffc01bf9b3536d2cc1638fed (patch)
tree5fd9bf938b0114b17e2174bbfa8d53afb5642c99 /apps
parent57f0ec1474bf5c0f0d5f361bd9909381ead9b915 (diff)
downloadrockbox-7cdae1ac657e3fe6ffc01bf9b3536d2cc1638fed.tar.gz
rockbox-7cdae1ac657e3fe6ffc01bf9b3536d2cc1638fed.zip
First attempt at gapless MP3 support using LAME header info.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6690 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/codecmpa.c49
1 files changed, 40 insertions, 9 deletions
diff --git a/apps/plugins/codecmpa.c b/apps/plugins/codecmpa.c
index 86211df566..b152f2cb3e 100644
--- a/apps/plugins/codecmpa.c
+++ b/apps/plugins/codecmpa.c
@@ -172,7 +172,8 @@ const unsigned char *OutputBufferEnd=OutputBuffer+OUTPUT_BUFFER_SIZE;
172 172
173mad_fixed_t mad_frame_overlap[2][32][18] IDATA_ATTR; 173mad_fixed_t mad_frame_overlap[2][32][18] IDATA_ATTR;
174unsigned char mad_main_data[MAD_BUFFER_MDLEN] IDATA_ATTR; 174unsigned char mad_main_data[MAD_BUFFER_MDLEN] IDATA_ATTR;
175 175/* TODO: what latency does layer 1 have? */
176int mpeg_latency[3] = { 0, 481, 529 };
176#ifdef USE_IRAM 177#ifdef USE_IRAM
177extern char iramcopy[]; 178extern char iramcopy[];
178extern char iramstart[]; 179extern char iramstart[];
@@ -185,6 +186,7 @@ extern char iramend[];
185enum plugin_status plugin_start(struct plugin_api* api, void* parm) 186enum plugin_status plugin_start(struct plugin_api* api, void* parm)
186{ 187{
187 struct codec_api *ci = (struct codec_api *)parm; 188 struct codec_api *ci = (struct codec_api *)parm;
189 struct mp3info *info;
188 int Status=0; 190 int Status=0;
189 size_t size; 191 size_t size;
190 int file_end; 192 int file_end;
@@ -199,6 +201,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
199#endif 201#endif
200 int i; 202 int i;
201 int yieldcounter = 0; 203 int yieldcounter = 0;
204 int stop_skip, start_skip;
202 205
203 /* Generic plugin inititialisation */ 206 /* Generic plugin inititialisation */
204 207
@@ -220,7 +223,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
220 ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2)); 223 ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2));
221 ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16)); 224 ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16));
222 225
223 next_track:
224 memset(&Stream, 0, sizeof(struct mad_stream)); 226 memset(&Stream, 0, sizeof(struct mad_stream));
225 memset(&Frame, 0, sizeof(struct mad_frame)); 227 memset(&Frame, 0, sizeof(struct mad_frame));
226 memset(&Synth, 0, sizeof(struct mad_synth)); 228 memset(&Synth, 0, sizeof(struct mad_synth));
@@ -235,6 +237,10 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
235 memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap)); 237 memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap));
236 Frame.overlap = &mad_frame_overlap; 238 Frame.overlap = &mad_frame_overlap;
237 Stream.main_data = &mad_main_data; 239 Stream.main_data = &mad_main_data;
240 /* This label might need to be moved above all the init code, but I don't
241 think reiniting the codec is necessary for MPEG. It might even be unwanted
242 for gapless playback */
243 next_track:
238 244
239#ifdef DEBUG_GAPLESS 245#ifdef DEBUG_GAPLESS
240 if (first) 246 if (first)
@@ -243,7 +249,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
243 fd = rb->open("/second.pcm", O_WRONLY | O_CREAT); 249 fd = rb->open("/second.pcm", O_WRONLY | O_CREAT);
244 first = false; 250 first = false;
245#endif 251#endif
246 252
253 info = ci->mp3data;
247 first_frame = false; 254 first_frame = false;
248 file_end = 0; 255 file_end = 0;
249 OutputPtr = OutputBuffer; 256 OutputPtr = OutputBuffer;
@@ -254,9 +261,29 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
254 261
255 ci->request_buffer(&size, ci->id3->first_frame_offset); 262 ci->request_buffer(&size, ci->id3->first_frame_offset);
256 ci->advance_buffer(size); 263 ci->advance_buffer(size);
264
265 if (info->enc_delay >= 0 && info->enc_padding >= 0) {
266 stop_skip = info->enc_padding - mpeg_latency[info->layer];
267 if (stop_skip < 0) stop_skip = 0;
268 start_skip = info->enc_delay + mpeg_latency[info->layer];
269 } else {
270 stop_skip = 0;
271 /* We want to skip this amount anyway */
272 start_skip = mpeg_latency[info->layer];
273 }
257 274
258 samplecount = ci->id3->length * (ci->id3->frequency / 100) / 10; 275 /* NOTE: currently this doesn't work, the below calculated samples_count
259 samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10; 276 seems to be right, but sometimes libmad just can't supply us with
277 all the data we need... */
278 if (info->frame_count) {
279 /* TODO: 1152 is the frame size in samples for MPEG1 layer 2 and layer 3,
280 it's probably not correct at all for MPEG2 and layer 1 */
281 samplecount = info->frame_count*1152 - (start_skip + stop_skip);
282 samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10;
283 } else {
284 samplecount = ci->id3->length * (ci->id3->frequency / 100) / 10;
285 samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10;
286 }
260 /* rb->snprintf(buf2, sizeof(buf2), "sc: %d", samplecount); 287 /* rb->snprintf(buf2, sizeof(buf2), "sc: %d", samplecount);
261 rb->splash(0, true, buf2); 288 rb->splash(0, true, buf2);
262 rb->snprintf(buf2, sizeof(buf2), "length: %d", ci->id3->length); 289 rb->snprintf(buf2, sizeof(buf2), "length: %d", ci->id3->length);
@@ -304,7 +331,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
304 /* This makes the codec to support partially corrupted files too. */ 331 /* This makes the codec to support partially corrupted files too. */
305 if (file_end == 30) 332 if (file_end == 30)
306 break ; 333 break ;
307 334
308 /* Fill the buffer */ 335 /* Fill the buffer */
309 Stream.error = 0; 336 Stream.error = 0;
310 file_end++; 337 file_end++;
@@ -345,18 +372,22 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
345 //} 372 //}
346 373
347 /* Convert MAD's numbers to an array of 16-bit LE signed integers */ 374 /* Convert MAD's numbers to an array of 16-bit LE signed integers */
348 for(i=0;i<Synth.pcm.length;i++) 375 /* We skip start_skip number of samples here, this should only happen for
376 very first frame in the stream. */
377 /* TODO: possible for start_skip to exceed one frames worth of samples? */
378 for (i = start_skip;i<Synth.pcm.length;i++)
349 { 379 {
380 start_skip = 0; /* not very elegant, and might want to keep this value */
350 samplesdone++; 381 samplesdone++;
351 //if (ci->mp3data->padding > 0) { 382 //if (ci->mp3data->padding > 0) {
352 // ci->mp3data->padding--; 383 // ci->mp3data->padding--;
353 // continue ; 384 // continue ;
354 //} 385 //}
355 if (!first_frame) { 386 /*if (!first_frame) {
356 if (detect_silence(Synth.pcm.samples[0][i])) 387 if (detect_silence(Synth.pcm.samples[0][i]))
357 continue ; 388 continue ;
358 first_frame = true; 389 first_frame = true;
359 } 390 }*/
360 391
361 /* Left channel */ 392 /* Left channel */
362 Sample=scale(Synth.pcm.samples[0][i],&d0); 393 Sample=scale(Synth.pcm.samples[0][i],&d0);