【问题标题】:FFT decibel value not correctFFT 分贝值不正确
【发布时间】:2026-01-26 23:45:01
【问题描述】:

我正在研究this的帖子,并且有一个将7000个样本填充到1000个样本信号的示例!

所以我尝试编写下面的代码来模拟这种情况,但输出与帖子图片不匹配:

在帖子中,预期的输出图像如下:

original post image

但我的输出图像如下所示:

显然:

  1. 信号分贝信息不匹配(峰值 -15.96 与 11)。
  2. 我的输出中不存在这两个峰值频率。

我的完整代码:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from matplotlib.ticker import FuncFormatter, MultipleLocator
import scipy.fftpack

num = 1000
samplerate = 100*1000000
freq1 = 1*1000000
freq2 = 1.05*1000000
duration = num/samplerate
T = 1.0/samplerate

x = np.arange(0,num,1)*T
y = np.sin(2*np.pi*freq1*x) + np.sin(2*np.pi*freq2*x)
fig,ax = plt.subplots(1,1,figsize=(8,6),constrained_layout=True)

M = 8000
x2 = np.arange(0,duration*8,T)
y2 = np.pad(y, (0, num*7), 'constant')

yfft = np.abs(scipy.fftpack.fft(y2,n=M))[:M//2]
freqs1 = np.fft.fftfreq(M,T)[:M//2]
freqs = np.arange(0, M)[:M//2]*(samplerate/M)
print(freqs[len(freqs)-1])
print(freqs1[len(freqs)-1])
ydb = 20*np.log10(yfft*2/M)

df = pd.DataFrame(list(zip(freqs,ydb)),columns=['freq','value'])
ax.plot(df['freq'],df['value'],marker='.')
print("signal length:%d,frequency length:%d"%(len(y2),len(freqs)))

xmin =   500000
xmax = 1500000
df = df.query('freq > %d and freq < %d'%(xmin,xmax))
ymin = df['value'].min()
ymax = df['value'].max()
ax.set_xlim([xmin,xmax])
ax.set_ylim([ymin,ymax])
ax.set_xticks(np.append(ax.get_xticks(),[xmin,xmax]))
ax.set_yticks(np.append(ax.get_yticks(),[ymin,ymax]))
ax.xaxis.set_major_formatter(FuncFormatter(
    lambda val,pos: '{:.1f}$MHz$'.format(val/1000000)
))
ax.tick_params(axis='x', rotation=45)
ax.grid()
print(freqs[1] - freqs[0])
plt.show()

【问题讨论】:

    标签: python numpy fft


    【解决方案1】:

    为了看到两个山峰,帖子作者在你发的图的标题中说:

    功率谱 - 7000 个时间样本和 1000 个零填充/8000 个 FFT 点

    您的y2 只有 1000 个支持样本,以及 7000 个填充样本。我这样做了:

    # Make the signal: 7000 points.
    x = np.arange(0, num*7, 1) * T
    y = np.sin(2*np.pi*freq1*x) + np.sin(2*np.pi*freq2*x)
    
    # Pad the signal with 1000 points.
    x2 = np.arange(0, num*8, 1) * T
    y2 = np.pad(y, (0, num), 'constant')
    

    现在信号看起来正确(绘制y2 vs x2):

    功率应为10分贝;我认为只需要针对这个更长的信号更新乘数,例如:

    ydb = 20*np.log10(yfft*7/M)
    

    我最终得到:

    【讨论】:

    • 谢谢,还有一个问题是为什么 fft 可以做 8000 个样本,我在想它应该是 2^13 = 8192 的幂。这是否意味着 fft 已经做了零填充?如果补零,那么输出应该是8192频率,fft怎么能输出8000频率!
    • 不,它不会填充到 8192。您可以在这个问题中了解它的作用:*.com/questions/13841296/…