如何同时使用 NAudio 生成信号和录音?
Posted
技术标签:
【中文标题】如何同时使用 NAudio 生成信号和录音?【英文标题】:How can I generate signal and record with NAudio at the same time? 【发布时间】:2019-03-08 03:27:40 【问题描述】:我想制作一个正弦信号,用扬声器播放,用 MIC 接收,然后录制。
我尝试制作一些程序来实现如下,但出现了一些问题。
生成正弦信号 -> 扬声器 -> 麦克风 -> 录音(波)
1) WaveOut: 我用了两个 WaveOut。
a) 生成信号
b) 录制波形文件。 有问题吗?
2) 回声:
a) 耳机:
如果我使用耳机,我可以听到纯正弦扫音。但是MIC听不到这个声音。然后它只会录制环境声音。
b) 演讲者:
如果我使用扬声器(相同的耳机线,我只是添加放大器和扬声器),我可以听到如下图的回声。并且 MIC 也记录了这个回声。 我可以猜到 MIC 收到了这个声音,并且在几毫秒后,扬声器在原始声音上添加了这个声音。但我不明白为什么扬声器会添加这个接收到的声音。如何录制没有回声?
3) 录音时间:
我想录制 2 秒。然后我使用了计时器并定义了 timer.Interval = 2 sec。 但实际记录时间超过2秒。有延迟吗?
4) 扫描时间:
我定义了 2 秒的扫描时间。但是在超过 2 秒的时间里,正弦扫描没有完成。在完成时间(约 2.2 秒)频率为 1.5kHz。 (我定义了结束频率 =2kHz)。
Recorded Echo Wave file
public partial class Form1 : Form
private WaveIn recorder;
private BufferedWaveProvider bufferedWaveProvider;
private SavingWaveProvider savingWaveProvider;
private WaveOut player;
private WaveOut player_sweep; // 190305
public Form1()
InitializeComponent();
private void OnStartRecording_Click(object sender, EventArgs e)
// set up the recorder
recorder = new WaveIn();
recorder.DataAvailable += RecorderOnDataAvailable;
// set up our signal chain
bufferedWaveProvider = new BufferedWaveProvider(recorder.WaveFormat);
savingWaveProvider = new SavingWaveProvider(bufferedWaveProvider, "temp.wav");
// set up playback
player = new WaveOut();
player.Init(savingWaveProvider);
// 190305 / Signal Generator : Sine 50~2000 Hz, 2 sec
SignalGenerator sweep_out = new SignalGenerator();
sweep_out.Gain = 1;
sweep_out.Frequency = 50;
sweep_out.FrequencyEnd = 2000;
sweep_out.SweepLengthSecs = 2;
sweep_out.Type = SignalGeneratorType.Sweep;
player_sweep = new WaveOut(); // 190305
player_sweep.Init(sweep_out); // 190305
// begin playback & record
recorder.StartRecording();
timer1.Enabled = true;
// begin playback & record
player.Play(); // Start Recording
player_sweep.Play(); // 190305
private void RecorderOnDataAvailable(object sender, WaveInEventArgs waveInEventArgs)
bufferedWaveProvider.AddSamples(waveInEventArgs.Buffer, 0, waveInEventArgs.BytesRecorded);
private void timer1_Tick(object sender, EventArgs e) // 190305
timer1.Enabled = false;
player_sweep.Stop(); // 190305
// stop playback
player.Stop();
// stop recording
recorder.StopRecording();
// finalise the WAV file
savingWaveProvider.Dispose();
【问题讨论】:
标记以备后用。回家后我会分享我的解决方案 【参考方案1】:我又学习了 NAudio。 (https://www.pluralsight.com/courses/audio-programming-naudio/) 我得到了如下解决方案。
我的目标:生成正弦信号 -> 扬声器 -> 麦克风 -> 录音(波)
使用这个,我想另外使用 FFT 来分析说话者的状况。
-
生成正弦信号:NAudio.Wave.SamplePrividers.SignalGenerator
扬声器输出:NAudio.Wave.WaveOut
麦克风:NAudio.Wave.WaveIn
记录(波形):NAudio.Wave.WaveFileWriter
// 源码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics; // for Process, Stopwatch
using NAudio.Wave; // for WaveOut, WaveIn
using NAudio.Wave.SampleProviders; // for SignalGenerator
namespace Speaker_Record-Wave
public partial class Form1 : Form
// 0) StopWatch
Stopwatch stopWatch;
// 1) Signal Gen -> Speaker
WaveOut waveOut;
SignalGenerator signalGenerator;
// 2) MIC -> Wave
WaveIn waveIn;
WaveFileWriter waveFileWriter;
public Form1()
InitializeComponent();
private void bt_Start_Click(object sender, EventArgs e)
// 0) StopWatch
stopWatch = new Stopwatch();
stopWatch.Start();
// 1) Signal Gen -> Speaker
Start_Signal();
// 3) Timer_Sweep
timer_Sweep.Interval = 1500;
timer_Sweep.Enabled = true;
// 2) MIC -> Wave
Start_Record();
private void timer_Sweep_Tick(object sender, EventArgs e)
// 3) Timer_Sweep
timer_Sweep.Enabled = false;
// 1) Signal Gen -> Speaker
waveOut.Stop();
// 2) MIC -> Wave
waveIn.StopRecording();
// 4) 공통
waveOut.Dispose();
waveIn.Dispose();
waveFileWriter.Dispose();
// 0) StopWatch
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
string es = String.Format("0:00:1:00:2:00:3:00",ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);
tb_Result.AppendText(es + "\n");
private void bt_Open_Folder_Click(object sender, EventArgs e)
Process.Start(".\\"); // Open Folder
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
// 1) Signal Gen -> Speaker
private void Start_Signal()
signalGenerator = new SignalGenerator();
signalGenerator.Type = SignalGeneratorType.Sweep;
signalGenerator.Frequency = 50;
signalGenerator.FrequencyEnd = 5000;
signalGenerator.SweepLengthSecs = 1.5;
waveOut = new WaveOut();
waveOut.DeviceNumber = 0;
waveOut.Init(signalGenerator);
waveOut.Play();
// 2) MIC -> Wave
private void Start_Record()
waveIn = new WaveIn();
waveIn.DeviceNumber = 0;
waveIn.WaveFormat = new WaveFormat(44100, 16, 1);
waveIn.DataAvailable += OnDataAvailable;
waveIn.RecordingStopped += OnRecordingStopped;
waveFileWriter = new WaveFileWriter("1_Recorded.wav", waveIn.WaveFormat);
waveIn.StartRecording();
// 2) MIC -> Wave
private void OnDataAvailable(object sender, WaveInEventArgs e)
if (waveFileWriter != null)
waveFileWriter.Write(e.Buffer, 0, e.BytesRecorded);
// 2) MIC -> Wave
private void OnRecordingStopped(object sender, StoppedEventArgs e)
waveIn.Dispose();
waveFileWriter.Dispose();
【讨论】:
以上是关于如何同时使用 NAudio 生成信号和录音?的主要内容,如果未能解决你的问题,请参考以下文章