如何将多个帧的 MFCC 拼接在一起?

信息处理 声音的 mfcc
2022-01-12 07:17:15

我正在尝试录制两次声音并比较两次录音。我两次都在播放完全相同的声音(例如,两次播放一个小的 .wav 文件并每次都录制它),所以我希望我的尝试不会上升到语音识别的复杂性......

我尝试计算 DFT(使用 FFT)并比较信号的两个功率谱(更准确地说,比较它们的 MSE - 均方误差),但结果令人沮丧(有时对于相同声音的录音,误差大于对于不同的声音)...

然后我发现了 MFCC 并为每个信号计算了它们。这为我将信号分成的每一帧留下了 12 个系数(详情如下)。我应该如何组合这些 12 个系数组来获得一些描述整个信号的值?

(附加它们并为两个阵列提取 MSE 也没有返回令人鼓舞的结果......)


以下是有关我计算 MFCC 的方式和我选择用于计算它的值的一些详细信息。也许在这里我做错了什么:

(采样率 = 22000 赫兹)

  1. 预强调。
  2. 帧大小 = 512,帧重叠 = 200。(因为“每个帧应该是 ~20-30 毫秒长”和 512 / 22000 = 0,023 秒 = 23 毫秒。因为“重叠应该是 ~10 毫秒和 200 / 22000 = 0,009 秒 = 9 毫秒)
  3. 对每个 512 尺寸的帧应用汉明窗。
  4. 将 FFT 应用于我的信号的每个窗口 512 大小的帧 => 512 个幅度,从女巫我只使用前 256 个。域:从 0 到 22000 的赫兹(分别到 11000)
  5. 计算 Mel 滤波器组:(最小频率 = 300 Hz,最大频率 = 11000 Hz)
    • 根据最小和最大频率计算 mels,然后计算这两个 mel 值之间的 26 个等距值。
    • 将它们转换回 Hz => 28 个频率滤波器的数组。
    • 为每三个连续值计算一个滤波器组(滤波器三角形)=> 28 - 2 = 26 个滤波器组。
    • 将步骤 4 中的整个功率谱(256 个幅度)通过每个三角形滤波器,以获得每个滤波器的“滤波器组能量”=> 26 大小的能量阵列。
  6. 应用对数:ln(每个能量)(它们仍然是频域值)
  7. 将 DCT 应用于记录的能量 => 26 大小的(时域?)值数组。
  8. 对于我的信号的每个215 大小的帧,只取前 12 => 12 个 MFCC 。
2个回答

我应该如何组合这些 12 个系数组来获得一些描述整个信号的值?

我不认为将系数的序列“展平”为215×121×N向量,然后计算这些向量之间的距离来比较两个声音是一个好主意。这种方法折叠了时间信息——声音随时间演变的方式。例如,假设您决定使用每个系数的标准差和平均值来“总结”MFCC 向量的序列(这是在某些应用中使用的技术)。如果你使用这种方法,一个声音和向后播放的相同声音都会产生完全相同的特征向量!这可能适用于识别不同乐器等简单任务,但只要需要保留时间信息(区分“halo”和“hola”,或演奏“boom boom tchik”与“boom tchik boom”的鼓乐器) ,从向量而不是序列的角度思考不再有效。

这可能不是你期望的答案,但我建议你停止在向量比较方面进行推理,而是想一种方法来比较 MFCC 帧本身的序列。您的方法 - 类似于计算向量序列之间的原始成对距离 - 对于两个序列之间的时间差异并不稳健。解决方案是使用Dynamic Time Warping它试图在时间上以最佳方式对齐两个序列(以便比较“hoooolaa”和“holaaa”产生与比较“hola”和“hola”相同的分数)。这种技术对于基本的语音命令识别来说已经足够好了。

另一种方法是通过具有几个状态的 HMM 对每个声音进行建模。并使用模型之间的距离作为相似性度量。这可以提高计算效率,并让您控制要尊重时间信息的严格程度(通过增加状态数量)。

您可以尝试自制类似于声音指纹识别的基本概念的东西。创建一个 Mel 能量的 2D 数组(甚至可以用图表来查看),挑选出所有局部最大值,然后比较两个图之间最近峰值对之间的 2D 距离作为相似性度量。