使用NAudio录制时的NullReferenceException (c#中)

本文关键字:NullReferenceException NAudio 使用 | 更新日期: 2023-09-27 18:05:53

我试图在c#中使用NAudio记录语音,我被困在两个地方:

1. A crash:

从这个页面稍微修改的代码形式,我得到一个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);
    }
}

大多数情况下,这发生在我开始录制第三次时。知道是什么引起的吗?

*2. Modifying rate and channels at runtime.*

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

谢谢。

使用NAudio录制时的NullReferenceException (c#中)

似乎即使缓冲区为空,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);
    }
}
}

}

您的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的方法的末尾不需要

return;

我认为,必须这样做:

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。