From 57f0ec1474bf5c0f0d5f361bd9909381ead9b915 Mon Sep 17 00:00:00 2001 From: Thom Johansen Date: Sun, 12 Jun 2005 14:03:31 +0000 Subject: 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 --- firmware/export/mp3data.h | 10 ++++++---- firmware/mp3data.c | 24 +++++++++++++++++++++++- 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 { long byte_count; /* File size in bytes */ long file_time; /* Length of the whole file in milliseconds */ int vbr_header_pos; + int enc_delay; /* Encoder delay, fetched from LAME header */ + int enc_padding; /* Padded samples added to last frame. LAME header */ }; /* Xing header information */ -#define VBR_FRAMES_FLAG 0x01 -#define VBR_BYTES_FLAG 0x02 -#define VBR_TOC_FLAG 0x04 - +#define VBR_FRAMES_FLAG 0x01 +#define VBR_BYTES_FLAG 0x02 +#define VBR_TOC_FLAG 0x04 +#define VBR_QUALITY_FLAG 0x08 unsigned long find_next_frame(int fd, long *offset, long max_offset, unsigned long last_header); unsigned 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 @@ #include #include #include "debug.h" +#include "logf.h" #include "mp3data.h" #include "file.h" #include "buffer.h" @@ -379,6 +380,12 @@ int get_mp3file_info(int fd, struct mp3info *info) return -1; memset(info, 0, sizeof(struct mp3info)); + /* These two are needed for proper LAME gapless MP3 playback */ + /* TODO: These can be found in a LAME Info header as well, but currently + they are only looked for in a Xing header. Xing and Info headers have + the exact same format, but Info headers are used for CBR files. */ + info->enc_delay = -1; + info->enc_padding = -1; if(!mp3headerinfo(info, header)) return -2; @@ -448,6 +455,22 @@ int get_mp3file_info(int fd, struct mp3info *info) if(vbrheader[7] & VBR_TOC_FLAG) /* Is table-of-contents there? */ { memcpy( info->toc, vbrheader+i, 100 ); + i += 100; + } + if (vbrheader[7] & VBR_QUALITY_FLAG) + { + /* We don't care about this, but need to skip it */ + i += 4; + } + i += 21; + info->enc_delay = (vbrheader[i] << 4) | (vbrheader[i + 1] >> 4); + info->enc_padding = ((vbrheader[i + 1] & 0x0f) << 8) | vbrheader[i + 2]; + if (!(info->enc_delay >= 0 && info->enc_delay <= 1152 && + info->enc_padding >= 0 && info->enc_padding <= 2*1152)) + { + /* Invalid data */ + info->enc_delay = -1; + info->enc_padding = -1; } } @@ -488,7 +511,6 @@ int get_mp3file_info(int fd, struct mp3info *info) vbrheader[12], vbrheader[13]); info->frame_count = BYTES2INT(vbrheader[14], vbrheader[15], vbrheader[16], vbrheader[17]); - info->file_time = info->frame_count * info->frame_time; info->bitrate = info->byte_count * 8 / info->file_time; -- cgit v1.2.3