Improvements for vbrfix plugin:
* Properly account for ID3v1 tags * Play time computation fixes * Add speech feedback Patch by Igor Poretsky Change-Id: Ia6df8fb171882a88527cfa9d3b76b705f09becdd
This commit is contained in:
parent
c46147c6b2
commit
22c6326974
6 changed files with 91 additions and 23 deletions
|
@ -16390,3 +16390,31 @@ id: VOICE_BAT_BENCH_KEYS
|
||||||
lcd_bitmap: "Error writing config"
|
lcd_bitmap: "Error writing config"
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_NOT_A_VBR_FILE
|
||||||
|
desc: in vbrfix plugin
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Not a VBR file"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Not a VBR file"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Not a VBR file"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_FILE_ERROR
|
||||||
|
desc: in vbrfix plugin
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "File error: %d"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "File error: %d"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "File error"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
|
|
@ -26,11 +26,21 @@ static char *audiobuf;
|
||||||
static size_t audiobuflen;
|
static size_t audiobuflen;
|
||||||
unsigned char xingbuf[1500];
|
unsigned char xingbuf[1500];
|
||||||
char tmpname[MAX_PATH];
|
char tmpname[MAX_PATH];
|
||||||
|
static long last_talk = 0;
|
||||||
|
|
||||||
static void xingupdate(int percent)
|
static void xingupdate(int percent)
|
||||||
{
|
{
|
||||||
rb->lcd_putsf(0, 1, "%d%%", percent);
|
rb->lcd_putsf(0, 1, "%d%%", percent);
|
||||||
rb->lcd_update();
|
rb->lcd_update();
|
||||||
|
if (rb->global_settings->talk_menu)
|
||||||
|
{
|
||||||
|
long now = *(rb->current_tick) / HZ;
|
||||||
|
if (now - last_talk >= 5)
|
||||||
|
{
|
||||||
|
rb->talk_value(percent, UNIT_PERCENT, false);
|
||||||
|
last_talk = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int insert_data_in_file(const char *fname, int fpos, char *buf, int num_bytes)
|
static int insert_data_in_file(const char *fname, int fpos, char *buf, int num_bytes)
|
||||||
|
@ -114,7 +124,7 @@ static int insert_data_in_file(const char *fname, int fpos, char *buf, int num_b
|
||||||
|
|
||||||
static void fileerror(int rc)
|
static void fileerror(int rc)
|
||||||
{
|
{
|
||||||
rb->splashf(HZ*2, "File error: %d", rc);
|
rb->splashf(HZ*2, ID2P(LANG_FILE_ERROR), rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char empty_id3_header[] =
|
static const unsigned char empty_id3_header[] =
|
||||||
|
@ -128,7 +138,6 @@ static bool vbr_fix(const char *selected_file)
|
||||||
struct mp3entry entry;
|
struct mp3entry entry;
|
||||||
int fd;
|
int fd;
|
||||||
int rc;
|
int rc;
|
||||||
int flen;
|
|
||||||
int num_frames;
|
int num_frames;
|
||||||
int numbytes;
|
int numbytes;
|
||||||
int framelen;
|
int framelen;
|
||||||
|
@ -152,18 +161,16 @@ static bool vbr_fix(const char *selected_file)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
flen = rb->lseek(fd, 0, SEEK_END);
|
|
||||||
|
|
||||||
xingupdate(0);
|
xingupdate(0);
|
||||||
|
|
||||||
num_frames = rb->count_mp3_frames(fd, entry.first_frame_offset,
|
num_frames = rb->count_mp3_frames(fd, entry.first_frame_offset,
|
||||||
flen, xingupdate, audiobuf, audiobuflen);
|
entry.filesize, xingupdate, audiobuf, audiobuflen);
|
||||||
|
|
||||||
if(num_frames) {
|
if(num_frames) {
|
||||||
/* Note: We don't need to pass a template header because it will be
|
/* Note: We don't need to pass a template header because it will be
|
||||||
taken from the mpeg stream */
|
taken from the mpeg stream */
|
||||||
framelen = rb->create_xing_header(fd, entry.first_frame_offset,
|
framelen = rb->create_xing_header(fd, entry.first_frame_offset,
|
||||||
flen, xingbuf, num_frames, 0,
|
entry.filesize, xingbuf, num_frames, 0,
|
||||||
0, xingupdate, true,
|
0, xingupdate, true,
|
||||||
audiobuf, audiobuflen);
|
audiobuf, audiobuflen);
|
||||||
|
|
||||||
|
@ -253,7 +260,7 @@ static bool vbr_fix(const char *selected_file)
|
||||||
{
|
{
|
||||||
/* Not a VBR file */
|
/* Not a VBR file */
|
||||||
DEBUGF("Not a VBR file\n");
|
DEBUGF("Not a VBR file\n");
|
||||||
rb->splash(HZ*2, "Not a VBR file");
|
rb->splash(HZ*2, ID2P(LANG_NOT_A_VBR_FILE));
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -261,6 +268,7 @@ static bool vbr_fix(const char *selected_file)
|
||||||
|
|
||||||
enum plugin_status plugin_start(const void *parameter)
|
enum plugin_status plugin_start(const void *parameter)
|
||||||
{
|
{
|
||||||
|
last_talk = *(rb->current_tick) / HZ;
|
||||||
|
|
||||||
if (!parameter)
|
if (!parameter)
|
||||||
return PLUGIN_ERROR;
|
return PLUGIN_ERROR;
|
||||||
|
|
|
@ -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.
|
* Calculates the size of the ID3v2 tag.
|
||||||
*
|
*
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#if CONFIG_CODEC == SWCODEC
|
#if CONFIG_CODEC == SWCODEC
|
||||||
char* id3_get_num_genre(unsigned int genre_num);
|
char* id3_get_num_genre(unsigned int genre_num);
|
||||||
#endif
|
#endif
|
||||||
|
int getid3v1len(int fd);
|
||||||
int getid3v2len(int fd);
|
int getid3v2len(int fd);
|
||||||
bool setid3v1title(int fd, struct mp3entry *entry);
|
bool setid3v1title(int fd, struct mp3entry *entry);
|
||||||
void setid3v2title(int fd, struct mp3entry *entry);
|
void setid3v2title(int fd, struct mp3entry *entry);
|
||||||
|
|
|
@ -71,7 +71,9 @@ static int getsonglength(int fd, struct mp3entry *entry)
|
||||||
if(bytecount < 0)
|
if(bytecount < 0)
|
||||||
return -1;
|
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
|
/* Validate byte count, in case the file has been edited without
|
||||||
* updating the header.
|
* 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->bitrate = info.bitrate;
|
||||||
entry->frequency = info.frequency;
|
entry->frequency = info.frequency;
|
||||||
entry->layer = info.layer;
|
entry->layer = info.layer;
|
||||||
|
@ -127,7 +132,7 @@ static int getsonglength(int fd, struct mp3entry *entry)
|
||||||
if (info.bitrate < 8)
|
if (info.bitrate < 8)
|
||||||
filetime = 0;
|
filetime = 0;
|
||||||
else
|
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
|
/* bitrate is in kbps so this delivers milliseconds. Doing bitrate / 8
|
||||||
* instead of filesize * 8 is exact, because mpeg audio bitrates are
|
* instead of filesize * 8 is exact, because mpeg audio bitrates are
|
||||||
* always multiples of 8, and it avoids overflows. */
|
* 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->title = NULL;
|
||||||
entry->filesize = filesize(fd);
|
entry->filesize = filesize(fd);
|
||||||
|
entry->id3v1len = getid3v1len(fd);
|
||||||
entry->id3v2len = getid3v2len(fd);
|
entry->id3v2len = getid3v2len(fd);
|
||||||
entry->tracknum = 0;
|
entry->tracknum = 0;
|
||||||
entry->discnum = 0;
|
entry->discnum = 0;
|
||||||
|
@ -174,10 +180,6 @@ bool get_mp3_metadata(int fd, struct mp3entry *entry)
|
||||||
return false;
|
return false;
|
||||||
entry->length = len;
|
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 */
|
/* only seek to end of file if no id3v2 tags were found */
|
||||||
if (!entry->id3v2len) {
|
if (!entry->id3v2len) {
|
||||||
setid3v1title(fd, entry);
|
setid3v1title(fd, entry);
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
#include "mp3data.h"
|
#include "mp3data.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
|
#include "metadata.h"
|
||||||
|
#include "metadata/metadata_parsers.h"
|
||||||
|
|
||||||
//#define DEBUG_VERBOSE
|
//#define DEBUG_VERBOSE
|
||||||
|
|
||||||
#ifdef 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)
|
static int buf_seek(int fd, int len)
|
||||||
{
|
{
|
||||||
fnf_read_index += 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;
|
len = fnf_read_index - fnf_buf_len;
|
||||||
|
|
||||||
|
@ -348,23 +351,22 @@ static int buf_seek(int fd, int len)
|
||||||
if(fnf_buf_len < 0)
|
if(fnf_buf_len < 0)
|
||||||
return -1;
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void buf_init(unsigned char* buf, size_t buflen)
|
static void buf_init(unsigned char* buf, size_t buflen)
|
||||||
{
|
{
|
||||||
fnf_buf = buf;
|
fnf_buf = buf;
|
||||||
fnf_buf_len = buflen;
|
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)
|
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
|
else
|
||||||
{
|
{
|
||||||
|
long offset;
|
||||||
|
|
||||||
VDEBUGF("-- No VBR header --\n");
|
VDEBUGF("-- No VBR header --\n");
|
||||||
|
|
||||||
/* There was no VBR header found. So, we seek back to beginning and
|
/* There was no VBR header found. So, we seek back to beginning and
|
||||||
* search for the first MPEG frame header of the mp3 stream. */
|
* 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);
|
result = get_next_header_info(fd, &bytecount, info, false);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
info->byte_count = filesize(fd) - getid3v1len(fd) - offset - bytecount;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytecount;
|
return bytecount;
|
||||||
|
@ -647,7 +653,7 @@ int count_mp3_frames(int fd, int startpos, int filesize,
|
||||||
num_frames = 0;
|
num_frames = 0;
|
||||||
cnt = 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);
|
mp3headerinfo(&info, header);
|
||||||
|
|
||||||
if(!header_template)
|
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 */
|
/* Advance from the last seek point to this one */
|
||||||
for(j = 0;j < pos - last_pos;j++)
|
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;
|
filepos += bytes;
|
||||||
mp3headerinfo(&info, header);
|
mp3headerinfo(&info, header);
|
||||||
buf_seek(fd, info.frame_size-4);
|
buf_seek(fd, info.frame_size-4);
|
||||||
|
|
Loading…
Reference in a new issue