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