我正在开发一个应用程序,该应用程序使用waveOut...
来自winmm.dll
. 该应用程序使用“跳跃式”缓冲区,它们基本上是一堆样本数组,您可以将它们转储到音频队列中。Windows 按顺序无缝播放它们,并且在每个缓冲区完成时 Windows 调用一个回调函数。在这个函数中,我将下一组样本加载到缓冲区中,然后处理它们,然后将缓冲区转储回音频队列。这样,音频就可以无限期地播放。
出于动画目的,我正在尝试将其合并waveOutGetPosition
到应用程序中(因为“缓冲区完成”回调是不规则的,足以导致生涩的动画)。 waveOutGetPosition
返回播放的当前位置,所以它是超精确的。
问题是在我的应用程序中,调用waveOutGetPosition
最终会导致应用程序锁定 - 声音停止并且调用永远不会返回。我把事情归结为一个简单的应用程序来演示这个问题。您可以在此处运行该应用程序:
http://www.musigenesis.com/SO/waveOut%20demo.exe
如果你只是一遍又一遍地听到一点点钢琴声,它就起作用了。它只是为了证明问题。这个项目的源代码在这里(所有的肉都在 LeapFrogPlayer.cs 中):
http://www.musigenesis.com/SO/WaveOutDemo.zip
第一个按钮以越级模式运行应用程序,无需调用waveOutGetPosition
. 如果单击此按钮,应用程序将永远播放而不会中断(X 按钮将关闭它并关闭它)。第二个按钮启动跳跃器并启动一个表单计时器,该计时器调用waveOutGetPosition
并显示当前位置。单击此按钮,应用程序将运行一会儿,然后锁定。在我的笔记本电脑上,它通常会在 15-30 秒内锁定;最多只需要一分钟。
我不知道如何解决这个问题,所以非常欢迎任何帮助或建议。我发现关于这个问题的帖子很少,但似乎存在潜在的死锁,无论是多次调用waveOutGetPosition
还是waveOutWrite
同时发生的调用。我可能过于频繁地调用它,系统无法处理。
编辑:忘了提,我在 Windows Vista 上运行它。这在其他操作系统上可能根本不会发生。
编辑2:除了这些(未回答的)帖子外,我在网上几乎没有发现这个问题:
编辑3:嗯,我现在可以随意重现这个问题。如果我waveOutGetPosition
在之后waveOutWrite
(在下面的代码行中)立即调用,则应用程序每次都会挂起。它还以一种特别糟糕的方式挂起 - 它似乎将我的整个操作系统锁定了一段时间,而不仅仅是应用程序本身。因此,waveOutGetPosition
如果死锁发生在与几乎相同的时间waveOutWrite
,而不仅仅是字面上的同时发生,这似乎可以解释为什么锁对我不起作用。是的。