创建频谱图

信息处理 fft 声音的 频谱 频谱图
2021-12-24 12:43:03

我一直在尝试找出这个任务的逻辑,并计划使用 KissFFT 源包来执行快速傅立叶变换。请让我知道这是否正确:

  1. 分配一个 FFT 结构,即。我正在使用的窗口大小kiss_fft_alloc(N,0,NULL,NULL) 在哪里。N输入缓冲区将是一个N类型为 的元素数组kiss_fft_scalarN/2 + 1输出缓冲区将是类型元素的数组kiss_fft_cpx
  2. 解码N(窗口大小)PCM 样本数。
  3. 对于每个 PCM 样本,平均每个通道的幅度(无符号样本)并从 0 缩放到 2(除以 65536.0),将结果存储到输入缓冲区中。
  4. 对输入缓冲区执行窗口化(即 Hanning)。
  5. 对输入缓冲区执行快速傅立叶变换,存储到输出缓冲区。由于我使用实数值作为输入,我可以使用kiss_fftr().
  6. 对于N/2输出值,获取变换数据的平方幅度,并使用以下公式将值转换为 dB 标度: 10 * log10 (re * re + im * im)
  7. 绘制N/2步骤 6 中的值。
  8. 丢弃输入缓冲区的前半部分,解码下一个(窗口大小/2)PCM 样本并对数据执行缩放和窗口化。这应该可以有效地滑动输入窗口并避免对已处理的 PCM 样本重做数学运算。
  9. 循环到第 5 步,重复这些步骤,直到处理完所有样本。
  10. 释放已使用的内存kiss_fft_alloc()

有人建议我在执行 FFT 之前从输入窗口中减去一个值,这样得到的 DC 值的幅度为零。我应该从输入数据中减去平均值还是平均值?

另外,在选择窗口大小时需要考虑哪些事项?除了根据 KissFFT 的说明它必须是偶数之外,使用小窗口大小是否有好处,即。它会提供更好的图表吗?我假设大窗口大小减少了必须执行的 FFT 的数量,这是使用大窗口大小的唯一好处吗?

最后,当我准备好绘制数据时,我该如何绘制它?当我过去在一些波形图逻辑上工作时,我只是为每个像素绘制了 3 个值x-轴(最小幅度,最大幅度,RMS幅度),但我不知道我应该如何处理频谱图数据。

提前感谢您提供的任何和所有指导。

1个回答

在我看来还不错。但是,在第 3 步中,您实际上希望将信号从 -1 缩放到 1,否则您将添加 DC。你提到了减去平均值——我不建议对频谱图这样做,因为这会有效地过滤掉 DC,如果它在那里,频谱图应该显示出来。

选择窗口大小就是权衡取舍。较大的窗口将为您提供更清晰的频率分辨率,但更模糊的时间分辨率。较短的窗口将给您相反的结果:更清晰的时间分辨率但更模糊的频率分辨率。The appropriate choice of window size will depend on the data you are trying to analyze. 通常它是 2 的幂,因为 FFT 倾向于喜欢 2 的幂。一个不错的经验法则是,您的窗口应该至少大约是您希望能够准确测量的最低频率周期的两倍解决。

您可能想知道是否有可能更好地处理这种权衡,并且有一些技术可以做到这一点:它们通常涉及一次计算具有多个不同 FFT 大小的频谱图,并将它们组合起来。这个网页上有一些很好的视觉信息:http ://www.izotope.com/tech/aes_adapt/

如果您的窗口尺寸太小,则两个非常接近的频率可能无法相互区分,因为它们最终都在同一个 FFT 箱中。如果您的窗口太大,两个及时关闭的事件可能会合并,或者一个急剧的瞬态可能会变成一个渐进的攻击。查看我发布的网页,了解一些可视化的方法。

较大的窗口大小不一定会减少 FFT 的数量。您已选择使用短时傅里叶变换计算频谱图,其中有一半 FFT 大小的重叠。如果需要,您可以使用更高的重叠因子。选择窗口大小更多的是权衡时间/频率,而不是需要计算多少 FFT。在设计频谱图(或任何 STFT)时,您可以考虑选择窗口大小和hop size(块之间的距离)作为独立参数。

当你绘制它时,时间通常在 x 轴上,频率在 y 轴上(通常是对数刻度、梅尔刻度等,而不是线性刻度),然后幅度用颜色强度表示,即非常暗的颜色对应于小幅度,非常亮的颜色对应于大幅度。