C++ 实时数据的STFT/滑动FFT

C++ 实时数据的STFT/滑动FFT,c++,c,c++11,audio,cinder,C++,C,C++11,Audio,Cinder,我最近接了一个项目,需要对传入的麦克风数据进行实时滑动FFT分析。我选择的环境是OpenGL和Cuband,使用C++。 这是我第一次体验音频编程,我有点困惑 这就是我试图在OpenGL应用程序中实现的目标: 因此,在每一帧中,都有一部分传入数据。在for循环中(因此是多次循环),将消耗当前数据的窗口,并对其执行FFT分析。对于For循环的下一次迭代,窗口将通过数据等推进“跃点大小”,直到到达数据的末尾 现在这个过程必须是连续的。但如上图所示,只要我当前的应用程序框架结束,当下一个框架的数据进

我最近接了一个项目,需要对传入的麦克风数据进行实时滑动FFT分析。我选择的环境是OpenGL和Cuband,使用C++。 这是我第一次体验音频编程,我有点困惑

这就是我试图在OpenGL应用程序中实现的目标:

因此,在每一帧中,都有一部分传入数据。在for循环中(因此是多次循环),将消耗当前数据的窗口,并对其执行FFT分析。对于For循环的下一次迭代,窗口将通过数据等推进“跃点大小”,直到到达数据的末尾

现在这个过程必须是连续的。但如上图所示,只要我当前的应用程序框架结束,当下一个框架的数据进来时,我就无法找到我离开前一个框架的位置(因为数据已经消失了)。您可以在图中看到,蓝色区域位于两帧之间

现在您可能会说,选择窗口大小/跃点大小的方式永远不会发生这种情况,但这是不可能的,因为在我的项目中,这些参数应该让用户可以配置

对于这种面向C++11的处理建议也非常欢迎


谢谢

我不确定是否100%理解您的场景,但听起来您可能想使用循环缓冲区。没有“标准”循环缓冲区,但是

但是,如果计划使用2个线程进行处理,则需要一个锁。例如,一个线程将等待音频输入,然后获取缓冲区锁,并从音频缓冲区复制到循环缓冲区。如果缓冲区中至少有
k
可用,则第二个线程将定期获取缓冲区锁并读取下一个
k
元素

您需要适当地调整缓冲区的大小,并确保始终以高于传入速率的速度处理数据,以避免循环缓冲区中的丢失

不确定为什么您提到缓冲区是无锁的,以及这是否是一项要求,我会首先尝试使用带锁的循环缓冲区,因为它在概念上似乎更简单,并且只有在必须时才使用无锁,因为在这种情况下,数据结构可能更复杂(但可能“生产者-消费者”无锁队列可以工作)


HTH.

感谢您发布一张图片,这很好地说明了问题所在

这里真正需要的是一个大小为
(window-1)
的缓冲区,您可以在其中存储来自“上一个”帧的零个或多个样本,以便在“下一个”帧中进行处理。在C++中,这将是:

std::vector<Sample> interframeBuffer;
interframeBuffer.reserve(windowSize - 1);

您应该始终使用单个向量,清除它并根据需要重新填充,以避免内存分配。这就是为什么我们在顶部调用
reserve()
,以避免以后的延迟。调用
clear()
不会释放内存,它只会将
size()
重置为零。

我不明白这句话:“一旦N个样本的数量完成并且当前缓冲区的处理完成,下一个传入缓冲区的第一个窗口数据块将与上一个缓冲区的最后一个窗口数据块有一个与k无关的间隙“-也许你能为那部分画一些ASCII图表吗?@JohnZwinck我包括了一幅图片,希望能描绘出我正在努力实现的目标。谢谢在第1帧中显示全部过程1、2、3、4、5。我认为你应该重新思考这个问题,你所谓的“通行证”应该被称为“框架”。使用0.25*framelength的跃点大小应该可以满足您的需要。libcinder中有一个专门用于此目的的功能(适合音频处理)。
for (const Sample& sample : interframeBuffer) {
    process(sample);
}
interframeBuffer.clear();