The duration of the song fluctuates during the first few seconds of MP4/AAC+ playback, and sometimes longer.
I can see why this might happen with an MP3 file that may not contain the appropriate/correct headers and/or may be truncated, but an MP4 should have the necessary atoms (mvhd, tkhd), to calculate an exact duration in advance of the actual audio playback.
I'm not 100% familiar with the formats of different streams. Right now the duration is just a calculation based off the bit rate the file length. The file length is always known, but the bit rate is the factor which is calculated. It's a combination of the sample rate, frames per packet, and the running average of the size of packets.
The fluctuation happens when the average size of the packets goes up or down, and that takes awhile to stabilize. Again, I'm not very familiar with audio formats. This is what mattgalagher's code did, and I just cleaned it up a bit.
If you know where to find these things in the structures that the audio framework provides, then I'd be more than happy to add it in!
OK, I'll dig into this a bit.
Improved duration calculation - #20
Because of #36, this does not work well with .aac files (.m4a is fine).
I've improved the duration calculation so it tries not to rely on the bitrate which can vary.
It first asks the AudioFileStream for an audio data packet count. If it returns without error, then this is used to give an accurate reading immediately.
If the AudioFileStream returns an error, it then tries to fetch the audio data packet count from our own calculations.
Lastly it will fallback to use the bitrate if all else fails. Currently, this will always happen with .aac files (.m4a files work fine). MP3s will fallback to this too but it works well for them.
There's still a half-second margin of error but that could be a bug elsewhere (eg. the progress method) rather than incorrect duration calculation. I've yet to look into this.
Further improved bitrate calculation - #20.
Some accuracy improvements to the progress method - #20.
Further improved duration calculation through pauses - #20.
Further improvements to bitrate calculation - #20.
Improved progress calculation after seeks - #20.
Progress and duration calculations should now be very accurate for the files we can get the data for. There should be no margin of error or fluctuation anymore for files with the proper headers (eg. M4A) or if they are CBR (constant bitrate). Even for raw AAC files where it does not contain the duration in the headers there is a lot less fluctuation now. From my testing it only fluctuates by up to 0.4 seconds depending on how even the stream starts. On a perfect stream the fluctuation can be just up to 0.1 seconds. If you do not show fractions of seconds then the fluctuation should be invisible in most cases. There is a couple second margin of error however because we don't get the data offsets for raw AAC. I'm not sure if much can be done about it. How we nearly get the duration is quite good. iTunes and such don't even show it.
Seeking has also drastically improved. It should work just about perfect now.