理论实验目的
在本实验中,我们将使用MATLAB对离散时间信号进行频域分析。本实验的主要目的是:
- 理解并掌握离散时间傅里叶变换(DTFT)的基本概念和性质
- 学习离散傅里叶变换(DFT)与DTFT之间的关系
- 利用快速傅里叶变换(FFT)计算离散时间序列的频谱
- 通过结果分析理解固定频率和时变频率(如语音信号)的数字信号频谱特点
- 理解线性卷积和循环卷积之间的关系,掌握FFT快速计算卷积的方法
- 培养频域分析能力,理解时域与频域的对应关系
频域分析是数字信号处理的核心内容之一。通过将时域信号变换到频域,我们可以更直观地观察信号的频率成分,这对于信号分析、滤波设计、通信系统等应用至关重要。
理论理论基础
1. 离散时间傅里叶变换(DTFT)
对于离散时间信号(DT)求其频域表达,使用DTFT,也就是离散时间傅里叶变换。此时的信号是一个离散的非周期的实数或复数序列。
DTFT分析式(正变换):
$$X(e^{j\omega}) = \sum_{n=-\infty}^{\infty} x[n]e^{-j\omega n}$$
其中 $\omega$ 为归一化角频率(弧度)
DTFT合成式(逆变换):
$$x[n] = \frac{1}{2\pi} \int_{-\pi}^{\pi} X(e^{j\omega})e^{j\omega n}d\omega$$
- 连续性:$X(e^{j\omega})$ 是关于频率 $\omega$ 的连续函数
- 周期性:$X(e^{j\omega})$ 是以 $2\pi$ 为周期的周期函数,即 $X(e^{j(\omega+2\pi)}) = X(e^{j\omega})$
- 对称性:若 $x[n]$ 为实序列,则 $X(e^{j\omega})$ 满足共轭对称性
计算机实现的限制:
在计算机系统中,想要实现一个连续的数值变量是不可能的,所以对DTFT的任何数值实现有两个要求:
- $x[n]$ 必须具有有限长度(序列长度有限)
- $X(e^{j\omega})$ 只能在连续频率变量 $\omega$ 的有限数量的样本处计算(频率采样点有限)
在满足这两条要求的前提下,我们可以通过MATLAB来计算一个DT序列的频谱。实际上,如果 $x[n]$ 是有限的,$\omega$ 的数量也是有限的,我们就把DTFT离散化了,这就引出了DFT。
2. 离散傅里叶变换(DFT)
理论上DTFT分析方程的计算是从负无穷到正无穷进行求和,在计算机中是不可实现的,我们使用DFT,也就是离散傅里叶变换来进行谱分析。
DFT与DTFT的关系:
有限长序列的DFT结果包含了N个离散频率点处的DTFT结果,这些离散频率点等间隔地分布在区间 $[0, 2\pi)$ 内。如果离散频率点数量足够多,我们就可以通过DFT近似得到DTFT的结果。
频率采样:
为了计算效率,我们将连续频率变量 $\omega$ 所在的 $0$ 到 $2\pi$ 的周期范围内,等分 N 个点:
$$\omega_k = \frac{2\pi k}{N}, \quad k = 0, 1, 2, \ldots, N-1$$
DFT正变换:
$$X[k] = \sum_{n=0}^{N-1} x[n]e^{-j\frac{2\pi kn}{N}}, \quad k = 0, 1, \ldots, N-1$$
其中 $k$ 为频率索引,对应频率 $\omega_k = 2\pi k/N$
逆离散傅里叶变换(IDFT):
$$x[n] = \frac{1}{N} \sum_{k=0}^{N-1} X[k]e^{j\frac{2\pi kn}{N}}, \quad n = 0, 1, \ldots, N-1$$
频率分辨率:DFT的频率分辨率为 $\Delta f = F_s/N$,其中 $F_s$ 为采样频率。增加 $N$ 可以提高频率分辨率,使频谱更加精细。
零填充(Zero Padding):在信号末尾补零可以增加DFT的计算点数 $N$,从而提高频率分辨率,使DFT结果更接近真实的DTFT。但需要注意,零填充并不增加新的信息,只是对DTFT进行更密集的采样。
3. 快速傅里叶变换(FFT)
FFT(Fast Fourier Transform)是计算DFT的一种高效算法,它将DFT的计算复杂度从 $O(N^2)$ 降低到 $O(N \log N)$。
MATLAB中的FFT函数:
% 如果 x 是包含 x[n] 的向量,0 ≤ n ≤ M-1
X = fft(x, N); % 计算N点DFT
% 计算x的DTFT的N个均匀间隔的样本,并存储在向量X中
重要说明:
- 零填充:如果 $N > M$(序列长度),fft 会自动在序列末尾补零
- 截断:如果 $N < M$,fft 会截取前 $N$ 个元素进行计算
- 频率范围:fft 函数计算区间 $[0, 2\pi)$ 中的DFT。要在区间 $[-\pi, \pi]$ 中计算,可以使用
fftshift函数进行移位 - 逆变换:
ifft函数可用于高效地计算IDFT
对于 $N=1024$ 点的DFT,直接计算需要约100万次复数乘法,而FFT只需要约1万次,计算效率提高约100倍!这使得实时信号处理成为可能。
4. 卷积定理
卷积定理是连接时域和频域的重要桥梁,在信号处理中有广泛应用。
时域卷积 ⟷ 频域相乘:
$$y[n] = x[n] * h[n] \quad \Longleftrightarrow \quad Y[k] = X[k] \cdot H[k]$$
其中 $*$ 表示卷积,$\cdot$ 表示点乘
线性卷积 vs 循环卷积:
| 特性 | 线性卷积 | 循环卷积 |
|---|---|---|
| 定义 | 两个有限长序列的卷积 | DFT域的点乘对应的时域操作 |
| 结果长度 | $L_1 + L_2 - 1$ | $\max(L_1, L_2)$ |
| MATLAB函数 | conv(x, h) | ifft(fft(x) .* fft(h)) |
| 关系 | 补零到 $L_1 + L_2 - 1$ 后,循环卷积等于线性卷积 | |
直接使用FFT计算的是循环卷积,而非线性卷积。要使循环卷积等于线性卷积,必须对两个序列都补零至少到长度 $L_1 + L_2 - 1$。
实践交互式信号频谱分析
实时信号生成器与频谱分析器
调整参数观察时域信号与其频谱的关系
- 正弦/余弦波的频谱是单一频率分量(冲激)
- 方波包含基频和奇次谐波分量
- 增加DFT点数 $N$ 可以提高频率分辨率,使频谱更平滑
- 注意观察频谱的对称性(实信号的频谱共轭对称)
实践示例讲解
例题:单位脉冲信号的频谱分析
问题:有信号 $x[n] = \delta[n]$(单位脉冲信号),回答以下问题。
问题 1:手动计算 $x[n]$ 所对应的DTFT
解:
根据DTFT定义:
$$X(e^{j\omega}) = \sum_{n=-\infty}^{\infty} x[n]e^{-j\omega n}$$
对于单位脉冲 $\delta[n]$:
$$X(e^{j\omega}) = \sum_{n=-\infty}^{\infty} \delta[n]e^{-j\omega n} = e^{-j\omega \cdot 0} = 1$$
结论:单位脉冲信号的DTFT恒等于1(幅度为1,相位为0),这意味着它包含所有频率成分,且各频率分量幅度相等。
问题 2:使用fft计算出8点DFT结果并画图显示
N = 8; % 假设计算8点DFT
n = 0:(N-1); % 时间索引:0到7
x = [1, zeros(1, 7)]; % 单位脉冲信号 δ[n]
k = 0:(N-1); % 频率索引:0到7
% 计算8点DFT
Xdft_8 = fft(x, N);
% 计算幅度谱和相位谱
mag_Xdft_8 = abs(Xdft_8); % 幅度谱
phase_Xdft_8 = angle(Xdft_8); % 相位谱(弧度)
% 绘制结果
figure;
subplot(2, 1, 1);
stem(k, mag_Xdft_8), grid on;
title('8点DFT幅度谱');
xlabel('频率索引 k'), ylabel('|X[k]|');
xlim([-0.2, 8.2]);
subplot(2, 1, 2);
stem(k, phase_Xdft_8), grid on;
title('8点DFT相位谱');
xlabel('频率索引 k'), ylabel('∠X[k] (弧度)');
xlim([-0.2, 8.2]);
结果分析:
- 幅度谱在所有频率点处均为1,验证了理论结果 $|X(e^{j\omega})| = 1$
- 相位谱为0,因为 $X(e^{j\omega}) = 1$ 是实数
- 这说明单位脉冲信号包含所有频率成分,且各频率分量幅度相等
问题 3:通过零填充提高频率分辨率
选择 $N = 100, 500, 1000$ 进行尝试,观察DFT是否接近DTFT。
% 原始信号
x = [1, zeros(1, 7)];
% 不同的DFT点数
N_values = [8, 100, 500, 1000];
figure;
for i = 1:length(N_values)
N = N_values(i);
k = 0:(N-1);
Xdft = fft(x, N);
mag_Xdft = abs(Xdft);
subplot(2, 2, i);
if N <= 100
stem(k, mag_Xdft), grid on;
else
plot(k, mag_Xdft), grid on; % N较大时用plot避免点重叠
end
title(sprintf('%d点DFT幅度谱', N));
xlabel('k'), ylabel('|X[k]|');
end
- $N=8$ 时:只有8个离散频率点,频谱较粗糙
- $N=100$ 时:频率点增加,频谱变得更平滑
- $N=500, 1000$ 时:频谱非常平滑,逼近连续的DTFT
- 所有情况下幅度均为1,验证了理论结果
结论:增加DFT点数(通过零填充)可以提高频率分辨率,使DFT更好地逼近DTFT。但要注意,这并不增加新的信息,只是对DTFT进行更密集的采样。
数字频率 $\omega$ 与 DFT索引 $k$ 的关系:
$$\omega_k = \frac{2\pi k}{N} \quad \text{(归一化角频率,弧度)}$$
或者用Hz表示(假设采样频率为 $F_s$):
$$f_k = \frac{kF_s}{N} \quad \text{(实际频率,Hz)}$$
因此,DFT的第 $k$ 个点对应的归一化频率为 $2\pi k/N$ 弧度。
实践练习一:指数序列的频谱分析
题目
设有离散时间序列 $x[n] = 0.7^n$,$0 \leq n \leq 7$
1 求出 $x[n]$ 所对应DTFT的解析式。
提示:利用几何级数求和公式 $\sum_{n=0}^{N-1} r^n = \frac{1-r^N}{1-r}$
2 根据例题计算出8点DFT($0 \leq k \leq 7$)并画出幅度相位谱。
3 根据例题计算出16点DFT($0 \leq k \leq 15$)并画出幅度相位谱。
4 根据例题计算出128点DFT($0 \leq k \leq 127$)并画出幅度相位谱。
注意:数据较多时使用 plot 函数代替 stem 函数。
5 观察第4题和第1题的结果,数字频率 $\omega$ 和DFT中 $k$ 的关系是什么?
实践练习二:卷积定理的验证
题目
设有两序列 $x[n] = [1, 1, 1, 1]$,$y[n] = [1, 1, 1, 1]$
1 对 $x$ 和 $y$ 做线性卷积(使用 conv 函数),把卷积结果用 stem 函数画出来。
2 手动计算 $x$ 和 $y$ 之间的圆周卷积结果。
提示:圆周卷积定义为 $z[n] = \sum_{m=0}^{N-1} x[m]y[(n-m) \bmod N]$,$n = 0, 1, 2, 3$
3 分别计算 $x$ 和 $y$ 的DFT,结果保存在 Xk 和 Yk 中。对结果做点乘,也就是计算 $Zk = Xk .* Yk$。对 Zk 求逆离散傅里叶变换(使用 ifft 函数)。如果你得到复数结果,使用 real 函数提取实数部分。确认你的结果与第2题获得的结果一致。使用 stem 函数绘制结果,观察结果中有多少个样本数和第1题中的结果一致?
4 对 $x$ 和 $y$ 尾部填零。首先对 $x$ 和 $y$ 分别添加一个零,重复第2题和第3题。有多少个样本和第1题的结果是一致的?需要补充多少零才能使结果和第1题中的完全一致,画图验证。
5 有两个新的序列 $u[n] = [-3, 5, 8, 6, 2, 2]$,$v[n] = [1, 1, 4, 2]$,重复以上问题并回答:对 $u$ 和 $v$ 各补充多少零可使得 $u$ 和 $v$ 之间的线性卷积结果等于循环卷积结果?
实践练习三:实际信号的频谱分析
题目
运行以下代码将 'tones.mat' 文件中的信号数据读取到MATLAB中,这个信号里面包含了多个不同频率的声音。
s = load('tones.mat');
x = s.y1;
变量 $x$ 现在就是声音信号。
1 计算 $x$ 所对应的DFT,假设 $N=25$。用 stem 函数画出幅度谱,你观察到了多少个主要频率分量?
2 对 $x$ 补零(调整 $N$ 值)并重新计算DFT的结果,你是否观察到了更多的频率分量?它们具体的频率是多少?尝试画出 $x$ 的图像,思考理解为什么要将时间信号变换到频域进行分析。
实践练习四:编写自定义DFT函数
题目
写一个自定义函数 X = MyDFT(x, N) 用以计算序列 $x$ 所对应的DFT。
函数要求:
- $N$ 的长度可能和序列真实长度 $M$ 不同
- 如果 $N > M$,则函数应该在 $x$ 的末尾补充零
- 如果 $N < M$,则应截取前 $N$ 段进行计算
- 写完后可以和MATLAB自带 fft() 函数进行比较
- 可以用 randn 函数创建随机测试向量
DFT定义:
$$X[k] = \sum_{n=0}^{N-1} x[n]e^{-j\frac{2\pi kn}{N}}, \quad k = 0, 1, \ldots, N-1$$
任务 编写 MyDFT 函数,并用多个测试用例验证其正确性(与 fft 函数比较)。比较两者的计算时间,分析效率差异。
实验总结
核心知识点
| 概念 | 关键要点 | 应用 |
|---|---|---|
| DTFT | 连续频率,周期 $2\pi$,理论分析工具 | 理解信号频率特性 |
| DFT | 离散频率,DTFT的采样版本 | 计算机数值计算 |
| FFT | 快速计算DFT,$O(N \log N)$ 复杂度 | 实时信号处理 |
| 零填充 | 提高频率分辨率,不增加新信息 | 精细频谱分析 |
| 卷积定理 | 时域卷积 ⟷ 频域相乘 | 快速卷积计算 |
常见问题
Q1: 为什么需要FFT,DFT不够用吗?
A: DFT和FFT计算结果相同,但FFT效率高得多。对于 $N=1024$,FFT比DFT快约100倍。在实时处理中,FFT是必需的。
Q2: 零填充会增加新的信息吗?
A: 不会。零填充只是对DTFT进行更密集的采样,使频谱看起来更平滑,但不会创造新信息。
Q3: 如何选择合适的DFT点数 $N$?
A: 一般原则:$N$ 应 $\geq$ 信号长度 $M$;若要提高频率分辨率,可增大 $N$;FFT在 $N$ 为2的幂次时最快。