0

我为我的 C# 应用程序找到了一个更简单的 NAudio 版本的开源代码。哪个对我来说更好,因为我要做的就是从扬声器中播放一个简短的声音,以测试它们是否已插入并正常工作,而且我还想听麦克风。该项目本身看起来还不错,但我觉得可以将其重构为更小的夹头。我发现的另一件事是 WaveOutBuffer.cs 和 WaveInBuffer.cs 文件非常相似。所以我开始制作一个抽象类 WaveBuffer。这将包含将传递的所有类似函数和变量。我遇到的麻烦如下。另一个文件 WaveNative.cs 中有委托。我对代表和活动非常陌生,所以我知道它有可能非常重要。但我不喜欢它的设置方式。所以我会发布每个文件中的内容以及它是如何使用的,然后展示我一直在努力工作的内容。也许在我们所有的思想之间,我们可以整合和重构它以使其更有效:)

所以首先。

WaveNative.cs

//callbacks
public delegate void WaveDelegate(IntPtr hdrvr, int uMsg, int dwUser, ref WaveHdr wavhdr, int dwParam2);

WaveInBuffer.cs / WaveOutBuffer.cs

    internal static void WaveInProc(IntPtr hdrvr, int uMsg, int dwUser, ref WaveNative.WaveHdr wavhdr, int dwParam2)
    {
        if (uMsg == WaveNative.MM_WIM_DATA)
        {
            try
            {
                GCHandle h = (GCHandle)wavhdr.dwUser;
                WaveInBuffer buf = (WaveInBuffer)h.Target;
                buf.OnCompleted();
            }
            catch
            {
            }
        }
    }
//WaveOutBuffer.cs version
    internal static void WaveOutProc(IntPtr hdrvr, int uMsg, int dwUser, ref WaveNative.WaveHdr wavhdr, int dwParam2)
    {
        if (uMsg == WaveNative.MM_WOM_DONE)
        {
            try
            {
                GCHandle h = (GCHandle)wavhdr.dwUser;
                WaveOutBuffer buf = (WaveOutBuffer)h.Target;
                buf.OnCompleted();
            }
            catch
            {
            }
        }
    }

WaveInRecorder.cs / WaveOutRecorder

private WaveNative.WaveDelegate m_BufferProc = new WaveNative.WaveDelegate(WaveInBuffer.WaveInProc);
private WaveNative.WaveDelegate m_BufferProc = new WaveNative.WaveDelegate(WaveOutBuffer.WaveOutProc);

最后,它们用于 PInvoke 调用,如下所示

    [DllImport(mmdll)]
    public static extern int waveOutOpen(out IntPtr hWaveOut, int uDeviceID, WaveFormat lpFormat, WaveDelegate dwCallback, int dwInstance, int dwFlags);
    [DllImport(mmdll)]
    public static extern int waveInOpen(out IntPtr phwi, int uDeviceID, WaveFormat lpFormat, WaveDelegate dwCallback, int dwInstance, int dwFlags);

我已经在 WaveBuffer 的抽象版本中整合了大多数其他内容,例如 HeaderData、标题的大小、IntPtr 数据、GCHandle HeaderHandle 和 HeaderDataHandle。WaitFor 命令、OnCompleteCommand、bool Busy 和 AutoResetEvent。不确定它的用途,但它的用途,但它在每个文件中使用相同,所以我只是将它移过来。感谢您的耐心和阅读本主题。

编辑

很抱歉造成混乱,我太专注于寻找所有这些东西,我忘了问我想问什么。基本上,问题是如何将这两个功能几乎完全相同的功能结合起来?这个 Delegate 如何从 WaveNative 工作,以便我可以在 WaveInBuffer/WaveOutBuffer 中创建一个新实例,这意味着同样的事情。我只是假设我必须总是从另一个调用一个,或者只调用基类一个。至于 m_BufferedProc 我将发布整个代码,因为我很难理解。请注意,我发布的这段代码不是我自己的。这里是

public class WaveInRecorder : IDisposable
{
    private IntPtr m_WaveIn;
    private WaveInBuffer m_Buffers; // linked list
    private WaveInBuffer m_CurrentBuffer;
    private Thread m_Thread;
    private BufferDoneEventHandler m_DoneProc;
    private bool m_Finished;

    private WaveNative.WaveDelegate m_BufferProc = new WaveNative.WaveDelegate(WaveInBuffer.WaveInProc);

    public static int DeviceCount
    {
        get { return WaveNative.waveInGetNumDevs(); }
    }

    public WaveInRecorder(int device, WaveFormat format, int bufferSize, int bufferCount, BufferDoneEventHandler doneProc)
    {
        m_DoneProc = doneProc;
        WaveInHelper.Try(WaveNative.waveInOpen(out m_WaveIn, device, format, m_BufferProc, 0, WaveNative.CALLBACK_FUNCTION));
        AllocateBuffers(bufferSize, bufferCount);
        for (int i = 0; i < bufferCount; i++)
        {
            SelectNextBuffer();
            m_CurrentBuffer.Record();
        }
        WaveInHelper.Try(WaveNative.waveInStart(m_WaveIn));
        m_Thread = new Thread(new ThreadStart(ThreadProc));
        m_Thread.Start();
    }
    ~WaveInRecorder()
    {
        Dispose();
    }
    public void Dispose()
    {
        if (m_Thread != null)
            try
            {
                m_Finished = true;
                if (m_WaveIn != IntPtr.Zero)
                    WaveNative.waveInReset(m_WaveIn);
                WaitForAllBuffers();
                m_Thread.Join();
                m_DoneProc = null;
                FreeBuffers();
                if (m_WaveIn != IntPtr.Zero)
                    WaveNative.waveInClose(m_WaveIn);
            }
            finally
            {
                m_Thread = null;
                m_WaveIn = IntPtr.Zero;
            }
        GC.SuppressFinalize(this);
    }
    private void ThreadProc()
    {
        while (!m_Finished)
        {
            Advance();
            if (m_DoneProc != null && !m_Finished)
                m_DoneProc(m_CurrentBuffer.Data, m_CurrentBuffer.Size);
            m_CurrentBuffer.Record();
        }
    }
    private void AllocateBuffers(int bufferSize, int bufferCount)
    {
        FreeBuffers();
        if (bufferCount > 0)
        {
            m_Buffers = new WaveInBuffer(m_WaveIn, bufferSize);
            WaveInBuffer Prev = m_Buffers;
            try
            {
                for (int i = 1; i < bufferCount; i++)
                {
                    WaveInBuffer Buf = new WaveInBuffer(m_WaveIn, bufferSize);
                    Prev.NextBuffer = Buf;
                    Prev = Buf;
                }
            }
            finally
            {
                Prev.NextBuffer = m_Buffers;
            }
        }
    }
    private void FreeBuffers()
    {
        m_CurrentBuffer = null;
        if (m_Buffers != null)
        {
            WaveInBuffer First = m_Buffers;
            m_Buffers = null;

            WaveInBuffer Current = First;
            do
            {
                WaveInBuffer Next = Current.NextBuffer;
                Current.Dispose();
                Current = Next;
            } while(Current != First);
        }
    }
    private void Advance()
    {
        SelectNextBuffer();
        m_CurrentBuffer.WaitFor();
    }
    private void SelectNextBuffer()
    {
        m_CurrentBuffer = m_CurrentBuffer == null ? m_Buffers : m_CurrentBuffer.NextBuffer;
    }
    private void WaitForAllBuffers()
    {
        WaveInBuffer Buf = m_Buffers;
        while (Buf.NextBuffer != m_Buffers)
        {
            Buf.WaitFor();
            Buf = Buf.NextBuffer;
        }
    }

请注意,该代码不是我的,而是 Ianier Munoz 的。我正在开发一个类似的版本,您可以在http://code.google.com/p/adli/source/browse/#svn%2Ftrunk%2FAspects%2FCustom%2FAudio浏览我从中提取的代码

我如何使用它(此处未完全实现)

http://code.google.com/p/adli/source/browse/trunk/Aspects/Panels/Main%20Panels/AudioBrightnessPanel.cs

看看我的麦克风测试的动作监听器。

再次为混乱感到抱歉,我将尽量不要再次发布没有问题的问题。

4

1 回答 1

0

好吧,如果块是互斥的,这意味着将两个块合并在一起很容易……(我删除了空的 catch 块,因为它是邪恶的)

internal static void WaveProc(IntPtr hdrvr, int uMsg, int dwUser, ref WaveNative.WaveHdr wavhdr, int dwParam2)
{
    GCHandle h = (GCHandle)wavhdr.dwUser;
    if (uMsg == WaveNative.MM_WIM_DATA)
    {
         WaveInBuffer buf = (WaveInBuffer)h.Target;
         buf.OnCompleted();
    }
    if (uMsg == WaveNative.MM_WOM_DONE)
    {
         WaveOutBuffer buf = (WaveOutBuffer)h.Target;
         buf.OnCompleted();
    }
}

private WaveNative.WaveDelegate m_BufferProc = new WaveNative.WaveDelegate(WaveInBuffer.WaveProc);

于 2012-05-10T18:01:21.630 回答