试图了解C#中关于NAudio的缓冲区

时间:2016-05-10 21:06:59

标签: c# naudio

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

1 个答案:

答案 0 :(得分:3)

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

这取决于你想要对音频数据做些什么。

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

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

如果您想分析数据(例如使用FFT进行傅里叶分析),那么我建议使用NAudio&#39; s ISampleProvider。该界面隐藏了所有原始字节,位深度内容,并允许您以简单的方式逐帧访问数据。

首先从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);
}

因为你想同时做两件事 - 同时录制和分析音频数据 - 你应该使用两个独立的线程。

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

快速入门,应该能让你更加紧密“#34;输出尝试以下内容:

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

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