首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >试图理解与NAudio有关的C#缓冲区

试图理解与NAudio有关的C#缓冲区
EN

Stack Overflow用户
提问于 2016-05-10 21:06:58
回答 1查看 6.1K关注 0票数 3

我是一名化学专业的学生,试图在NAudio中使用C#从我的计算机麦克风中收集数据(计划稍后切换到音频端口,以防这与这一问题的答案相关)。我了解源流是什么,以及NAudio如何使用事件处理程序来了解是否开始从所述流读取信息,但在处理从流中读取的数据时,我遇到了困难。据我了解,缓冲区数组是从源流(使用AddSamples命令)以字节或WAV格式填充的。现在,我所要做的就是填充缓冲区并将其内容写入控制台或进行简单的可视化。我似乎无法将我的值从缓冲区中提取出来,而且我已经尝试将其作为WAV和字节数组来处理。有人能帮助我理解NAudio如何从底层开始工作,以及如何从缓冲区中提取数据并以更有用的格式(即双倍格式)存储它吗?下面是我到目前为止处理NAudio的代码及其附带的所有内容:

代码语言:javascript
运行
复制
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;
}
EN

回答 1

Stack Overflow用户

发布于 2016-05-11 21:11:06

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

这在某种程度上取决于你想对音频数据做些什么。

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

代码语言:javascript
运行
复制
var bytesPerFrame = sourceStream.WaveFormat.BitsPerSample / 8
                  * sourceStream.WaveFormat.Channels

如果您想分析数据(例如,傅立叶分析和快速傅立叶变换),那么我建议使用NAudio的ISampleProvider。这个接口隐藏了所有原始字节、位深度的内容,并允许您以一种简单的方式逐帧访问数据。

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

代码语言:javascript
运行
复制
var samples = waveBuffer.ToSampleProvider();

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

代码语言:javascript
运行
复制
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有一个很好的起点。

为了快速启动,这将使您的输出“更连贯”,请尝试如下:

将此字段添加到类中:

代码语言:javascript
运行
复制
ISampleProvider samples;

将这一行添加到方法startRecording()

代码语言:javascript
运行
复制
samples = waveBuffer.ToSampleProvider();

像这样扩展sourceStream_DataAvailable()

代码语言:javascript
运行
复制
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);
}
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37148997

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档