我为我的 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浏览我从中提取的代码
我如何使用它(此处未完全实现)
看看我的麦克风测试的动作监听器。
再次为混乱感到抱歉,我将尽量不要再次发布没有问题的问题。