试图理解C#中关于NAudio的缓冲区
我是一名化学专业学生,试图在C#中使用NAudio从我的计算机麦克风收集数据(计划稍后切换到音频端口,以防这与如何得到答案有关)。 我理解源流是什么,以及NAudio如何使用事件处理程序来知道是否开始从所述流中读取信息,但是在处理从流中读取的数据时我感到困惑。 据我了解,从源流(使用AddSamples命令)以字节或WAV格式填充缓冲区数组。 现在,我正在尝试做的就是填充缓冲区并在控制台上编写其内容或进行简单的可视化。 我似乎无法从缓冲区中获取我的值,并且我已经尝试将其视为WAV和字节数组。 有人能帮我理解NAudio如何从头开始工作,以及如何从缓冲区中提取数据并以更有用的格式(即双打)存储它? 这是我到目前为止处理NAudio的代码以及随之而来的所有代码:
public NAudio.Wave.BufferedWaveProvider waveBuffer = null; // clears buffer NAudio.Wave.WaveIn sourceStream = null; // clears source stream public void startRecording(int samplingFrequency, int deviceNumber, string fileName) { sourceStream = new NAudio.Wave.WaveIn(); // initializes incoming audio stream sourceStream.DeviceNumber = deviceNumber; // specifies microphone device number sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(samplingFrequency, NAudio.Wave.WaveIn.GetCapabilities(deviceNumber).Channels); // specifies sampling frequency, channels waveBuffer = new NAudio.Wave.BufferedWaveProvider(sourceStream.WaveFormat); // initializes buffer sourceStream.DataAvailable += new EventHandler(sourceStream_DataAvailable); // event handler for when incoming audio is available sourceStream.StartRecording(); PauseForMilliSeconds(500); // delay before recording is stopped sourceStream.StopRecording(); // terminates recording sourceStream.Dispose(); sourceStream = null; } void sourceStream_DataAvailable(object sender, NAudio.Wave.WaveInEventArgs e) { waveBuffer.AddSamples(e.Buffer, 0, e.BytesRecorded); // populate buffer with audio stream waveBuffer.DiscardOnBufferOverflow = true; }
免责声明:我对NAudio没有那么多经验。
这取决于你想要对音频数据做什么。
如果您只想存储或转储数据(无论是文件目标还是控制台),那么您不需要BufferedWaveProvider
。 只需在事件处理程序sourceStream_DataAvailable()
直接执行任何操作即可。 但请记住,您将数据作为原始字节接收,即实际构成录制音频的单个帧(也称为样本)的字节数取决于波形格式:
var bytesPerFrame = sourceStream.WaveFormat.BitsPerSample / 8 * sourceStream.WaveFormat.Channels
如果你想分析数据(例如用FFT进行傅里叶分析),那么我建议使用NAudio的ISampleProvider
。 该界面隐藏了所有原始字节,位深度内容,并允许您以简单的方式逐帧访问数据。
首先从BufferedWaveProvider
创建一个ISampleProvider
,如下所示:
var samples = waveBuffer.ToSampleProvider();
然后,您可以使用Read()
方法访问示例帧。 确保使用BufferedBytes
上的BufferedBytes
属性检查数据是否实际可用:
while (true) { var bufferedFrames = waveBuffer.BufferedBytes / bytesPerFrame; if (bufferedFrames < 1) continue; var frames = new float[bufferedFrames]; samples.Read(frames, 0, bufferedFrames); DoSomethingWith(frames); }
因为你想同时做两件事 - 同时录制和分析音频数据 - 你应该使用两个独立的线程。
有一个小型的GitHub项目,它使用NAudio对录制的音频数据进行DTMF分析。 您可能希望了解如何将所有内容整合在一起。 文件DtmfDetector\Program.cs
有一个很好的起点。
要快速启动,应该为您提供“更连贯”的输出,请尝试以下操作:
将此字段添加到您的class级:
ISampleProvider samples;
将此行添加到方法startRecording()
:
samples = waveBuffer.ToSampleProvider();
像这样扩展sourceStream_DataAvailable()
:
void sourceStream_DataAvailable(object sender, NAudio.Wave.WaveInEventArgs e) { waveBuffer.AddSamples(e.Buffer, 0, e.BytesRecorded); waveBuffer.DiscardOnBufferOverflow = true; var bytesPerFrame = sourceStream.WaveFormat.BitsPerSample / 8 * sourceStream.WaveFormat.Channels var bufferedFrames = waveBuffer.BufferedBytes / bytesPerFrame; var frames = new float[bufferedFrames]; samples.Read(frames, 0, bufferedFrames); foreach (var frame in frames) Debug.WriteLine(frame); }