第 1 章:DFT 深入 / DFT In-Depth

1.1 为什么需要 DFT?

在数字信号处理中,我们天然面对的是离散时间信号 $x[n]$——它由 ADC(模数转换器)采样得到。对这样的信号做频域分析,理论上已有工具:离散时间傅里叶变换(DTFT, Discrete-Time Fourier Transform)

$$X(e^{j\omega}) = \sum_{n=-\infty}^{\infty} x[n] , e^{-j\omega n}$$

DTFT 的输出是关于角频率 $\omega$ 的连续函数——频谱是连续的。这对理论分析很好,但在计算机中无法存储和处理一个"连续函数"。

核心矛盾:计算机只能处理有限长度的离散数据,而 DTFT 输出连续频谱。

解决思路很自然:在频域上也采样,取有限个等间隔的频率点。这就是 DFT(Discrete Fourier Transform,离散傅里叶变换)的出发点。

flowchart LR
    A["连续信号 x(t)"] -->|时域采样| B["离散序列 x[n]"]
    B -->|DTFT| C["连续频谱 X(e^jω)"]
    C -->|频域采样| D["离散频谱 X[k] — DFT"]
    style A fill:#1565C0,color:#fff
    style B fill:#228B22,color:#fff
    style C fill:#5E35B1,color:#fff
    style D fill:#C62828,color:#fff

1.2 数学背景

1.2.1 欧拉公式(Euler’s Formula)

$$e^{j\theta} = \cos\theta + j\sin\theta$$

DFT 的核心运算是复指数 $e^{-j\frac{2\pi}{N}kn}$,它实际上代表一个旋转的单位圆上的点

1.2.2 矩阵表示

DFT 可以写成矩阵乘法形式:

$$\mathbf{X} = W_N \cdot \mathbf{x}$$

其中 $[W_N]_{k,n} = e^{-j\frac{2\pi}{N}kn}$,$k, n = 0, 1, \ldots, N-1$。


1.3 DFT 定义

正变换(DFT)

$$X[k] = \sum_{n=0}^{N-1} x[n] , e^{-j\frac{2\pi}{N}kn}, \quad k = 0, 1, \ldots, N-1$$

反变换(IDFT)

$$x[n] = \frac{1}{N}\sum_{k=0}^{N-1} X[k] , e^{j\frac{2\pi}{N}kn}, \quad n = 0, 1, \ldots, N-1$$

伪代码

1
2
3
4
5
6
function DFT(x[0..N-1]):
    for k = 0 to N-1:
        X[k] = 0
        for n = 0 to N-1:
            X[k] += x[n] * exp(-j * 2π * k * n / N)
    return X[0..N-1]

1.4 DFT 的物理含义

频率对应关系

$$f_k = \frac{k \cdot f_s}{N}, \quad k = 0, 1, \ldots, N-1$$

  • $k=0$:直流分量(DC)
  • $k = N/2$:奈奎斯特频率 $f_s/2$

幅度谱与相位谱

$$X[k] = |X[k]| \cdot e^{j\angle X[k]}$$


1.5 DFT 与 DTFT 的关系

DFT 是 DTFT 在 $N$ 个等间隔频率点上的采样:

$$X[k] = X(e^{j\omega})\Big|_{\omega = \frac{2\pi k}{N}}$$

操作后果
时域采样(连续→离散)频域周期延拓
频域采样(连续→离散)时域周期延拓
flowchart TB
    subgraph "对偶关系"
        A["时域采样"] --> B["频域周期延拓"]
        C["频域采样"] --> D["时域周期延拓"]
    end
    style A fill:#1565C0,color:#fff
    style B fill:#1565C0,color:#fff
    style C fill:#C62828,color:#fff
    style D fill:#C62828,color:#fff

1.6 DFT 的性质

1.6.1 线性性

$$a \cdot x_1[n] + b \cdot x_2[n] \xleftrightarrow{\text{DFT}} a \cdot X_1[k] + b \cdot X_2[k]$$

1.6.2 实信号的共轭对称性

若 $x[n]$ 为实序列,则 $X[k] = X^*[N-k]$,即 $|X[k]| = |X[N-k]|$。

1.6.3 圆周移位(Circular Shift)

$$x[(n-m)_N] \xleftrightarrow{\text{DFT}} X[k] \cdot e^{-j\frac{2\pi}{N}km}$$

1.6.4 圆周卷积 vs 线性卷积

$$x_1[n] \circledast x_2[n] \xleftrightarrow{\text{DFT}} X_1[k] \cdot X_2[k]$$

要计算线性卷积,需补零到至少 $L_1 + L_2 - 1$ 点。

1.6.5 Parseval 定理

$$\sum_{n=0}^{N-1} |x[n]|^2 = \frac{1}{N}\sum_{k=0}^{N-1} |X[k]|^2$$


1.7 频率分辨率

$$\Delta f = \frac{f_s}{N}$$

补零(Zero-padding)

补零提供频谱插值,不增加真实分辨率。真正的频率分辨率由有效观测时间 $T_{\text{obs}} = N \cdot T_s$ 决定。

flowchart LR
    A["原始 N 点"] -->|DFT| B["N 个频谱点"]
    A -->|补零到 M 点| C["M 个频谱点\n更密集的插值"]
    B -.->|"分辨率由 N 决定"| D["Δf = fs/N"]
    C -.->|"插值密度由 M 决定"| E["Δf_interp = fs/M"]
    style A fill:#1565C0,color:#fff
    style B fill:#228B22,color:#fff
    style C fill:#5E35B1,color:#fff
    style D fill:#E65100,color:#fff
    style E fill:#E65100,color:#fff

1.8 频谱泄漏(Spectral Leakage)

有限长截断等价于时域乘以矩形窗,对应频域与 sinc 函数卷积,旁瓣导致能量扩散。

窗函数选择

窗函数主瓣宽度旁瓣衰减适用场景
矩形窗最窄~13 dB频率精确对齐 bins 时
Hann 窗~31 dB通用频谱分析
Hamming 窗~41 dB语音处理
Blackman 窗~57 dB需要极低旁瓣时

1.9 工程应用:频谱分析完整流程

flowchart TB
    A["模拟信号 x(t)"] -->|ADC 采样| B["数字序列 x[n]"]
    B -->|截取 N 点| C["加窗 x_w[n] = x[n]·w[n]"]
    C -->|可选:补零| D["FFT"]
    D --> E["X[k]"]
    E --> F["|X[k]| 幅度谱"]
    E --> G["∠X[k] 相位谱"]
    F --> H["频率轴映射 fk = k·fs/N"]
    style A fill:#1565C0,color:#fff
    style B fill:#228B22,color:#fff
    style C fill:#E65100,color:#fff
    style D fill:#5E35B1,color:#fff
    style E fill:#C62828,color:#fff
    style F fill:#1565C0,color:#fff
    style G fill:#1565C0,color:#fff
    style H fill:#228B22,color:#fff

Python 完整示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import numpy as np
import matplotlib.pyplot as plt

fs = 1000                    # 采样率 1000 Hz
T = 1.0                      # 观测时间 1 秒
N = int(fs * T)              # 1000 点
t = np.arange(N) / fs

# 生成信号:50 Hz + 120 Hz + 噪声
x = np.sin(2 * np.pi * 50 * t) + 0.5 * np.sin(2 * np.pi * 120 * t) + 0.2 * np.random.randn(N)

# 加 Hann 窗
w = np.hanning(N)
xw = x * w

# FFT
X = np.fft.fft(xw, n=2048)  # 补零到 2048 点
freqs = np.fft.fftfreq(2048, 1/fs)

# 绘制单边幅度谱
plt.figure(figsize=(10, 4))
plt.plot(freqs[:1024], np.abs(X[:1024]) / N)
plt.xlabel('频率 (Hz)')
plt.ylabel('幅度')
plt.title('频谱分析结果')
plt.grid(True)
plt.show()

1.10 小结

概念关键要点
DFT 动机DTFT 连续频谱 → 频域采样 → DFT 离散有限
DFT 定义$N$ 点输入 → $N$ 点输出,复指数基分解
频率对应$f_k = k \cdot f_s / N$
频率分辨率$\Delta f = f_s / N$,由有效观测时间决定
补零插值频谱,不增加真实分辨率
频谱泄漏有限截断的后果,窗函数可抑制
工程流程采样 → 截取 → 加窗 → FFT → 幅度/相位谱