“为什么我的 DFT 响应不同?”的简短回答 是你有一个非常小的时间带宽积的啁啾。持续时间更长或扫过更大频率范围的啁啾声变得更接近理想啁啾声。
(来自https://en.wikipedia.org/wiki/Chirp_spectrum,尽管该页面总体上也有些混乱)
矩形的形状。频率函数与采样频率无关fs(假设您的采样速度比奈奎斯特频率足够快),与添加额外的零填充无关。
我同意原书通过将图形绘制为直线而不是矩形而令人困惑。@Envidia 的帖子已经说明了更大的时间带宽乘积将如何使频率响应接近理想的 rect 函数,对于非无限离散信号,吉布振铃是不可避免的。
回复:谜题“为什么频率 10 的正弦波比频率 1->2 啁啾移动得慢?”
我只是想包括这个,因为我犯了同样的错误,并且看到新的信号处理学生也这样做。大多数信号处理文本大多包含带有连续变量的数学公式,因此很容易认为cos(2 * pi * f * t)
用 Python 或 MATLAB 编写意味着您的角相位是2πft因此频率是变量f
,无论代码变量t
和f
持有什么。
虽然看起来像做f = linspace(1, 2); cos(2 * pi * f * t)
意味着余弦是“从 1 到 2 的扫描频率”,但瞬时频率cos(ϕ(t)) 是的导数ϕ,ϕ˙(t)(如上所述)。
因此,仅当您从 0 开始时间并且具有f = linspace(1, 2)
. 这将获得您期望的相位图(余弦的参数)和余弦本身:
但如果你有类似的东西t = linspace(1, 2, n)
,扫描相同频率范围的相位不再只是2 * pi * f * t
。
从扫f1(t)到f2(t), 你会想要创建函数f(t)作为一条线从f1(t)到f2(t). 然后使用的值t您正在考虑并求解斜率和截距。这可确保相位的斜率与您尝试扫描的频率相匹配。
这是一个差异示例,使用略有不同的数字(如果您尝试“将频率从 1 扫描到 2”,但您查看的时间从 1 开始而不是 0 并持续 1 秒)。左边是阶段,右边是cos(phase)
查看它们摆动速度的图。红色的错误方式是做
t = linspace(1, 2); f = linspace(1, 2); phase_wrong = 2 * pi * f * t
。通过与 2 的恒定斜率相位相比,它肯定在任何地方都有 2 的频率,您可以看到这种方法的斜率比 2 更陡,因此它不是从 1 到 2 扫描频率。
(情节代码:)
import matplotlib.pyplot as plt
from numpy import pi, cos, linspace
n = 500
t = linspace(0, 2, n)
f = linspace(1, 2, n)
fig, axes = plt.subplots(1, 2)
ax = axes[0]
ax.plot(t, 2 * pi * 1 * t, c="b", label="freq=1")
ax.plot(t, 2 * pi * 2 * t, c="cyan", label="freq=2")
ax.plot(t, 2 * pi * f * t, c="red", label="sweep 1->2")
ax.set_title(r"$\phi(t)$")
ax.legend()
ax = axes[1]
ax.plot(t, cos(2 * pi * 1 * t), c="b", label="freq=1")
ax.plot(t, cos(2 * pi * 2 * t), c="cyan", label="freq=2")
ax.plot(t, cos(2 * pi * f * t), c="red", label="sweep 1->2")
ax.set_title(r"$\cos(\phi(t))$")
ax.legend()
fig, axes = plt.subplots(1, 2)
t = linspace(1, 2, n)
phi_right = pi * (t ** 2 - 1)
f = linspace(1, 2, n)
phi_wrong = 2 * pi * f * t
# Compare to a constant freq (straight phase line)
const_freq = 2
ax = axes[0]
ax.plot(t, 2 * pi * const_freq * t, c="b", label=f"{const_freq = }")
# Make it start at same spot as constant freq phase line
offset1 = phi_right[0] - 2 * pi * const_freq * t[0]
ax.plot(t, phi_right - offset1, c="cyan", label="correct: f sweeps 1 -> 2")
offset2 = phi_wrong[0] - 2 * pi * const_freq * t[0]
ax.plot(t, phi_wrong - offset2, c="red", label="wrong way (2 pi f t)")
ax.set_title(r"$\phi(t)$")
ax.legend()
ax = axes[1]
ax.plot(t, cos(2 * pi * const_freq * t), c="b", label=f"{const_freq = }")
ax.plot(t, cos(phi_right), c="cyan", label="correct: f sweeps 1 -> 2")
ax.plot(t, cos(phi_wrong), c="red", label="wrong way (2 pi f t)")
ax.legend()
ax.set_title(r"$\cos(\phi(t))$")
(@OverLordGoldDragon 还指出了他的更多真实代码示例,这可能比仅数学公式更有用:https ://overlordgolddragon.github.io/test-signals/#signal-general-forms-derivations )