如何将 FFT 应用于录音以获取频率?

Posted

技术标签:

【中文标题】如何将 FFT 应用于录音以获取频率?【英文标题】:How do I apply FFT onto an audio recording to get a frequency? 【发布时间】:2016-12-19 23:45:55 【问题描述】:

这应该是针对 android 应用程序的,因此所讨论的语言显然是 Java。 我正在尝试录制一些音频并获得主导频率。这是为了一个非常特定的目的,我需要检测的频率是另一个设备发出的纯声音。我已经完成了录制部分,所以我唯一需要做的就是从它生成的缓冲区中计算频率。

我知道我应该使用称为 FFT 的东西,所以我将它们放入我的项目中:http://introcs.cs.princeton.edu/java/97data/FFT.java 和 http://introcs.cs.princeton.edu/java/97data/Complex.java.html

我知道对此有很多问题,但没有一个给出我能理解的答案。其他人的链接断开了。

有谁知道怎么做,并用比较简单的方式解释一下?

【问题讨论】:

见this question。 【参考方案1】:

通常,DFT(包括 FFT)实现将采用 N 个时域样本(您的记录)并在频域中产生 N/2 个复数值。复数值的角度代表相位,其绝对值代表幅度。通常输出的值会从最低频率到最高频率排序。

某些实现可能会输出 N 个复数值,但额外的值是多余的,除非您的输入包含复数值。它不应该在你的情况下。这就是为什么许多实现输入实数值并输出 N/2 复数值的原因,因为这是 FFT 最常见的用途。

因此,您将需要计算输出的绝对值,因为幅度是您感兴趣的。复数的绝对值是它的实数平方和的平方和的平方根这是一个复杂的组件。

每个值的确切频率取决于输入样本的数量和样本之间的间隔。位置 i 的值的频率(假设 i 从 0 变为 N/2 - 1)将为 i *(采样频率)/N。

这是假设您的 N 是偶数,而不是试图解释 N 是奇数的情况,为了简单起见,我建议您保持 N 偶数。对于 FFT,N 始终是 2 的幂,因此 N 始终是偶数。

如果您要在最短时间 T 内寻找音调,那么我还建议以 T/2 大小的块处理输入。

【讨论】:

所以在这种情况下,将音频数据的缓冲区转换为复数数组是否正确,在我发布的第一个链接中将其输入到 FFT 函数中,从输出中获取最高数字,然后按照您描述的方式找到该数字的绝对值? @superchampionoftheworld 您必须查看您正在使用的 FFT 实现的文档,以确定它期望的输入。我之前使用过一个库,其中一个函数需要输入复数,另一个函数需要输入实数。如果您的函数需要输入复数,那么您可以将虚部设置为零的值发送给它。 我刚刚检查了您的链接。是的,对于该实现,您需要将输入转换为复数。将实部设置为您的输入,将虚部设置为零。 我知道如何求单个复数的绝对值,但是如何获得数组的绝对值,也就是FFT函数输出的结果? 我实际上让我的应用程序按照需要运行,使用了一种叫做过零的东西。【参考方案2】:

傅立叶变换是一种数学技术,可让您在时域和频域之间来回转换时间相关信号。

FFT 是一种用于快速有效地计算离散变换的计算机算法。

您将对时间信号进行采样,然后对其应用 FFT 以获得样本的幅度与频率。

如果您没有数学背景,这不是一个容易的话题。它假定您对三角学(正弦和余弦)、函数和微积分有很好的了解。如果你没有那个,你将很难阅读和理解你能找到的任何参考资料。

如果您没有该背景,请尽量将库 FFT 函数视为黑匣子并使用它返回的内容。

【讨论】:

以上是关于如何将 FFT 应用于录音以获取频率?的主要内容,如果未能解决你的问题,请参考以下文章

更改块大小会导致 FFT 分析失败

将 FFT 应用于 1024 个样本的每个块

从歌曲中获取当前音频频率 - Java(也许使用 FFT?)

iPhone应用程序仅在特定频率以上录音

快速傅立叶变换应用窗口和重叠

如何识别 FFT 数据的局部最大值