NAudio.MmException

发布于 2024-12-23 10:39:30 字数 2630 浏览 5 评论 0原文

我正在尝试如何使用 Naudio 播放 mp3。我的简单应用程序有一个窗口窗体和一个用于播放/暂停音乐的按钮。然而,该应用程序有两个主要问题:

虽然它的目的是如果音乐正在播放并且按下播放按钮,则应用程序应该停止播放。相反,当重新按下按钮时,应用程序会重新启动音乐,然后(有时)抛出异常 如果按下按钮两次或三次(并且没有任何延迟),应用程序会抛出 NAudio.MmException (Message=InvalidParameter 调用 acmStreamClose) 有人可以告诉我我的代码有什么问题吗?下面是我的代码:

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();
        }
    }
}

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();
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

星光不落少年眉 2024-12-30 10:39:30

查看 DirectSoundOut 源,播放和暂停的实现不支持恢复。也就是说,发生在你身上的事情正是它应该发生的。调用播放始终从流的开头开始。
您应该使用 WaveOut 来代替。它支持通过再次调用 Play 来恢复,就像您在代码中的操作一样。

output = new NAudio.Wave.WaveOut();

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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文