c# - 如何异步播放声音,但自己在队列中?

标签 c# .net audio asynchronous

我只想依次播放 4 个声音(声音 1-> 声音 2-> 声音 3),但在每次播放期间都不会停止我的代码流,也不会等待每个声音结束。

我到处搜索这个,但我阅读的每个方向都陷入了其他问题。

到目前为止,我最好的选择是:使用我已经使用过的 System.Media 中的 SoundPlayer 并制作我自己的队列函数,但是 Soundplayer 没有“完成播放”事件,所以我不知道何时开始下一个声音。 (真的吗,微软?)

其他解决方案和问题: DirectSound 在 .NET (c#) 中工作似乎很复杂。 Win Playsound 并没有真正帮助,因为它也无法排队。

最佳答案

您可以尝试在 UI 外的线程上使用 PlaySync,例如:后台线程,正如某些人评论的那样。

这是一个示例(未经测试)对队列使用线程安全* BlockingCollection
* 你可以在线程内外使用

您可能想要创建自己的类或方法,在每次声音结束时触发一个事件。或者您可以在线程中循环队列,因为 PlaySync 将自行等待。

using System.Threading;
using System.Collections.Concurrent;
namespace PlaySound
{
    public partial class Form1 : Form
    {
        private Thread soundPlayThread;
        private BlockingCollection<string> speakQueue = new BlockingCollection<string>();
        private CancellationTokenSource cancelSoundPlay;
        private int soundPlayCount = 0;

        public Form1()
        {
            InitializeComponent();
            cancelSoundPlay = new CancellationTokenSource();
        }

        private void btnStartSoundPlay_Click(object sender, EventArgs e)
        {
            StartSoundPlay();
        }

        private void btnStopSoundPlay_Click(object sender, EventArgs e)
        {
            cancelSoundPlay.Cancel();
            Console.WriteLine("Sound play cancelled.");
        }

        private void btnAddToQueue_Click(object sender, EventArgs e)
        {
            speakQueue.Add("MyFile.wav");
        }

        private void queueAndPlay(string loc)
        {
            if (!File.Exists(loc=loc+".wav"))
                loc=configPath+"soundnotfound.wav";
            speakQueue.Add(loc);
            StartSoundPlay();
        }


        private void StartSoundPlay()
        {
            //Sound Player Loop Thread
            if (this.soundPlayThread == null || !this.soundPlayThread.IsAlive)
            {
                this.soundPlayThread = new Thread(SoundPlayerLoop);
                this.soundPlayThread.Name = "SoundPlayerLoop";
                this.soundPlayThread.IsBackground = true;
                this.soundPlayThread.Start();
                Console.WriteLine("Sound play started");
            }
        }
        //Method that the outside thread will use outside the thread of this class
        private void SoundPlayerLoop()
        {
            var sound = new SoundPlayer();
            foreach (String soundToPlay in this.speakQueue.GetConsumingEnumerable(cancelSoundPlay.Token))
            {
                //http://msdn.microsoft.com/en-us/library/system.media.soundplayer.playsync.aspx
                speaker.SoundLocation=soundToPlay;
                //Here the outside thread waits for the following play to end before continuing.
                sound.PlaySync();
                soundPlayCount++;
                Console.WriteLine("Sound play end. Count: " + soundPlayCount);
            }
        }
    }
}

关于c# - 如何异步播放声音,但自己在队列中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22208258/

相关文章:

c++ - 零延迟麦克风环回、侧音

vb.net - 检查耳机是否在VB.net中

c# - 在方法类的消息框中显示变量

c# - 使用 DotNetZip 从 zip 文件中提取特定文件夹

c# - 在 C# 中,如果我要返回一个点但找不到坐标,我应该返回什么?

.net - 向 ASP.NET 程序员教授 ASP.NET MVC 的最佳学习资源是什么?

c++ - 带有波形文件的 QAudioFormat

c# - 使用 ITextSharp(旧版本)将多个文件合并为 pdf

.net - 托管 System::Diagnostics::Debugger::Launch 函数的非托管/ native 替代方案?

c# - 使用 "DescribeInstanceStatus"例程过滤 EC2 实例 - AWS SDK