6

注意:这不是重复的,除相关问题外,我还有特定要求。

首先,我想绘制音频文件 (.wav) 的频谱,就像 audacity 所做的那样(类似:如何从傅里叶变换中绘制频谱)。

到目前为止,我能够读写 wav 文件。但我的问题是我不确切知道需要传递给 FFT 函数的值。顺便说一句,我在 C# 中使用 Exocortex 进行 FFT。FFT 函数要求我传递一个具有正确大小(512、1024,...我假设)的复数数组、一个可选的长度整数参数和傅立叶方向(向前/向后)。

具体问题:

  1. Exocortex 库中的 Complex(类)有两个值,即 Real 和 Imaginary。我有一系列样本,那么哪些应该是真实的,哪些应该是虚构的?
  2. 我有 wav 文件,所以长度应该是可变的。如何将其传递给 FFT 函数?我是否应该选择一个尺寸(512/1024/等),将整个样本划分为该尺寸,然后将其全部传递给 FFT?
  3. 我怎么知道应该在 x 轴上列出哪些频率?
  4. 如何绘制 FFT 数据?(我希望 x 轴为频率,y 轴为分贝)

如果您不明白我的意思,请尝试使用 Audacity,导入音频文件,然后单击分析 > 绘制频谱。这些是想要重建的东西。请详细回答我的问题,因为我真的很想学习这个。我对此只有一点背景。我只是数字信号处理的新手。另外请尽可能不要将我引导到其他 FFT 站点,因为他们没有具体回答我的问题。


编辑:

我做了一些阅读,发现了如何对音频数据进行 FFT,但只能以 2 的幂次方。那么我如何在长度不是 2 次方的音频文件中做同样的事情呢?根据一些我需要使用“窗口”。我也对其进行了一些搜索,发现它只需要稍后处理一部分波形。请记住,我想获取音频文件的 FFT,而不是其中的一部分。那我现在该怎么办?请帮忙 :(

4

1 回答 1

7

签名是

public static void  FFT( float[] data, int length, FourierDirection direction )
  1. 您传递一个复数数组,表示为对。由于您只有实数(样本),因此您应该将样本放在数组中的偶数位置 - data[0]、data[2]、data[4] 等。奇数位置应为 0,data[1] = data[3] = 0...
  2. 长度是您要计算 FFT 的样本数量,它应该正好是数据数组长度的一半。您可以对整个 WAV 或其中的一部分进行 FFT - 取决于您希望看到的内容。Audacity 将绘制文件选定部分的功率谱,如果您希望这样做,请传递整个 WAV 或选定部分。
  3. FFT 只会显示高达采样率一半的频率。因此,您的值应该在 0 到采样率的一半之间。值的数量取决于您拥有的样本数量(样本数量会影响计算的精度)
  4. Audacity 绘制功率谱。您应该获取收到的数组中的每个复数对并计算其 ABS。ABS 定义为 sqrt(r^2+i^2)。每个 ABS 值将对应一个频率。

这是一个工作代码的示例:

float[] data = new float[8];
data[0] = 1; data[2] = 1; data[4] = 1; data[6] = 1;
Fourier.FFT(data, data.Length/2, FourierDirection.Forward);

我给它 4 个样本,都一样。所以我希望只在频率为 0 时得到一些东西。事实上,在运行它之后,我得到了

数据[0] == 1,数据[2] == 1,数据[4] == 1,数据[6] == 1

其他都是0。

如果我想使用复杂数组重载

Complex[] data2 = new Complex[4];
data2[0] = new Complex(1,0);
data2[1] = new Complex(1, 0);
data2[2] = new Complex(1, 0);
data2[3] = new Complex(1, 0);
Fourier.FFT(data2,data2.Length,FourierDirection.Forward);

请注意,这里的第二个参数等于数组的长度,因为每个数组成员都是一个复数。我得到和以前一样的结果。

我想我之前错过了复杂的超载。除非您的数据已经成对出现,否则我似乎不太容易出错并且使用起来更自然。

于 2013-08-09T06:51:26.820 回答