尝试了解 C# 中与 NAudio 相关的缓冲区

2024-01-03

我是一名化学专业的学生,​​试图在 C# 中使用 NAudio 从计算机的麦克风收集数据(计划稍后切换到音频端口,以防与如何回答这个问题有关)。我了解什么是源流,以及 NAudio 如何使用事件处理程序来了解是否开始从所述流读取信息,但在处理从流中读取的数据时,我感到很困惑。据我了解,缓冲区数组是从源流中以字节或 WAV 格式填充的(使用 AddSamples 命令)。现在,我要做的就是填充缓冲区并将其内容写入控制台或进行简单的可视化。我似乎无法从缓冲区中获取我的值,并且我尝试将其视为 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<NAudio.Wave.WaveInEventArgs>(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 进行傅立叶分析),那么我建议使用 NAudioISampleProvider。该接口隐藏了所有原始字节、位深度的内容,让您可以轻松地逐帧访问数据。

首先创建一个ISampleProvider从你的BufferedWaveProvider像这样:

var samples = waveBuffer.ToSampleProvider();

然后您可以使用以下命令访问示例框架Read()方法。确保检查数据是否确实可用BufferedBytes您的财产BufferedWaveProvider:

while (true)
{
    var bufferedFrames = waveBuffer.BufferedBytes / bytesPerFrame;        

    if (bufferedFrames < 1)
        continue;

    var frames = new float[bufferedFrames];
    samples.Read(frames, 0, bufferedFrames);

    DoSomethingWith(frames);
}

因为您想同时做两件事——同时记录和分析音频数据——所以您应该为此使用两个单独的线程。

有一个使用 NAudio 的小型 GitHub 项目 https://github.com/bert2/DtmfDetection用于录制音频数据的 DTMF 分析。您可能想了解一些如何将它们整合在一起的想法。文件DtmfDetector\Program.cs https://github.com/bert2/DtmfDetection/blob/master/DtmfDetector/Program.cs有一个良好的起点。


为了快速启动并为您提供“更连贯”的输出,请尝试以下操作:

将此字段添加到您的类中:

ISampleProvider samples;

将此行添加到您的方法中startRecording():

samples = waveBuffer.ToSampleProvider();

Extend 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);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

尝试了解 C# 中与 NAudio 相关的缓冲区 的相关文章

随机推荐