【问题标题】:Recognising tone of the audio识别音频的音调
【发布时间】:2010-12-20 08:05:26
【问题描述】:

我有一把吉他,我需要我的电脑能够分辨出正在播放的音符,识别音调。是否可以在 python 中做到这一点,pygame 也可以吗?能够在 pygame 中做到这一点会非常有帮助。

【问题讨论】:

  • 你是将电脑直接插入电脑还是依靠电脑麦克风?

标签: python audio


【解决方案1】:

要识别音频信号的频率,您可以使用 FFT (fast Fourier transform) 算法。据我所知,PyGame 无法录制音频,也不支持 FFT 变换。

首先,您需要从声卡中采集原始采样数据;这种数据称为 PCM(脉冲编码调制)。在 Python 中捕获音频的最简单方法是使用 PyAudio library(Python 绑定到 PortAudio)。 GStreamer 也可以,这对你的目的来说可能是矫枉过正。以 48000 Hz 的速率捕获 16 位样本是非常典型的,这可能是普通声卡所能提供的最好的。

获得原始 PCM 音频数据后,您可以使用 scipy library 中的 fftpack 模块通过 FFT 变换运行样本。这将为您提供分析的音频信号的频率分布,即特定频带中的信号强度。然后,就是找到信号最强的频率。

可能需要一些额外的过滤来避免harmonic frequencies我不确定。

【讨论】:

  • 有处理一系列音符的标准方法吗?
  • 我不知道你在问什么,你能详细说明一下吗?
  • 如果您对一系列音符进行 FFT,您将获得有关主要频率的信息,但会丢失有关音符时间位置的信息。 (或者我错了吗?)我想你可以尝试切掉原始音频,以便将 FFT 应用于单个音符,但要弄清楚切到哪里似乎很难。
  • 没错,通常的方法是将输入分解成足够小的块,从而不会丢失时序上下文。当然,这是定时精度和频率精度之间的权衡。
  • 如果您想了解更多信息,请查看短期傅立叶变换,关于音高检测,您可以使用 yin 算法
【解决方案2】:

我曾经写过一个实用程序来做这件事——它分析正在播放的声音。

您可以查看代码here(或者您可以下载整个项目。它集成了吉他英雄开源克隆 Frets On Fire,以创建真正的吉他英雄)。它使用吉他、口琴和口哨进行了测试 :) 代码很难看,但它可以工作 :)

我使用 pymedia 进行记录,并使用 scipy 进行 FFT。

除了其他人已经注意到的基础知识,我可以给你一些提示:

  1. 如果您从麦克风录制,会有很多噪音。您将不得不使用大量的反复试验来设置阈值和声音清理方法以使其正常工作。一种可能的解决方案是使用电吉他,并将其输出插入音频输入。这对我来说效果最好。
  2. 具体来说,50Hz 附近有很多噪音。这还不错,但它的泛音(见下文)分别为 100 Hz 和 150 Hz,这接近吉他的 G2 和 D3....正如我所说的,我的解决方案是改用电吉他。
  3. 在检测速度和准确性之间需要权衡取舍。您采集的样本越多,检测声音所需的时间就越长,但您会更准确地检测到确切的音高。如果您真的想以此为基础制作一个项目,您可能需要使用多个时间尺度。
  4. 当播放一个音调时,它有overtones。有时,几秒钟后,泛音甚至可能比基音更强大。如果你不处理这个,你的程序会认为它听到 E2 几秒钟,然后是 E3。为了克服这个问题,我使用了一个当前播放声音的列表,然后只要这个音符,或者它的一个泛音在其中有能量,我就假设它正在播放相同的音符......
  5. 当有人连续 2 次(或多次)演奏同一个音符时,特别难以检测到,因为很难将其与声级的随机波动区分开来。你会在我的代码中看到我必须使用一个必须配置为匹配所用吉他的常量(显然每把吉他都有自己的功率波动模式)。

【讨论】:

  • 你愿意再次上传源代码吗?看起来他们把它拿下来了
【解决方案3】:

您需要使用音频库,例如内置的audioop

分析正在播放的特定音符并非易事,但可以使用这些 API 完成。

也可以使用:http://wiki.python.org/moin/PythonInMusic

【讨论】:

  • audioop 模块只能做相当原始的分析和压缩技术。这根本不足以满足提问者的目的。 wiki 链接是一个很长的链接列表,可能会导致比它避免的更多的混乱。
【解决方案4】:

非常相似的问题:

将声音变成一系列音符并不是一件容易的事,尤其是同时处理多个音符。通读“频率估计”和“音符识别”的 Google 结果。

我有一些Python frequency estimation examples,但这只是从吉他录音中获取音符所需解决的一部分。

【讨论】:

    【解决方案5】:

    这个link 展示了一些人在 VB.NET 中执行此操作,但在下面的这些链接中捕获了实现目标所需完成的基本操作。

    【讨论】:

      猜你喜欢
      • 2010-12-02
      • 2013-03-08
      • 1970-01-01
      • 1970-01-01
      • 2017-10-13
      • 1970-01-01
      • 2016-08-07
      • 1970-01-01
      相关资源
      最近更新 更多