diff options
author | Solomon Peachy <pizza@shaftnet.org> | 2019-08-08 16:49:16 -0400 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2019-08-13 17:07:07 +0200 |
commit | 22c63269749aa6471235f9547e53bc9d6f8ce41b (patch) | |
tree | 124f52e0a3341a88b44ac7bc6c4ca6731f49f1a7 | |
parent | c46147c6b2a70068e71f4baa34e4ca0892ca4f92 (diff) | |
download | rockbox-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.lang | 28 | ||||
-rw-r--r-- | apps/plugins/vbrfix.c | 22 | ||||
-rw-r--r-- | lib/rbcodec/metadata/id3tags.c | 23 | ||||
-rw-r--r-- | lib/rbcodec/metadata/metadata_parsers.h | 1 | ||||
-rw-r--r-- | lib/rbcodec/metadata/mp3.c | 14 | ||||
-rw-r--r-- | lib/rbcodec/metadata/mp3data.c | 26 |
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; | |||
26 | static size_t audiobuflen; | 26 | static size_t audiobuflen; |
27 | unsigned char xingbuf[1500]; | 27 | unsigned char xingbuf[1500]; |
28 | char tmpname[MAX_PATH]; | 28 | char tmpname[MAX_PATH]; |
29 | static long last_talk = 0; | ||
29 | 30 | ||
30 | static void xingupdate(int percent) | 31 | static 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 | ||
36 | static int insert_data_in_file(const char *fname, int fpos, char *buf, int num_bytes) | 46 | 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 | |||
114 | 124 | ||
115 | static void fileerror(int rc) | 125 | static 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 | ||
120 | static const unsigned char empty_id3_header[] = | 130 | static 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 | ||
262 | enum plugin_status plugin_start(const void *parameter) | 269 | enum 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 | */ | ||
1144 | int 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 |
23 | char* id3_get_num_genre(unsigned int genre_num); | 23 | char* id3_get_num_genre(unsigned int genre_num); |
24 | #endif | 24 | #endif |
25 | int getid3v1len(int fd); | ||
25 | int getid3v2len(int fd); | 26 | int getid3v2len(int fd); |
26 | bool setid3v1title(int fd, struct mp3entry *entry); | 27 | bool setid3v1title(int fd, struct mp3entry *entry); |
27 | void setid3v2title(int fd, struct mp3entry *entry); | 28 | 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) | |||
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) | |||
340 | static int buf_seek(int fd, int len) | 343 | static 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 | ||
363 | static void buf_init(unsigned char* buf, size_t buflen) | 365 | static 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 | ||
370 | static unsigned long buf_find_next_frame(int fd, long *offset, long max_offset) | 372 | 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) | |||
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); |