小组会议录音常常不清楚。桌上的麦克风不会知道谁是主讲人,也不会自动把旁边人的声音、空调声、房间回声分开。它只记录一个位置上的空气振动。回放时听到的混乱,已经被写进了同一条波形。

下面这段 WHAMR 样例 136 会贯穿前两份材料。WHAMR 是一个常用于语音分离研究的数据集,混合语音里带有噪声和混响。图中横轴是时间,纵轴是采样值。波形离 0 越远,表示这一刻记录到的振动越强。

WHAMR 样例 136 的混合语音波形

这条波形看起来只是一串上下起伏的曲线。对电脑来说,它确实也只是一串数字。要理解语音增强和分离,第一步不是先看神经网络,而是先弄清楚:声音是什么,麦克风怎样把声音变成数字,为什么研究里常把波形变成 STFT。

声音是什么

声音是空气压力随时间的变化。人说话时,声带振动,气流经过口腔、舌头、牙齿和鼻腔后形成不同声音。这个振动会让周围空气一会儿被压紧,一会儿变稀。压力变化传到耳朵,我们听见声音;传到麦克风,麦克风把它转换成电信号。

几个词先讲清楚:

概念 先这样理解 在波形里怎么看
振动 空气压力反复变大、变小 曲线围绕 0 上下摆动
幅度 振动强弱,常和响度有关 曲线离 0 越远,幅度越大
频率 每秒振动多少次,常和音高有关 同样时间里摆动越密,频率越高
波形 声音随时间变化的记录 横轴是时间,纵轴是采样值

一句话不是一个固定频率。元音通常比较平稳,辅音会带来更短、更尖、更像噪声的变化,停顿又会让能量突然下降。会议录音更复杂,因为多个人、噪声和房间反射会同时进入同一条记录。

麦克风怎样把声音变成数字

麦克风里有一个很薄的膜片。空气压力变化推动膜片,膜片运动再被转换成电压变化。电压本来是连续变化的,但电脑不能保存无限多个连续值,所以声卡会按固定时间间隔取点。

整个链路可以写成:

1
空气压力变化 -> 麦克风膜片振动 -> 电压变化 -> 采样 -> 数字波形 -> wav 文件

采样就是按固定时间间隔记录一次电压。采样率是每秒记录多少个点。样例 136 的采样率是 8 kHz,也就是每秒 8000 个采样点。如果采样率是 16 kHz,就是每秒 16000 个点。

从空气振动到采样点

把局部波形放大,可以看到采样点。图里的圆点才是 wav 文件真正保存的数字,连线只是为了帮助人眼看趋势。

采样点放大图

如果只有一个麦克风,可以把音频写成:

表示第几个采样点。 是第一个点, 是第二个点。

如果有多个麦克风,可以写成:

表示第几个麦克风。多麦克风不只是多存几条波形。同一个声源到不同麦克风的距离不同,到达时间、强度和相位也会不同。这些差异后面会变成空间信息。

声音的表示形式

同一段声音可以用不同方式表示。表示方式决定模型容易看到什么,也决定我们怎样解释模型。

表示形式 看到的信息 适合解释什么
时域波形 waveform 声音随时间怎样变化 采样、响度、停顿、冲击
频域表示 spectrum 一小段声音里有哪些频率 低频、高频、元音和噪声的分布
时频表示 STFT / spectrogram 每个时间段里有哪些频率 语音随时间变化、多人重叠、增强和分离

时域波形直观,但看不出某个时刻到底有哪些频率。频谱能看频率,但如果只对整段录音做一次频谱,就会丢掉“什么时候发生”的信息。语音一直在变,所以研究里常用时频表示:既保留时间,又保留频率。由于声音在空间中传播,其中也包含着空间的关系。

先从一小段声音看频率

频率分析可以先从一小段稳定声音开始。傅里叶变换的直觉是:一段复杂波形可以看成许多不同频率的正弦波叠加。低频成分变化慢,高频成分变化快。语音里的元音、辅音、噪声在频率分布上通常不一样。

对一帧离散信号 做 DFT,可以写成:

这里:

符号 意思
个采样点
这一帧里参与计算的采样点数
个频率格点
虚数单位,满足
个频率上的复数结果

FFT 是快速计算 DFT 的算法。平时说“做 FFT”,通常就是把一小段波形变成一组频率成分。

单帧 FFT 示意图

左边是一小段加窗后的语音,右边是这一帧的频率成分。频率分析告诉我们这一小段声音里低频和高频分别有多少能量。

为什么需要 STFT

如果只对整段会议录音做一次 FFT,会得到“整段录音总体有哪些频率”。这对语音不够用,因为语音内容随时间变化。某个辅音可能只持续几十毫秒,某个说话人可能只在某几个时间段出现。

这里推荐一个供参考的视频方便理解:
编程大冒险:音频分析详解 - Sebastian Lague

STFT,Short-Time Fourier Transform,短时傅里叶变换,就是把长音频切成很多短片段,每段分别做 FFT。这样得到的是一张“时间帧 × 频率格点”的表。

STFT 的流程是:

1
长波形 -> 分帧 -> 加窗 -> 每帧做 FFT -> STFT 复数矩阵

分帧:把长音频切成短窗口

分帧就是把一条长音频切成很多短片段。语音在很长时间上不稳定,但在二三十毫秒的小窗口里,可以近似看作比较稳定。

常见设置是每帧 32 ms,相邻帧间隔 16 ms。相邻窗口有重叠,切口附近的信息不会突然丢失。

分帧示意图

帧长决定每一小段有多长。帧移,也叫 hop size,决定相邻帧之间移动多少采样点。帧移越小,时间轴越密,计算量也越大。

加窗:让每一帧的边缘更平滑

直接硬切一段波形,会在边缘制造突变。FFT 会把这种突变当成额外频率,造成不必要的频谱泄漏。加窗就是给一帧里的每个采样点乘一个平滑权重。

Hann window 是常见窗函数。它的中间权重大,边缘权重小。它不是为了删掉边缘声音,而是让短片段更平滑。

Hann window 和加窗后的一帧语音

加窗可以写成:

这里 是第几个时间帧, 是帧移, 是窗函数。 表示第 帧取出来并加窗后的信号。

STFT 公式逐项解释

把分帧、加窗和 FFT 合起来,就得到 STFT:

这个公式可以按“取出一帧,再检测频率”来读。

符号 意思 对应动作
个采样点 原始数字波形
帧使用的窗函数 分帧和加窗
hop size,帧移 相邻帧移动多少采样点
FFT 点数 决定频率格点
第几个时间帧 时间位置
第几个频率格点 频率位置
虚数单位 让结果能表示幅度和相位
帧、第 个频率上的 STFT 系数 一个复数

一步一步看:

  1. 把第 帧附近的波形取出来,并让边缘变平滑。
  2. 像一个频率检测器,用来检测第 个频率。
  3. 对所有 求和,就得到这个时间帧、这个频率格点上的复数值。

每一时间帧做一次 FFT,再按时间顺序排起来,就是 STFT 矩阵。

STFT 矩阵坐标轴

把 STFT 的幅度用颜色画出来,就是频谱图。颜色亮,表示这个时间和频率位置能量强;颜色暗,表示能量弱。

WHAMR 样例 136 的频谱图

复数 STFT:实部、虚部、幅度和相位

STFT 的每个格子通常是复数。复数可以写成:

是实部, 是虚部。复数还能转换成幅度和相位:

幅度描述这个时频点能量有多强。相位描述这个频率成分在波形里的位置关系。初学时常先看幅度,因为频谱图就是把幅度画成颜色。但多麦克风任务不能只看幅度。不同麦克风之间的到达时间差会体现在相位差里,空间滤波也需要处理复数权重。

这就是 STFT 在多通道语音增强里仍然重要的原因。它既有清楚的物理意义,又能把时间、频率、相位和空间线索放在一个统一坐标系里。

从 STFT 转换回声音

模型处理完 STFT 后,通常还要通过 iSTFT 回到波形。iSTFT 可以理解成反向过程:每个时间帧用 inverse FFT 变回短波形,再按原来的帧移叠加回长波形。

1
估计的 STFT -> 每帧 inverse FFT -> overlap-add -> 估计波形

如果模型只改幅度、不改相位,iSTFT 时常复用混合语音的相位。如果模型直接预测复数 STFT 或空间滤波器,实部和虚部都会影响最后的波形。

补充阅读