实时音频输入的每分钟节拍数
我想编写一个简单的C应用程序来监视输入音频,并为我提供每分钟的当前心跳(滚动平均值)。
我看过这篇关于gamedev的文章,那绝对没有帮助。我经历了一下,试图实现他正在做的事情,但是那没有用。
我知道必须有很多解决方案,因为很多DJ软件都可以做到这一点,但是我自己没有找到任何开源库或者说明的运气。
解决方案
回答
这绝不是一个简单的问题。我将只给我们一个概述。
我们可以执行以下操作:
- 计算信号块(例如5毫秒)的平均(均方根)响度。 (以前从未做过,我不知道合适的块大小是多少。)
- 使用FFT算法对"阻塞"信号进行傅立叶变换。
- 在变换后的信号中找到幅度最大的分量。
傅立叶变换基本上是一种计算信号中所有频率强度的方法。如果我们对"阻塞"信号执行此操作,则拍子的频率有望成为最强的拍子。
也许我们需要首先应用一个滤波器,以专注于通常包含有关BPM最多信息的特定频率(如低音)。
回答
并不是我不知道如何实现这一点,但是从音频工程的角度来看,我们需要首先进行过滤。低音鼓打击将是第一个检查。低通滤波器可以为我们提供大约200Hz以下的任何声音,应该可以使我们清晰地了解低音鼓。可能还需要一个门来清除谐波低的其他乐器的杂波。
下一个要检查的是小军鼓。我们必须均衡这一个。圈套器发出的"裂痕"距离内存约1.5kHz,但是我们必须明确限制这一点。
下一个挑战将是为时髦节拍制定一种算法。我们将如何以编程方式找到节拍1?我想我们会跟踪以前的节拍并使用与某物或者另一物匹配的模式。因此,我们可能需要一些酒吧才能准确找到节拍。然后还有计时问题,例如4 / 4、3 / 4、6 / 8,哇,我无法想象要准确地做到这一点需要什么!我相信对于音频硬件/软件公司来说,这是值得的。
回答
有一个出色的项目叫做Dancing Monkeys,该程序从音乐中生成DDR舞步。它所做的大部分工作都是基于(必要时非常准确的)节拍分析,他们的项目文件详细介绍了各种节拍检测算法及其对任务的适用性。它们包括对每种算法的原始论文的引用。他们还为解决方案发布了matlab代码。我相信我们可以在其中找到所需的东西。
此处提供所有信息:http://monket.net/dancing-monkeys-v2/Main_Page
回答
使用滑动窗口FFT计算功率谱:
抽取1024个样本:
double[] signal = stream.Take(1024);
将其馈入FFT算法:
double[] real = new double[signal.Length]; double[] imag = new double[signal.Length); FFT(signal, out real, out imag);
我们将得到一个真实的部分和一个虚构的部分。不要丢弃虚构部分。对虚部做同样的事情。虽然虚部确实是与实相异相的pi / 2,但它仍然包含50%的频谱信息。
编辑:
计算功率而不是振幅,以便在大声时有一个大数字,在安静时有一个接近零的数字:
for (i=0; i < real.Length; i++) real[i] = real[i] * real[i];
对于虚部也是如此。
for (i=0; i < imag.Length; i++) imag[i] = imag[i] * imag[i];
现在,我们具有最近1024个样本的功率谱。频谱的第一部分是低频,频谱的最后部分是高频
频率。
如果要在流行音乐中找到BPM,则可能应该专注于低音。我们可以通过将功率谱的较低部分相加来获得低音强度。使用哪个数字取决于采样频率:
double bassIntensity = 0; for (i=8; i < 96; i++) bassIntensity += real[i];
现在再次执行相同操作,但是在计算新光谱之前,将窗口移至256个样本。现在,我们最终要计算每256个样本的bassIntensity。
这对于BPM分析是一个很好的输入。当低音很安静时,我们没有节拍,而当低音很大时,我们会跳动。
祝你好运!
回答
最简单的方法是让用户按节拍节奏拍打一个按钮,然后将拍打次数除以时间。
回答
首先,Hallgrim产生的不是功率谱密度函数。可以通过自相关函数得出任何信号中的统计周期。自相关信号的傅立叶变换是功率谱密度。 PSD中除0 Hz以外的主要峰值将对应于信号的有效周期性(以Hz为单位)...