缩放条形图的 FFT 频率范围

信息处理 fft 频谱 Python
2022-02-17 03:40:29

我正在尝试使用FFT将音频数据的频谱显示为条形图

如果我有440 Hz且采样率为44100 Hz的正弦波数据并分析其前 1024 个样本,我将得到一个具有 1024 个 FFT 值的数组。我知道这些值的前半部分(512)表示频率范围等于采样率的一半(22050 Hz)。

因此,要绘制条形图,我只需从 FFT 数组中获取前 15-20 个值,计算每个元素的频率范围并绘制它。

  • 在 FFT 大小为1024 I 的情况下,每个频率约为 43 Hz宽。
  • 但是,如果我将 FFT 大小更改为2048 ,则每个频率范围都是~21.5 Hz所以正弦波频谱的峰值将在我的 15-20 条之外。

所以我想问一下是否可以针对频率范围和恒定图形条数对X 轴进行缩放/归一化?

限制数据的示例是:

  • 频率范围 0-500 Hz
  • 图表上有 16 个条形图

我想这是某种箱/幅度分组。但是我应该对它们求和还是得到最大值?当分组的 bin 编号不是整数时,可以用幅度做什么?(我希望我的解释不会太混乱,很难选择正确的术语)

谢谢。

这是我在Python中的测试代码:(
我使用了int另一个文件导入的静态数组,该数组表示正弦波)

import scipy.io.wavfile as wavfile
import scipy
import scipy.fftpack
import numpy as np
from scipy.signal.windows import *
from matplotlib import pyplot as plt

from imp.sine_440_hex import *

def run():
  # fp = 'e:/sine_440_hz.wav'
  # FS, data = wavfile.read(fp)

  # data - array of int for a sine wave at 440Hz and amplitude 0.5
  DS = len(data)
  FS = 44100

  FN = 1024
  # FN = 2048
  MAXS = 32768

  MN = 15   # number of first frequencies in the FFT result

  ndata = np.array(data)
  ndata = ndata / MAXS

  w = np.hamming(FN)
  y = ndata[:FN] * w

  freqs = scipy.fftpack.fftfreq(FN, 1/FS)
  mags = abs(scipy.fft(y))

  dbfs = 20 * np.log10(mags * 2 / np.sum(w))
  dbs = dbfs + 120

  # -------- plot --------
  fr_res = freqs[:MN]
  db_res = dbs[:MN]

  ax1 = plt.subplot(211)
  plt.plot(fr_res, db_res)
  plt.grid(True)
  plt.xlabel('Frequency [Hz]')
  plt.ylabel('Amplitude [dB]')

  ax2 = plt.subplot(212)
  plt.bar(fr_res, db_res, fr_res[1]-10)
  plt.grid(True)
  ax2.set_ylim([80, 120])
  ax2.set_xticks(fr_res)
  ax2.set_xticklabels(fr_res.astype(int))

  plt.show()

# -------
run()

示例图:

对于FN = 1024 https://i.imgur.com/wSK80w8.png 对于FN = 2048 https://i.imgur.com/tdOJq4X.png

1个回答

为此,请使用频率而不是箱。要将 bin 编号转换为它所代表的频率,请使用:

f=kNFFTFs

在哪里:

  • k是您要恢复其实际频率的 bin 编号
  • Fs是采样频率
  • NFFT是 FFT 的点数

你可以锻炼你的NFFT以确保您扫描的频率范围将分为 16 段。例如,覆盖频率范围fl=300fh=3000赫兹与Nbars=16酒吧和Fs=44100Hz,你必须使用:

NFFT=FsNbars|fhfl|

基本上,你计算出两个频率之间的间距fl,fh16段,然后将其“翻译”为Fs(但是这个比例已经被简化了,这就是为什么FsNbars)

结果是:

NFFT=4410016|3000300|261.3333

必须四舍五入到262点。

所以,现在你知道你的 FFT 有 262 个点,间距为FsNFFT=44100262168.3206赫兹。

您的第一个垃圾箱位于300168.32061.7823这将不得不四舍五入2和 3000 Hz 应该在 bin2+16=18.

让我们来看看,18262441003029.7709赫兹。

希望这可以帮助。