FS#10139 - Broken seeking in very long audio files.

Attached to Project: Rockbox
Opened by Paul Louden (Llorean) - Saturday, 18 April 2009, 09:18 GMT
Last edited by Andree Buschmann (Buschel) - Monday, 20 April 2009, 19:11 GMT
Task Type Bugs
Category Music playback
Status Closed
Assigned To No-one
Operating System Gigabeat S
Severity Low
Priority Normal
Reported Version Daily build (which?)
Due in Version Undecided
Due Date Undecided
Percent Complete 100%
Votes 0
Private No


I've tested this on Gigabeat S, though it seems reasonable that it's a swplayback / buffering issue.

Tested in r20728.

File length is ~21hrs long (audiobook). I have a bookmark 17.5 hours into the file. If I resume the bookmark all is well. If I seek, for example, one second from where I am, I get audio completely unrelated to where I am. If I stop and then resume playback, it resumes that unrelated audio, but the progress bar is now showing that I'm playing from 5.5 hours into the file (which is approximately correct judging from the part of the book I'm now hearing).
This task depends upon

Closed by  Andree Buschmann (Buschel)
Monday, 20 April 2009, 19:11 GMT
Reason for closing:  Fixed
Additional comments about closing:  Fxied with r20755
Comment by Andree Buschmann (Buschel) - Sunday, 19 April 2009, 09:19 GMT
Can you give some more details about the file (format, samplingrate, bitrate, VBR/CBR, filesize)? The seek is implement different for each codec, so there are main differences in the handling. From what you describe I expect some int-overflow as the amount of samples (assuming 44.1kHz is used) or bits (assuming 128kbit/s is used) exceeds uint32.
Comment by Paul Louden (Llorean) - Sunday, 19 April 2009, 12:34 GMT
44.1khz 144 Kbps avg VBR MP3 with a filesize in the 1.3 GB range.
Comment by Andree Buschmann (Buschel) - Sunday, 19 April 2009, 15:40 GMT
i cannot code from this PC, but please try the following: In file "/apps/codecs/mpa.c" in function "get_file_pos(int newtime)" please change lines

percent = (newtime*100) / id3->length;
remainder = (newtime*100) % id3->length;

to (e.g. this is used for mp3 cbr files in within the same function)

percent = ( (newtime/1000) *100) / (id3->length/1000);
remainder = ( (newtime/1000) *100) % (id3->length/1000);

or to (convert newtime to int64, convert result back to uint32)

percent = (unsigned int) ( ( (int64_t)(newtime)*100) / id3->length);
remainder = (unsigned int)(((int64_t)(newtime)*100) % id3->length);

As far as I can see newtime is sent in milliseconds. Your 17.5h lead to 17.5*3600*1000 ms which are then multiplied with 100. This overflows the uint32-variable "percent". The modulo part is 5.5h long...So, theory seems to match the bug.
Comment by Paul Louden (Llorean) - Monday, 20 April 2009, 11:00 GMT
I used (newtime)%(id3->length / 100) and it seems to work fine.
Comment by Andree Buschmann (Buschel) - Monday, 20 April 2009, 18:29 GMT
A cleaner and better readable solution. Can you please test?

Edit: v01 was faulty, please use v02.