我使用 audacity 生成具有 48KHz 采样率和 1 秒持续时间的 10Hz 音调。然后用下面的脚本加载它来绘制 FFT 图:
from scipy.io import wavfile
from scipy.fftpack import fft, fftfreq
import matplotlib.pyplot as plt
from pydub import AudioSegment
import numpy as np
wav_filename = "\\test\\10Hz.wav"
samplerate, data = wavfile.read(wav_filename)
total_samples = len(data)
limit = int((total_samples /2)-1)
fft_abs = abs(fft(data))*2/total_samples
fft_db = 20*np.log10(fft_abs/32760)
freqs = fftfreq(total_samples,1/samplerate)
# plot the frequencies
plt.plot(freqs[:limit], fft_db[:limit])
plt.xscale('log',basex=10)
plt.title("Frequency spectrum")
plt.xlabel('Hz')
plt.ylabel('amplitude')
plt.show()
但如果我使用 audacity 来查看频谱图,那就太好了。
我应该如何改进我的脚本以获得更好的 FFT 绘图?
最佳答案
WAV 文件的特定频谱模式是由 Audacity 应用的噪声形抖动生成的,以减轻量化造成的失真。
信号以带符号的 16 位整数形式存储在 WAV 文件中。这quantization使信号非常不准确:2^15 是 32768:0.5/32768 的相对误差很可能并且计算 DFT 可能会增加它。那大约是 1e-5,或 -96dB。因此,如果不小心将信号值强制转换为最接近的整数,则任何低于 96dB 的频率都可以作为量化噪声丢弃。
然而,导出的 WAV 文件的频谱看起来非常好,因为所有频率的幅度都低于 -100dB,唯一的异常(exception)是正弦波的频率,其幅度接近 0dB。 问题需要重新表述:Audacity 如何为 WAV 文件获得如此准确的频谱?
导出的值经过优化以提高光谱的准确性。实际上,单个导出值的准确性不如将浮点值转换为整数精确。我在 audacity 中生成了一个振幅为 0.8 的正弦波,并将其导出为 WAV 签名的 16 位 PCM。量化误差可以计算为:
x=np.linspace(0,1,len(data),endpoint=False)
data2=np.sin(10*2*np.pi*x)
data=data.astype(np.double)
plt.plot(x, data-0.8*32768*data2, label="data-sin(x)")
#plt.xscale('log',basex=10)
plt.title("signal")
plt.xlabel('time, s')
plt.ylabel('amplitude')
plt.show()
如果将信号值简单地转换为最接近的整数并倒入 WAV 文件中,则生成的误差将低于 0.5。实际逐点误差约为 5。
A noise-shaped dither Audacidy 中考虑通过添加人类几乎听不到的高频噪声来改善量化信号的动态范围。 there , there和 there .
您可以 choose the dither in Audacity 甚至禁用它。进入首选项=>质量!如果不考虑dither,真实空间中的pointwise error更小:
但频谱上的量化误差较高:
矩形抖动可用于恢复看起来像白噪声的东西: 它可能是您使用的最佳选择,因为频谱上的误差约为 -125dB,逐点误差为 +-1。
关于python - FFT噪声频率去除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57892632/