WINMM库问题 [英] WinMM Library Issues

查看:247
本文介绍了WINMM库问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个WINMM库包装库,公开waveout的和WaveIn类录制和播放原始音频流的目的。

一切都很正常,但为了后续如何处理完成的缓冲区操作系统的规格,我添加了一个线程,联合国prepares的缓冲区和释放内存。我也得到了所有的同步下跌,从而使类固体和线程安全的。

不过,似乎有一个罕见的问题,即我想补充一个缓冲的waveout的设备和操作系统返回成功code,但如果设备复位立即后记,操作系统不缓冲区标记为完成,并将其返回给应用程序。

这似乎是失去了缓冲。所以,问题是,我跟踪发送到设备的各个缓冲区的计数和阻塞加入关闭()函数,该函数清除它们的主​​题。

任何意见,或已知的bug?

PS:这似乎不是发生在一个四核在Vista中,但不会发生在我的双核在XP专业版

EDIT1:我完全愿意暴露的完整源$ C ​​$ C,一旦我把它上传和属性格式许可的codePLEX,如果这将有助于任何人

EDIT2:发布库codePLEX: HTTP://winmm.$c$ cplex.com/

下面是什么原因导致这一问题的想法:

 公共部分类的MainView:表
{
    私人WaveIn waveIn =新WaveIn(WaveIn.WaveInMapperDeviceId);
    私人waveout的waveout的=新waveout的(WaveOut.WaveOutMapperDeviceId);

    公众的MainView()
    {
        的InitializeComponent();

        WAVEFORMAT格式= WaveFor​​mat.Pcm44Khz16BitMono;

        waveOut.Open(格式);

        waveIn.DataReady + =新的EventHandler< D​​ataReadyEventArgs>(WaveIn_DataReady);

        //调整这些值会影响内部缓冲线程。
        //设置过小的QUEUESIZE与太小的缓冲区大小的
        //会导致缓冲区欠载,这听起来像是波涛汹涌的声音。
        waveIn.BufferQueueSize = 200;
        waveIn.BufferSize = 64;

        waveIn.Open(格式);

        waveIn.Start();
    }

    无效WaveIn_DataReady(对象发件人,DataReadyEventArgs E)
    {
        如果(waveout的!= NULL)
        {
            锁定(waveout的)
            {
                //我们有锁后,检查空,
                //因为waveout的可能已被处理
                //在另一个锁。
                如果(waveout的!= NULL)
                {
                    waveOut.Write(e.Data);
                }
            }
        }
    }

    私人无效MainView_FormClosed(对象发件人,FormClosedEventArgs E)
    {
        如果(waveIn!= NULL)
        {
            锁定(waveIn)
            {
                waveIn.Dispose();
                waveIn = NULL;
            }
        }

        如果(waveout的!= NULL)
        {
            锁定(waveout的)
            {
                waveOut.Dispose();
                waveout的= NULL;
            }
        }
    }
}
 

解决方案

我会首先创建一个单独的对象上锁定。这应该(用,因为你之前锁定后办理入住手续的一半左右),简化了很多的空检查逻辑的。

其次,处置您的变量将不会设置为,所以你的其他检查仍然会通过,因为对象不为空,只能丢弃。所以,我会做

  waveOut.Dispose();
waveout的= NULL;
 

,以确保其显式设置为null。

I wrote a WinMM library wrapper library that exposes WaveOut and WaveIn classes for the purpose of recording and playing raw audio streams.

Everything works great, but in order to follow the operating system specs on how to handle the finished buffers, I added a thread that unprepares the buffers and frees the memory. I also got all of the synchronization down, so that the classes are solid and thread-safe.

However, there seems to be a rare issue where I add a buffer to the WaveOut device and the operating system returns a success code, but if the device is reset immediately afterwords, the OS does not mark the buffer as finished and return it to the application.

It seems that it is loosing the buffers. So, the problem is, I'm keeping track of the count of individual buffers sent to the device and blocking joining the Close() function to the thread that cleans them up.

Any ideas, or known bugs?

PS: This does NOT seem to happen on a Quad Core in Vista, but does happen on my Dual Core in XP pro.

EDIT1: I'm totally willing to expose the full source code, once I get it uploaded and propery licensed on codeplex, if that would help anybody.

EDIT2: Posted library to CodePlex: http://winmm.codeplex.com/

Here is an idea of what causes the issue:

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;
            }
        }
    }
}

解决方案

I would first create a separate object on which to lock. That should simplify a lot of your null-checking logic (by about half since you check before and after the lock).

Second, Dispose will not set your variable to null, so your other checks will still pass through because the object is not null, only disposed. So I would do

waveOut.Dispose();
waveout = null;

to make sure that it is explictly set to null.

这篇关于WINMM库问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆