私の C# アプリケーション用の NAudio のはるかに単純なバージョンであるオープンソース コードを見つけました。私がやろうとしているのは、スピーカーから短い音を出して、プラグが差し込まれて動作していることをテストすることだけであり、マイクも聞きたいからです。プロジェクト自体は問題ないように見えましたが、少しリファクタリングして小さなチャックにすることができると感じました。私が見つけたもう 1 つのことは、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);
HeaderData、ヘッダーのサイズ、IntPtr データ、GCHandle、HeaderHandle、HeaderDataHandle など、他のほとんどのものを WaveBuffer の抽象バージョンに統合しました。WaitFor コマンド、OnCompleteCommand、bool Busy、および AutoResetEvent。何に使われているかはわかりませんが、使用されていますが、各ファイルで同じように使用されているので、移動しました。このスレッドを最後までお読みいただき、ありがとうございます。
編集
混乱させてすみません、私はこれらすべてのものを見つけることに夢中になり、私が何を尋ねるつもりだったのかを尋ねるのを忘れました. 基本的に問題は、ほぼ同じことを行うこれら 2 つの機能をどのように組み合わせることができるかということです。このデリゲートは、WaveInBuffer/WaveOutBuffer で新しいインスタンスを作成できるように、WaveNative からどのように機能し、同じことを意味しますか。私は、常に別のクラスを呼び出すか、基本クラスを呼び出す必要があると想定しました。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で参照できます。
私はそれをどのように使用しますか(完全には実装されていません)
マイク テストのアクション リスナーを見てください。
混乱して申し訳ありませんが、質問なしで質問を投稿しないようにします。