Thursday, 13 May 2010

Converting MP3 to WAV with NAudio

One of the more common support requests with NAudio is how to convert MP3 files to WAV. Here’s a simple function that will do just that:

public static void Mp3ToWav(string mp3File, string outputFile)
{
    using (Mp3FileReader reader = new Mp3FileReader(mp3File))
    {
        using (WaveStream pcmStream = WaveFormatConversionStream.CreatePcmStream(reader))
        {
            WaveFileWriter.CreateWaveFile(outputFile, pcmStream);
        }
    }
}

… and that’s all there is to it.

Notes:

  1. There is no need to wrap pcmStream with a BlockAlignReductionStream since we are not repositioning the MP3 file, just reading it from start to finish.
  2. It uses the ACM MP3 decoder that comes with Windows to decompress the MP3 data.
  3. To be able to pass the MP3 data to the ACM converter we need to do some parsing of the MP3 file itself (specifically the MP3 frames and ID3 tags). Unfortunately, there are some MP3 files that NAudio cannot parse (notably the sample ones that come with Windows 7). My attempts at tracking down the cause of this problem have so far failed. (the basic issue is that after reading the ID3v2 tag, we don’t end up in the right place in the MP3 file to read a valid MP3Frame – see MP3FileReader.cs). Please let me know if you think you have a solution to this.

10 comments:

Anonymous said...

Hi ! Have you tested Mp3-Sharp to see if some errors are reproducible at the same stream offset ? I often come across MP3 files with a few weird frames, so I tend to just skip them instead of failing the entire conversion.

http://robburke.net/mle/mp3sharp/

Cheers, Dan

Unknown said...

I might have a go loading them with MP3Sharp, but I can't use any of their code unfortunately since it is GPL

Anonymous said...

The Windows 7 MP3 music clips fail because they have a wrong layer code in some headers. However you can safely skip them.

Take a look at:

Bitstream.cs
nextFrame()
read_header()
isSyncMark()
"INVALID LAYER DETECTED"
==> SKIP :)

Joymon said...

Do you have any idea to convert WAV to Mp3 in Silverlight?

Unknown said...

@joymon - do you mean MP3 to WAV?

Anonymous said...

Hi Mark,

I'd like to convert WAV to MP3. I've downloaded NAudio from codeplex but I can only find an MP3FileReader - is there an equivalent of an MP3FileWriter?

To make matters more complicated I'd like to perform the conversion on the fly. I have some recordings in WAV (from a phone system) and would like to convert them in realtime as they are downloaded. I have a solution working which automates lame, but because I need to convert the whole file before streaming it gives me an appreciable delay.

Any advice you have would be much appreciated.

Regards,

Daniel

Unknown said...

I'm afraid NAudio cannot convert to MP3. Your best bet is to use LAME.exe

Anton said...

Hi Mark....

I have been unable to find an email address to contact you directly, so I thought I would post my question here...

I am looking for an audio component and was wondering if nAudio was able to acheive what I require.
My requirements are as follows:

I have multiple audio tracks with nothing but music.
I have multiple recorded voice tracks no longer than 2-3 seconds each.
What I would like to do is "overlay" a voice track onto an audio
track at a specified time and output the results to a single file.
E.g. Audio track is 2 minutes long, and I would like to insert
the voice track at 23 seconds as well 1m 05 seconds and at 1m 40
seconds.

Can nAudio achieve this sort of task for me??
I am using VB.Net and I would need to accomplish this through code (API)...

Your assistance would be greatly appreciated.

Anton

ah said...

Sorry I am late on this, I am new to NAudio (looks wicked btw). When calling WaveFileWriter.CreateWaveFile, is there a way to get the progress of the decoding?

Unknown said...

@ah - look at the source code for CreateWaveFile - it is just a helper method that reads from the source and writes to the WAV file in a simple loop. You can easily write it yourself with whatever progress indicators you want.