【发布时间】:2020-07-15 05:24:43
【问题描述】:
这里我使用numpy 的fft 函数来绘制由10000Hz 正弦波生成的PCM 波的fft。但是我得到的情节的幅度是错误的。
使用我在控制台本身打印的fftfreq 函数使频率正确。我的python代码在这里。
import numpy as np
import matplotlib.pyplot as plt
frate = 44100
filename = 'Sine_10000Hz.bin' #signed16 bit PCM of a 10000Hz sine wave
f = open('Sine_10000Hz.bin','rb')
y = np.fromfile(f,dtype='int16') #Extract the signed 16 bit PCM value of 10000Hz Sine wave
f.close()
####### Spectral Analysis #########
fft_value = np.fft.fft(y)
freqs = np.fft.fftfreq(len(fft_value)) # frequencies associated with the coefficients:
print("freqs.min(), freqs.max()")
idx = np.argmax(np.abs(fft_value)) # Find the peak in the coefficients
freq = freqs[idx]
freq_in_hertz = abs(freq * frate)
print("\n\n\n\n\n\nfreq_in_hertz")
print(freq_in_hertz)
for i in range(2):
print("Value at index {}:\t{}".format(i, fft_value[i + 1]), "\nValue at index {}:\t{}".format(fft_value.size -1 - i, fft_value[-1 - i]))
#####
n_sa = 8 * int(freq_in_hertz)
t_fft = np.linspace(0, 1, n_sa)
T = t_fft[1] - t_fft[0] # sampling interval
N = n_sa #Here it is n_sample
print("\nN value=")
print(N)
# 1/T = frequency
f = np.linspace(0, 1 / T, N)
plt.ylabel("Amplitude")
plt.xlabel("Frequency [Hz]")
plt.xlim(0,15000)
# 2 / N is a normalization factor Here second half of the sequence gives us no new information that the half of the FFT sequence is the output we need.
plt.bar(f[:N // 2], np.abs(fft_value)[:N // 2] * 2 / N, width=15,color="red")
输出来自控制台(我在这里只粘贴最少的打印)
freqs.min(), freqs.max()
-0.5 0.49997732426303854
freq_in_hertz
10000.0
Value at index 0: (19.949569768991054-17.456031216294324j)
Value at index 44099: (19.949569768991157+17.45603121629439j)
Value at index 1: (9.216783424692835-13.477631008179145j)
Value at index 44098: (9.216783424692792+13.477631008179262j)
N value=
80000
频率提取正确,但在图中我正在做的事情是不正确的,我不知道。
更新作品:
- 当我将
n_sa = 10 * int(freq_in_hertz)行中的乘法因子 10 更改为 5 时,我得到了正确的绘图。对不对我看不懂 - 在
plt.xlim(0,15000)行中,如果我再次将最大值增加到 20000,则不会进行绘图。直到 15000 才能正确绘制。 - 我使用 Audacity 工具生成了这个
Sine_10000Hz.bin,在该工具中,我生成了一个持续时间为 1 秒、采样率为 44100 的频率为 10000Hz 的正弦波。然后我将此音频导出为无标头的签名 16 位(意味着原始 PCM)。我可以使用这个脚本重新生成这个正弦波。我也想计算这个的FFT。所以我预计在 10000Hz 处有一个峰值,振幅为 32767。你可以看到我在n_sa = 8 * int(freq_in_hertz)行中更改了乘法因子8而不是10。因此它奏效了。但幅度显示不正确。我将在此处附上我的新图
【问题讨论】:
标签: python-3.x numpy matplotlib plot fft