我想编写一个简单的C#应用程序来监听线路输入音频并给出每分钟的当前(好的,滚动平均)节拍。
我见过this gamedev article,这绝对没有帮助。我经历了并尝试实施他正在做的事情,但它只是没有用。
我知道必须有大量的解决方案,因为很多DJ软件都能做到这一点,但我没有找到任何开源库或自己做的指示。
答案 0 :(得分:26)
使用滑动窗口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分析的一个很好的输入。当低音安静时你没有节拍,当它很响时你就会有节拍。
祝你好运!答案 1 :(得分:15)
有一个名为Dancing Monkeys的出色项目,它在程序上从音乐中产生DDR舞步。它所做的大部分工作都基于(必然是非常准确的)节拍分析,他们的项目文章详细描述了各种节拍检测算法及其对任务的适用性。它们包括对每种算法的原始论文的引用。他们还为他们的解决方案发布了matlab代码。我相信你可以找到你需要的东西。
答案 2 :(得分:8)
不是我知道如何实现这一点,但从音频工程的角度来看,你需要先过滤。低音鼓点击将是第一个检查。低通滤波器可以为您提供低于200Hz的任何信号,可以为您提供非常清晰的低音鼓图像。也可能需要一个门来清除其他谐振器低的其他仪器的杂波。
接下来的检查将是网罗点击。你必须得到这个EQ。来自小军鼓的“裂缝”距离记忆大约1.5kHz,但你需要明确地控制它。
接下来的挑战是制定一个时髦的节拍算法。你会如何以编程方式找到1?我想你会跟踪以前的节拍,并使用匹配某些东西或其他东西的模式。所以,你可能需要几个小节才能准确找到节拍。然后有时间问题,如4 / 4,3 / 4,6 / 8,哇,我无法想象准确地做到这一点需要什么!我相信音频硬件/软件公司值得花一些钱。
答案 3 :(得分:6)
这绝不是一个容易的问题。我会尽量给你一个概述。
您可以做的事情如下:
也许您需要首先应用过滤器,以专注于通常包含有关BPM的最多信息的特定频率(如低音)。
答案 4 :(得分:5)
我发现这个库似乎有一个非常可靠的实现,用于检测每分钟节拍数。 http://soundtouchdotnet.codeplex.com/
它基于http://www.surina.net/soundtouch/index.html,用于很多DJ项目http://www.surina.net/soundtouch/applications.html
答案 5 :(得分:1)
首先,Hallgrim正在制作的不是功率谱密度函数。任何信号中的统计周期都可以通过自相关函数得出。自相关信号的傅里叶变换是功率谱密度。除了0 Hz以外,PSD中的主导峰值将对应于信号中的有效周期(以Hz为单位)......
答案 6 :(得分:0)
简单的方法是让用户按节拍的节拍点击一个按钮,然后计算点击次数除以时间。
答案 7 :(得分:0)
我建议您查看BASS音频库和BASS.NET包装器。它有一个内置的BPMCounter类。
有关此特定功能的详细信息,请访问: http://bass.radio42.com/help/html/0833aa5a-3be9-037c-66f2-9adfd42a8512.htm