使用 NAudio 录制音频并在麦克风输入静音时写入文件

Posted

技术标签:

【中文标题】使用 NAudio 录制音频并在麦克风输入静音时写入文件【英文标题】:Recording audio with NAudio and writing to a file when microphone input goes silent 【发布时间】:2016-12-14 08:38:06 【问题描述】:

我使用 NAudio 编写了这两个函数来记录和写入波形文件。如果不执行最后一行并超出本地范围,我找不到停止第一个函数的策略。

audio_Rec 方法从 main 函数调用,audioSource_DataAvailable 函数在 WaveInEvent 中有缓冲数据时执行。我认为, audioSource_DataAvailable 函数仅在 audio_Rec 方法的范围内运行,并且当代码到达 audio_Rec 的最后一行时(下一行) ,

Console.Write("Recording Starts...\n");

它超出范围并执行主函数的下一行。 (主要没有提到)。我想要一种方法在录制音频时保持 audio_Rec 方法,直到在 audioSource_DataAvailable 函数中的给定条件下停止录制。

countsummation 是公共成员变量。

audio_Rec 方法

    public void audio_Rec()
    
        audiosource = new WaveInEvent();
        audioSource.DeviceNumber = 0;
        audioSource.WaveFormat = new WaveFormat(16000, 16, 1);

        audioSource.DataAvailable += new EventHandler<WaveInEventArgs>(audioSource_DataAvailable);
        waveFile = new WaveFileWriter(@"d:/dev/csharp/wspeechrec/new_wave.wav", audioSource.WaveFormat);

        audioSource.StartRecording();
        Console.Write("Recording Starts...\n");

        //Thread.Sleep(7000);
    

audioSource_DataAvailable 函数

    void audioSource_DataAvailable(object sender, WaveInEventArgs e)
    
        count++;
        if (count%5 == 0)
        
            if (summation < 150000) 
                audioSource.StopRecording();
                Console.Write("Recording Stopped!");
            
            Console.WriteLine(count * 100 + "ms :"+summation);
            summation = 0;
        

        Console.WriteLine(count+" "+summation);
        byte[] buf = new byte[e.BytesRecorded];
        buf = e.Buffer;
        int[] Ints = new int[e.BytesRecorded / 2]; 

        for(int i=0;i<buf.Length;i+=2)
        
            Ints[i/2] = BitConverter.ToInt16(buf, i);
        

        int[] newInts = Ints.Select(x => Math.Abs(x)).ToArray();
        summation = newInts.Sum();

        if (waveFile != null)
        
            waveFile.Write(e.Buffer, 0, e.BytesRecorded);
            waveFile.Flush();
        
    

可以随意忽略第二个函数中的算法。他们可以被忽略。 非常感谢任何帮助。谢谢

【问题讨论】:

【参考方案1】:

您可以尝试以下方法:

处理来自 NAudio wave 设备的 RecordingStopped 事件。 在类级别创建EventSemaphore 或其他一些同步原语。 当RecordingStopped 处理程序被触发时,启动同步原语。 在您退出主方法之前,只需对该原语执行WaitOne()

您在DataAvailable 处理程序中的StopRecording 调用会导致对Stopped 处理程序的调用,这会触发信号量,然后唤醒您的主线程以便它可以退出。

示例(我偏爱信号量,所以这就是我正在使用的):

using System.Threading;

Semaphore AudioSync = new Semaphore(0, int.MaxValue);

public void audio_Rec()

    audioSource = new WaveInEvent();
    audioSource.DeviceNumber = 0;
    audioSource.WaveFormat = new WaveFormat(16000, 16, 1);

    // Register for the 'RecordingStopped' event.
    audioSource.PlaybackStopped += this.audioSource_PlaybackStopped;

    audioSource.DataAvailable += new EventHandler<WaveInEventArgs>(audioSource_DataAvailable);
    waveFile = new WaveFileWriter(@"d:/dev/csharp/wspeechrec/new_wave.wav", audioSource.WaveFormat);

    audioSource.StartRecording();
    Console.Write("Recording Starts...\n");

    // Now just wait for the "PlaybackStopped" event handler to signal completion.
    AudioSync.WaitOne();   // <-------------------------------------

Stopped 事件处理程序:

void audioSource_PlaybackStopped( object sender, StoppedEventArgs e )

    // Wakes up the main thread.
    AudioSync.Release();

【讨论】:

感谢您的帮助。我想出了一种使用while循环的方法。我刚刚在最后一行 (Console.Write("Recording Starts...\n");) 的末尾添加了一个 while(!flag) 循环,它不断检查“flag == true?”。我在“录制停止”行之后添加了“flag = true”。现在运行顺利。 你能澄清一下你的算法吗?这些数值从何而来? count % 5 == 0 和 summation

以上是关于使用 NAudio 录制音频并在麦克风输入静音时写入文件的主要内容,如果未能解决你的问题,请参考以下文章

[C#] NAudio 各种常见使用方式 播放 录制 转码 音频可视化

NAudio 记录和保存麦克风输入和扬声器输出

在控制台应用程序中使用 NAudio 录制麦克风音频

使用 NAudio 使用 asioout 录制时如何使声音更大?

错误的 .wav 格式录制音频 NAudio 库

RemoteIO 录制的音频文件为静音或 4KB