summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThom Johansen <thomj@rockbox.org>2005-06-12 14:03:31 +0000
committerThom Johansen <thomj@rockbox.org>2005-06-12 14:03:31 +0000
commit57f0ec1474bf5c0f0d5f361bd9909381ead9b915 (patch)
tree3b4ffb949a1fa8dffa9fa78f47b44fc531b7e811
parentca19564eec76831b2888c62d619b8837586d8a8a (diff)
downloadrockbox-57f0ec1474bf5c0f0d5f361bd9909381ead9b915.tar.gz
rockbox-57f0ec1474bf5c0f0d5f361bd9909381ead9b915.zip
Added support for reading LAME header delay and padding fields for proper gapless MP3 support.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6689 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/export/mp3data.h10
-rw-r--r--firmware/mp3data.c24
2 files changed, 29 insertions, 5 deletions
diff --git a/firmware/export/mp3data.h b/firmware/export/mp3data.h
index c031cc20ce..a7f2e3d7f0 100644
--- a/firmware/export/mp3data.h
+++ b/firmware/export/mp3data.h
@@ -47,13 +47,15 @@ struct mp3info {
47 long byte_count; /* File size in bytes */ 47 long byte_count; /* File size in bytes */
48 long file_time; /* Length of the whole file in milliseconds */ 48 long file_time; /* Length of the whole file in milliseconds */
49 int vbr_header_pos; 49 int vbr_header_pos;
50 int enc_delay; /* Encoder delay, fetched from LAME header */
51 int enc_padding; /* Padded samples added to last frame. LAME header */
50}; 52};
51 53
52/* Xing header information */ 54/* Xing header information */
53#define VBR_FRAMES_FLAG 0x01 55#define VBR_FRAMES_FLAG 0x01
54#define VBR_BYTES_FLAG 0x02 56#define VBR_BYTES_FLAG 0x02
55#define VBR_TOC_FLAG 0x04 57#define VBR_TOC_FLAG 0x04
56 58#define VBR_QUALITY_FLAG 0x08
57 59
58unsigned long find_next_frame(int fd, long *offset, long max_offset, unsigned long last_header); 60unsigned long find_next_frame(int fd, long *offset, long max_offset, unsigned long last_header);
59unsigned long mem_find_next_frame(int startpos, long *offset, long max_offset, 61unsigned long mem_find_next_frame(int startpos, long *offset, long max_offset,
diff --git a/firmware/mp3data.c b/firmware/mp3data.c
index 32b3be4ffc..2b58710715 100644
--- a/firmware/mp3data.c
+++ b/firmware/mp3data.c
@@ -32,6 +32,7 @@
32#include <string.h> 32#include <string.h>
33#include <stdbool.h> 33#include <stdbool.h>
34#include "debug.h" 34#include "debug.h"
35#include "logf.h"
35#include "mp3data.h" 36#include "mp3data.h"
36#include "file.h" 37#include "file.h"
37#include "buffer.h" 38#include "buffer.h"
@@ -379,6 +380,12 @@ int get_mp3file_info(int fd, struct mp3info *info)
379 return -1; 380 return -1;
380 381
381 memset(info, 0, sizeof(struct mp3info)); 382 memset(info, 0, sizeof(struct mp3info));
383 /* These two are needed for proper LAME gapless MP3 playback */
384 /* TODO: These can be found in a LAME Info header as well, but currently
385 they are only looked for in a Xing header. Xing and Info headers have
386 the exact same format, but Info headers are used for CBR files. */
387 info->enc_delay = -1;
388 info->enc_padding = -1;
382 if(!mp3headerinfo(info, header)) 389 if(!mp3headerinfo(info, header))
383 return -2; 390 return -2;
384 391
@@ -448,6 +455,22 @@ int get_mp3file_info(int fd, struct mp3info *info)
448 if(vbrheader[7] & VBR_TOC_FLAG) /* Is table-of-contents there? */ 455 if(vbrheader[7] & VBR_TOC_FLAG) /* Is table-of-contents there? */
449 { 456 {
450 memcpy( info->toc, vbrheader+i, 100 ); 457 memcpy( info->toc, vbrheader+i, 100 );
458 i += 100;
459 }
460 if (vbrheader[7] & VBR_QUALITY_FLAG)
461 {
462 /* We don't care about this, but need to skip it */
463 i += 4;
464 }
465 i += 21;
466 info->enc_delay = (vbrheader[i] << 4) | (vbrheader[i + 1] >> 4);
467 info->enc_padding = ((vbrheader[i + 1] & 0x0f) << 8) | vbrheader[i + 2];
468 if (!(info->enc_delay >= 0 && info->enc_delay <= 1152 &&
469 info->enc_padding >= 0 && info->enc_padding <= 2*1152))
470 {
471 /* Invalid data */
472 info->enc_delay = -1;
473 info->enc_padding = -1;
451 } 474 }
452 } 475 }
453 476
@@ -488,7 +511,6 @@ int get_mp3file_info(int fd, struct mp3info *info)
488 vbrheader[12], vbrheader[13]); 511 vbrheader[12], vbrheader[13]);
489 info->frame_count = BYTES2INT(vbrheader[14], vbrheader[15], 512 info->frame_count = BYTES2INT(vbrheader[14], vbrheader[15],
490 vbrheader[16], vbrheader[17]); 513 vbrheader[16], vbrheader[17]);
491
492 info->file_time = info->frame_count * info->frame_time; 514 info->file_time = info->frame_count * info->frame_time;
493 info->bitrate = info->byte_count * 8 / info->file_time; 515 info->bitrate = info->byte_count * 8 / info->file_time;
494 516