1. 先从结论清单说起:离散傅里叶变换到底有哪些“常用结论”
做信号处理的人,不管你是搞音频算法、通信基带,还是做故障诊断,早晚都要跟离散时间傅里叶变换(DTFT)打交道。我以前上课的时候,老师把一堆性质往黑板上一写,线性、时移、频移、卷积、帕塞瓦尔,当时记是记住了,但说实话,没几个是真证过的。等到后来自己做项目,发现很多结论用起来不对味,回头重新翻书,才意识到“会用”和“真懂”之间的差距有多大。
这篇文章我不想堆公式,而是挑离散系统傅里叶变换里最常用的几组结论,把证明过程掰开揉碎了讲清楚。重点放在:为什么这些结论长这样、证明的关键步骤卡在哪里、以及实际做题和写代码时怎么用它们不出错。适合正在学信号与系统的学生、考研复习党,以及工作中需要补一补理论基础的工程师。
先列一个清单,这就是我们这篇文章要逐个攻克的常用结论:
- DTFT的定义与存在条件,以及它和离散时间周期信号的关系
- 线性性质、时移性质、频移性质的证明
- 卷积定理(时域卷积对应频域相乘)
- 相乘性质(时域相乘对应频域卷积,带周期性修正)
- 帕塞瓦尔定理(能量守恒)
- 对称性结论(实信号的幅度谱偶对称、相位谱奇对称)
- 三角脉冲的傅里叶变换,以及一个好用的记忆方法
- 相位问题:为什么很多教科书上的结论“丢了相位”,实际计算时怎么找回来
这些结论在教科书里往往是零散给出的,每一条单独看都不难,但串起来用的时候,很容易在细节上翻车。我后面会按照“先定义、再性质、后应用”的顺序来展开,每一步都给出完整的推导,并标注出那些容易被忽略的前提条件。
有人可能会问:现在都用FFT算了,Matlab一个fft()下去什么都出来了,还学这些手推的东西干什么?我的回答是:FFT算出来的是一个有限长序列的离散傅里叶变换(DFT),而不是DTFT的完整频谱。你用FFT看到的谱线、泄漏、栅栏效应,这些现象全部源于DTFT和DFT之间的关系。不懂DTFT,你就永远搞不明白为什么加窗、为什么补零、为什么频谱会“糊”成一团。所以说,这些“纸面功夫”恰恰是工程直觉的地基。
2. 从定义出发:DTFT的表达式与存在条件
DTFT的定义式是这样的:
[ X(e^{j\omega}) = \sum_{n=-\infty}^{+\infty} x[n] e^{-j\omega n} ]
其中 (x[n]) 是离散时间序列,(\omega) 是归一化数字角频率,单位是弧度/样本。注意,这里(\omega)是一个连续变量,所以即便(x[n])是离散的,它的频谱(X(e^{j\omega}))也是连续函数,而且一定是周期的,周期是(2\pi)。
为什么是周期函数?很简单:
[ X(e^{j(\omega+2\pi)}) = \sum_{n=-\infty}^{+\infty} x[n] e^{-j(\omega+2\pi)n} = \sum_{n=-\infty}^{+\infty} x[n] e^{-j\omega n} e^{-j2\pi n} ]
因为(e^{-j2\pi n}=1)对所有整数(n)成立,所以(X(e^{j(\omega+2\pi)})=X(e^{j\omega}))。这就是DTFT周期性的来源。
这个周期性的结论看起来不起眼,但它解释了一个初学者很容易困惑的问题:为什么数字频率只有(0\sim 2\pi)(或者(-\pi\sim\pi)),而模拟频率可以一直往上加?因为数字频率本身就是“归一化”过的,它跟模拟频率的换算是(\omega = \Omega T_s),(T_s)是采样周期。一旦采样,高于奈奎斯特频率的成分就会折叠回来,这在频谱上就表现为周期性延拓。
2.1 存在条件:绝对可和与能量有限
DTFT不是对所有序列都有定义的。最常用的存在条件是绝对可和:
[ \sum_{n=-\infty}^{+\infty} |x[n]| < +\infty ]
这个条件保证了级数逐点收敛,(X(e^{j\omega}))是连续的。如果只是能量有限,也就是:
[ \sum_{n=-\infty}^{+\infty} |x[n]|^2 < +\infty ]
那DTFT是均方意义下收敛的,频谱可能存在间断点。
这两种收敛的差别很微妙,但工程上经常用到。比如单位阶跃序列(u[n]),它既不绝对可和,也不能量有限,严格来说DTFT不存在。但我们在实际信号处理里经常要给阶跃、符号等信号“强行”写一个频谱表达式,这时候就要引入冲激函数。教科书上对这类信号的处理方式是用极限定义,或者通过指数衰减序列取极限来逼近。
我个人的经验是:做题的时候,先看一眼序列长什么样,如果它是指数衰减型的,那放心大胆地用定义算;如果是常数、阶跃、周期序列这类,就得小心,结果里往往藏着一个冲激项(或者说若干个冲激串)。
2.2 逆变换:从频谱回到序列
DTFT的逆变换(IDTFT)定义是:
[ x[n] = \frac{1}{2\pi} \int_{-\pi}^{\pi} X(e^{j\omega}) e^{j\omega n} d\omega ]
这个式子从直观上理解非常漂亮:它告诉我们,任意一个离散序列都可以分解成无数个频率为(\omega)、幅度为(X(e^{j\omega}))的复指数信号的叠加。积分区间只在(-\pi\sim\pi)里面取,因为超出这个范围的频率跟区间内的某个频率是“一回事”。
证明IDTFT可以这样走:把DTFT的定义式代入IDTFT:
[ \frac{1}{2\pi} \int_{-\pi}^{\pi} \left[\sum_{m=-\infty}^{+\infty} x[m] e^{-j\omega m}\right] e^{j\omega n} d\omega ]
交换积分和求和的次序(在绝对可和条件下合法):
[ \sum_{m=-\infty}^{+\infty} x[m] \cdot \frac{1}{2\pi} \int_{-\pi}^{\pi} e^{j\omega(n-m)} d\omega ]
积分那一项是可以直接算出来的:
[ \frac{1}{2\pi} \int_{-\pi}^{\pi} e^{j\omega(n-m)} d\omega = \frac{\sin[\pi(n-m)]}{\pi(n-m)} ]
当(n=m)的时候,这个值等于1;当(n\neq m)的时候,因为(\sin[\pi(n-m)]=0),所以等于0。换句话说,这个积分就是离散域的单位冲激(\delta[n-m])。代回去,就得到:
[ \sum_{m} x[m] \delta[n-m] = x[n] ]
整个证明到这里就闭合了,逻辑链完整且干净。
写代码的时候,我们很少直接做IDTFT积分,都是用IDFT(逆离散傅里叶变换)来近似。但理解IDTFT的意义对做滤波器设计很有帮助:FIR滤波器设计里的窗函数法,本质上就是“先算理想滤波器的无限长冲激响应,再用窗函数截断近似为有限长”,中间那一步用的就是IDTFT的积分。
3. 五大基本性质的证明与工程含义
这一节进入正题,把最常用的几个性质逐一证明。它们不是孤立的知识点,而是后面推导卷积定理、帕塞瓦尔公式的工具。
3.1 线性性质:最基础也是最能出错的地方
如果(x[n]\leftrightarrow X(e^{j\omega})),(y[n]\leftrightarrow Y(e^{j\omega})),那么:
[ a x[n] + b y[n] \leftrightarrow a X(e^{j\omega}) + b Y(e^{j\omega}) ]
证明只用一步,把线性组合代入定义,然后利用求和可拆分的性质即可。
线性性质看起来简单到不值一提,但实际用的时候有两个坑值得注意。
第一个坑是ROC(收敛域)问题。虽然DTFT不像z变换那样有一块明显的收敛域,但“绝对可和”这个条件本质上是依赖序列的衰减速度快慢的。两个各自都绝对可和的序列做线性组合之后,仍然绝对可和,这个没问题。但如果一个序列不绝对可和,是靠冲激项扩展定义的(比如常数序列),两个这样的序列相减,可能抵消掉冲激项,也可能产生新的冲激项,处理起来非常容易错。
第二个坑跟“叠加”有关。我们做系统分析时,经常说“线性系统满足叠加定理”,所以对输入信号分解后用频谱逐个处理再合起来。这个思路本身没错,但只适用于线性时不变系统。如果系统里带非线性环节,比如平方律检波、比较器,就不能用DTFT直接做线性拆分了。这类问题我建议改用频域卷积的思路来处理,或者直接在时域做数值仿真。
3.2 时移性质:为什么是乘上(e^{-j\omega n_0})而非其他形式
若(y[n] = x[n-n_0]),则:
[ Y(e^{j\omega)} = e^{-j\omega n_0} X(e^{j\omega}) ]
证明代入定义:
[ Y(e^{j\omega}) = \sum_{n=-\infty}^{+\infty} x[n-n_0] e^{-j\omega n} ]
令(m=n-n_0),则(n=m+n_0),代入得:
[ Y(e^{j\omega}) = \sum_{m=-\infty}^{+\infty} x[m] e^{-j\omega(m+n_0)} = e^{-j\omega n_0} \sum_{m=-\infty}^{+\infty} x[m] e^{-j\omega m} = e^{-j\omega n_0} X(e^{j\omega}) ]
这里只有一个细节需要注意:新的求和变量(m)的取值范围仍然是整个整数集,因为(n-n_0)遍历所有整数,所以不需要修改求和上下限。很多初学者在这个地方会犹豫“要不要改求和范围”,答案是“不用”。
工程上,时移性质最常见的用途有两个。一个是分析滤波器相频响应:一个长度有限、系数对称的FIR滤波器,其相位响应对应一个固定时延((N-1)/2),这个时延就是从时移性质来的。另一个是分析波束形成里的相控阵:每个阵元接收的信号由于到达时间不同,在频域上就是乘了一个与角度相关的相位因子,波束扫描的核心公式就是从时移性质里推出来的。
3.3 频移性质:理解调制与变频的钥匙
若(y[n] = e^{j\omega_0 n} x[n]),则:
[ Y(e^{j\omega}) = X(e^{j(\omega-\omega_0)}) ]
证明直接代入定义:
[ Y(e^{j\omega}) = \sum_{n} x[n] e^{j\omega_0 n} e^{-j\omega n} = \sum_{n} x[n] e^{-j(\omega-\omega_0) n} = X(e^{j(\omega-\omega_0)}) ]
这个性质在通信里的地位极高。数字调制、频谱搬移、正交混频,全部都是在用频移性质。
但这里必须提醒一个工程上经常犯的错误:频谱搬移不是“免费”的。离散系统的频谱是(2\pi)周期的,搬移后原来的频谱一片一片地平移,一旦搬移量太大,就会发生混叠。很多人在做数字上变频的时候,直接把基带信号乘一个高频载波序列,结果频谱混叠得一塌糊涂,就是因为忽视了频移后的周期性重叠问题。
具体来说,假设基带信号的频谱集中在(-\pi/2 \sim \pi/2),现在要搬到(\omega_0 = 2\pi \times 0.3)的位置上去,那么搬移后频谱的中心在(2\pi \times 0.3)处,向两边延伸,在周期延拓的时候就会跟相邻周期重叠。解决办法一般是在搬移前先做插值提高采样率,这个操作的数学本质就是给频谱在周期内留出足够的安全间隔,避免搬移后的频谱混到一起。
3.4 卷积定理:时域卷积对应频域相乘
若(y[n] = x[n] * h[n]),则:
[ Y(e^{j\omega}) = X(e^{j\omega}) H(e^{j\omega}) ]
证明过程是:
[ Y(e^{j\omega}) = \sum_{n} \left[\sum_{k} x[k] h[n-k]\right] e^{-j\omega n} ]
交换求和顺序(绝对可和条件下合法):
[ Y(e^{j\omega}) = \sum_{k} x[k] \sum_{n} h[n-k] e^{-j\omega n} ]
对内层和式用时移性质,得到:
[ \sum_{n} h[n-k] e^{-j\omega n} = e^{-j\omega k} H(e^{j\omega}) ]
代回去:
[ Y(e^{j\omega}) = \sum_{k} x[k] e^{-j\omega k} H(e^{j\omega}) = X(e^{j\omega}) H(e^{j\omega}) ]
整个证明最核心的“机关”就是内层求和用时移性质换成了(e^{-j\omega k}H(e^{j\omega})),剩下的就是把常数因子(H(e^{j\omega}))从求和里提出来。
卷积定理是整个线性系统频域分析法的基石。滤波器设计、信道建模、系统辨识,全部建立在这个结论上。工程上,线性卷积可以用FFT加分段重叠相加法来快速实现,其理论依据正是卷积定理:先在频域相乘,再逆变换回时域。
3.5 相乘性质(频域卷积定理):非线性的入口
若(y[n] = x_1[n] x_2[n]),则有:
[ Y(e^{j\omega}) = \frac{1}{2\pi} \int_{-\pi}^{\pi} X_1(e^{j\theta}) X_2(e^{j(\omega-\theta)}) d\theta ]
这个性质的证明比卷积定理稍微麻烦一点,因为它需要利用IDTFT把(x_1[n])表示成频谱积分,再代入(y[n])的定义中,最后交换积分求和次序。
[ Y(e^{j\omega}) = \sum_{n} x_1[n] x_2[n] e^{-j\omega n} ]
把(x_1[n] = \frac{1}{2\pi}\int_{-\pi}^{\pi} X_1(e^{j\theta}) e^{j\theta n} d\theta)代进去:
[ Y(e^{j\omega}) = \sum_{n} \left[\frac{1}{2\pi}\int_{-\pi}^{\pi} X_1(e^{j\theta}) e^{j\theta n} d\theta\right] x_2[n] e^{-j\omega n} ]
交换积分与求和:
[ Y(e^{j\omega}) = \frac{1}{2\pi}\int_{-\pi}^{\pi} X_1(e^{j\theta}) \left[\sum_{n} x_2[n] e^{-j(\omega-\theta)n}\right] d\theta ]
中括号里正好是(X_2(e^{j(\omega-\theta)})),因此结论成立。
相乘性质在工程上意味着:时域相乘(调制、加窗、信号相乘)会在频域上产生频谱卷积,直观表现就是频谱被“抹平”或者“搬移”。这就是为什么乘一个窗函数后,频谱会出现主瓣变宽、旁瓣泄漏。很多人做频谱分析时看到泄漏就头疼,其实根源就在这个定理:你把一段无限长信号乘上矩形窗,等效于在频域把原信号的频谱与(\mathrm{sinc})函数的频谱做卷积,每个频点都被(\mathrm{sinc})的旁瓣“污染”了。理解了这一点,你对窗函数的选择就会变得有方向感,而不是盲目试几个窗就完事。
4. 帕塞瓦尔定理与能量谱的关系
帕塞瓦尔定理也是“常用结论”里的高频考点。它的表述是:
[ \sum_{n=-\infty}^{+\infty} |x[n]|^2 = \frac{1}{2\pi} \int_{-\pi}^{\pi} |X(e^{j\omega})|^2 d\omega ]
翻译成人话就是:时域算出来的总能量等于频域算出来的总能量。这里的(|X(e^{j\omega})|^2)称为能量谱密度,单位频率上的能量分布。
4.1 证明过程
从时域能量出发:
[ \sum_{n} |x[n]|^2 = \sum_{n} x[n] x^*[n] ]
其中(x^[n])是共轭。利用IDTFT写出(x[n])的表达式,同时利用共轭性质得到(x^[n])的频域表示。具体写法是:
[ x[n] = \frac{1}{2\pi}\int_{-\pi}^{\pi} X(e^{j\omega}) e^{j\omega n} d\omega ]
[ x^[n] = \frac{1}{2\pi}\int_{-\pi}^{\pi} X^(e^{j\omega}) e^{-j\omega n} d\omega ]
代回能量式:
[ \sum_{n} |x[n]|^2 = \sum_{n} \frac{1}{2\pi}\int X(e^{j\omega}) e^{j\omega n} d\omega \cdot \frac{1}{2\pi}\int X^*(e^{j\theta}) e^{-j\theta n} d\theta ]
交换积分和求和顺序后,对(n)的求和等于(2\pi\delta(\omega-\theta)),可以消掉一个积分,最后就得到:
[ \sum_{n} |x[n]|^2 = \frac{1}{2\pi} \int_{-\pi}^{\pi} X(e^{j\omega}) X^*(e^{j\omega}) d\omega = \frac{1}{2\pi} \int_{-\pi}^{\pi} |X(e^{j\omega})|^2 d\omega ]
证明本身不复杂,关键是注意共轭的处理:频域共轭对应时域取共轭后的时间反转,不要把它跟一般复数运算搞混。
4.2 帕塞瓦尔定理的使用心得
做工程的时候,我用这个定理做过两件比较实在的事。第一件是验证FFT算法的正确性:算完FFT后,把频域各个点的幅度平方加起来,跟时域序列的平方和做一个比较,误差应该非常小。如果这个校验不过,那基本可以确定是FFT实现有bug,或者有数据越界的问题。第二件是估计信噪比:把信号能量的实测值跟理论频谱积分的值比对,可以反过来推测噪声能量占了多少,评估系统底噪是否异常。
另外,有一个常见认知误区我必须提一下:帕塞瓦尔定理说的是总能量守恒,但不代表每个频点的能量都不变。经过一个非理想滤波器后,通带内频点能量下降,通带外的能量被滤除,总能量自然减小,这是正常的。不要拿帕塞瓦尔定理去验证“信号通过滤波器后每个频点幅度是否还等于原幅度”,那是两回事。
5. 对称性结论与相位问题的陷阱
5.1 实信号的幅度谱偶对称、相位谱奇对称
对于实序列(x[n]),它的DTFT满足:
[ X(e^{j\omega}) = X^*(e^{-j\omega}) ]
把这个式子拆成实部和虚部来看。设(X(e^{j\omega})=A(\omega)+jB(\omega)),那么(X^*(e^{-j\omega})=A(-\omega)-jB(-\omega))。两边对照可以得到:
[ A(\omega)=A(-\omega) ] [ B(\omega)=-B(-\omega) ]
也就是说,实部是偶函数,虚部是奇函数。进一步可以推出:
- 幅度谱(|X(e^{j\omega})|)是偶函数
- 相位谱(\angle X(e^{j\omega}))是奇函数
这个结论在画频谱图时非常方便:你只需要画出(0\sim\pi)范围内的幅度谱和相位谱,另一半自然对称或反对称地补全。
证明的关键在于:实序列的共轭和原序列相等(因为实数的共轭就是它自己),求DTFT后得到(X(e^{j\omega})=X^*(e^{-j\omega}))。
5.2 相位谱“失常”的常见原因
实际使用MATLAB的angle()函数画相位谱时,你会发现相位曲线不是平滑的直线,而是锯齿状跳变,反复在(\pi)和(-\pi)之间跌宕。很多人以为这是“bug”,其实这是因为相位被折叠到主值区间((-\pi,\pi])内了。
举例来说,一个纯延迟系统(H(e^{j\omega})=e^{-j\omega n_0})的相位是(-\omega n_0)。当(n_0)比较大时,这个相位在(-\pi\sim\pi)范围内来回绕圈,画出来就是锯齿。要还原真实的线性相位,你需要用相位解缠绕(unwrap)算法,MATLAB里有unwrap()函数。
更隐蔽的一个坑是:数字滤波器在阻带内的相位响应几乎无意义。因为阻带内幅度接近0,相位是由数值噪声主导的,angle()算出来的值在(-\pi)和(\pi)之间随机跳变。看到这种相位图千万别慌,它不是系统坏了,而是数值精度问题。正确的做法是只在通带内讨论相位响应,或者使用幅度加权相位来评估。
5.3 对称性结论在滤波器设计中的活用
实系数FIR滤波器的频率响应满足上述对称性。设计带通滤波器时,用频率取样法构造目标响应,只需要在正频率部分定义幅度值,负频率部分自动镜像生成。这个操作在代码里就是频域数组拼接:先构造正频率部分,再翻转共轭出负频率部分。
我见过不少新手在写频率取样法时,忘了构造负频率部分,直接把目标频谱丢给ifft(),结果出来的时域序列是复数的,滤波器系数根本不是实的。后来我习惯在ifft之后加一行断言:检查实部共轭对称性是否满足,若不过就立刻报错。这样能尽早发现问题,不用等仿真结果乱套了才回头查。
6. 三角脉冲的傅里叶变换:一个背起来很爽的记忆方法
三角脉冲的傅里叶变换是考点里的常客,很多同学觉得它难背,因为它要么算出一个(\mathrm{sinc}^2)形式的表达式,要么算出一个带平方倒数的表达式,前前后后推导挺麻烦的。这里分享一个我用了很多年的记忆方法,简洁实用。
6.1 核心思路:两次差分,把三角脉冲变成三个冲激
设离散时间三角脉冲定义为高度递减的序列,比如:
[ x[n] = \begin{cases} 1 - \frac{|n|}{N}, & |n| \leq N \ 0, & \text{otherwise} \end{cases} ]
这个序列的样子就是一个以(n=0)为顶点的等腰三角形。
在离散域里,三角脉冲和矩形脉冲之间有天然的“二阶差分”关系:对三角脉冲做二阶差分,会在顶点和两个端点处冒出一正一负的冲激对。
具体来说,记(r[n])为长度为(2N+1)的三角脉冲。将它做一阶差分(r[n]-r[n-1]),会得到一个阶梯形序列,再做一次差分,最终得到的是三个冲激:
[ r[n]-2r[n-1]+r[n-2] = \delta[n+N] - 2\delta[n] + \delta[n-N] ]
注意我这里写的是“广义”差分形式,用移位和冲激来表示。
根据DTFT的线性性质和时移性质,对上式两边取DTFT。右边直接可以写出来:
[ e^{j\omega N} - 2 + e^{-j\omega N} = 2\cos(\omega N) - 2 = -4\sin^2\left(\frac{\omega N}{2}\right) ]
左边呢,差分运算对应于频域乘以((1-e^{-j\omega})^2),所以:
[ (1-e^{-j\omega})^2 X(e^{j\omega}) = -4\sin^2\left(\frac{\omega N}{2}\right) ]
因此:
[ X(e^{j\omega}) = \frac{-4\sin^2\left(\frac{\omega N}{2}\right)}{(1-e^{-j\omega})^2} ]
再化简一下。注意(1-e^{-j\omega} = e^{-j\omega/2}\cdot 2j\sin(\omega/2)),所以:
[ (1-e^{-j\omega})^2 = -4 e^{-j\omega} \sin^2(\omega/2) ]
代进去,负号消掉:
[ X(e^{j\omega}) = \frac{\sin^2\left(\frac{\omega N}{2}\right)}{e^{-j\omega}\sin^2(\omega/2)} = e^{j\omega} \left[\frac{\sin(\omega N/2)}{\sin(\omega/2)}\right]^2 ]
这里多出来的(e^{j\omega})因子是差分操作的边界效应带来的,它不改变幅度谱的形状,只影响相位。很多教材会忽略这个线性相位因子,说三角脉冲的频谱是(\sin^2(\omega N/2)/\sin^2(\omega/2)),大家也习惯了。
6.2 记忆锚点
把推导过程浓缩成三个关键词:
- 第一次出现“分子的平方”:因为三角脉冲是矩形脉冲卷积自己得到的,卷积定理要求频域相乘,而矩形脉冲的DTFT是一个Dirichlet核,所以三角脉冲的频谱是它的平方。
- 第二次出现“分母的sin”:分母的(\sin(\omega/2))来源于离散域差分的频域对应,它专门负责把“离散”的味道带出来。
- 连续域的类比:连续域的三角脉冲傅里叶变换是(\mathrm{sinc}^2),离散域只是把(\mathrm{sinc})换成Dirichlet核(采样形式),本质是一样的。
要用一句话记住的话:矩形卷积矩形等于三角,所以频谱是一个(\sin)除以另一个(\sin)的平方。这个方法我用了好几年,做题时几乎不用翻书,直接在脑子里搭出频谱的结构。
6.3 配套的“相位”记忆
有人可能会问:“为什么有的书上写三角脉冲频谱是正的,有的书带一个相位因子?”这取决于差分运算的起点。用中心差分定义的时候推导会自然带出一个(e^{j\omega}),用对称定义直接算积分则会避开。实际上,对于对称的实信号,幅度谱才是我们更关心的,相位谱通常在信号完全对称时是线性的,且斜率和时间中心的位置相关。
做题的时候我的习惯是这样的:先判断三角脉冲的对称轴在哪里,对称轴在(n=0)处,则频谱是实偶函数,没有多余相位项;如果对称轴在某个非零位置,需要乘一个对应的时移相位因子。这个习惯避免了大量的符号错误。
7. 对称对称再对称:共轭对称在离散频谱中的角色
我一直觉得离散傅里叶变换的性质里,最容易被低估的就是共轭对称性。它不仅是理论上的美丽结论,更是工程实践的“高效工具”。
7.1 通用共轭对称结论
对于任意复序列(x[n]),可以拆成共轭对称分量和共轭反对称分量。话说回来,DTFT也有类似的分解,但工程上更常用的是那么一句话:如果时域序列是实序列,频域一定满足共轭对称。这个结论我已经在前面证明过了。
进一步地,如果时域序列是实偶序列,即(x[n]=x[-n]),那么它的DTFT也是实偶函数:
[ X(e^{j\omega}) = \sum_{n} x[n] \cos(\omega n) - j\sum_{n} x[n] \sin(\omega n) ]
因为(x[n])偶对称,(\sin(\omega n))奇对称(关于(n)),乘积的奇函数项求和为0,虚部消失,剩下的是偶函数形式的实部:
[ X(e^{j\omega}) = \sum_{n} x[n]\cos(\omega n) = x[0] + 2\sum_{n=1}^{\infty} x[n]\cos(\omega n) ]
如果时域序列是实奇序列,(x[n]=-x[-n]),则它的DTFT是纯虚奇函数。这两条结论在分析窗函数、滤波器冲激响应时使用频率极高。
7.2 工程上的“半频谱”技巧
实信号的频谱共轭对称,意味着负频率部分的信息是完全冗余的。在做FFT后处理时,我们通常只取前一半((0\sim N/2))的频谱数据来分析,后一半是需要丢弃或者用共轭对称性来校验的。这不仅省存储,也省计算。
有一次我在调试一个振动信号分析程序时,发现时域数据明明是实数,但FFT出来的虚部不为零,而且幅度谱也不对称。排查了半天,最后发现问题出在数据采集模块:某一路AD通道的零点漂移导致信号叠加了一个缓变趋势项。这个趋势项本质上不是一个纯实数序列,在做FFT时破坏了共轭对称性。后来我在预处理阶段加了一阶差分去趋势,再配合平滑滤波,频谱立刻变得规整了。可见“共轭对称”还可以当异常检测的判据用。
7.3 与希尔伯特变换的关联
共轭对称性的一个延伸是解析信号。一个实信号(x[n])的解析信号(z[n]=x[n]+j\hat{x}[n]),其频谱只保留正频率部分,正频率幅度加倍,负频率部分为零。这个操作的极点是利用了频谱的共轭对称:因为原实信号的负频率部分可以通过正频率共轭推出来,所以丢掉负频率不会损失信息,反而能去除镜像频率,方便后续的包络提取和瞬时频率计算。
在工程中,我经常用Matlab的hilbert()函数提取窄带信号的包络。这个函数的内部原理就是把FFT后的负半边谱置零,再做IFFT。理解了共轭对称,你就明白为什么它能用“砍一半频谱”的方式得到包络了。
8. 傅里叶变换与相位:一组容易“翻车”的操作细节
把“傅里叶变换+相位”作为关键词提出来,说明相位问题是大家实际使用中的高频痛点。我这里集中讲几个最常踩的坑,以及对应的处理办法。
8.1 零点附近的相位跳动
计算一个实偶信号的相位谱时,理论上相位应该恒为0,但实际用angle()算出来,在频谱过零点附近会出现剧烈的相位跳变。原因很简单:当(|X(e^{j\omega})|)接近0时,实部和虚部的小数值噪声主导了整个比值,arctan的结果就变成了噪声。这种情况在频谱零点处尤其明显。
处理办法有三个:一是画相位谱时把幅度小于某个阈值(比如最大幅度的千分之一)的频点置为不显示或者置为0;二是使用相位解缠绕并配合幅度加权;三是用群延迟来替代相位做系统分析,群延迟的定义是相位对频率的负导数,它对幅度极小值点的敏感度低一些。
8.2 开方运算带来的相位二义性
傅里叶变换在某些应用里需要做“频谱开方”,比如设计匹配滤波器、计算倒谱。问题在于,复数开方在数学上是有二义性的,结果可以选择两个相差(\pi)的相位。不加处理的话,IFFT会得到错误的时域信号。
我在做最小相位滤波器恢复时遇到过一次这样的问题:从幅度谱出发,想恢复最小相位冲激响应。如果我直接在频域里对复频谱做log,再IFFT求倒谱,然后做窗函数截断,这一系列操作中,log运算会把相位信息转换为一种连续的形式,但如果原始相位有跳变,log后就会产生伪迹。解决办法是先对相位做解缠绕,再参与后续运算,或者在频域定义域上保证相位连续。
8.3 频谱插值与相位的关系
做FFT时经常要补零来“提高频谱分辨率”。注意,补零本身不会增加任何新的信息,它只能让频谱图更平滑,看起来更“细腻”。补零后,频谱曲线在原有的频率采样点处的值不变,但两个采样点之间的值是通过隐含的插值计算出来的。由于相位是频率的连续函数,补零后画出来的相位谱曲线看起来更连续,于是很多人误以为补零能“把相位测准”。实际上,真正的相位值取决于信号的物理特性,补零改不了它。
要想获得真实的相位测量,关键是确保时间同步和窗函数选择正确。对周期信号做FFT时,建议信号长度尽量包含整数个信号周期,否则频谱泄漏会造成幅度和相位的双偏差。个中原因,还是出在矩形窗截断对应的频域卷积这个基本结论上。
8.4 相位解缠绕的操作要诀
MATLAB的unwrap()用起来很简单,但它有个默认的阈值——当相邻相位跳变超过(\pi)时才进行修正。如果相位跳变恰好接近(\pi),unwrap可能会误判,把本不该解的跳变也解了,或者该解的跳变漏掉。这个时候可以先用interp1把相位网格加密,再unwrap,然后重采样回来,效果会好不少。还有一种更稳妥的做法:用复指数的比值来计算相位变化量,即:
[ \Delta\theta[n] = \text{angle}\left(e^{j\theta[n]} / e^{j\theta[n-1]}\right) ]
这样计算出来的相位增量天然落在((-\pi,\pi])区间内,再做累积求和就不容易出错。
9. 我自己做证明题时的一套固定流程
学完这些性质,证明题到底该怎么做?我总结了一个流程,基本适用于教科书里绝大多数“证明某某性质”的题目。
第一步,先写定义式。不管是证明左边还是右边,总得有一个起点。定义式是最保险的起点,因为它只需要你把变换式抄一遍就能写出来。
第二步,寻找可以交换运算顺序的地方。傅里叶变换的证明里,最常用的操作就是交换求和与积分、交换求和与求和。理论上,这需要函数满足一定的收敛条件,但考试和习题里给出的序列通常都满足绝对可和,所以放心大胆地用。
第三步,想尽一切办法把内层表达式凑成一个已知变换对。比如证明卷积定理时,内层求和正好用时移性质;证明相乘性质时,内层求和正好是另一个信号的DTFT。如果你发现凑不出来,多半是因为少用了一个时移或者频移的变体。
第四步,化简到最后一步,如果得到了目标表达式,就收尾。如果多了或少了系数,先检查(1/2\pi)的系数有没有漏掉。DTFT和IDTFT定义里的系数是最容易出错的地方,好在不同教材的定义基本统一,逆变换前有一个(1/2\pi)。
第五步,也是我最想强调的,就是验证边界条件。证明完一个公式后,代一个简单信号进去验证一下。比如证明时移性质后,取(x[n]=1),看看(x[n-n_0]=1)时频谱是不是还是原来的周期冲激串。这种验证做多了,对公式的记忆会特别牢固。
10. 从结论到系统:这些性质怎么支撑线性时不变系统分析
系统分析的终极目标是:给定一个输入信号和一个系统(通常用冲激响应(h[n])或频率响应(H(e^{j\omega}))来描述),求出输出信号。有了卷积定理,这个问题就变成:
[ y[n] = x[n] * h[n] \quad \leftrightarrow \quad Y(e^{j\omega}) = X(e^{j\omega}) H(e^{j\omega}) ]
频域相乘比时域卷积好算得多,而且物理意义清晰:系统的幅频响应(|H(e^{j\omega})|)决定了输入信号各频率分量的放大或衰减程度,相频响应(\angle H(e^{j\omega}))决定了各频率分量的时延。这个关系让人直观地理解了“滤波”的本质。
用这个关系分析系统时,需要注意几个边界问题。一个是系统稳定性的概念:通过检查(H(e^{j\omega}))是否对所有(\omega)有界,可以判断系统的BIBO稳定性。这一点跟z变换的收敛域检查是等价的,但用DTFT检查更直接——因为它是沿着单位圆取值的,如果单位圆在收敛域内,说明系统稳定。
第二个是对实际的物理信号来说,输入频谱往往不是绝对可和的,因为很多信号的频谱里带有冲激成分。此时卷积定理两边都包含冲激项的乘积和卷积,需要特别留意混叠项。我之前写过一个求两个余弦信号乘积频谱的程序,直接用相乘性质时忘了处理冲激卷积产生的副本,结果画出来的频谱多了好几根孤立的谱线,调试了半天才醒悟过来。
第三个是一个经常被忽视的结论:线性时不变系统的输出频谱等于输入频谱乘以系统频率响应,这个结论隐含了系统初始状态为零的前提。如果你要分析的系统有非零初始状态(比如电容初始电压不为零),那么时域卷积的表达式就不完整,必须在系统方程的差分方程里补充初始条件对应的项。很多刚学Z变换的同学在这里踩坑,其实在DTFT的框架下也是一样的道理。
从更加工程化的角度看,这些性质组合在一起,构成了数字信号处理的基本工作流。设计滤波器时,先用理想滤波器频率响应做IDTFT求出无限长冲激响应,再用窗函数截断并评估泄漏;实现快速卷积时,用FFT做循环卷积再修正为线性卷积;分析调制系统时,用频移性质和相乘性质理解频谱搬移。整个过程环环相扣,每一条都是后面一步的基石。
我个人的体会是:不要把这些结论当公式背,而是当工具熟练使用。背下来的公式,过段时间就模糊了;但如果你亲手推导过两遍,并且在代码里验证过,你会非常自然地知道“什么时候该用哪一条性质”。就像我是一个木匠,工具箱里的每把锯子,我都亲手上过油试过硬度的,用起来心里才踏实。
最后再分享一个小技巧。当你在做题或者做项目时,发现傅里叶变换的结果跟预期不一致,先别急着怀疑变换本身。老办法:取一个极端简单的情形,比如单一冲激、单一边沿,或者常数序列,把边界条件代进去算一遍。这个习惯帮我找到了很多自己计算里的低级错误,也能帮你快速定位到底是公式弄错了,还是代码的索引没对齐。