From 22c63269749aa6471235f9547e53bc9d6f8ce41b Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Thu, 8 Aug 2019 16:49:16 -0400 Subject: Improvements for vbrfix plugin: * Properly account for ID3v1 tags * Play time computation fixes * Add speech feedback Patch by Igor Poretsky Change-Id: Ia6df8fb171882a88527cfa9d3b76b705f09becdd --- lib/rbcodec/metadata/id3tags.c | 23 +++++++++++++++++++++++ lib/rbcodec/metadata/metadata_parsers.h | 1 + lib/rbcodec/metadata/mp3.c | 14 ++++++++------ lib/rbcodec/metadata/mp3data.c | 26 ++++++++++++++++---------- 4 files changed, 48 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/rbcodec/metadata/id3tags.c b/lib/rbcodec/metadata/id3tags.c index cda8ce3b7a..8236244d79 100644 --- a/lib/rbcodec/metadata/id3tags.c +++ b/lib/rbcodec/metadata/id3tags.c @@ -1134,6 +1134,29 @@ void setid3v2title(int fd, struct mp3entry *entry) } } +/* + * Calculates the size of the ID3v1 tag if any. + * + * Arguments: file - the file to search for a tag. + * + * Returns: the size of the tag or 0 if none was found + */ +int getid3v1len(int fd) +{ + char buf[4]; + + if (-1 == lseek(fd, -128, SEEK_END)) + return 0; + + if (read(fd, buf, 3) != 3) + return 0; + + if (strncmp(buf, "TAG", 3)) + return 0; + + return 128; +} + /* * Calculates the size of the ID3v2 tag. * diff --git a/lib/rbcodec/metadata/metadata_parsers.h b/lib/rbcodec/metadata/metadata_parsers.h index 9f03c79bb5..45cf140012 100644 --- a/lib/rbcodec/metadata/metadata_parsers.h +++ b/lib/rbcodec/metadata/metadata_parsers.h @@ -22,6 +22,7 @@ #if CONFIG_CODEC == SWCODEC char* id3_get_num_genre(unsigned int genre_num); #endif +int getid3v1len(int fd); int getid3v2len(int fd); bool setid3v1title(int fd, struct mp3entry *entry); void setid3v2title(int fd, struct mp3entry *entry); diff --git a/lib/rbcodec/metadata/mp3.c b/lib/rbcodec/metadata/mp3.c index 661fea8e51..2096e70898 100644 --- a/lib/rbcodec/metadata/mp3.c +++ b/lib/rbcodec/metadata/mp3.c @@ -71,7 +71,9 @@ static int getsonglength(int fd, struct mp3entry *entry) if(bytecount < 0) return -1; - bytecount += entry->id3v2len; + /* Subtract the meta information from the file size to get + the true size of the MP3 stream */ + entry->filesize -= entry->id3v1len + entry->id3v2len; /* Validate byte count, in case the file has been edited without * updating the header. @@ -99,6 +101,9 @@ static int getsonglength(int fd, struct mp3entry *entry) } } + entry->filesize -= bytecount; + bytecount += entry->id3v2len; + entry->bitrate = info.bitrate; entry->frequency = info.frequency; entry->layer = info.layer; @@ -127,7 +132,7 @@ static int getsonglength(int fd, struct mp3entry *entry) if (info.bitrate < 8) filetime = 0; else - filetime = (entry->filesize - bytecount) / (info.bitrate / 8); + filetime = entry->filesize / (info.bitrate >> 3); /* bitrate is in kbps so this delivers milliseconds. Doing bitrate / 8 * instead of filesize * 8 is exact, because mpeg audio bitrates are * always multiples of 8, and it avoids overflows. */ @@ -163,6 +168,7 @@ bool get_mp3_metadata(int fd, struct mp3entry *entry) { entry->title = NULL; entry->filesize = filesize(fd); + entry->id3v1len = getid3v1len(fd); entry->id3v2len = getid3v2len(fd); entry->tracknum = 0; entry->discnum = 0; @@ -174,10 +180,6 @@ bool get_mp3_metadata(int fd, struct mp3entry *entry) return false; entry->length = len; - /* Subtract the meta information from the file size to get - the true size of the MP3 stream */ - entry->filesize -= entry->first_frame_offset; - /* only seek to end of file if no id3v2 tags were found */ if (!entry->id3v2len) { setid3v1title(fd, entry); diff --git a/lib/rbcodec/metadata/mp3data.c b/lib/rbcodec/metadata/mp3data.c index 8a134dd534..49f9786c29 100644 --- a/lib/rbcodec/metadata/mp3data.c +++ b/lib/rbcodec/metadata/mp3data.c @@ -39,6 +39,9 @@ #include "mp3data.h" #include "platform.h" +#include "metadata.h" +#include "metadata/metadata_parsers.h" + //#define DEBUG_VERBOSE #ifdef DEBUG_VERBOSE @@ -340,7 +343,7 @@ static int buf_getbyte(int fd, unsigned char *c) static int buf_seek(int fd, int len) { fnf_read_index += len; - if(fnf_read_index > fnf_buf_len) + if(fnf_read_index >= fnf_buf_len) { len = fnf_read_index - fnf_buf_len; @@ -348,23 +351,22 @@ static int buf_seek(int fd, int len) if(fnf_buf_len < 0) return -1; - fnf_read_index = 0; - fnf_read_index += len; + fnf_read_index = len; } - if(fnf_read_index > fnf_buf_len) + if(fnf_read_index >= fnf_buf_len) { return -1; } - else - return 0; + + return 0; } static void buf_init(unsigned char* buf, size_t buflen) { fnf_buf = buf; fnf_buf_len = buflen; - fnf_read_index = 0; + fnf_read_index = buflen; } static unsigned long buf_find_next_frame(int fd, long *offset, long max_offset) @@ -601,14 +603,18 @@ int get_mp3file_info(int fd, struct mp3info *info) } else { + long offset; + VDEBUGF("-- No VBR header --\n"); /* There was no VBR header found. So, we seek back to beginning and * search for the first MPEG frame header of the mp3 stream. */ - lseek(fd, -info->frame_size, SEEK_CUR); + offset = lseek(fd, -info->frame_size, SEEK_CUR); result = get_next_header_info(fd, &bytecount, info, false); if(result) return result; + + info->byte_count = filesize(fd) - getid3v1len(fd) - offset - bytecount; } return bytecount; @@ -647,7 +653,7 @@ int count_mp3_frames(int fd, int startpos, int filesize, num_frames = 0; cnt = 0; - while((header = buf_find_next_frame(fd, &bytes, header_template))) { + while((header = buf_find_next_frame(fd, &bytes, startpos + filesize))) { mp3headerinfo(&info, header); if(!header_template) @@ -723,7 +729,7 @@ int create_xing_header(int fd, long startpos, long filesize, /* Advance from the last seek point to this one */ for(j = 0;j < pos - last_pos;j++) { - header = buf_find_next_frame(fd, &bytes, header_template); + header = buf_find_next_frame(fd, &bytes, startpos + filesize); filepos += bytes; mp3headerinfo(&info, header); buf_seek(fd, info.frame_size-4); -- cgit v1.2.3