深入理解MFCC(梅尔频率倒谱系数)

article/2025/10/20 22:20:51

从倒谱图出发

  • MFCC是Mel Frequency Cepstral Coefficient的简称,要理解MFCC特征,就需要先明白这里引入的一个新的概念——Cepstral,这个形容词的名词形式为Cepstrum,即倒谱图(频谱图Spectrum前四个字母倒着拼)
  • 倒谱图是用来“提取”语音的音色(timbre)的,音色是区分说话人最有力的特征,尤其是在前深度学习时代。先直接给出求倒谱图的公式:
    C [ x ( n ) ] = F − 1 [ l o g ( ∣ F [ x ( n ) ] ∣ 2 ) ] C[x(n)] = F^{-1}[ log(|F[x(n)]|^2) ] C[x(n)]=F1[log(F[x(n)]2)]
  • 其中 x ( n ) x(n) x(n)是离散化的原始信号, F [ ⋅ ] F[\cdot] F[]是离散傅里叶变换, l o g ( ∣ ⋅ ∣ 2 ) log(|\cdot|^2) log(2)对离散傅里叶变换的结果,先取幅值,再取平方,最后取对数, F − 1 [ ⋅ ] F^{-1}[\cdot] F1[]是离散傅里叶逆变换。
    下面是每一步的演示图:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 最后逆变换得到的倒谱图,横坐标为倒频率(Quefrency,频率的倒数,单位是秒),纵坐标是振幅。
  • 最后一张图中的所谓1st rhamonic,是从倒谱图的右边往左看的第一个尖峰,实际上,这个1st rhamonic对应原始信号的基频。
  • 要理解本节的内容,需要有离散傅里叶变换和梅尔时频谱图的知识,可以参考深入理解傅里叶变换(三)和深入理解梅尔刻度、梅尔滤波器组和梅尔时频谱图。

为什么倒谱图能提取音色

  • 最初发出振动从而产生声音的物体,被称为声源,对于语音而言,声源就是人的声带。
  • 人的肺部排出气体,这些气体通过声门(glottis),形成脉冲(glottis pulse),此时的脉冲频率决定了声音的音高,脉冲使声带振动,声带具有共振频率,会加强该脉冲。因为声源就是人的声带,所以声带的共振频率,称为此时这段语音的基频
  • 该脉冲还需要通过声道(vocal tract)才能从人的口中离开,成为能听到的语音。声道具有共振频率,随着声道的形状和大小变化,共振频率会发生变化,声道的共振频率的存在,使语音信号出现共振峰
  • 声门脉冲、基频和共振峰、声强,对应声音的三要素:音高、音色、响度。
    在这里插入图片描述
  • 那么倒谱图为什么能提取音色呢?我们想象最开始通过声门的气体,是一种信号,称为Glottal pulses,记为 h ( t ) h(t) h(t),声带和声道的作用等效为一个复杂的滤波器,记为 e ( t ) e(t) e(t),输出的语音信号是Glottal pulses被声道滤波后的信号,记为 x ( t ) x(t) x(t),注意,此时都是连续信号,那么存在下列等式:
    x ( t ) = h ( t ) ∗ e ( t ) x(t) = h(t) * e(t) x(t)=h(t)e(t)
  • 其中, ∗ * 指卷积运算。离散化之后,再进行离散傅里叶变换,时域卷积等价于频域乘积:
    X ( n ) = H ( n ) ⋅ E ( n ) X(n) = H(n) \cdot E(n) X(n)=H(n)E(n)
  • 接下来,先取幅值,再取平方,最后取对数:
    l o g [ ∣ X ( n ) ∣ 2 ] = 2 l o g ∣ H ( n ) ∣ + 2 l o g ∣ E ( n ) ∣ log[|X(n)|^2] = 2log|H(n)| + 2log|E(n)| log[X(n)2]=2logH(n)+2logE(n)
  • 现在已经将语音信号,分解成两个信号的和了,如下图:
    在这里插入图片描述
  • 左下角是 2 l o g ∣ E ( n ) ∣ 2log|E(n)| 2logE(n),右下角是 2 l o g ∣ H ( n ) ∣ 2log|H(n)| 2logH(n),左下角实际上是语音信号的包络线,右下角是语音信号减去包络线之后的信号。其中,包络线有几个突起的峰(原本应该是尖峰,取对数之后平滑了),表征了基频和共振峰,是我们希望提取的信号。
  • 最后一步是是用离散傅里叶逆变换,得到倒谱图。

MFCC

  • 对于一段音频,MFCC的提取流程如下:
    1. 对音频信号进行预加重,从而降低部分高频能量。这一步可以简单采用下式处理:
      x [ n ] = x [ n ] − α x [ n − 1 ] , 0.9 ≤ α ≤ 1.0 x[n] = x[n] - \alpha x[n-1],0.9 \le \alpha \le 1.0 x[n]=x[n]αx[n1],0.9α1.0
    2. 短时傅里叶变换
    3. 梅尔滤波器滤波,得到梅尔时频谱图
    4. 取对数,分离信号
    5. 离散余弦变换
    6. 选取倒谱系数
  • MFCC的提取过程改良了最后一步,把离散傅里叶逆变换,改成了离散余弦变换。
  • 因为log-power spectrum的信号,可以视为两个信号的叠加,而我们要提取的基频和共振峰,可以视为叠加后的信号的低频部分。
  • 所以MFCC将log-power spectrum视为一种时域信号,对其进行傅里叶分析,然后取前 n m f c c n_{mfcc} nmfcc 个频率所对应的运算值,作为最后的MFCC特征。
  • 此外,使用离散余弦变换有如下的好处:
    • 是简化版的离散傅里叶变换
    • 运算结果是实数,正是MFCC所需要的
    • 解耦了不同梅尔滤波器组之间的重合权重,使提取出的特征更加相互独立,适用于机器学习
    • 输入log-power spectrum,输出MFCC特征,起到了降维作用

MFCC的输出

  • 通常选取前12个系数,再拼接一个当前frame的能量,共13个。

  • 越靠前的系数,包含越多的基频和共振峰的信息。

  • 取得13个系数后,还会在时序上,对13个系数求一阶差分和二阶差分,二阶差分等价于对一阶差分求一阶差分。一阶差分有后向差分、前向差分的区别,也可以对后向差分和前向差分求均值得到中心差分,中心差分误差最小:

    • 前向差分
      Δ x [ n ] = x [ n + 1 ] − x [ n ] \Delta x[n] = x[n+1] - x[n] Δx[n]=x[n+1]x[n]
    • 后向差分
      Δ x [ n ] = x [ n ] − x [ n − 1 ] \Delta x[n] = x[n] - x[n-1] Δx[n]=x[n]x[n1]
    • 中心差分
      Δ x [ n ] = x [ n + 1 ] − x [ n − 1 ] 2 \Delta x[n] = \frac{x[n+1]-x[n-1]}{2} Δx[n]=2x[n+1]x[n1]

    其中, x [ n ] x[n] x[n]表示第n帧的13个系数,将一阶差分和二阶差分与原函数值拼接起来,得到39个系数。

  • MFCC的输出可以表示为一个二维数组,shape为 [ n m f c c , f r a m e s ] [n_{mfcc},frames] [nmfcc,frames],由于是二维数组,所以可以用热力图可视化。

MFCC的优缺点

  • 优点
    • 相比较梅尔时频谱图,以更少的数据量描述了时频谱图的信息,前者滤波器个数通常为80,MFCC特征个数通常为39
    • 相比较梅尔时频谱图,特征之间的相关性更低,具有更好的区分性
    • 能提取出表征基频和共振峰的信息,滤去其他无关信息
    • 在基于GMM的声学模型中效果较好
  • 缺点
    • 相比较梅尔时频谱图,计算量更大,因为MFCC是在梅尔时频谱图的基础上得到的
    • 对噪声,尤其是加性噪声,不够鲁棒
    • 人工设计的痕迹太重,导致更大的经验风险
    • 对语音合成无效,因为不存在从MFCC特征到音频信号的逆变换

演示

  • 注意:librosa的MFCC提取算法,
    • 默认没有将当前frame的能量作为第13个系数,可以自行求,然后拼接
    • 此外,默认没有一阶差分和二阶差分,也可以自行求,然后拼接
  • 下列代码就计算了一阶差分和二阶差分,然后拼接并可视化。
import librosa
import librosa.display
import matplotlib.pyplot as plt
import numpy as npif "__main__" == __name__:filepath = r"20- Extracting MFCCs with Python\female_audio.wav"signal, sr = librosa.load(path=filepath, sr=16000)N_FFT = 512N_MELS = 80N_MFCC = 13mel_spec = librosa.feature.melspectrogram(y=signal,sr=sr,n_fft=N_FFT,hop_length=sr // 100,win_length=sr // 40,n_mels=N_MELS)mfcc = librosa.feature.mfcc(S=librosa.power_to_db(mel_spec), n_mfcc=N_MFCC)delta_mfcc = librosa.feature.delta(data=mfcc)delta2_mfcc = librosa.feature.delta(data=mfcc, order=2)mfcc = np.concatenate([mfcc, delta_mfcc, delta2_mfcc], axis=0)librosa.display.specshow(data=mfcc,sr=sr,n_fft=N_FFT,hop_length=sr // 100,win_length=sr // 40,x_axis="s")plt.colorbar(format="%d")plt.show()

在这里插入图片描述

  • 音频信号处理的知识非常广袤,本系列只讲解了用于机器学习的音频信号处理知识。

http://chatgpt.dhexx.cn/article/6bD3uiAL.shtml

相关文章

MFCC特征提取

在语音识别方面,最常用到的语音特征就是梅尔倒谱系数(Mel-scaleFrequency Cepstral Coefficients,简称MFCC)。 MFCC的提取过程包括预处理、快速傅里叶变换、Mei滤波器组、对数运算、离散余弦变换、动态特征提取等步骤。 1.预处理 …

MFCC算法讲解及实现(matlab)

史上最详细的MFCC算法实现(附测试数据) 1.matlab安装voicebox语音包2.MFCC原理讲解3.MFCC算法设计实现(matlab)3.1 .wav格式语音文件提取【x(200000*1)】3.2 预加重【x(200000*1)】3.3 分帧{S(301*1103)}3.4 加窗{C(301*1103)}3.5…

Parquet encoding

Dictionary encoding

Parquet原理剖析

行存VS列存 广义的数据分析系统大致分为可以分为计算层、数据格式层和存储层。 计算层主要负责数据查询的介入和各种逻辑计算,如:MR、Spark、Flink。 存储层承载数据持久化存储,以文件语义或类似文件语义(对象存储)对接计算层。 数据格式层&…

Spark 实战 - 3.一文搞懂 parquet

一.引用 parquet 文件常见于 Spark、Hive、Streamin、MapReduce 等大数据场景,通过列式存储和元数据存储的方式实现了高效的数据存储与检索,下面主要讲 parquet 文件在 spark 场景下的存储,读取与使用中可能遇到的坑。 二.Parquet 加载方式 …

Spark Parquet使用

Spark SQL下的Parquet使用最佳实践和代码实战 分类: spark-sql(1) 一、Spark SQL下的Parquet使用最佳实践 1)过去整个业界对大数据的分析的技术栈的Pipeline一般分为以下两种方式: a)Data Source -> HD…

Arrow 之 Parquet

Parquet-format 左边是文件开头及具体的数据, 右边是文件结尾的 Footer Metadata There are three types of metadata: file metadata, column (chunk) metadata and page header metadata. All thrift structures are serialized using the TCompactProtocol. Co…

parquet存入mysql_解密列存 parquet

在做数据分析的时候,相对于传统关系型数据库,我们更倾向于计算列之间的关系。在使用传统关系型数据库时,基于此的设计,我们会扫描很多我们并不关心的列,这导致了查询效率的低下,大部分数据库 io 比较低效。因此目前出现了列式存储。Apache Parquet 是一个列式存储的文件格…

Parquet原理

在互联网大数据应用场景下,通常数据量很大且字段很多, 但每次查询数据只针对其中的少数几个字段,这时候列式存储是极佳的选择。 列式存储要解决的问题: 把IO只给查询需要用到的数据 只加载需要被计算的列空间节省 列式的压缩效…

parquet--golang使用

github 其实如果不适用一些可视化工具解析parquet文件,不太好看parquet文件内部正常应该是什么样的。但是使用一些可视化工具的话,可以发现,parquet文件会像表格,如excel文件,csv文件那样,排列数据。通过结…

Parquet

动机 创建Parquet是利用压缩性,高效的列式存储来在Haddop生态圈任何项目中应用. 记住Parquet是构建在复杂嵌套的数据结构, 并且使用记录分解和集成的算法在Dremely论文中描述.我们相信这种方法是更强大的的可以非常简单的使嵌套命令空间的扁平化. Parquet构建可以非常高效的…

Parquet 存储格式

1.介绍 Apache Parquet 是 Hadoop 生态圈中一种新型列式存储格式,它可以兼容 Hadoop 生态圈中大多数计算框架(Mapreduce、Spark 等),被多种查询引擎支持(Hive、Impala、Drill 等),并且它是语言和平台无关的。 2.特点…

parquet 简介

参考文章:parquet 简介 Parquet原理 【2019-05-29】Parquet 简介 Apache Parquet是一种能够有效存储嵌套数据的列式存储格式。 面向分析型业务的列式存储格式 由 Twitter 和 Cloudera 合作开发,2015 年 5 月从 Apache 的孵化器里毕业成为 Apache 顶…

Parquet文件详解

1、parquet文件简介 Apache Parquet是Apache Hadoop生态系统的一种免费的开源面向列的数据存储格式。 它类似于Hadoop中可用的其他列存储文件格式,如RCFile格式和ORC格式。 Apache Parquet 是由 Twitter 和 Cloudera 最先发起并合作开发的列存项目,也是…

Gson解析json数据

gson是谷歌推出的,除此之外还有阿里的FastJson,官方json和jackjson。下面通过一个实例来讲解使用gson来解析json数据: 1.先做好准备工作,在网上下载Gson的jar包,放到工程的libs(没有此目录的话自己建一个)目录下: ht…

Android Gson解析json

前言: 解析json的库有很多,如:JSON-Java、Gson、Jackson、FastJson…而Gson是谷歌的,相信自有它的好处 简介 用于json与java对象之间的转换通过 序列化和反序列化 实现功能强大,稳定性也好 使用 Gson提供了两个方…

Android 使用 Gson 解析 json 数据及生成

1.导入 Gson 包 第一种导入Gson 包的方式 在 app 文件下的 build.gradle 文件 导入 gson:2.9.1 包 implementation com.google.code.gson:gson:2.9.1第二种导入Gson 包的方式 直接去下载最新的 Gson 包 下载链接:gson.jar 选择最新的包进行下载 将下载的 gson…

用Gson解析json

首先我们需要导入gson的jar包,因为gson解析方法不是java官方的而是谷歌提供的。 一.把json数据转成java对象 首先因为已经手动导入了jar包,现在只需创建解析器对象,当然首先得有一个json类型的文件地址,和文件输出流 第二步调用…

Android --Gson解析json数据

Android --Gson解析json数据 private void analyseJson() throws Exception {InputStream isgetAssets().open("dataTest.json");ByteArrayOutputStream baosnew ByteArrayOutputStream();byte[] bytesnew byte[1024];int len;while ((lenis.read(bytes))!-1){baos.…

Gson解析json字符串

Gson 怎样使用gson把一个json字符串解析成一个jsonObject对象 因此我要把上面的fastjson转换成是gson,如下图: JsonObject object new JsonParser().parse(result).getAsJsonObject();怎样从gson中取出键的值 使用gson把json字符串转换成一个list集合 …