【问题标题】:Beats per minute from real-time audio input来自实时音频输入的每分钟节拍数
【发布时间】:2010-09-09 21:59:37
【问题描述】:

我想编写一个简单的 C# 应用程序来监控线路输入音频并为我提供当前(嗯,滚动平均)每分钟节拍数。

我见过this gamedev article,这绝对没有帮助。我经历并尝试实施他正在做的事情,但它没有工作。

我知道必须有大量的解决方案来解决这个问题,因为很多 DJ 软件都可以做到这一点,但我没有找到任何开源库或自己做的说明。

【问题讨论】:

  • 另一篇您可能会感兴趣的文章...http://werner.yellowcouch.org/Papers/bpm04/您可以在此处找到现有的 BPM 检测库:http://www.mmartins.com/mmartins/bpmdetection/bpmdetection.asp ...以及在此处找到 C# BPM 检测库:http://adionsoft.net/bpm/跨度>
  • 2 个名字:Eric D. Scheirer Masataka Goto 谷歌他们,他们写了很多关于节拍检测(实时和离线)的文章。非常有趣的材料。另外作为旁注,我认为除了节拍检测之外,您可能对节拍预测感兴趣。
  • 我相信雅阁有你想要的必要算法。此外,还有很多有趣的机器学习算法,带来更多乐趣!如果我没记错的话,教程/示例程序中有一个示例。雅阁网

标签: c# audio signal-processing


【解决方案1】:

我发现这个库似乎有一个非常可靠的实现来检测每分钟节拍https://github.com/owoudenberg/soundtouch.net

它基于http://www.surina.net/soundtouch/index.html,在很多DJ项目中使用http://www.surina.net/soundtouch/applications.html

【讨论】:

    【解决方案2】:

    我建议查看 BASS 音频库和 BASS.NET 包装器。它有一个内置的 BPMCounter 类。

    此特定功能的详细信息可在以下位置找到 http://bass.radio42.com/help/html/0833aa5a-3be9-037c-66f2-9adfd42a8512.htm.

    【讨论】:

      【解决方案3】:

      使用滑动窗口 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 分析来说是一个很好的输入。当低音很安静时,你没有节拍,当它响亮时,你有节拍。

      祝你好运!

      【讨论】:

      • 您确实意识到仅使用 1024 个样本您将无法计算 BPM(每分钟节拍数)...对吗?您只是在计算那个“微小”的 1024 字节长样本中的最高频率。
      • 我在小样本中计算最高频率是正确的,但后来我建议将窗口移动256个样本并重新计算。结果是可用于计算 BPM 的序列。我只描述了如何解决问题的第一部分。
      • Sacha 这只是缩放单位的问题。在计算 BPM 之前,您无需分析一分钟的样本。 BPM 只是传达信号周期的一种更具音乐性的方式。
      • 不要丢掉虚部,它只是相位!相位由 arctan(imag/real) 给出,这对于这个问题是无用的。重要的部分,幅度,由 real^2 + imag^2 给出,而不仅仅是 real^2。
      • 正如你所说,这只是解决方案的第一部分......事实上,你刚刚计算了一个序列,显示低频幅度如何随时间变化(几乎就像应用低频-通过过滤器)。换句话说,解决方案比您的答案中看起来要困难得多。
      【解决方案4】:

      首先,Hallgrim 产生的不是功率谱密度函数。任何信号的统计周期都可以通过自相关函数得出。自相关信号的傅立叶变换是功率谱密度。 PSD 中除 0 Hz 以外的主要峰值将对应于信号中的有效周期性(以 Hz 为单位)...

      【讨论】:

        【解决方案5】:

        最简单的方法是让用户按照节拍的节奏点击一个按钮,然后计算点击次数除以时间。

        【讨论】:

        • 对于我尝试使用该工具的目的,点击确实不是一个好的解决方案。我希望它是全自动的,我知道这是可能的。
        【解决方案6】:

        有一个名为 Dancing Monkeys 的出色项目,它通过音乐程序生成 DDR 舞步。它所做的大部分工作都是基于(必须非常准确)节拍分析,他们的项目论文详细描述了各种节拍检测算法及其对任务的适用性。它们包括对每种算法的原始论文的引用。他们还为他们的解决方案发布了 matlab 代码。我敢肯定,在这些之间你可以找到你需要的。

        都可以在这里找到:http://monket.net/dancing-monkeys-v2/Main_Page

        【讨论】:

          【解决方案7】:

          并不是说我知道如何实现这一点,但从音频工程的角度来看,您需要先进行过滤。低音鼓击打将是第一个检查。一个低通滤波器可以为您提供低于 200Hz 的任何值,应该可以让您清楚地看到低音鼓。可能还需要一个门来清除来自其他具有如此低谐波的乐器的杂波。

          接下来要检查的是军鼓命中。你必须均衡这个。军鼓发出的“裂纹”大约是记忆中的 1.5kHz,但你肯定需要对它进行门控。

          下一个挑战是为时髦节拍制定算法。您将如何以编程方式找到节拍 1?我想您会跟踪以前的节拍并使用匹配某事或其他内容的模式。因此,您可能需要几个小节才能准确找到节拍。然后是 4/4、3/4、6/8 之类的时间问题,哇,我无法想象要准确地做到这一点需要什么!我相信这对音频硬件/软件公司来说是值得的。

          【讨论】:

          • 这可能就是为什么在 Google 上很难找到明确的答案(更不用说代码示例了!);)
          【解决方案8】:

          这绝不是一个简单的问题。我会尽量给你一个概述。

          您可以执行以下操作:

          1. 计算信号在块上的平均(均方根)响度,例如 5 毫秒。 (以前从未这样做过,我不知道合适的块大小是多少。)
          2. 使用 FFT 算法对“阻塞”信号进行傅里叶变换。
          3. 在变换后的信号中找出幅度最大的分量。

          傅里叶变换基本上是一种计算信号中所有频率强度的方法。如果您对“阻塞”信号执行此操作,则节拍的频率有望成为最强的。

          也许您需要先应用一个过滤器,以专注于通常包含最多 BPM 信息的特定频率(如低音)。

          【讨论】:

          • 1.计算信号在 5 毫秒内的平均(均方根)响度。 (以前从未这样做过,我不知道什么是好的块大小。) 2. 使用 FFT 算法对“阻塞”信号进行傅里叶变换。 3. 找到变换后信号中幅度最大的分量。我真的不明白为什么你首先发出 rms 信号,以及为什么它是在块上完成的(因为 FFT 通常在信号的窗口上工作)。此外,FFT 会为您提供转移到能量时域的信号,因此这实际上与第一个相同
          猜你喜欢
          • 2017-12-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-31
          • 2013-07-05
          • 1970-01-01
          • 2018-04-19
          • 1970-01-01
          相关资源
          最近更新 更多