13
WaveStream waveStream = new Mp3FileReader(mp3FileToPlay);
var waveOut = new WaveOut();
waveOut.Init(waveStream); 
waveOut.Play();

This throws an exception:

WaveBadFormat calling waveOutOpen

The encoding type is "MpegLayer3" as NAudio.

How can I play a mp3 file with NAudio?

Rookian
  • 19,841
  • 28
  • 110
  • 180

3 Answers3

52

For users of NAudio 1.6 and above, please do not use the code in the original accepted answer. You don't need to add a WaveFormatConversionStream, or a BlockAlignReductionStream, and you should avoid using WaveOut with function callbacks (WaveOutEvent is preferable if you are not in a WinForms or WPF application). Also, unless you want blocking playback, you would not normally sleep until audio finishes. Just subscribe to WaveOut's PlaybackStopped event.

The following code will work just fine to play an MP3 in NAudio:

var reader = new Mp3FileReader("test.mp3");
var waveOut = new WaveOut(); // or WaveOutEvent()
waveOut.Init(reader); 
waveOut.Play();
Dan
  • 11,077
  • 20
  • 84
  • 119
Mark Heath
  • 48,273
  • 29
  • 137
  • 194
  • Hey mark, thank you for your answer. I would like to know, according to your answer, where does the "test.mp3" file should be located at? – Eido95 May 07 '16 at 13:35
  • 1
    Wow. Such a high voted answer with the exact code as written by OP - or where exactly is the difference? I can't spot one. – Thomas Weller Nov 02 '17 at 14:20
  • WaveOut is disposable but never disposed in your code. If you dispose it, the audio stops playing. If you don't dispose it, it will likely only play until the garbage collector collects it. – Thomas Weller Nov 02 '17 at 14:45
  • Also, the file remains in use, if the reader is not closed. This makes it impossible to e.g. move or rename the file in Explorer, even if playback has already stopped. – Thomas Weller Nov 21 '17 at 22:01
  • @ThomasWeller that's because I'm assuming you're playing in a WinForms or WPF app. The code to dispose the Mp3FileReader and WaveOut device should happen when you've finished playing or are closing the form. See [this tutorial](https://github.com/naudio/NAudio/blob/master/Docs/PlayAudioFileWinForms.md) for more details – Mark Heath Nov 22 '17 at 09:18
  • 3
    @ThomasWeller you're right the question and answer have the same code. The difference is the date. When the original question asked, Mp3FileReader did not emit PCM from its Read method so the code didn't work. The original accepted answer is now not a recommended way to solve the problem. – Mark Heath Nov 22 '17 at 09:24
  • 4
    @MarkHeath - I recently stumbled upon NAudio after finally deciding that wmp's constant corruption of my playlists warranted a personal mp3 player project. In less than a day, with your library, I was able to easily create a wmp clone that respects playlists. I found your calling-out herein for your answer rather ironic, considering that you are, in fact, the author of NAudio. Your library has integrated so well into .NET 4.7+ on Windows 10 that it's only taken a few hours to fully implement. 6 years on from your initial reply, the code still performs as written. Thank you. – BJS3D Mar 14 '19 at 02:07
10

Try like this:

class Program
{
    static void Main()
    {
        using (var ms = File.OpenRead("test.mp3"))
        using (var rdr = new Mp3FileReader(ms))
        using (var wavStream = WaveFormatConversionStream.CreatePcmStream(rdr))
        using (var baStream = new BlockAlignReductionStream(wavStream))
        using (var waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback()))
        {
            waveOut.Init(baStream);
            waveOut.Play();
            while (waveOut.PlaybackState == PlaybackState.Playing)
            {
               Thread.Sleep(100);
            }
        }
    }
}

Edit this code is now out of date (relates to NAudio 1.3). Not recommended on newer versions of NAudio. Please see alternative answer.

Mark Heath
  • 48,273
  • 29
  • 137
  • 194
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    This does not work. "InvalidParameter calling acmStreamPrepareHeader" – Rookian Mar 21 '10 at 19:51
  • I've just downloaded the latest version of NAudio (http://www.codeplex.com/naudio) and tested this code with an mp3 on my computer. It worked for me. – Darin Dimitrov Mar 21 '10 at 19:53
  • Do you have a 64bit environment? I have recompiled the solution using x64, release mode and changed the .net platform from .NET 2.0 to 3.5 ... maybe because of this I get the errors? – Rookian Mar 21 '10 at 19:56
  • 1
    Yes I am running on Win7 64bit, I had to target x86 in the project properties for this to work. Targeting `Any CPU` threw a `BadImageFormatException` for `NAudio.dll`. – Darin Dimitrov Mar 21 '10 at 19:59
  • thanks! Now it works :) I read anywhere that one shall recompile NAudio to x64 ... – Rookian Mar 21 '10 at 20:06
  • 1
    x64 support in NAudio is hopefully coming very soon. See recent checkins - http://naudio.codeplex.com/SourceControl/list/changesets – Mark Heath Mar 30 '10 at 10:33
0

my preferred way to play any MP3 files with NAudio is this. I prefer to block the playing thread until Playback stopped with event listeners. Also, for the best compatibility, I use MP3Sharp to load the MP3 file and then pass it to NAudio since NAudio did not come with MP3 codecs.

using System;
using NAudio.Wave;
using System.Threading;
using MP3Sharp;
using System.IO;

namespace jessielesbian.NAudioTest
{
    public static class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("loading and parsing MP3 file...");
            MP3Stream stream = new MP3Stream("c:\\workspaces\\Stunning!  Boeing's 737 MAX on Flying Display.mp3");
            WaveFormat waveFormat = new WaveFormat(stream.Frequency, stream.ChannelCount);
            Console.WriteLine("allocating playback cache...");
            FastWaveBuffer fastWaveBuffer = new FastWaveBuffer(waveFormat, (int) stream.Length);
            Console.WriteLine("populating playback cache...");
            stream.CopyTo(fastWaveBuffer);
            fastWaveBuffer.Seek(0, SeekOrigin.Begin);
            Console.WriteLine("unloading MP3 file...");
            stream.Dispose();
            Console.WriteLine("prepairing player...");
            WaveOutEvent waveOutEvent = new WaveOutEvent();
            waveOutEvent.Init(fastWaveBuffer);
            waveOutEvent.Volume = 1;
            Console.WriteLine("arming ManualResetEvent...");
            ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            waveOutEvent.PlaybackStopped += (object sender, StoppedEventArgs e) => {
                manualResetEvent.Set();
            };
            Console.WriteLine("done!");
            waveOutEvent.Play();
            manualResetEvent.WaitOne();
        }
    }
    public sealed class FastWaveBuffer : MemoryStream, IWaveProvider
    {
        public FastWaveBuffer(WaveFormat waveFormat, byte[] bytes) : base(bytes)
        {
            WaveFormat = waveFormat;
        }
        public FastWaveBuffer(WaveFormat waveFormat, int size = 4096) : base()
        {
            WaveFormat = waveFormat;
            Capacity = size;
        }
        public WaveFormat WaveFormat
        {
            get;
        }
    }
}

Jessie Lesbian
  • 1,273
  • 10
  • 14