44.1kHz采样率WAV文件前100采样点FFT计算结果异常原因问询
100点FFT绘制音频频谱结果异常的原因分析
核心原因1:频率分辨率不足
FFT的频率分辨率计算公式为 采样率 / FFT点数,你使用的44.1KHz采样率下,100点FFT的频率分辨率为 44100/100 = 441Hz,也就是说你最多只能区分间隔≥441Hz的频率成分。
而常规音频(语音、音乐等)的基频通常在80~1000Hz区间,相邻泛音的间隔远小于441Hz,100点FFT完全无法区分这些临近的频率成分,所有能量会混叠在同一个频率桶中,最终得到的结果自然不符合预期。
当你使用2048点FFT时,频率分辨率约为 44100/2048 ≈ 21.5Hz,这个分辨率足够区分绝大多数常规音频的频率成分,因此结果符合预期。
核心原因2:频谱截断泄漏
你直接截取前100个采样点做FFT,相当于对原始时域信号加了一个矩形窗,矩形窗的主瓣宽度为2倍频率分辨率,100点下主瓣宽度就达到了882Hz,同时矩形窗的旁瓣衰减很低,会导致单频信号的能量扩散到相邻的多个频率桶中,进一步模糊频谱的特征,放大了低分辨率带来的问题。
代码存在的额外问题
你当前生成频率轴的逻辑有误:实信号的FFT结果是共轭对称的,有效频率范围只有0到采样率的一半(即0~22050Hz),你生成的频率轴到44100Hz,相当于把对称的负频率部分也重复绘制了,会出现镜像频谱,即使分辨率足够也会显示异常。
修正后的代码逻辑参考:
import numpy as np import matplotlib.pyplot as plt import scipy.io.wavfile def normalizeAudio(data): return np.float32(data / np.max(np.abs(data))) SAMPLE_FOR = 1 # in seconds samplerate, data = scipy.io.wavfile.read(r'Recording.wav') data = normalizeAudio(data[0:int(samplerate*SAMPLE_FOR)]) fft_n = 2048 # 可根据需要的分辨率调整,分辨率=44100/fft_n fft_out = np.fft.fft(data[0:fft_n]) # 直接用fftfreq生成频率轴,仅取前半部分有效频率 freq_vector = np.fft.fftfreq(fft_n, 1/samplerate)[:fft_n//2] plt.plot(freq_vector, np.abs(fft_out[:fft_n//2])) plt.xlabel("频率(Hz)") plt.ylabel("幅度") plt.show()
内容的提问来源于stack exchange,提问作者yarin Cohen
相关产品推荐
相关产品推荐

