使用NAudio录制时出现NullReferenceException(在c#中)

使用NAudio录制时出现NullReferenceException(在c#中),c#,nullreferenceexception,naudio,C#,Nullreferenceexception,Naudio,我正试图用C#中的NAudio录制声音,我被困在两个地方: 1。崩溃: 通过对页面中的代码形式稍加修改,我得到了一个NullReferenceException。以下是崩溃日志: ************** Exception Text ************** System.NullReferenceException: Object reference not set to an instance of an object. at NAudio.Wave.WaveIn.Callb

我正试图用C#中的NAudio录制声音,我被困在两个地方:

1。崩溃:

通过对页面中的代码形式稍加修改,我得到了一个
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);
    }
}
使用系统;
使用System.Windows.Forms;
使用系统线程;
使用NAudio.波;
公开课FOO
{
静态波温s_波温;
[状态线程]
静态void Main(字符串[]参数)
{
init();
Application.Run();
}
公共静态无效记录()
{
while(true)
{
Console.WriteLine(“按Enter键开始录制。\n”);
Console.ReadLine();
s_WaveIn.StartRecording();
Console.WriteLine(“按Enter键停止录制。\n”);
Console.ReadLine();
s_WaveIn.停止录制();
}
}
公共静态无效设备单元(整数速率、整数通道)
{
s_WaveIn=新的WaveIn();
s_WaveIn.WaveFormat=新的波形(速率、通道);
s_WaveIn.buffer毫秒=1000;
s_WaveIn.DataAvailable+=新事件处理程序(SendCaptureSamples);
}
公共静态void init()
{
设备单元(44100,2);
线程t1=新线程(委托(){
记录();
});
t1.Start();
}
静态无效SendCaptureSamples(对象发送器,WaveInEventArgs e)
{
WriteLine(“记录的字节:{0}”,e.BytesRecorded);
}
}
大多数情况下,当我第三次开始录音时就会发生这种情况。你知道这是什么原因吗

*2。在运行时修改速率和通道。*

在我的实际代码中,我使用
s_WaveIn.WaveFormat=新的波形(新的波形速率,新的信道)重置波形格式StartRecording()
之前的代码>。我没有调用
Dispose()
,因为这需要重置
DataAvailable
回调,为此,我需要另一个消息循环。这种方法正确吗?还是应该先调用Dispose,然后用新格式重新初始化s_WaveIn


谢谢。

您的
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();
}

返回void

的方法结束时不需要code>。即使缓冲区为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);
    }
}
}

}

我认为,必须这样做:

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);
    }
}

我得到了同样的NullReferenceException。作者没有在建议的类WaveIn中添加行。 据我所知,没有提供这种用途。示例中的作者库不调用StopRecording(),只是停止记录传入的信息,而是继续处理它(例如测量音量),并调用StopRecording()以完全停止,将数据接收到数据WaveIn
因此,我认为在调用StopRecording()

谢谢后,有必要使用新的WaveIn。是,
init
中不需要“Application.Run”。修正了。我减少了原始代码,只保留了需要在此处发布的内容,因此错过了在
Main
中删除线程创建。也删除了。但我相信,这些变化与我提到的崩溃无关。如果我错了,请纠正我。谢谢。欢迎继续。因此,在这里,解释为什么使用您的解决方案,而不仅仅是如何使用,是一个很好的实践。这将使你的答案更有价值,并有助于进一步的读者更好地理解你是如何做到这一点的。我还建议您查看我们的常见问题:。