summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2019-08-08 16:49:16 -0400
committerSolomon Peachy <pizza@shaftnet.org>2019-08-13 17:07:07 +0200
commit22c63269749aa6471235f9547e53bc9d6f8ce41b (patch)
tree124f52e0a3341a88b44ac7bc6c4ca6731f49f1a7
parentc46147c6b2a70068e71f4baa34e4ca0892ca4f92 (diff)
downloadrockbox-22c63269749aa6471235f9547e53bc9d6f8ce41b.tar.gz
rockbox-22c63269749aa6471235f9547e53bc9d6f8ce41b.zip
Improvements for vbrfix plugin:
* Properly account for ID3v1 tags * Play time computation fixes * Add speech feedback Patch by Igor Poretsky Change-Id: Ia6df8fb171882a88527cfa9d3b76b705f09becdd
-rw-r--r--apps/lang/english.lang28
-rw-r--r--apps/plugins/vbrfix.c22
-rw-r--r--lib/rbcodec/metadata/id3tags.c23
-rw-r--r--lib/rbcodec/metadata/metadata_parsers.h1
-rw-r--r--lib/rbcodec/metadata/mp3.c14
-rw-r--r--lib/rbcodec/metadata/mp3data.c26
6 files changed, 91 insertions, 23 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 23b5fa62a1..5b04b13bfa 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -16390,3 +16390,31 @@ id: VOICE_BAT_BENCH_KEYS
16390 lcd_bitmap: "Error writing config" 16390 lcd_bitmap: "Error writing config"
16391 </voice> 16391 </voice>
16392</phrase> 16392</phrase>
16393<phrase>
16394 id: LANG_NOT_A_VBR_FILE
16395 desc: in vbrfix plugin
16396 user: core
16397 <source>
16398 *: "Not a VBR file"
16399 </source>
16400 <dest>
16401 *: "Not a VBR file"
16402 </dest>
16403 <voice>
16404 *: "Not a VBR file"
16405 </voice>
16406</phrase>
16407<phrase>
16408 id: LANG_FILE_ERROR
16409 desc: in vbrfix plugin
16410 user: core
16411 <source>
16412 *: "File error: %d"
16413 </source>
16414 <dest>
16415 *: "File error: %d"
16416 </dest>
16417 <voice>
16418 *: "File error"
16419 </voice>
16420</phrase>
diff --git a/apps/plugins/vbrfix.c b/apps/plugins/vbrfix.c
index af7b817002..768ec9d99f 100644
--- a/apps/plugins/vbrfix.c
+++ b/apps/plugins/vbrfix.c
@@ -26,11 +26,21 @@ static char *audiobuf;
26static size_t audiobuflen; 26static size_t audiobuflen;
27unsigned char xingbuf[1500]; 27unsigned char xingbuf[1500];
28char tmpname[MAX_PATH]; 28char tmpname[MAX_PATH];
29static long last_talk = 0;
29 30
30static void xingupdate(int percent) 31static void xingupdate(int percent)
31{ 32{
32 rb->lcd_putsf(0, 1, "%d%%", percent); 33 rb->lcd_putsf(0, 1, "%d%%", percent);
33 rb->lcd_update(); 34 rb->lcd_update();
35 if (rb->global_settings->talk_menu)
36 {
37 long now = *(rb->current_tick) / HZ;
38 if (now - last_talk >= 5)
39 {
40 rb->talk_value(percent, UNIT_PERCENT, false);
41 last_talk = now;
42 }
43 }
34} 44}
35 45
36static int insert_data_in_file(const char *fname, int fpos, char *buf, int num_bytes) 46static 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
114 124
115static void fileerror(int rc) 125static void fileerror(int rc)
116{ 126{
117 rb->splashf(HZ*2, "File error: %d", rc); 127 rb->splashf(HZ*2, ID2P(LANG_FILE_ERROR), rc);
118} 128}
119 129
120static const unsigned char empty_id3_header[] = 130static const unsigned char empty_id3_header[] =
@@ -128,7 +138,6 @@ static bool vbr_fix(const char *selected_file)
128 struct mp3entry entry; 138 struct mp3entry entry;
129 int fd; 139 int fd;
130 int rc; 140 int rc;
131 int flen;
132 int num_frames; 141 int num_frames;
133 int numbytes; 142 int numbytes;
134 int framelen; 143 int framelen;
@@ -152,18 +161,16 @@ static bool vbr_fix(const char *selected_file)
152 return true; 161 return true;
153 } 162 }
154 163
155 flen = rb->lseek(fd, 0, SEEK_END);
156
157 xingupdate(0); 164 xingupdate(0);
158 165
159 num_frames = rb->count_mp3_frames(fd, entry.first_frame_offset, 166 num_frames = rb->count_mp3_frames(fd, entry.first_frame_offset,
160 flen, xingupdate, audiobuf, audiobuflen); 167 entry.filesize, xingupdate, audiobuf, audiobuflen);
161 168
162 if(num_frames) { 169 if(num_frames) {
163 /* Note: We don't need to pass a template header because it will be 170 /* Note: We don't need to pass a template header because it will be
164 taken from the mpeg stream */ 171 taken from the mpeg stream */
165 framelen = rb->create_xing_header(fd, entry.first_frame_offset, 172 framelen = rb->create_xing_header(fd, entry.first_frame_offset,
166 flen, xingbuf, num_frames, 0, 173 entry.filesize, xingbuf, num_frames, 0,
167 0, xingupdate, true, 174 0, xingupdate, true,
168 audiobuf, audiobuflen); 175 audiobuf, audiobuflen);
169 176
@@ -253,7 +260,7 @@ static bool vbr_fix(const char *selected_file)
253 { 260 {
254 /* Not a VBR file */ 261 /* Not a VBR file */
255 DEBUGF("Not a VBR file\n"); 262 DEBUGF("Not a VBR file\n");
256 rb->splash(HZ*2, "Not a VBR file"); 263 rb->splash(HZ*2, ID2P(LANG_NOT_A_VBR_FILE));
257 } 264 }
258 265
259 return false; 266 return false;
@@ -261,6 +268,7 @@ static bool vbr_fix(const char *selected_file)
261 268
262enum plugin_status plugin_start(const void *parameter) 269enum plugin_status plugin_start(const void *parameter)
263{ 270{
271 last_talk = *(rb->current_tick) / HZ;
264 272
265 if (!parameter) 273 if (!parameter)
266 return PLUGIN_ERROR; 274 return PLUGIN_ERROR;
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
@@ -1135,6 +1135,29 @@ void setid3v2title(int fd, struct mp3entry *entry)
1135} 1135}
1136 1136
1137/* 1137/*
1138 * Calculates the size of the ID3v1 tag if any.
1139 *
1140 * Arguments: file - the file to search for a tag.
1141 *
1142 * Returns: the size of the tag or 0 if none was found
1143 */
1144int getid3v1len(int fd)
1145{
1146 char buf[4];
1147
1148 if (-1 == lseek(fd, -128, SEEK_END))
1149 return 0;
1150
1151 if (read(fd, buf, 3) != 3)
1152 return 0;
1153
1154 if (strncmp(buf, "TAG", 3))
1155 return 0;
1156
1157 return 128;
1158}
1159
1160/*
1138 * Calculates the size of the ID3v2 tag. 1161 * Calculates the size of the ID3v2 tag.
1139 * 1162 *
1140 * Arguments: file - the file to search for a tag. 1163 * Arguments: file - the file to search for a 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 @@
22#if CONFIG_CODEC == SWCODEC 22#if CONFIG_CODEC == SWCODEC
23char* id3_get_num_genre(unsigned int genre_num); 23char* id3_get_num_genre(unsigned int genre_num);
24#endif 24#endif
25int getid3v1len(int fd);
25int getid3v2len(int fd); 26int getid3v2len(int fd);
26bool setid3v1title(int fd, struct mp3entry *entry); 27bool setid3v1title(int fd, struct mp3entry *entry);
27void setid3v2title(int fd, struct mp3entry *entry); 28void 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)
71 if(bytecount < 0) 71 if(bytecount < 0)
72 return -1; 72 return -1;
73 73
74 bytecount += entry->id3v2len; 74 /* Subtract the meta information from the file size to get
75 the true size of the MP3 stream */
76 entry->filesize -= entry->id3v1len + entry->id3v2len;
75 77
76 /* Validate byte count, in case the file has been edited without 78 /* Validate byte count, in case the file has been edited without
77 * updating the header. 79 * updating the header.
@@ -99,6 +101,9 @@ static int getsonglength(int fd, struct mp3entry *entry)
99 } 101 }
100 } 102 }
101 103
104 entry->filesize -= bytecount;
105 bytecount += entry->id3v2len;
106
102 entry->bitrate = info.bitrate; 107 entry->bitrate = info.bitrate;
103 entry->frequency = info.frequency; 108 entry->frequency = info.frequency;
104 entry->layer = info.layer; 109 entry->layer = info.layer;
@@ -127,7 +132,7 @@ static int getsonglength(int fd, struct mp3entry *entry)
127 if (info.bitrate < 8) 132 if (info.bitrate < 8)
128 filetime = 0; 133 filetime = 0;
129 else 134 else
130 filetime = (entry->filesize - bytecount) / (info.bitrate / 8); 135 filetime = entry->filesize / (info.bitrate >> 3);
131 /* bitrate is in kbps so this delivers milliseconds. Doing bitrate / 8 136 /* bitrate is in kbps so this delivers milliseconds. Doing bitrate / 8
132 * instead of filesize * 8 is exact, because mpeg audio bitrates are 137 * instead of filesize * 8 is exact, because mpeg audio bitrates are
133 * always multiples of 8, and it avoids overflows. */ 138 * always multiples of 8, and it avoids overflows. */
@@ -163,6 +168,7 @@ bool get_mp3_metadata(int fd, struct mp3entry *entry)
163{ 168{
164 entry->title = NULL; 169 entry->title = NULL;
165 entry->filesize = filesize(fd); 170 entry->filesize = filesize(fd);
171 entry->id3v1len = getid3v1len(fd);
166 entry->id3v2len = getid3v2len(fd); 172 entry->id3v2len = getid3v2len(fd);
167 entry->tracknum = 0; 173 entry->tracknum = 0;
168 entry->discnum = 0; 174 entry->discnum = 0;
@@ -174,10 +180,6 @@ bool get_mp3_metadata(int fd, struct mp3entry *entry)
174 return false; 180 return false;
175 entry->length = len; 181 entry->length = len;
176 182
177 /* Subtract the meta information from the file size to get
178 the true size of the MP3 stream */
179 entry->filesize -= entry->first_frame_offset;
180
181 /* only seek to end of file if no id3v2 tags were found */ 183 /* only seek to end of file if no id3v2 tags were found */
182 if (!entry->id3v2len) { 184 if (!entry->id3v2len) {
183 setid3v1title(fd, entry); 185 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 @@
39#include "mp3data.h" 39#include "mp3data.h"
40#include "platform.h" 40#include "platform.h"
41 41
42#include "metadata.h"
43#include "metadata/metadata_parsers.h"
44
42//#define DEBUG_VERBOSE 45//#define DEBUG_VERBOSE
43 46
44#ifdef DEBUG_VERBOSE 47#ifdef DEBUG_VERBOSE
@@ -340,7 +343,7 @@ static int buf_getbyte(int fd, unsigned char *c)
340static int buf_seek(int fd, int len) 343static int buf_seek(int fd, int len)
341{ 344{
342 fnf_read_index += len; 345 fnf_read_index += len;
343 if(fnf_read_index > fnf_buf_len) 346 if(fnf_read_index >= fnf_buf_len)
344 { 347 {
345 len = fnf_read_index - fnf_buf_len; 348 len = fnf_read_index - fnf_buf_len;
346 349
@@ -348,23 +351,22 @@ static int buf_seek(int fd, int len)
348 if(fnf_buf_len < 0) 351 if(fnf_buf_len < 0)
349 return -1; 352 return -1;
350 353
351 fnf_read_index = 0; 354 fnf_read_index = len;
352 fnf_read_index += len;
353 } 355 }
354 356
355 if(fnf_read_index > fnf_buf_len) 357 if(fnf_read_index >= fnf_buf_len)
356 { 358 {
357 return -1; 359 return -1;
358 } 360 }
359 else 361
360 return 0; 362 return 0;
361} 363}
362 364
363static void buf_init(unsigned char* buf, size_t buflen) 365static void buf_init(unsigned char* buf, size_t buflen)
364{ 366{
365 fnf_buf = buf; 367 fnf_buf = buf;
366 fnf_buf_len = buflen; 368 fnf_buf_len = buflen;
367 fnf_read_index = 0; 369 fnf_read_index = buflen;
368} 370}
369 371
370static unsigned long buf_find_next_frame(int fd, long *offset, long max_offset) 372static 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)
601 } 603 }
602 else 604 else
603 { 605 {
606 long offset;
607
604 VDEBUGF("-- No VBR header --\n"); 608 VDEBUGF("-- No VBR header --\n");
605 609
606 /* There was no VBR header found. So, we seek back to beginning and 610 /* There was no VBR header found. So, we seek back to beginning and
607 * search for the first MPEG frame header of the mp3 stream. */ 611 * search for the first MPEG frame header of the mp3 stream. */
608 lseek(fd, -info->frame_size, SEEK_CUR); 612 offset = lseek(fd, -info->frame_size, SEEK_CUR);
609 result = get_next_header_info(fd, &bytecount, info, false); 613 result = get_next_header_info(fd, &bytecount, info, false);
610 if(result) 614 if(result)
611 return result; 615 return result;
616
617 info->byte_count = filesize(fd) - getid3v1len(fd) - offset - bytecount;
612 } 618 }
613 619
614 return bytecount; 620 return bytecount;
@@ -647,7 +653,7 @@ int count_mp3_frames(int fd, int startpos, int filesize,
647 num_frames = 0; 653 num_frames = 0;
648 cnt = 0; 654 cnt = 0;
649 655
650 while((header = buf_find_next_frame(fd, &bytes, header_template))) { 656 while((header = buf_find_next_frame(fd, &bytes, startpos + filesize))) {
651 mp3headerinfo(&info, header); 657 mp3headerinfo(&info, header);
652 658
653 if(!header_template) 659 if(!header_template)
@@ -723,7 +729,7 @@ int create_xing_header(int fd, long startpos, long filesize,
723 /* Advance from the last seek point to this one */ 729 /* Advance from the last seek point to this one */
724 for(j = 0;j < pos - last_pos;j++) 730 for(j = 0;j < pos - last_pos;j++)
725 { 731 {
726 header = buf_find_next_frame(fd, &bytes, header_template); 732 header = buf_find_next_frame(fd, &bytes, startpos + filesize);
727 filepos += bytes; 733 filepos += bytes;
728 mp3headerinfo(&info, header); 734 mp3headerinfo(&info, header);
729 buf_seek(fd, info.frame_size-4); 735 buf_seek(fd, info.frame_size-4);