我有一个为 RSS 提要播放摩尔斯电码的 C# 项目。我使用托管 DirectX 编写它,但发现托管 DirectX 已过时且已弃用。我的任务是播放纯正弦波阵发,其间穿插着静默期(代码),它们的持续时间精确计时。我需要能够调用一个在这么多毫秒内播放纯音的函数,然后是 Thread.Sleep() 然后播放另一个,等等。在最快的情况下,音调和空格可以短至 40 毫秒。
它在托管 DirectX 中运行良好。为了获得精确定时的音调,我创建了 1 秒。正弦波进入辅助缓冲区,然后播放一定持续时间的音调,我在缓冲区结束后的 x 毫秒内向前搜索,然后播放。
我试过 System.Media.SoundPlayer。这是一个失败者[编辑 - 请参阅下面的答案],因为您必须 Play()、Sleep(),然后是 Stop() 才能获得任意音调长度。结果是音调太长,因 CPU 负载而异。实际停止音调需要不确定的时间。
然后我开始了漫长的尝试使用NAudio 1.3。我最终得到了一个提供音调数据的内存驻留流,然后再次向前寻找,将所需的音调长度留在流中,然后播放。这在 DirectSoundOut 类上工作了一段时间(见下文),但 WaveOut 类很快就死了,内部断言说尽管 PlayerStopped = true,但缓冲区仍在队列中。这很奇怪,因为我玩到最后,然后在音调结束和下一个音调开始之间等待相同的持续时间。您会认为在开始播放 40 毫秒音调后的 80 毫秒,它不会在队列中有缓冲区。
DirectSoundOut 有一段时间运行良好,但它的问题是,对于每个音调突发 Play(),它都会分离一个单独的线程。最终(5分钟左右)它只是停止工作。在 VS2008 IDE 中运行项目时,您可以在输出窗口中看到一个又一个线程退出的线程。我在播放过程中不创建新对象,我只是 Seek() 音流然后一遍又一遍地调用 Play(),所以我认为孤立缓冲区/任何堆积直到它被阻塞都不是问题。
我对此没有耐心,所以我希望这里有人面临类似的要求,并且可以引导我朝着可能的解决方案前进。