声信号处理工程研究(2)---频域图(频谱图)

1. 从时域到频域:为什么需要频谱图?

当你用麦克风录制一段声音时,MATLAB显示的波形图就像心电图一样起伏——这是典型的时域表示。横轴是时间,纵轴是振幅,但它隐藏了一个关键问题:我们看不出这段音频里到底有哪些频率的声音。就像混合了红、绿、蓝三种颜色的白光,时域图只显示最终混合结果,而频域图却能像棱镜般将光分解成不同颜色。

**快速傅里叶变换(FFT)**就是这样的"数学棱镜"。它把时域信号分解成不同频率的正弦波分量,每个分量都有对应的幅度和相位。想象你在钢琴上同时按下C4(261.6Hz)和E4(329.6Hz)两个键,时域图只会显示叠加后的复杂波形,而频域图会清晰呈现两个独立的频率峰值。

提示:采样率决定了频域分析的频率上限。根据奈奎斯特定理,有效频率范围只能是0到采样率的一半。例如44.1kHz采样率下,最高可分析22.05kHz的频率分量。

2. FFT原理与MATLAB实现

2.1 傅里叶变换的数学本质

任何周期信号都可以表示为不同频率正弦波的叠加。FFT是离散傅里叶变换(DFT)的高效算法,将N点时域数据转换为N点频域数据。MATLAB中的fft函数默认采用Cooley-Tukey算法,计算复杂度为O(NlogN)。

关键公式:

X_k = Σ [x_n * exp(-j*2πkn/N)] (k=0,1,...,N-1)

其中x_n是时域采样值,X_k是对应的频域复数,包含幅度和相位信息。

2.2 实战:语音信号频谱分析

我们用一个实际案例演示如何用MATLAB生成频谱图:

% 读取音频文件(建议使用16bit单声道wav) [y, Fs] = audioread('speech.wav'); % 计算单边频谱 N = length(y); Y = fft(y); P2 = abs(Y/N); % 双边谱 P1 = P2(1:N/2+1); % 单边谱 P1(2:end-1) = 2*P1(2:end-1); % 构建频率轴 f = Fs*(0:(N/2))/N; % 绘制频谱图 figure; plot(f, P1); title('单边幅度谱'); xlabel('频率(Hz)'); ylabel('幅度'); grid on;

这段代码会显示从0Hz到奈奎斯特频率(Fs/2)的频谱。如果你看到在1kHz处有个明显峰值,说明音频中含有约1kHz的主要频率成分。

3. 频谱图的深入解读

3.1 频谱图中的关键特征

  • 基频:最低频率分量,决定音高
  • 谐波:基频整数倍的频率分量,决定音色
  • 噪声基底:广泛分布的低幅度频率成分

例如小提琴的频谱会有规律的谐波结构,而白噪声的频谱则呈现平坦分布。

3.2 窗函数的选择

直接做FFT会产生频谱泄漏(spectral leakage),解决方法是在FFT前加窗:

window = hann(N); % 汉宁窗 y_windowed = y .* window; Y = fft(y_windowed);

常用窗函数对比:

窗类型主瓣宽度旁瓣衰减适用场景
矩形窗最窄-13dB瞬态信号分析
汉宁窗中等-31dB一般音频分析
平顶窗最宽-93dB幅度精确测量

4. 高级应用:短时傅里叶变换

对于非平稳信号(如语音),需要**短时傅里叶变换(STFT)**来观察频率随时间变化:

figure; spectrogram(y, hann(256), 128, 1024, Fs, 'yaxis'); colorbar;

这段代码会生成三维语谱图:

  • x轴:时间
  • y轴:频率
  • 颜色亮度:能量强度

在语音分析中,你可以清晰看到元音的共振峰(Formant)结构,以及辅音的高频噪声特征。

5. 常见问题排查

问题1:频谱出现镜像对称

  • 原因:忘记取单边谱
  • 解决:使用P1 = P2(1:N/2+1)并修正幅度

问题2:频率分辨率不足

  • 原因:FFT点数太少
  • 解决:增加采样时长或使用fft(x, N)补零

问题3:频谱波动剧烈

  • 原因:信噪比太低
  • 解决:多次平均(Periodogram法)或改用Welch方法

我在分析电机噪声时曾遇到一个典型案例:时域波形看起来是简单的周期性噪声,但频谱图揭示了在1.2kHz和3.6kHz有两个紧密相邻的峰值,最终发现是轴承缺陷导致的特定频率共振。这个例子充分说明频域分析在故障诊断中的价值。

频谱图不仅是理论工具,更是工程实践的"听诊器"。当你下次处理音频信号时,不妨先问问:这段声音里藏着哪些看不见的频率秘密?