如何正确分析音频输入/频谱

信息处理 fft 声音的 爪哇
2022-01-16 14:53:25

我对 Java 和信号处理很陌生,但我被分配了一个处理音频处理的项目。我给我的主题是一个游戏,它具有分析歌曲(任何给定歌曲)的组件并根据当前播放的频率(实时)输出数据。即:随着歌曲播放,它输出当前频率(每秒输出当前频率)。

我在stackoverflow上被告知使用FFT。他们说“只是做一个 FFT”,但这对我来说毫无意义吗?你如何进行 FFT?我已阅读教程,基本上了解它是什么,但不知道如何实现它,如:

  • 最适合这种处理的音频文件的数据类型是什么?
  • FFT的输入到底是什么
  • 我如何解释结果

有人可以就如何处理音频信号提出一个简单易懂的演练/教程吗?此外,如果有人知道 Java 的 FFT 的良好实现,我将不胜感激。

2个回答

让我们来看看。我不知道 Java 类或它对信号处理的支持类型,但我会给你一些指导。语言中实现的具体细节,你必须弄清楚。

要对音频文件进行任何类型的处理,您需要“原始”数据,这意味着音频文件具有未压缩的音频样本。例如,WAV 格式,它通常具有 16 位有符号 2 补码的样本。

如果您要使用计算机并进行离线处理,则将该值转换为双精度值可能是一个好主意(在当今的大多数处理器中,这意味着 64 位浮点数)。

因此,您将有来自文件的连续双数字流。然后,您需要定义一种处理连续数据的方法。一种标准的、非常广泛使用的方法是使用循环缓冲区(即使它处于脱机状态,我假设您希望您的代码高效,并且将整个文件作为数组加载到内存中并不是最好的解决方案)。无论是那个或只是一个普通的缓冲区,都是你的选择。缓冲区长度应该是 2 的幂(对 Cooley-Tukey radix-2 算法的效率有影响)。

现在您需要进行实际的 FFT。这仅仅是缓冲区(数学上是一个向量)乘以 FFT 矩阵。这个操作实际上是如何在 Java 中执行的,不知道。在 C 语言中,它只是将指向数组的指针和长度传递给 FFT 例程,该例程要么返回指向动态分配内存的指针,要么将结果留在传递给它的数组中。

最后,您会得到一个由 M 个复数组成的数组(假设带有信号的数组/缓冲区/向量的长度为 M)。然后你可以随心所欲地使用它。

例如,您可以取每个复数的大小并找到最大值,以检测基频可能在哪里(虽然非常近似)。

附加功能:更先进的处理技术将包括预先加窗以避免泄漏,进行零填充以在加窗频谱上获得更高的分辨率等。

希望能帮助到你。

如果你足够好, JAVA你可以使用JTRANSFORMS一个 java 库,FFT它可能会为你提供帮助

根据您的需要,这听起来像是

在此处输入图像描述

使用 Java Sound API 进行音乐可视化

在 7Steps 中使用 Ruby 中的 FFT 进行音乐可视化

您可以根据需要按照以下简单步骤操作:

*习惯一些音频术语

1.读取播放帧(假设为 20-30 毫秒),您的帧大小取决于您sampling rate假设您使用的采样率为 8000 并且每个样本是16bit signed little endian,那么您的 20 毫秒帧将是 160 个样本

注意:尝试播放raw文件而不是压缩mp3文件。

2.获取原始数据帧并执行FFT

3.正确执行Windowing

4.您的输出 FFT 结果将有两个实数和复数分量尝试从中获取幅度图,这只是absolute复数分量的值,您的峰值为您提供dominant frequency

5.看看下面的简单教程

FFT 的好教程

FFT 工程师指南

FFT 教程

FFT 概述