1

C# で NAudio を使用して音声を録音しようとしていますが、2 つの場所で立ち往生しています。

1. A crash:

THIS SOページのコードを少し変更すると、 NullReferenceException. クラッシュログは次のとおりです。

************** Exception Text **************
System.NullReferenceException: Object reference not set to an instance of an object.
   at NAudio.Wave.WaveIn.Callback(IntPtr waveInHandle, WaveMessage message, IntPtr userData, WaveHeader waveHeader, IntPtr reserved)
   at NAudio.Wave.WaveWindow.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

コードは次のとおりです。

using System;
using System.Windows.Forms;
using System.Threading;
using NAudio.Wave;

public class FOO
{
    static WaveIn s_WaveIn;

    [STAThread]
    static void Main(string[] args)
    {
        init();
        Application.Run();
    }

    public static void record()
    {
    while (true)
    {
        Console.WriteLine("Hit Enter to START Recording.\n");
        Console.ReadLine();

        s_WaveIn.StartRecording();

        Console.WriteLine("Hit Enter to STOP recording.\n");
        Console.ReadLine();

        s_WaveIn.StopRecording();
    }
    }

    public static void DeviceInit(int rate, int channels)
    {
    s_WaveIn = new WaveIn();
    s_WaveIn.WaveFormat = new WaveFormat(rate, channels);

    s_WaveIn.BufferMilliseconds = 1000;
    s_WaveIn.DataAvailable += new EventHandler<WaveInEventArgs>(SendCaptureSamples);
    }

    public static void init()
    {
    DeviceInit(44100, 2);

    Thread t1 = new Thread(delegate() {
        record();
        });
    t1.Start();
    }

    static void SendCaptureSamples(object sender, WaveInEventArgs e)
    {
    Console.WriteLine("Bytes recorded: {0}", e.BytesRecorded);
    }
}

ほとんどの場合、これは 3 回目の録音を開始したときに発生します。何がこれを引き起こしているのでしょうか?

*2. Modifying rate and channels at runtime.*

私の実際のコードでは、 をs_WaveIn.WaveFormat = new WaveFormat(new_rate, new_channels);呼び出す前に使用して波形フォーマットをリセットしていますStartRecording()Dispose()コールバックをリセットする必要があるため、呼び出していません。そのためDataAvailableには、別のメッセージ ループが必要です。このアプローチは正しいですか、それとも最初に Dispose を呼び出してから、新しい形式で s_WaveIn を再初期化する必要がありますか?

ありがとうございました。

4

4 に答える 4

1

あなたのMain方法は奇妙に見えます。何のためのスレッドですか?

これを使用するだけです:

[STAThread]
static void Main(string[] args)
{
    init();
    Application.Run();
}

メソッドinitもアプリケーションを実行します。なんで?
次のように変更してみてください。

public static void init()
{
    DeviceInit(44100, 2);

    Thread t1 = new Thread(delegate() {
        record();
    });
    t1.Start();
}

return;を返すメソッドの最後には必要ありませんvoid

于 2011-08-18T12:00:47.910 に答える
1

バッファが null の場合でも、DataAvailable コールバックが呼び出されているようです。

WaveIn.csファイル内の関数を変更しましたが、現在は正常に機能しています。これが正しいかどうかはわかりませんが、今のところ、これでうまくいっています。

private void Callback(IntPtr waveInHandle, WaveInterop.WaveMessage message, IntPtr userData, WaveHeader waveHeader, IntPtr reserved)
{
    if (message == WaveInterop.WaveMessage.WaveInData)
    {
    GCHandle hBuffer = (GCHandle)waveHeader.userData;
    WaveInBuffer buffer = (WaveInBuffer)hBuffer.Target;
if (buffer != null)
{
    if (DataAvailable != null)
    {
    DataAvailable(this, new WaveInEventArgs(buffer.Data, buffer.BytesRecorded));
    }
    if (recording)
    {
    buffer.Reuse();
    }
}
else
{
    if (RecordingStopped != null)
    {
    RecordingStopped(this, EventArgs.Empty);
    }
}
}

}

于 2011-08-23T10:32:21.293 に答える
0

同じ NullReferenceException が発生しました。作成者は、提案されたクラスWaveInに行を追加しませんでした。私が理解しているように、そのような使用は提供されていません。例の作成者ライブラリはStopRecording ()を呼び出さず、着信情報の記録を停止するだけですが、処理を続行し (たとえば、音量を測定するため) 、完全に停止してデータをデータWaveInに受信するためにStopRecording ()を呼び出します。 . したがって、 StopRecording()を呼び出した後、新しい WaveIn を使用する必要があると思います。

于 2013-09-20T07:08:19.920 に答える
0

私は、それはこのように行われなければならないと思います:

GCHandle hBuffer = (GCHandle)waveHeader.userData;
WaveInBuffer buffer = (WaveInBuffer)hBuffer.Target;

if (buffer == null)
{
    return; // with this new line, everything works fine
}

if (DataAvailable != null)
{
    DataAvailable(this, new WaveInEventArgs(buffer.Data, buffer.BytesRecorded));
}

if (recording)
{
    buffer.Reuse();
}
else
{
    if (RecordingStopped != null)
    {
        RecordingStopped(this, EventArgs.Empty);
    }
}
于 2011-11-14T10:31:08.073 に答える