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

发布于 2024-11-30 11:48:45 字数 2382 浏览 6 评论 0原文

我正在尝试在 C# 中使用 NAudio 录制语音,但我被困在两个地方:

1。崩溃:

这样< /a> 页面,我收到 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。在运行时修改速率和通道。*

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

谢谢。

I am trying to record voice using NAudio in C# and I am stuck at two places:

1. A crash:

With a slightly modified form of code from THIS SO page, I am getting a NullReferenceException. Here is the crash log:

************** 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)

and the code is:

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

Most of the times, this happens when I start recording THIRD time. Any idea what could be causing this?

*2. Modifying rate and channels at runtime.*

In my actual code, I am resetting wave format using s_WaveIn.WaveFormat = new WaveFormat(new_rate, new_channels); before calling StartRecording(). I am not calling Dispose() because that would require resetting the DataAvailable callback, and for that, I would need another message loop. Is this approach correct or should I first call Dispose and then reinitialize s_WaveIn with new format?

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一直在等你来 2024-12-07 11:48:45

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

}

It Seems that DataAvailable callback is getting called even when buffer is null.

I modified a function in WaveIn.cs file and its working fine now. I am not sure if this is correct, but for now, this is working for me.

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

}

謌踐踏愛綪 2024-12-07 11:48:45

您的 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;

Your Main method looks odd. What is the thread for?

Just use this:

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

Your init method also runs the application. Why?
Try changing it to:

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

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

return; is not needed at the end of a method returning void.

萌逼全场 2024-12-07 11:48:45

我认为,必须以这种方式完成:

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

I think, it has to be done in this way:

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);
    }
}
月下客 2024-12-07 11:48:45

我得到了相同的 NullReferenceException。作者没有在提议的类 WaveIn 中添加行。
据我了解,不提供此类用途。示例中的作者库没有调用 StopRecording (),只是停止记录传入的信息,但继续处理它(例如测量音量),并调用 StopRecording ()< /strong> 完全停止接收数据到数据WaveIn
因此,我认为在调用StopRecording()之后有必要使用一个新的WaveIn。

I got the same NullReferenceException. The author did not add lines to the proposed class WaveIn.
Such use is not provided, as I understand it. Author library in the examples does not calls StopRecording (), and just stops to record incoming information, but continues to process it (for example to measure the volume), and calls StopRecording () for a complete stop to recive data to the data WaveIn.
Thus, I believe that it is necessary to use a new WaveIn after calling StopRecording ().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文