5

最近我问了这个问题:如何从 FFT 中获得基频?(您实际上不需要阅读它)

我现在的疑惑吧:倒谱算法怎么用?

我只是不知道如何使用它,因为我知道的唯一语言是 ActionScript 3,因此我很少参考 C、Java 等中的本机函数,以及我应该如何在 AS 上实现它们. 大多数文章都是关于这些语言的=/(尽管欢迎使用除 AS 以外的其他语言的答案,请解释一下脚本的工作原理)

我发现的关于倒谱以查找 FFT 结果的基频的文章告诉我应该这样做:

signal → FT → abs() → square → log → FT → abs() → square → power cepstrum

数学上:|F{log(|F{f(t)}|²)}|²

重要信息:

  • 我正在闪存中开发吉他调音器
  • 这是我第一次处理高级声音
  • 我正在使用 FFT 从到达用户麦克风的信号中提取频率区间,但我无法从中获取基频

我不知道:

  • 如何在 ARRAY 中应用正方形(我的意思是,我的 FFT 给我的数据是一个数组。我应该将它自己相乘吗?当我尝试 fftResults * fftResults 时,ActionScript 的调试会引发错误)
  • 如何应用“日志”。即使我只有一个号码,我也不知道如何应用它。
  • 复倒谱和功率倒谱有什么区别。另外,我应该使用它们中的哪一个?我正在尝试开发吉他调音器。

谢谢!

4

3 回答 3

6

请注意,FFT 的输出是一个复数值数组,即每个 bin = re + j*im。我认为你可以结合 abs 和 square 运算并计算re*re + im*im每个 bin。这为每个 bin 提供了一个正值,显然您可以很容易地计算每个 bin 的 log 值。然后,您需要对此对数平方数据进行第二次 FFT,并再次使用第二次 FFT 的输出计算re*re + im*im每个 bin。然后,您将拥有一组正值,这些正值将具有一个或多个峰值,代表您输入的一个或多个基频。

于 2011-02-07T20:06:53.053 回答
2

自相关是最简单、最合乎逻辑的方法,也是最好的起点。

为了让它工作,从一个简单的自相关开始,然后,如有必要,按照 YIN 提供的大纲进行改进。(YIN 基于与细化的自相关。但您是否需要这些细化取决于您的具体情况。)通过这种方式,您也可以边做边学,而不是试图一次性理解整个事情。

尽管 FFT 方法也可以工作,但它们有点令人困惑。问题是您真正追求的是时期,而 FFT 并不能很好地代表这一点。缺少的基波就是一个很好的例子,如果你有 2Hz 和 3Hz,基波是 1Hz,但在 FFT 中没有,而 1Hz 在基于时间的表示(例如自相关)中是显而易见的。除此之外,泛音不一定是谐波和噪音等......所有这些问题通常最好从直接解决问题的方法开始。

于 2011-02-09T18:11:07.700 回答
1

找到基频 (F0) 的方法有很多。

对于 Java 等语言,有许多库已经实现了这些类型的算法(你可以研究它们的源代码)。

  • 在Comirva(开源)中实现的 MFCC(基于倒谱)。
  • Audacity(测试版!)(开源)提供倒谱、自相关、增强自相关、
  • 基于自相关的阴(示例
  • 在 FFT 之后查找最大信号值

所有这些算法可能对你很有帮助。然而,获得 F0(以赫兹为单位的一个值)的最简单方法是使用阴。

于 2011-02-07T19:40:31.703 回答