【问题标题】:Trying to understand buffers with regard to NAudio in C#试图理解 C# 中关于 NAudio 的缓冲区
【发布时间】:2016-05-12 05:38:17
【问题描述】:

我是一名化学专业的学生,​​试图在 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;
}

【问题讨论】:

  • 欢迎来到 SO。请仔细检查您的代码格式。
  • 尝试增加 500 毫秒的暂停并在暂停期间发出声音。 WaveIn 源只会在实际录制一些声音时触发 sourceStream_DataAvailable()。当麦克风没有记录时,不会调用事件处理程序。另外,您是如何从BufferedWaveProvider 读取数据的?您说您正在尝试打印/显示音频数据,但您没有显示执行此操作的代码。
  • @Abbondanza 我尝试过延迟一系列不同的时间间隔(最长超过 500 毫秒),我可以看到某种形式的数据被读出。我之前从源流方法(我发布的代码的最后一块)写入控制台;从那以后我删除了它,但它是一个简单的Debug.WriteLine() 命令。我的主要问题是:我如何从缓冲区读取数据/一般使用缓冲区?我已经尝试将 Array.CopyBlockCopy 放到一个单独的临时数组中,但我没有设法得到任何连贯的结果。

标签: c# naudio


【解决方案1】:

免责声明:我对 NAudio 没有太多经验。


这在某种程度上取决于您要对音频数据做什么。

如果您只是想存储或转储数据(无论是文件目标还是控制台),那么您不需要BufferedWaveProvider。只需在事件处理程序sourceStream_DataAvailable() 中直接执行您想做的任何事情。但请记住,您以原始字节的形式接收数据,即实际构成录制音频的单个帧(又名样本)的字节数取决于波形格式:

var bytesPerFrame = sourceStream.WaveFormat.BitsPerSample / 8
                  * sourceStream.WaveFormat.Channels

如果您想分析数据(例如使用 FFT 进行傅立叶分析),那么我建议使用 NAudio 的 ISampleProvider。这个接口隐藏了所有原始字节、位深度的东西,让您可以轻松地逐帧访问数据。

首先从您的BufferedWaveProvider 创建一个ISampleProvider,如下所示:

var samples = waveBuffer.ToSampleProvider();

然后您可以使用Read() 方法访问示例帧。确保通过BufferedWaveProvider 上的BufferedBytes 属性检查数据是否实际可用:

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

    if (bufferedFrames < 1)
        continue;

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

    DoSomethingWith(frames);
}

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

有一个small GitHub project that uses NAudio 用于对录制的音频数据进行 DTMF 分析。您可能想看看如何将它们组合在一起。文件DtmfDetector\Program.cs 有一个很好的起点。


为了快速开始,应该给你“更连贯”的输出尝试以下:

将此字段添加到您的班级:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-18
    • 2013-01-09
    • 1970-01-01
    • 2018-06-29
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多