我找到了一个开源代码,它是我的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。不知道它用于什么,但它用于,但它在每个文件中使用相同所以我只是移动它。感谢您的耐心和阅读此帖。
修改
抱歉这令人困惑,我找到了所有这些东西,我忘了问我的意思。基本上我的问题是如何将这两个几乎完全相同的功能结合起来呢?这个委托如何从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浏览我从中提取的代码
我如何使用它(未完全实现在这里)
查看麦克风测试的动作监听器。
再次对此感到抱歉,我会尽量不再回答问题。
答案 0 :(得分:0)
嗯,你有互相排斥,如果块意味着很容易将2合并在一起...(我删除了空捕获块,因为它的邪恶)
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);