连续 WASAPI 环形缓冲区采样

Posted

技术标签:

【中文标题】连续 WASAPI 环形缓冲区采样【英文标题】:Continuous WASAPI Ring-Buffer Sampling 【发布时间】:2018-11-18 18:23:48 【问题描述】:

如何使用 WASAPI(或类似的东西)将音频连续采样到(线程安全的)环形缓冲区中,以便消费者线程可以在设定的时间间隔内从该缓冲区中读取?

目前我们有一个.sample() 方法,它在设定的采样间隔后返回一大块样本,但是由于内存分配等原因,这有相当大的开销。也许这个方法可以优化;我很确定我们做错了。

std::vector<short> sampler2::sample()

    // prepare header
    waveInPrepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));

    // insert a wave input buffer
    waveInAddBuffer(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));

    // commence sampling input
    waveInStart(hWaveIn);

    // sleep for the duration of a sample interval
    std::this_thread::sleep_for(milliseconds(SAMPLE_INTERVAL));

    // create vector
    std::vector<short> samplesChunk(&waveIn[0], &waveIn[0] + NUMPTS);

    // return vector
    return samplesChunk;

GitHub 链接:sampler2.h & sampler2.cpp

代码非常糟糕,我们不知道如何正确使用 WASAPI。我们的目标是(快速)创建一个采样器类,它可以利用 >10 毫秒的采样间隔。

【问题讨论】:

【参考方案1】:

您的示例使用 waveout API。您可以查看MSDN 以获取 WASAPI 参考和用法。 以下是 WASAPI 使用的基本说明: 客户端调用IAudioRenderClient接口中的方法将渲染数据写入端点缓冲区。要请求特定大小的端点缓冲区,客户端调用IAudioClient::Initialize方法。要获取分配的缓冲区的大小(可能与请求的大小不同),客户端调用IAudioClient::GetBufferSize 方法。 为了通过端点缓冲区移动渲染数据流,客户端交替调用IAudioRenderClient::GetBuffer 方法和IAudioRenderClient::ReleaseBuffer 方法。客户端以一系列数据包的形式访问端点缓冲区中的数据。 GetBuffer 调用检索下一个数据包,以便客户端可以用渲染数据填充它。将数据写入数据包后,客户端调用 ReleaseBuffer 将完成的数据包添加到渲染队列中。 还有这个Microsoft C++ WASAPI example。

【讨论】:

两者有什么区别?谢谢,我去看看! WaveOut 是 Windows 中的旧 API 集。而 WASAPI 是一个核心音频 API,并且从 Vista 开始就可用。它需要一个特定的驱动程序实现。

以上是关于连续 WASAPI 环形缓冲区采样的主要内容,如果未能解决你的问题,请参考以下文章

怎么计算环形缓冲区长度

环形缓冲区大小和反写阈值

微控制器的环形缓冲区

环形缓冲区

关于环形缓冲区

数据结构之环形缓冲器