在 C# 中确定声音何时完成播放

Posted

技术标签:

【中文标题】在 C# 中确定声音何时完成播放【英文标题】:Determining when a sound has finished playing in C# 【发布时间】:2009-01-07 23:01:10 【问题描述】:

情况如下: 用户查找内容。

播放提示音,因为他查找的项目上有通知 用户关闭通知 - 应用程序继续检索信息 用户收到一个“叮”,告诉他们信息已完成检索 应用程序开始向 TextToSpeech 发送某些属性 应用程序遇到第二个通知,内部通知数据并发送另一个警报(文本语音暂停,然后在警报完成后恢复) 文本到语音已完成,播放另一个“叮”,让用户知道它已阅读所有内容

我们目前使用队列以有序的方式处理声音,以防止声音重叠。我们目前仅在调用 SoundAdded 事件时播放队列中的声音。这是我们在向队列中添加声音时触发的自定义事件。目前,每次调用事件只会播放一种声音。我们遇到了一个问题,在播放某些声音后,它们会“锁定”队列,阻止进一步的声音被处理。即使没有播放声音,我们也总是通过“解锁”队列来解决这个问题。然而,这仍然给我们留下了队列得到播放声音的问题。

我能想到的解决此问题的唯一方法是添加一个循环以在仍有声音等待播放时继续尝试播放声音。目前,主线程正在处理声音,我可能需要将声音处理移至单独的线程,但我不确定处理声音的最佳方法是什么。

所以...我的问题...是否有一个很好的声音库可供我们使用,其中包括声音结束的事件。或者......创造这样一个东西的最佳方法是什么?

【问题讨论】:

【参考方案1】:

我不知道是否已经有一个 .NET 库可以让你这样做,但我认为你可以很容易地从 Windows API 中 P/Invoke PlaySound 并使用它来播放你的声音。只要您不指定 SND_ASYNC 标志,它就应该阻塞,直到声音播放完毕,此时您可以播放下一个声音。正如您所提到的,您肯定希望在不同的线程中执行此操作。

【讨论】:

我们目前正在使用 Windows API 中的 PlaySound,我们几乎肯定会将声音移动到另一个线程并播放 SND_SYNC。其他开发人员之一建议使用消费者线程,该线程在队列中引发 SoundAdded 事件之前一直处于休眠状态。 感谢所有帮助。我们终于让声音按照我们想要的方式工作了。【参考方案2】:

扩展 Jon 的回答:在 .NET 2.0 及更高版本中,您可以使用 My.Computer.Audio.Play 和 AudioPlayMode.WaitToComplete 选项。

编辑:要在 C# 上下文中使用它,请参阅 Microsoft 的 How to: Use the My Namespace (C# Programming Guide)。

【讨论】:

我不完全确定如何让它在 C# 中工作。在MSDN上看,好像只有VB.NET。 您仍然可以使用 C# 或任何其他 .NET 语言的 Microsoft.VisualBasic 命名空间中的内容,所以我会采用这种方式,而不是使用 PlaySound 进行 P/Invoke。 @Justin:这是来自 MS 的示例:msdn.microsoft.com/en-us/library/ms173136.aspx【参考方案3】:

如果您同步播放声音(在您管理的新线程上),您将知道它们何时完成。

但是你似乎有两个问题;一个是知道声音何时结束,另一个是队列的建立。如果您有可以自定义的声音,如果您的用户选择很长的录音(例如 10 秒以上)作为声音,您的应用程序会受到什么影响?

我建议您在处理过程中采用与在 UI 上显示文件名相同的方法。也就是说,您显示的是最新的文件名,而不是每个文件名(否则文件名队列会增长并且您的 UI 会滞后)。如果可以的话,您应该在事件发生时播放声音(允许重叠声音),或者如果声音不是队列中最新的声音,则应该丢弃(不播放)声音。

【讨论】:

以上是关于在 C# 中确定声音何时完成播放的主要内容,如果未能解决你的问题,请参考以下文章

如何检测声音文件何时完成?

您如何检测声音文件何时完成?

montouch 检测声音何时播放完毕

我想在我的 Android 游戏中播放音乐以及分析声音数据。使用 Unity C#

C ++确定声音是不是播放完毕

如何以编程方式确定系统设备声音设置?