3. 采样定理验证
任务目标
对高频正弦波以不同采样率进行采样,通过观察频谱中混叠成分的位置与幅度,直观验证奈奎斯特采样定理:当采样率 fs < 2·f0 时,信号频率将折叠至 [0, fs/2] 区间内,无法由采样值唯一重建。
环境与依赖
Python 3.8+,仅需 NumPy 与 Matplotlib。无需其他第三方库。
核心原理与实现
设连续正弦波频率为 f0 = 800 Hz,分别采用三种采样率:
fs1 = 2000 Hz(满足奈奎斯特条件,fs1 > 2·f0)fs2 = 1200 Hz(不满足,fs2 < 2·f0)fs3 = 1000 Hz(临界欠采样,fs3 = 2·f0/1.6,混叠最严重)
对每种采样率生成 N = 2048 个采样点,计算 FFT 并绘制幅度谱。混叠频率的理论值为 |f0 - k·fs| 中落在 [0, fs/2] 的最小值,代码中直接标注该理论值供比对。
完整代码
import numpy as np
import matplotlib.pyplot as plt
# 参数设置
f0 = 800.0 # 原始信号频率 (Hz)
N = 2048 # 采样点数
fs_list = [2000.0, 1200.0, 1000.0] # 三种采样率 (Hz)
t_max_list = [N / fs for fs in fs_list] # 每种采样率对应的总时长
# 生成连续时间基准(用于绘制原始波形,仅作参考)
t_cont = np.linspace(0, 0.01, 2000)
x_cont = np.sin(2 * np.pi * f0 * t_cont)
fig, axes = plt.subplots(3, 1, figsize=(10, 9))
fig.suptitle(f'采样定理验证:f0 = {f0:.0f} Hz', fontsize=14)
for idx, fs in enumerate(fs_list):
# 采样
n = np.arange(N)
t = n / fs
x = np.sin(2 * np.pi * f0 * t)
# FFT 与频率轴
X = np.fft.fft(x) / N
freq = np.fft.fftfreq(N, d=1.0 / fs)
half = N // 2
mag = np.abs(X[:half])
freq_half = freq[:half]
# 理论混叠频率(折叠到 [0, fs/2])
alias = np.abs(f0 - np.round(f0 / fs) * fs)
if alias > fs / 2:
alias = fs - alias
# 绘制频谱
ax = axes[idx]
ax.stem(freq_half, mag, linefmt='C0-', markerfmt='C0o', basefmt='C1-', label='FFT幅度谱')
ax.axvline(fs / 2, color='red', linestyle='--', linewidth=1.2, label=f'fs/2 = {fs/2:.0f} Hz')
ax.axvline(f0, color='green', linestyle=':', linewidth=1.2, label=f'原始频率 {f0:.0f} Hz')
if alias != f0: # 有混叠时标注
ax.axvline(alias, color='purple', linestyle='-.', linewidth=1.5,
label=f'混叠频率 ≈ {alias:.1f} Hz')
ax.set_xlim(0, fs / 2 + 200)
ax.set_ylim(0, 0.6)
ax.set_xlabel('频率 (Hz)')
ax.set_ylabel('幅度')
ax.set_title(f'采样率 fs = {fs:.0f} Hz({"满足" if fs >= 2*f0 else "不满足"}奈奎斯特条件)')
ax.legend(fontsize=8)
ax.grid(alpha=0.3)
plt.tight_layout()
plt.savefig('sampling_theorem.png', dpi=150)
plt.show()
# 控制台输出验证信息
print('=== 采样定理验证结果 ===')
for fs in fs_list:
alias = np.abs(f0 - np.round(f0 / fs) * fs)
if alias > fs / 2:
alias = fs - alias
status = '满足' if fs >= 2 * f0 else '不满足'
print(f'fs = {fs:5.0f} Hz | {status} | 理论混叠频率 = {alias:6.1f} Hz')
运行方式
python sampling_theorem.py
验证方法与判定标准
- 频谱峰值位置:观察每个子图中幅度谱的最大峰值频率。当
fs = 2000 Hz时,峰值应位于800 Hz;当fs = 1200 Hz时,峰值应位于400 Hz(即800 - 1200×round(800/1200) = 800-1200×1 = -400,取值后折叠到400 Hz);当fs = 1000 Hz时,峰值应位于200 Hz(800 - 1000×1 = -200,折叠到200 Hz)。 - 控制台输出比对:程序打印的理论混叠频率应与频谱图中紫色虚线位置一致,且与上述手算值吻合。
- 判定通过条件:三个子图的峰值频率分别等于各自的理论混叠频率(误差小于一个频率分辨率
fs/N),且fs = 2000 Hz时峰值位于原始频率处无偏移,即验证了采样定理。
预期输出(确定性结论)
=== 采样定理验证结果 ===
fs = 2000 Hz | 满足 | 理论混叠频率 = 800.0 Hz
fs = 1200 Hz | 不满足 | 理论混叠频率 = 400.0 Hz
fs = 1000 Hz | 不满足 | 理论混叠频率 = 200.0 Hz
该输出由代码逻辑直接唯一确定,非实测数据。频谱图中三个峰值将分别出现在 800 Hz、400 Hz、200 Hz 处,直观展示欠采样导致的频率折叠现象。