如何缩放Wave文件的FFT输出?

3

音频文件:44100 Hz,16 位,双声道。

我使用FFT计算输出的每个频率bin的幅度。但我不知道如何将其缩放以绘制(实时)频谱。

有人能帮我吗?


许多重复 - 例如参见使用Java中的FFT算法进行音频频谱分析 - Paul R
上面链接中的比例方法只转换为分贝。因为我不知道使用FFT算法后的复杂输出的最大值。我只知道一个实例输出的最大值,但是每N毫秒,我都有另一个输出。请帮帮我! - cobazet
我无法计算所有输出并找到它们的最大值,这太难了。 - cobazet
2个回答

4

好的,有多种方法可以做到这一点...

例如:如果您想要一个分贝刻度,对于每个虚拟样本,计算

ymag = (x.real^2 + x.imag^2)

您只需要遍历一半的数组,因为您只需要正频率;第二半部分将只是第一半部分的重复,实际数据输入FFT。

搜索所得值中的最小值和最大值并存储它们。如果您的最小值为零,请选择一些非常小的值来代替您的最小值。(0.000001或其他)。然后,将您的最小分贝值设置为mindB = 10 * log10(最小值)。

现在,返回的第一个值(sample [0])将是您的直流偏移量,您可能希望将其设置为零。

然后,对于每个样本,计算:ydB = 10 * log10(ymag / maximum)。

这应该给您一个表示每个样本频率分贝下降的数组。您可以按需缩放此数组;如果您的绘图区域从y = 5到y = 200,则可以使用以下内容:

yscaled = ((ydB / -mindB) *(200-5)+ 200)

我还会确保缩放值符合范围,以防有FP舍入误差。

yscaled = min(max(yscaled,5),200)

我已经有一段时间没有做这个了,所以如果有任何数学错误,请谅解。:)


1
@cobazet,我看到了你上面的评论;我认为这会给你想要的东西。据我回忆,它将比例尺从-inf dB近似到0 dB...如果这对你不起作用,请告诉我,我会进一步研究它。 - shelleybutterfly
1
你只需要找到刚刚进行FFT的数据中的最小值和最大值,而不是整个数据集。换句话说,如果你使用了一个32768点的FFT,那么你只需要找到你正在处理的16384个点中的最大值... - shelleybutterfly
2
虽然如此,如果需要一个0 dB参考点来表示整个数据块的所有实时FFT的绝对最大值的0 dB,则必须事先知道该点。如果您需要这个,您唯一的选择是事先选择一个值作为最大值,可能是通过实验找到一个合适的值。您还可以选择实际可能的最大值,这将与您的输入数据最大可能值有关,但很可能会在顶部留下很多额外的空间... - shelleybutterfly
1
返回翻译文本:不;结果应该是小于0的;它从最高功率频段计算dB下降,因此所有内容都将小于或等于零;这就是为什么缩放使用“-mindB”的原因...我还发现一些关于我曾经使用的内容的注释,显然我们使用了0.000000001。 - shelleybutterfly
1
所以,在我给出的例子中,如果您的绘图区域从y=5到y=200,那么您应该在尝试近似负无穷分贝时得到缩放值为5,并且您应该得到代表0分贝的缩放值为200。(我可能在某个地方缩放不当,但这就是想法。) - shelleybutterfly
显示剩余2条评论

1
不同的FFT实现具有不同的比例因子,可能相差N、1/N或1/sqrt(N),其中N是FFT的长度。对于至少一种有符号整数输入FFT,最大比例约为sqrt(2) * N * 2^(b - 1),其中b是小数点左侧的位数(在您的情况下为16,在FFT之前将通道加入较大的数据类型中可能为17)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接