Dillion Ecmark
Dillion Ecmark

Reputation: 724

NAudio.MmException

I'm experimenting on how to play mp3 using Naudio. My simple app has one windows form and one button to play/pause the music. The app however has two major problem:

While it was intended that if the music is playing and the play button is pressed, the app should stop playing. Instead when the button is re-pressed, the app restart the music and then (sometime) throw an exception If the button is pressed two or three times (and without any delay) ,the app throw a NAudio.MmException (Message=InvalidParameter calling acmStreamClose) Can someone tell me what's wrong with my code? Below is my code:

using System;
using System.Windows.Forms;
namespace NaudioTesting
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private NAudio.Wave.BlockAlignReductionStream stream = null;

        private NAudio.Wave.DirectSoundOut output = null;


        public void LoadFile(string filePath)
        {
            DisposeWave();

            if (filePath.EndsWith(".mp3"))
            {
                NAudio.Wave.WaveStream pcm =
                    NAudio.Wave.WaveFormatConversionStream.CreatePcmStream(new NAudio.Wave.Mp3FileReader(filePath));
                stream = new NAudio.Wave.BlockAlignReductionStream(pcm);
            }
            else if (filePath.EndsWith(".wav"))
            {
                NAudio.Wave.WaveStream pcm = new NAudio.Wave.WaveChannel32(new NAudio.Wave.WaveFileReader(filePath));
                stream = new NAudio.Wave.BlockAlignReductionStream(pcm);
            }
            else throw new InvalidOperationException("Not a correct audio file type.");

            output = new NAudio.Wave.DirectSoundOut();
            output.Init(stream);
            output.Play();
        }

        private void playPauseButton_Click(object sender, EventArgs e)
        {
            string filePath = "GetLoud.mp3";
            LoadFile(filePath);
            if (output != null)
            {
                if (output.PlaybackState == NAudio.Wave.PlaybackState.Playing) output.Pause();
                else if (output.PlaybackState == NAudio.Wave.PlaybackState.Paused) output.Play();
            }
        }

        private void DisposeWave()
        {
            try
            {
                if (output != null)
                {
                    if (output.PlaybackState == NAudio.Wave.PlaybackState.Playing) output.Stop();
                    output.Dispose();
                    output = null;
                }
                if (stream != null)
                {
                    stream.Dispose();
                    stream = null;
                }
            }
            catch (NAudio.MmException)
            {
                throw;
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            DisposeWave();
        }
    }
}

Upvotes: 2

Views: 4871

Answers (1)

Tomislav Markovski
Tomislav Markovski

Reputation: 12346

Looking at the DirectSoundOut source, the implementation for Play and Pause doesn't support resuming. Namely, what happens to you is exactly what it should. Calling play will always start from begining of the stream. You should use WaveOut instead. It supports resuming by calling Play again, just like what you have in your code.

output = new NAudio.Wave.WaveOut();

Upvotes: 1

Related Questions