WinMM 库问题

Posted

技术标签:

【中文标题】WinMM 库问题【英文标题】:WinMM Library Issues 【发布时间】:2009-04-02 17:01:35 【问题描述】:

我编写了一个 WinMM 库包装库,它公开 WaveOut 和 WaveIn 类,用于录制和播放原始音频流。

一切都很好,但是为了遵循操作系统规范关于如何处理完成的缓冲区,我添加了一个线程来取消准备缓冲区并释放内存。我还关闭了所有同步,因此这些类是可靠且线程安全的。

但是,似乎有一个罕见的问题,即我向 WaveOut 设备添加缓冲区并且操作系统返回成功代码,但如果设备随后立即重置,操作系统不会将缓冲区标记为已完成并返回它到应用程序。

似乎它正在失去缓冲区。所以,问题是,我正在跟踪发送到设备的各个缓冲区的计数,并阻止将 Close() 函数连接到清理它们的线程。

有什么想法或已知的错误吗?

PS:这似乎不会发生在 Vista 的四核上,但发生在我的 XP pro 的双核上。

EDIT1:我完全愿意公开完整的源代码,一旦我将它上传并在 codeplex 上获得适当许可,如果这对任何人都有帮助的话。

EDIT2:将库发布到 CodePlex:http://winmm.codeplex.com/

以下是导致问题的原因:

public partial class MainView : Form

    private WaveIn waveIn = new WaveIn(WaveIn.WaveInMapperDeviceId);
    private WaveOut waveOut = new WaveOut(WaveOut.WaveOutMapperDeviceId);

    public MainView()
    
        InitializeComponent();

        WaveFormat format = WaveFormat.Pcm44Khz16BitMono;

        waveOut.Open(format);

        waveIn.DataReady += new EventHandler<DataReadyEventArgs>(WaveIn_DataReady);

        // Tweaking these values affects the internal buffering thread.
        // Setting too small of a QueueSize with too small of a BufferSize
        //  will cause buffer underruns, which will sound like choppy audio.
        waveIn.BufferQueueSize = 200;
        waveIn.BufferSize = 64;

        waveIn.Open(format);

        waveIn.Start();
    

    void WaveIn_DataReady(object sender, DataReadyEventArgs e)
    
        if (waveOut != null)
        
            lock (waveOut)
            
                // We have to check for null after the lock,
                //  because waveOut may have been disposed
                //  inside another lock.
                if (waveOut != null)
                
                    waveOut.Write(e.Data);
                
            
        
    

    private void MainView_FormClosed(object sender, FormClosedEventArgs e)
    
        if (waveIn != null)
        
            lock (waveIn)
            
                waveIn.Dispose();
                waveIn = null;
            
        

        if (waveOut != null)
        
            lock (waveOut)
            
                waveOut.Dispose();
                waveOut = null;
            
        
    

【问题讨论】:

【参考方案1】:

我将首先创建一个单独的object 来锁定。这应该可以简化很多空值检查逻辑(因为您在锁定之前和之后检查了大约一半)。

其次,Dispose 不会将您的变量设置为null,因此您的其他检查仍将通过,因为该对象不为空,只是已处置。所以我会这样做

waveOut.Dispose();
waveout = null;

确保它被明确设置为 null。

【讨论】:

啊,关于单独对象的好主意。此外,在我遇到问题的实际应用程序上,我明确地将其设置为 null。 既然您至少提供了一些建设性的反馈,我将给予您赏金,即使我不确定问题是否已解决。

以上是关于WinMM 库问题的主要内容,如果未能解决你的问题,请参考以下文章

是否在每个 Windows 安装中都可以找到声音库 WINMM.DLL?

python 使用winmm库 usb

MonoDevelop + NAudio + Ubuntu Linux 告诉我找不到 Winmm.dll?

Windows Phone 开发:使用 winmm.dll 播放内部 mp3 文件

#pragma 注释(lib,“Winmm.lib”)不工作

win32——音乐媒体处理