summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-09-10 12:28:16 +0000
committerJens Arnold <amiconn@rockbox.org>2005-09-10 12:28:16 +0000
commitec9b202a921996945ebd42a7edba1326754d7737 (patch)
treef88c7d9ee1ff94c3a5cefdba0d30c78b84e72d62
parent1996dca15a495c09986cefc02086e03a53244f3a (diff)
downloadrockbox-ec9b202a921996945ebd42a7edba1326754d7737.tar.gz
rockbox-ec9b202a921996945ebd42a7edba1326754d7737.zip
Reworked handling of MPEG audio frame & file info: * Fixed frame size calculation for layer 1 (all versions) and layer 2 (V2/V2.5). * Exact frame time (expressed as a fraction) for way more precise playtime calculation at 44100/22050/11025Hz sample frequency. * Exact playtime<->position conversion for CBR also used for resume position. * More compact code, long policy.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7505 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/bookmark.c2
-rw-r--r--apps/playback.c10
-rw-r--r--apps/screens.c2
-rw-r--r--apps/settings.h4
-rw-r--r--apps/wps-display.c4
-rw-r--r--firmware/export/id3.h38
-rw-r--r--firmware/export/mp3data.h26
-rw-r--r--firmware/id3.c8
-rw-r--r--firmware/mp3data.c187
-rw-r--r--firmware/mpeg.c12
10 files changed, 136 insertions, 157 deletions
diff --git a/apps/bookmark.c b/apps/bookmark.c
index c157d01662..593bfe98cb 100644
--- a/apps/bookmark.c
+++ b/apps/bookmark.c
@@ -389,7 +389,7 @@ static char* create_bookmark()
389 389
390 /* create the bookmark */ 390 /* create the bookmark */
391 snprintf(global_bookmark, sizeof(global_bookmark), 391 snprintf(global_bookmark, sizeof(global_bookmark),
392 "%d;%d;%d;%d;%d;%d;%d;%s;%s", 392 "%d;%ld;%d;%d;%ld;%d;%d;%s;%s",
393 resume_index, 393 resume_index,
394 id3->offset, 394 id3->offset,
395 playlist_get_seed(NULL), 395 playlist_get_seed(NULL),
diff --git a/apps/playback.c b/apps/playback.c
index 6fd63d5a0f..1677e3138b 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -2008,7 +2008,7 @@ static void mp3_set_elapsed(struct mp3entry* id3)
2008 /* find wich percent we're at */ 2008 /* find wich percent we're at */
2009 for (i=0; i<100; i++ ) 2009 for (i=0; i<100; i++ )
2010 { 2010 {
2011 if ( id3->offset < (int)(id3->toc[i] * (id3->filesize / 256)) ) 2011 if ( id3->offset < id3->toc[i] * (id3->filesize / 256) )
2012 { 2012 {
2013 break; 2013 break;
2014 } 2014 }
@@ -2048,8 +2048,8 @@ static void mp3_set_elapsed(struct mp3entry* id3)
2048 } 2048 }
2049 } 2049 }
2050 else 2050 else
2051 /* constant bitrate == simple frame calculation */ 2051 /* constant bitrate, use exact calculation */
2052 id3->elapsed = id3->offset / id3->bpf * id3->tpf; 2052 id3->elapsed = id3->offset / (id3->bitrate / 8);
2053} 2053}
2054 2054
2055/* Copied from mpeg.c. Should be moved somewhere else. */ 2055/* Copied from mpeg.c. Should be moved somewhere else. */
@@ -2092,8 +2092,8 @@ int mp3_get_file_pos(void)
2092 (id3->elapsed / 1000); 2092 (id3->elapsed / 1000);
2093 } 2093 }
2094 } 2094 }
2095 else if (id3->bpf && id3->tpf) 2095 else if (id3->bitrate)
2096 pos = (id3->elapsed/id3->tpf)*id3->bpf; 2096 pos = id3->elapsed * (id3->bitrate / 8);
2097 else 2097 else
2098 { 2098 {
2099 return -1; 2099 return -1;
diff --git a/apps/screens.c b/apps/screens.c
index 10e1cdd188..bba5b279e2 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -1398,7 +1398,7 @@ bool browse_id3(void)
1398 id3->vbr ? str(LANG_ID3_VBR) : (const unsigned char*) ""); 1398 id3->vbr ? str(LANG_ID3_VBR) : (const unsigned char*) "");
1399 line = draw_id3_item(line, top, LANG_ID3_BITRATE, buf); 1399 line = draw_id3_item(line, top, LANG_ID3_BITRATE, buf);
1400 1400
1401 snprintf(buf, sizeof(buf), "%d Hz", id3->frequency); 1401 snprintf(buf, sizeof(buf), "%ld Hz", id3->frequency);
1402 line = draw_id3_item(line, top, LANG_ID3_FRECUENCY, buf); 1402 line = draw_id3_item(line, top, LANG_ID3_FRECUENCY, buf);
1403 1403
1404#if CONFIG_CODEC == SWCODEC 1404#if CONFIG_CODEC == SWCODEC
diff --git a/apps/settings.h b/apps/settings.h
index 1c1e664b90..327b79a7ee 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -215,13 +215,13 @@ struct user_settings
215#ifdef HAVE_SPDIF_POWER 215#ifdef HAVE_SPDIF_POWER
216 bool spdif_enable; /* S/PDIF power on/off */ 216 bool spdif_enable; /* S/PDIF power on/off */
217#endif 217#endif
218 218
219 /* resume settings */ 219 /* resume settings */
220 220
221 bool resume; /* resume option: 0=off, 1=on */ 221 bool resume; /* resume option: 0=off, 1=on */
222 int resume_index; /* index in playlist (-1 for no active resume) */ 222 int resume_index; /* index in playlist (-1 for no active resume) */
223 int resume_first_index; /* index of first track in playlist */ 223 int resume_first_index; /* index of first track in playlist */
224 int resume_offset; /* byte offset in mp3 file */ 224 unsigned long resume_offset; /* byte offset in mp3 file */
225 int resume_seed; /* shuffle seed (-1=no resume shuffle 0=sorted 225 int resume_seed; /* shuffle seed (-1=no resume shuffle 0=sorted
226 >0=shuffled) */ 226 >0=shuffled) */
227 227
diff --git a/apps/wps-display.c b/apps/wps-display.c
index 1794e53549..3c3cc98ed4 100644
--- a/apps/wps-display.c
+++ b/apps/wps-display.c
@@ -598,7 +598,7 @@ static char* get_tag(struct mp3entry* cid3,
598 return buf; 598 return buf;
599 599
600 case 'f': /* File Frequency */ 600 case 'f': /* File Frequency */
601 snprintf(buf, buf_size, "%d", id3->frequency); 601 snprintf(buf, buf_size, "%ld", id3->frequency);
602 return buf; 602 return buf;
603 603
604 case 'p': /* File Path */ 604 case 'p': /* File Path */
@@ -626,7 +626,7 @@ static char* get_tag(struct mp3entry* cid3,
626 } 626 }
627 627
628 case 's': /* File Size (in kilobytes) */ 628 case 's': /* File Size (in kilobytes) */
629 snprintf(buf, buf_size, "%d", id3->filesize / 1024); 629 snprintf(buf, buf_size, "%ld", id3->filesize / 1024);
630 return buf; 630 return buf;
631 631
632 case 'c': /* File Codec */ 632 case 'c': /* File Codec */
diff --git a/firmware/export/id3.h b/firmware/export/id3.h
index 6c6507159a..47a084d67a 100644
--- a/firmware/export/id3.h
+++ b/firmware/export/id3.h
@@ -61,39 +61,37 @@ struct mp3entry {
61 unsigned char genre; 61 unsigned char genre;
62 unsigned int codectype; 62 unsigned int codectype;
63 unsigned int bitrate; 63 unsigned int bitrate;
64 unsigned int frequency; 64 unsigned long frequency;
65 unsigned int id3v2len; 65 unsigned long id3v2len;
66 unsigned int id3v1len; 66 unsigned long id3v1len;
67 unsigned int first_frame_offset; /* Byte offset to first real MP3 frame. 67 unsigned long first_frame_offset; /* Byte offset to first real MP3 frame.
68 Used for skipping leading garbage to 68 Used for skipping leading garbage to
69 avoid gaps between tracks. */ 69 avoid gaps between tracks. */
70 unsigned int vbr_header_pos; 70 unsigned long vbr_header_pos;
71 unsigned int filesize; /* in bytes */ 71 unsigned long filesize; /* without headers; in bytes */
72 unsigned int length; /* song length */ 72 unsigned long length; /* song length in ms */
73 unsigned int elapsed; /* ms played */ 73 unsigned long elapsed; /* ms played */
74 74
75 int lead_trim; /* Number of samples to skip at the beginning */ 75 int lead_trim; /* Number of samples to skip at the beginning */
76 int tail_trim; /* Number of samples to remove from the end */ 76 int tail_trim; /* Number of samples to remove from the end */
77 77
78 /* Added for Vorbis */ 78 /* Added for Vorbis */
79 unsigned long samples; /* number of samples in track */ 79 unsigned long samples; /* number of samples in track */
80 80
81 /* MP3 stream specific info */ 81 /* MP3 stream specific info */
82 long bpf; /* bytes per frame */ 82 unsigned long frame_count; /* number of frames in the file (if VBR) */
83 long tpf; /* time per frame */
84 long frame_count; /* number of frames in the file (if VBR) */
85 83
86 /* Xing VBR fields */ 84 /* Xing VBR fields */
87 bool vbr; 85 bool vbr;
88 bool has_toc; /* True if there is a VBR header in the file */ 86 bool has_toc; /* True if there is a VBR header in the file */
89 unsigned char toc[100];/* table of contents */ 87 unsigned char toc[100]; /* table of contents */
90 88
91 /* these following two fields are used for local buffering */ 89 /* these following two fields are used for local buffering */
92 char id3v2buf[300]; 90 char id3v2buf[300];
93 char id3v1buf[3][32]; 91 char id3v1buf[3][32];
94 92
95 /* resume related */ 93 /* resume related */
96 int offset; /* bytes played */ 94 unsigned long offset; /* bytes played */
97 int index; /* playlist index */ 95 int index; /* playlist index */
98 96
99 /* FileEntry fields */ 97 /* FileEntry fields */
diff --git a/firmware/export/mp3data.h b/firmware/export/mp3data.h
index db1a93b8d6..3961664815 100644
--- a/firmware/export/mp3data.h
+++ b/firmware/export/mp3data.h
@@ -20,9 +20,9 @@
20#ifndef _MP3DATA_H_ 20#ifndef _MP3DATA_H_
21#define _MP3DATA_H_ 21#define _MP3DATA_H_
22 22
23#define MPEG_VERSION2_5 0 23#define MPEG_VERSION1 0
24#define MPEG_VERSION1 1 24#define MPEG_VERSION2 1
25#define MPEG_VERSION2 2 25#define MPEG_VERSION2_5 2
26 26
27struct mp3info { 27struct mp3info {
28 /* Standard MP3 frame header fields */ 28 /* Standard MP3 frame header fields */
@@ -30,23 +30,25 @@ struct mp3info {
30 int layer; 30 int layer;
31 bool protection; 31 bool protection;
32 int bitrate; 32 int bitrate;
33 int frequency; 33 long frequency;
34 int padding; 34 int padding;
35 int channel_mode; 35 int channel_mode;
36 int mode_extension; 36 int mode_extension;
37 int emphasis; 37 int emphasis;
38 int frame_size; /* Frame size in bytes */ 38 int frame_size; /* Frame size in bytes */
39 int frame_time; /* Frame duration in milliseconds */ 39 int frame_samples; /* Samples per frame */
40 int ft_num; /* Numerator of frametime in milliseconds */
41 int ft_den; /* Denominator of frametime in milliseconds */
40 42
41 bool is_vbr; /* True if the file is VBR */ 43 bool is_vbr; /* True if the file is VBR */
42 bool has_toc; /* True if there is a VBR header in the file */ 44 bool has_toc; /* True if there is a VBR header in the file */
43 bool is_xing_vbr; /* True if the VBR header is of Xing type */ 45 bool is_xing_vbr; /* True if the VBR header is of Xing type */
44 bool is_vbri_vbr; /* True if the VBR header is of VBRI type */ 46 bool is_vbri_vbr; /* True if the VBR header is of VBRI type */
45 unsigned char toc[100]; 47 unsigned char toc[100];
46 long frame_count; /* Number of frames in the file (if VBR) */ 48 unsigned long frame_count; /* Number of frames in the file (if VBR) */
47 long byte_count; /* File size in bytes */ 49 unsigned long byte_count; /* File size in bytes */
48 long file_time; /* Length of the whole file in milliseconds */ 50 unsigned long file_time; /* Length of the whole file in milliseconds */
49 int vbr_header_pos; 51 unsigned long vbr_header_pos;
50 int enc_delay; /* Encoder delay, fetched from LAME header */ 52 int enc_delay; /* Encoder delay, fetched from LAME header */
51 int enc_padding; /* Padded samples added to last frame. LAME header */ 53 int enc_padding; /* Padded samples added to last frame. LAME header */
52}; 54};
diff --git a/firmware/id3.c b/firmware/id3.c
index f1aa821fba..dfbcb9699d 100644
--- a/firmware/id3.c
+++ b/firmware/id3.c
@@ -863,10 +863,10 @@ static int getid3v2len(int fd)
863 */ 863 */
864static int getsonglength(int fd, struct mp3entry *entry) 864static int getsonglength(int fd, struct mp3entry *entry)
865{ 865{
866 unsigned int filetime = 0; 866 unsigned long filetime = 0;
867 struct mp3info info; 867 struct mp3info info;
868 int bytecount; 868 long bytecount;
869 869
870 /* Start searching after ID3v2 header */ 870 /* Start searching after ID3v2 header */
871 if(-1 == lseek(fd, entry->id3v2len, SEEK_SET)) 871 if(-1 == lseek(fd, entry->id3v2len, SEEK_SET))
872 return 0; 872 return 0;
@@ -912,8 +912,6 @@ static int getsonglength(int fd, struct mp3entry *entry)
912 * always multiples of 8, and it avoids overflows. */ 912 * always multiples of 8, and it avoids overflows. */
913 } 913 }
914 914
915 entry->tpf = info.frame_time;
916 entry->bpf = info.frame_size;
917 entry->frame_count = info.frame_count; 915 entry->frame_count = info.frame_count;
918 916
919 entry->vbr = info.is_vbr; 917 entry->vbr = info.is_vbr;
diff --git a/firmware/mp3data.c b/firmware/mp3data.c
index 6f4c560578..c2d4cd2c37 100644
--- a/firmware/mp3data.c
+++ b/firmware/mp3data.c
@@ -31,6 +31,7 @@
31#include <stdlib.h> 31#include <stdlib.h>
32#include <string.h> 32#include <string.h>
33#include <stdbool.h> 33#include <stdbool.h>
34#include <limits.h>
34#include "debug.h" 35#include "debug.h"
35#include "logf.h" 36#include "logf.h"
36#include "mp3data.h" 37#include "mp3data.h"
@@ -39,7 +40,7 @@
39 40
40#define DEBUG_VERBOSE 41#define DEBUG_VERBOSE
41 42
42#define BYTES2INT(b1,b2,b3,b4) (((long)(b1 & 0xFF) << (3*8)) | \ 43#define BYTES2INT(b1,b2,b3,b4) (((long)(b1 & 0xFF) << (3*8)) | \
43 ((long)(b2 & 0xFF) << (2*8)) | \ 44 ((long)(b2 & 0xFF) << (2*8)) | \
44 ((long)(b3 & 0xFF) << (1*8)) | \ 45 ((long)(b3 & 0xFF) << (1*8)) | \
45 ((long)(b4 & 0xFF) << (0*8))) 46 ((long)(b4 & 0xFF) << (0*8)))
@@ -58,37 +59,34 @@
58#define ORIGINAL_MASK (1L << 2) 59#define ORIGINAL_MASK (1L << 2)
59#define EMPHASIS_MASK 3L 60#define EMPHASIS_MASK 3L
60 61
61/* Table of bitrates for MP3 files, all values in kilo. 62/* MPEG Version table, sorted by version index */
62 * Indexed by version, layer and value of bit 15-12 in header. 63static const signed char version_table[4] = {
63 */ 64 MPEG_VERSION2_5, -1, MPEG_VERSION2, MPEG_VERSION1
64const int bitrate_table[2][3][16] =
65{
66 {
67 {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
68 {0,32,48,56, 64,80, 96, 112,128,160,192,224,256,320,384,0},
69 {0,32,40,48, 56,64, 80, 96, 112,128,160,192,224,256,320,0}
70 },
71 {
72 {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},
73 {0, 8,16,24,32,40,48, 56, 64, 80, 96,112,128,144,160,0},
74 {0, 8,16,24,32,40,48, 56, 64, 80, 96,112,128,144,160,0}
75 }
76}; 65};
77 66
78/* Table of samples per frame for MP3 files. 67/* Bitrate table for mpeg audio, indexed by row index and birate index */
79 * Indexed by layer. Multiplied with 1000. 68static const short bitrates[5][16] = {
80 */ 69 {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0}, /* V1 L1 */
81const long bs[3] = {384000, 1152000, 1152000}; 70 {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0}, /* V1 L2 */
71 {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,0}, /* V1 L3 */
72 {0,32,48,56, 64, 80, 96,112,128,144,160,176,192,224,256,0}, /* V2 L1 */
73 {0, 8,16,24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,0} /* V2 L2+L3 */
74};
82 75
83/* Table of sample frequency for MP3 files. 76/* Bitrate pointer table, indexed by version and layer */
84 * Indexed by version and layer. 77static const short *bitrate_table[3][3] =
85 */ 78{
79 {bitrates[0], bitrates[1], bitrates[2]},
80 {bitrates[3], bitrates[4], bitrates[4]},
81 {bitrates[3], bitrates[4], bitrates[4]}
82};
86 83
87const int freqtab[][4] = 84/* Sampling frequency table, indexed by version and frequency index */
85static const long freq_table[3][3] =
88{ 86{
89 {11025, 12000, 8000, 0}, /* MPEG version 2.5 */ 87 {44100, 48000, 32000}, /* MPEG Version 1 */
90 {44100, 48000, 32000, 0}, /* MPEG Version 1 */ 88 {22050, 24000, 16000}, /* MPEG version 2 */
91 {22050, 24000, 16000, 0}, /* MPEG version 2 */ 89 {11025, 12000, 8000}, /* MPEG version 2.5 */
92}; 90};
93 91
94/* check if 'head' is a valid mp3 frame header */ 92/* check if 'head' is a valid mp3 frame header */
@@ -117,97 +115,77 @@ static bool is_mp3frameheader(unsigned long head)
117 115
118static bool mp3headerinfo(struct mp3info *info, unsigned long header) 116static bool mp3headerinfo(struct mp3info *info, unsigned long header)
119{ 117{
120 int bittable = 0; 118 int bitindex, freqindex;
121 int bitindex; 119
122 int freqindex;
123
124 /* MPEG Audio Version */ 120 /* MPEG Audio Version */
125 switch((header & VERSION_MASK) >> 19) { 121 info->version = version_table[(header & VERSION_MASK) >> 19];
126 case 0: 122 if (info->version < 0)
127 /* MPEG version 2.5 is not an official standard */
128 info->version = MPEG_VERSION2_5;
129 bittable = MPEG_VERSION2 - 1; /* use the V2 bit rate table */
130 break;
131
132 case 1:
133 return false; 123 return false;
134 124
135 case 2: 125 /* Layer */
136 /* MPEG version 2 (ISO/IEC 13818-3) */ 126 info->layer = 3 - ((header & LAYER_MASK) >> 17);
137 info->version = MPEG_VERSION2; 127 if (info->layer == 3)
138 bittable = MPEG_VERSION2 - 1;
139 break;
140
141 case 3:
142 /* MPEG version 1 (ISO/IEC 11172-3) */
143 info->version = MPEG_VERSION1;
144 bittable = MPEG_VERSION1 - 1;
145 break;
146 }
147
148 switch((header & LAYER_MASK) >> 17) {
149 case 0:
150 return false; 128 return false;
151 case 1:
152 info->layer = 2;
153 break;
154 case 2:
155 info->layer = 1;
156 break;
157 case 3:
158 info->layer = 0;
159 break;
160 }
161 129
162 info->protection = (header & PROTECTION_MASK)?true:false; 130 info->protection = (header & PROTECTION_MASK) ? true : false;
163 131
164 /* Bitrate */ 132 /* Bitrate */
165 bitindex = (header & 0xf000) >> 12; 133 bitindex = (header & BITRATE_MASK) >> 12;
166 info->bitrate = bitrate_table[bittable][info->layer][bitindex]; 134 info->bitrate = bitrate_table[info->version][info->layer][bitindex];
167 if(info->bitrate == 0) 135 if(info->bitrate == 0)
168 return false; 136 return false;
169 137
170 /* Sampling frequency */ 138 /* Sampling frequency */
171 freqindex = (header & 0x0C00) >> 10; 139 freqindex = (header & SAMPLERATE_MASK) >> 10;
172 info->frequency = freqtab[info->version][freqindex]; 140 if (freqindex == 3)
173 if(info->frequency == 0)
174 return false; 141 return false;
142 info->frequency = freq_table[info->version][freqindex];
175 143
176 info->padding = (header & 0x0200)?1:0; 144 info->padding = (header & PADDING_MASK) ? 1 : 0;
177 145
178 /* Calculate number of bytes, calculation depends on layer */ 146 /* Calculate number of bytes, calculation depends on layer */
179 switch(info->layer) { 147 if (info->layer == 0) {
180 case 0: 148 info->frame_samples = 384;
181 info->frame_size = info->bitrate * 48000; 149 info->frame_size = (12000 * info->bitrate / info->frequency
182 info->frame_size /= 150 + info->padding) * 4;
183 freqtab[info->version][freqindex] << bittable; 151 }
184 break; 152 else {
185 case 1: 153 if ((info->version > MPEG_VERSION1) && (info->layer == 2))
186 case 2: 154 info->frame_samples = 576;
187 info->frame_size = info->bitrate * 144000; 155 else
188 info->frame_size /= 156 info->frame_samples = 1152;
189 freqtab[info->version][freqindex] << bittable; 157 info->frame_size = (1000/8) * info->frame_samples * info->bitrate
190 break; 158 / info->frequency + info->padding;
191 default:
192 info->frame_size = 1;
193 } 159 }
194 160
195 info->frame_size += info->padding; 161 /* Frametime fraction calculation.
196 162 This fraction is reduced as far as possible. */
197 /* Calculate time per frame */ 163 if (freqindex != 0) { /* 48/32/24/16/12/8 kHz */
198 info->frame_time = bs[info->layer] / 164 /* integer number of milliseconds, denominator == 1 */
199 (freqtab[info->version][freqindex] << bittable); 165 info->ft_num = 1000 * info->frame_samples / info->frequency;
166 info->ft_den = 1;
167 }
168 else { /* 44.1/22.05/11.025 kHz */
169 if (info->layer == 0) {
170 info->ft_num = 147000 * 384 / info->frequency;
171 info->ft_den = 147;
172 }
173 else {
174 info->ft_num = 49000 * info->frame_samples / info->frequency;
175 info->ft_den = 49;
176 }
177 }
200 178
201 info->channel_mode = (header & 0xc0) >> 6; 179 info->channel_mode = (header & CHANNELMODE_MASK) >> 6;
202 info->mode_extension = (header & 0x30) >> 4; 180 info->mode_extension = (header & MODE_EXT_MASK) >> 4;
203 info->emphasis = header & 3; 181 info->emphasis = header & EMPHASIS_MASK;
204 182
205#ifdef DEBUG_VERBOSE 183#ifdef DEBUG_VERBOSE
206 DEBUGF( "Header: %08x, Ver %d, lay %d, bitr %d, freq %d, " 184 DEBUGF( "Header: %08x, Ver %d, lay %d, bitr %d, freq %ld, "
207 "chmode %d, mode_ext %d, emph %d, bytes: %d time: %d\n", 185 "chmode %d, mode_ext %d, emph %d, bytes: %d time: %d/%d\n",
208 header, info->version, info->layer+1, info->bitrate, 186 header, info->version, info->layer+1, info->bitrate,
209 info->frequency, info->channel_mode, info->mode_extension, 187 info->frequency, info->channel_mode, info->mode_extension,
210 info->emphasis, info->frame_size, info->frame_time); 188 info->emphasis, info->frame_size, info->ft_num, info->ft_den);
211#endif 189#endif
212 return true; 190 return true;
213} 191}
@@ -252,7 +230,7 @@ static unsigned long __find_next_frame(int fd, long *offset, long max_offset,
252 if(*offset) 230 if(*offset)
253 DEBUGF("Warning: skipping %d bytes of garbage\n", *offset); 231 DEBUGF("Warning: skipping %d bytes of garbage\n", *offset);
254#endif 232#endif
255 233
256 return header; 234 return header;
257} 235}
258 236
@@ -380,9 +358,6 @@ int get_mp3file_info(int fd, struct mp3info *info)
380 358
381 memset(info, 0, sizeof(struct mp3info)); 359 memset(info, 0, sizeof(struct mp3info));
382 /* These two are needed for proper LAME gapless MP3 playback */ 360 /* These two are needed for proper LAME gapless MP3 playback */
383 /* TODO: These can be found in a LAME Info header as well, but currently
384 they are only looked for in a Xing header. Xing and Info headers have
385 the exact same format, but Info headers are used for CBR files. */
386 info->enc_delay = -1; 361 info->enc_delay = -1;
387 info->enc_padding = -1; 362 info->enc_padding = -1;
388 if(!mp3headerinfo(info, header)) 363 if(!mp3headerinfo(info, header))
@@ -435,7 +410,10 @@ int get_mp3file_info(int fd, struct mp3info *info)
435 { 410 {
436 info->frame_count = BYTES2INT(vbrheader[i], vbrheader[i+1], 411 info->frame_count = BYTES2INT(vbrheader[i], vbrheader[i+1],
437 vbrheader[i+2], vbrheader[i+3]); 412 vbrheader[i+2], vbrheader[i+3]);
438 info->file_time = info->frame_count * info->frame_time; 413 if (info->frame_count <= ULONG_MAX / info->ft_num)
414 info->file_time = info->frame_count * info->ft_num / info->ft_den;
415 else
416 info->file_time = info->frame_count / info->ft_den * info->ft_num;
439 i += 4; 417 i += 4;
440 } 418 }
441 419
@@ -510,7 +488,10 @@ int get_mp3file_info(int fd, struct mp3info *info)
510 vbrheader[12], vbrheader[13]); 488 vbrheader[12], vbrheader[13]);
511 info->frame_count = BYTES2INT(vbrheader[14], vbrheader[15], 489 info->frame_count = BYTES2INT(vbrheader[14], vbrheader[15],
512 vbrheader[16], vbrheader[17]); 490 vbrheader[16], vbrheader[17]);
513 info->file_time = info->frame_count * info->frame_time; 491 if (info->frame_count <= ULONG_MAX / info->ft_num)
492 info->file_time = info->frame_count * info->ft_num / info->ft_den;
493 else
494 info->file_time = info->frame_count / info->ft_den * info->ft_num;
514 info->bitrate = info->byte_count * 8 / info->file_time; 495 info->bitrate = info->byte_count * 8 / info->file_time;
515 496
516 /* We don't parse the TOC, since we don't yet know how to (FIXME) */ 497 /* We don't parse the TOC, since we don't yet know how to (FIXME) */
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index ff74cf96a8..8d2d13b6ee 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -348,7 +348,7 @@ static void set_elapsed(struct mp3entry* id3)
348 /* find wich percent we're at */ 348 /* find wich percent we're at */
349 for (i=0; i<100; i++ ) 349 for (i=0; i<100; i++ )
350 { 350 {
351 if ( id3->offset < (int)(id3->toc[i] * (id3->filesize / 256)) ) 351 if ( id3->offset < id3->toc[i] * (id3->filesize / 256) )
352 { 352 {
353 break; 353 break;
354 } 354 }
@@ -388,8 +388,8 @@ static void set_elapsed(struct mp3entry* id3)
388 } 388 }
389 } 389 }
390 else 390 else
391 /* constant bitrate == simple frame calculation */ 391 /* constant bitrate, use exact calculation */
392 id3->elapsed = id3->offset / id3->bpf * id3->tpf; 392 id3->elapsed = id3->offset / (id3->bitrate / 8);
393} 393}
394 394
395int audio_get_file_pos(void) 395int audio_get_file_pos(void)
@@ -405,7 +405,7 @@ int audio_get_file_pos(void)
405 unsigned int percent, remainder; 405 unsigned int percent, remainder;
406 int curtoc, nexttoc, plen; 406 int curtoc, nexttoc, plen;
407 407
408 percent = (id3->elapsed*100)/id3->length; 408 percent = (id3->elapsed*100)/id3->length;
409 if (percent > 99) 409 if (percent > 99)
410 percent = 99; 410 percent = 99;
411 411
@@ -431,8 +431,8 @@ int audio_get_file_pos(void)
431 (id3->elapsed / 1000); 431 (id3->elapsed / 1000);
432 } 432 }
433 } 433 }
434 else if (id3->bpf && id3->tpf) 434 else if (id3->bitrate)
435 pos = (id3->elapsed/id3->tpf)*id3->bpf; 435 pos = id3->elapsed * (id3->bitrate / 8);
436 else 436 else
437 { 437 {
438 return -1; 438 return -1;