naudio / NAudio

Audio and MIDI library for .NET
MIT License
5.37k stars 1.09k forks source link

Mp3FileReader loses the first frame while reading mp3 files #333

Open Chlorie opened 6 years ago

Chlorie commented 6 years ago

I'm currently developing a rhythm game level editor in Unity, and since Unity doesn't allow reading mp3 in standalone I was thinking about using NAudio to handle that thing. But while using Mp3FileReader to read the file I found some issues with it. I need to get the samples of the audio file so that I could transfer them to a Unity AudioClip for later controls, but I found that the first frame of the mp3 file is lost. I'm using this to read the samples new Mp3FileReader(stream).ToSampleProvider().Read(samples, 0, length) I tested with several files, and the length shown in NAudio differs from that shown in Audition for about 26ms (an mp3 frame), and Audition's timing is definitely right. An offset of 26ms is already a HUGE offset for rhythm games and is unbearable. I'm manually adding zeros before the samples to fix the problem for now, but is there any workaround for this problem to get correct samples, or can you fix this issue later? Thanks!

markheath commented 6 years ago

Mp3FileReader attempts to find the first frame, but its possible that it misses it in some cases. Or it could even be a problem with the ACM codec. Are you able to use MediaFoundationReader, which should have more reliable frame detection code.

NetNerd commented 5 years ago

I believe the issue here isn't a frame being missed in parsing (OP says they tested multiple files with same results), but that NAudio deliberately skips Xing/Info frames whereas at least some (possibly many) other pieces of software don't.

To test if this is the cause, I encoded some files using ffmpeg (LAME) and compared them to original wave files in Adobe Audition CS6 and Audacity 2.0.3.
In both cases, there was a 2257 sample delay on the MP3 files. This matches the delays shown at http://mp3decoders.mp3-tech.org/decoders_lame.html for LAME including the VBR header: 576 samples of encoder delay, 529 samples of decoder delay, and 1152 samples for the added header frame.

This indicates that at least some other software decodes the header as silent audio instead of skipping it, something understandable given that it does look like an audio frame. There's likely also programs that can recognise the header, or even go as far as accounting for encoder/decoder delay too.

 

This provides two approaches:

 

I think for most applications this is fine in its current state, especially because MP3 is far from an ideal format for getting precise timing in the first place.

NetNerd commented 5 years ago

Hmmm... I noticed that ffmpeg (command line, not tested as library) seems to decode my test files with encoder delay removed. This means there is likely no real consensus on any of the three possible ways to handle file start delay.
Perhaps I should get around to updating my old version of Audacity to see if it also behaves like this now. (that's getting a bit off topic though)