summaryrefslogtreecommitdiffstats
path: root/apps/codecs/mpa.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/mpa.c')
-rw-r--r--apps/codecs/mpa.c59
1 files changed, 58 insertions, 1 deletions
diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c
index f9a27f5b41..a18a5e8090 100644
--- a/apps/codecs/mpa.c
+++ b/apps/codecs/mpa.c
@@ -109,6 +109,61 @@ int get_file_pos(int newtime)
return pos;
}
+static void set_elapsed(struct mp3entry* id3)
+{
+ unsigned long offset = id3->offset > id3->first_frame_offset ?
+ id3->offset - id3->first_frame_offset : 0;
+
+ if ( id3->vbr ) {
+ if ( id3->has_toc ) {
+ /* calculate elapsed time using TOC */
+ int i;
+ unsigned int remainder, plen, relpos, nextpos;
+
+ /* find wich percent we're at */
+ for (i=0; i<100; i++ )
+ if ( offset < id3->toc[i] * (id3->filesize / 256) )
+ break;
+
+ i--;
+ if (i < 0)
+ i = 0;
+
+ relpos = id3->toc[i];
+
+ if (i < 99)
+ nextpos = id3->toc[i+1];
+ else
+ nextpos = 256;
+
+ remainder = offset - (relpos * (id3->filesize / 256));
+
+ /* set time for this percent (divide before multiply to prevent
+ overflow on long files. loss of precision is negligible on
+ short files) */
+ id3->elapsed = i * (id3->length / 100);
+
+ /* calculate remainder time */
+ plen = (nextpos - relpos) * (id3->filesize / 256);
+ id3->elapsed += (((remainder * 100) / plen) *
+ (id3->length / 10000));
+ }
+ else {
+ /* no TOC exists. set a rough estimate using average bitrate */
+ int tpk = id3->length /
+ ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
+ 1024);
+ id3->elapsed = offset / 1024 * tpk;
+ }
+ }
+ else
+ {
+ /* constant bitrate, use exact calculation */
+ if (id3->bitrate != 0)
+ id3->elapsed = offset / (id3->bitrate / 8);
+ }
+}
+
/* this is the codec entry point */
enum codec_status codec_main(void)
{
@@ -145,8 +200,10 @@ next_track:
current_frequency = ci->id3->frequency;
codec_set_replaygain(ci->id3);
- if (ci->id3->offset)
+ if (ci->id3->offset) {
ci->seek_buffer(ci->id3->offset);
+ set_elapsed(ci->id3);
+ }
else
ci->seek_buffer(ci->id3->first_frame_offset);