语音处理入门——语音的声学处理

语音的声学处理通常称为特征提取或者信号分析,特征是表示语音信号的一个时间片的矢量。常见的特征类型有LPC(线性预测编码)特征和PLP(感知线性预测编码),该特征称为声谱特征,使用形成波形的不同频度的分布来表示这个波形,这种频度分布称为声谱。

1. 基本概念

(1)声波

说话者使用特定的方式通过声门由口腔或鼻腔流出,就造成了空气压力变化,我们将描画空气压力对于时间的变化情况的方法来表示声波。声波在空气中是一种纵波,它的振动方向和传播方向是一致的。

波有两个重要的特征:频度(frequency)和振幅(amplitude)

频度:是1s内波本身重复的次数,或称为‘周’(cycle)

振幅:空气压力变化的大小是振幅,振幅越高,压力越大

人类感知特性::音高(pitch)是与频率有关,音强是和语音的响度有关。

(参考:语音识别:原理与应用) 

(2)声谱

声谱特征是根据Fourier对于复杂波的深入研究提出来的。Fouries指出,每个复杂波都可以表示为很多频度不同的简单波的总和。声谱是一个波的这些不同频度成分的表示。声谱图也称为幅度谱或者幅值谱,横轴是时间,纵轴是频率,一般是指短时傅里叶变换后得到的不含相位信息的时频图,对于梅尔谱变换成为功率谱。

(3)频谱

频谱是频率密度的简称,就是频率的分布曲线。复杂振荡分解为振幅不同和频率不同的谐振荡,这些谐振荡的幅值按频率排列的图形叫频谱。

(4)周期图

周期图是一种信号功率谱密度估计方法。为得到功率谱固估值,先取信号序列的离散傅里叶变换,然后取其幅频特征的平方并除以序列长度N,由于序列的离散傅里叶具有周期性,因而这种功率谱也具有周期性,常称为周期图。

(5)常见指标

过零率(zero crossing rate)是信号符号变化的比率,即,在每帧中,语音信号从正变为负或从负变为正的次数。过零率越大,频率近似越高。

谱质心(Spectral Centroid)是描述音色属性的重要物理参数之一,是频率成分的重心,是在一定频率范围内通过能量加权平均的频率,其单位是Hz。它是声音信号的频率分布和能量分布的重要信息。谱质心描述了声音的明亮度,具有阴暗、低沉品质的声音倾向有较多低频内容,谱质心相对较低,具有明亮、欢快品质的多数集中在高频,谱质心相对较高。

声谱衰减是对声音信号形状(波形图)的一种衡量,表示低于总频谱能量的指定百分比的频率。

色度频率是音乐音频有趣且强大的表示,其中整个拼欧被投影到12个区间,代表音乐八度音的12个不同的半音(或色度)

2. 信号处理

输入的声波要进行数字化,就是进行模拟-数字转换,也称为声谱特征的抽取过程,抽取过程从声波本身开始,以特征矢量结束。模拟-数字转换的过程分为两步:采样(sampling)和量化(quantization)。

(1)采样

采样是指对模拟信号在时间域上的离散化过程,即把一个时间上连续、幅度上连续的模拟信号转换成时间上离散、幅度上连续的信号。

采样率是每秒采样点数,通常的采样率是8khz,16khz,采样的方法通常是奈奎斯特(Nyquist)定理,当采样率大于信号中最高频率的两倍时,采样之后的数字信号能够完整保留原始信号中的信息。

(2)量化

量化是将采样之后的实数值进行整数化的过程,量化之后还会有编码过程,常见的编码有PCM编码(脉冲编码调制),MP3编码等。

3.特征提取

语音识别需要进行特征提取,就是提取语音信号中有助于理解语音内容的部分而丢弃其他的东西,常见的语音特征提取方式如下图:

 3.1 预处理

预处理过程是对语音信号进行预加重、分帧和加窗处理,目的是对信号进行合理分段。

(1)预加重

因为高频信号的能量通常较低,受到的抑制影响越大,因此需要增加高频部分的能量,即补偿语音信号高频部分的振幅。好处有:增加高频部分的能量使得能量分布更加均衡;防止傅里叶变换的数值计算不稳定;有可能增加信噪比,计算公式为

y_{t}=x_{t}-\alpha x_{t-1}

其中\alpha是预加重的系数,默认为0.97

(2)分帧

语音信号是一个非平稳信号,但是考虑在发浊音时声带有规律地振动,即基音频率在短时间范围内是相对固定的,语音信号具有短时平稳特性,认为10ms~30ms的语音信号是一个准稳态过程。短时分析主要采用分帧方式,相邻两帧之间的基因可能发生变化,为保证声学特征参数的平滑性,一般采用重叠取帧的方式。

将语音信号进行切割,且保证一定的重复率。核心参数有帧长(每帧的长度)和帧移(移动的距离)。对信号进行分帧,范围是20-40ms,通常采用25ms,考虑到信号的重叠性,每次移动10ms,通常一帧(信号的采样频率是16kHZ)有16000*25/1000=400个样本点。移动10ms,则16000*10/1000=160个样本点,则每次移动160个样本。

(换算详情:1s=1000ms,1khz=1000hz,赫兹是频率单位),如果最后一帧不够400个样本点,可以考虑用0补齐。

分帧方式相当于对语音信号进行了加矩形窗的处理,易出现频谱泄露,因此需要加窗函数。

(3)加窗 

考虑到语音信号的短时平稳性,对每帧信号进行加窗处理,常见的窗函数有:汉明窗、汉宁窗、布莱克曼窗。公式为

x_{l}[n]=w[n]x[n+lL]

其中,w[n]是窗函数,N是窗长,l是帧索引,L是帧移。

3.2 各类特征(更多细节实现看参考资料)

(1)前期资料

美尔尺度(Mel Scale)

美尔尺度是建立从人类的听觉感知的频率到声音实体频率直接的映射。通过把频率转换为美尔尺度,特征能够更好的匹配人类的听觉感知效果。从频率到梅尔频率的转换公式,

从梅尔频率到频率的转换公式为:

梅尔滤波器组

梅尔滤波器的长度与功率谱相等,每个滤波器只有对于需要采集的频率范围是非零,其余都是0。

计算梅尔滤波器组的参数

  • 转换,使用梅尔尺度公式将最小和最大频率转换为美尔尺度的频率,假设最值是300Hz,8kHz,梅尔频率是401.25Mel,2834.99Mel

  • 划分,若我们有10个滤波器,则需要12个点(加上最大、最小频率),并在最值范围内平均分配

  • 将梅尔频率转换为频率,

  • 创建滤波器组

第一个滤波器开始于第一个点(300Hz),峰值在第二个点(517Hz)结束于第三个点(781Hz),第一个滤波器开始于第二个点(517Hz),峰值在第三个点(781Hz)结束于第四个点(1103Hz),公式为

Bark频率

临时频带是在某一段频率范围内纯音和噪声功率相等,则该纯音处于刚好能被听到的临界状态,一个临界频带的宽带被称为一个Bark,Bark频率z(f)和线性频率f的对应关系如下:

(2)FBank特征

FBank特征提取的步骤:

  • 对语音信号进行分帧处理

  • 用周期图法进行功率谱估计(短时傅里叶)

  • 对功率谱用Mel滤波器组进行滤波,计算每个滤波器里的能量(fBank特征)

  • 对每个滤波器的能量取log

(3)MFCC特征

MFCC特征提取的步骤:

  • 对语音信号进行分帧处理

  • 用周期图法进行功率谱估计(短时傅里叶)

  • 对功率谱用Mel滤波器组进行滤波,计算每个滤波器里的能量(fBank特征)

  • 对每个滤波器的能量取log

  • 进行离散余弦变换(DCT)

  • 保留DCT的第2-13个系数,去掉其他

(3)PLP特征

  • 对语音信号进行分帧处理

  • 用周期图法进行功率谱估计(短时傅里叶)

  • 临界频带分析(Bark滤波器)

  • 等响度预加重

  • 强度响度转换

  • 逆傅里叶变换

  • 线性预测,通过使线性预测到的采样点值在最小均方误差约束下逼近实际语音采样点值,可以求取一组唯一的预测系数,简称为线性预测编码(Linear prediction coding,LPC)

(4)区别与联系

滤波器:MFCC、FBank是用梅尔滤波器,PLP是Bark滤波器。

STFT:三者都采用短时傅里叶变换。

优点:FBank保留更多原始特征,适用于DNN建模;MFCC去相关性较好,适合GMM建模;PLP抗燥性更强。

4.librosa中的实现

4.1 流程图

4.2 相关函数的参数

(1)MFCC参数

 4.3 实现细节

(1)MFCC函数

def mfcc(y=None, sr=22050, S=None, n_mfcc=20, dct_type=2, norm="ortho", lifter=0, **kwargs
):if S is None:S = power_to_db(melspectrogram(y=y, sr=sr, **kwargs))M = scipy.fftpack.dct(S, axis=0, type=dct_type, norm=norm)[:n_mfcc]if lifter > 0:M *= (1+ (lifter / 2)* np.sin(np.pi * np.arange(1, 1 + n_mfcc, dtype=M.dtype) / lifter)[:, np.newaxis])return Melif lifter == 0:return Melse:raise ParameterError("MFCC lifter={} must be a non-negative number".format(lifter))

(2)功率谱计算(melspectrogram)+滤波

该函数里边包含了功率谱计算和Mel滤波器进行滤波的过程,其中_spectrogram是进行功率谱计算,filters.mel则建立滤波器。

def melspectrogram(y=None,sr=22050,S=None,n_fft=2048,hop_length=512,win_length=None,window="hann",center=True,pad_mode="reflect",power=2.0,**kwargs):S, n_fft = _spectrogram(y=y,S=S,n_fft=n_fft,hop_length=hop_length,power=power,win_length=win_length,window=window,center=center,pad_mode=pad_mode,)# Build a Mel filtermel_basis = filters.mel(sr, n_fft, **kwargs)return np.dot(mel_basis, S)

功率谱计算主要是用短时傅里叶变换stft计算:

def _spectrogram(y=None,S=None,n_fft=2048,hop_length=512,power=1,win_length=None,window="hann",center=True,pad_mode="reflect"):if S is not None:# Infer n_fft from spectrogram shapen_fft = 2 * (S.shape[0] - 1)else:# Otherwise, compute a magnitude spectrogram from inputS = (np.abs(stft(y,n_fft=n_fft,hop_length=hop_length,win_length=win_length,center=center,window=window,pad_mode=pad_mode,))** power)return S, n_fft

mel滤波器是通过filter.mel进行滤波器建立:

def mel(sr,n_fft,n_mels=128,fmin=0.0,fmax=None,htk=False,norm="slaney",dtype=np.float32):if fmax is None:fmax = float(sr) / 2# Initialize the weightsn_mels = int(n_mels)weights = np.zeros((n_mels, int(1 + n_fft // 2)), dtype=dtype)# Center freqs of each FFT binfftfreqs = fft_frequencies(sr=sr, n_fft=n_fft)# 'Center freqs' of mel bands - uniformly spaced between limitsmel_f = mel_frequencies(n_mels + 2, fmin=fmin, fmax=fmax, htk=htk)fdiff = np.diff(mel_f)ramps = np.subtract.outer(mel_f, fftfreqs)for i in range(n_mels):# lower and upper slopes for all binslower = -ramps[i] / fdiff[i]upper = ramps[i + 2] / fdiff[i + 1]# .. then intersect them with each other and zeroweights[i] = np.maximum(0, np.minimum(lower, upper))if norm == "slaney":# Slaney-style mel is scaled to be approx constant energy per channelenorm = 2.0 / (mel_f[2 : n_mels + 2] - mel_f[:n_mels])weights *= enorm[:, np.newaxis]else:weights = util.normalize(weights, norm=norm, axis=-1)# Only check weights if f_mel[0] is positiveif not np.all((mel_f[:-2] == 0) | (weights.max(axis=1) > 0)):# This means we have an empty channel somewherewarnings.warn("Empty filters detected in mel frequency basis. ""Some channels will produce empty responses. ""Try increasing your sampling rate (and fmax) or ""reducing n_mels.")return weights

5. 实例

import librosa
import librosa.display as displayv = librosa.load('./english.wav')mfcc = librosa.feature.mfcc(v[0])import matplotlib.pyplot as pltdisplay.specshow(mfcc)
plt.colorbar()
# display.waveshow(v[0])

结果:

6.额外数学原理

6.1 短时傅里叶变换

声音信号是随时间变化,通过傅里叶变换只能将其转换到频域,失去了时域信息,无法看出频率分布随时间变化规律。短时傅里叶是把一段长信号分帧、加窗,再对每一帧做快速傅里叶变换(FFT),最后把每一帧的结果沿另一个维度堆叠起来,就得到了二维信号形式。

利用离散傅里叶变换(DFT)把每一帧信号变换到时域,公式是

其中,s(n)表示时域信号, si(n)是第i帧的数据,n范围是[1,400],Si(k)是第i帧的第k个复数,Pi(k)是第i帧的功率谱,h(n)是一个N点的窗函数,K是DFT的长度,计算功率谱:

经过短时傅里叶变换之后,得到一个复数,复数的实部代表频率的振幅,复数的虚部代表频率的相位,即得到功率谱。

参考:

语音信号的梅尔频率倒谱系数(MFCC)的原理讲解及python实现 - 凌逆战 - 博客园

MFCC特征提取教程 - 李理的博客

语音识别:原理与应用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466628.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基础呀基础,用二极管防止反接,你学会了吗?

使用新的电源,第一次给设备供电时,要特别注意电源的正负极性标注。比如电源适配器,铭牌上面有标注插头的极性。这个符号说明插头的里面是正极,外面是负极,即“内正外负”。但是也有反过来的,下面这款是“内…

李宏毅的可解释模型——三个任务

1、问题 观看了李宏毅老师的机器学习进化课程之可解释的机器学习,课程中对主要是针对黑盒模型进行白盒模型转化的技巧和方法进行了简单介绍,详细细节可以参考《Interpretable Machine Learning》。像一些线性模型、树形模型是可解释的ML model&#xff…

柔性数组和环形队列之间的故事

之前的文章,讲解了柔性数组,有很多人留言,提到一些问题。刚好,之前发关于环形队列的文章有些问题,这次刚好拿出来一起说一下,并用柔性数组实现一个环形队列。柔性数组的上一篇文章环形队列C语言实现文章1、…

STM32——时钟系统

STM32——时钟系统 宗旨:技术的学习是有限的,分享的精神是无限的。 一、时钟树 普通的MCU,一般只要配置好GPIO 的寄存器,就可以使用了。STM32为了实现低功耗,设计了非常复杂的时钟系统,必须开启外设时钟才…

目标检测发展路程(一)——Two stage

目标检测是计算机视觉领域中非常重要的一个研究方向,它是将图像或者视频中目标与其他不感兴趣的部分进行区分,判断是否存在目标,确定目标位置,识别目标种类的任务,即定位分类。传统的目标检测模型有VJ.Det[1,2],HOG.De…

都2021年了,c/c++开发竟然还能继续吃香??

年后就迎来了金三银四,你准备好2021年的跳槽涨薪计划了吗?今天我就来给大家分享,c/c作为老牌开发常青树,还能与java/python/go较较劲的岗位和技术在哪里!同时,给大家整理了2021年系统全面技术学习资料。文末…

目标检测模型——One stage(YOLO v5的模型解析及应用)

1. 简介 目标检测分为Two stage和One stage,只使用一个网络同时产生候选区域并预测出物体的类别和位置,所以它们通常被叫做单阶段检测算法(One stage)。本篇文章只讲One stage模型,常见的模型有YOLO,SSD。 目标检测发…

腾讯回应QQ读取用户浏览器历史记录

腾讯QQ官方认证账号在知乎回应“QQ扫描读取所有浏览器的历史记录”表示,PC QQ存在读取浏览器历史用以判断用户登录安全风险的情况,读取的数据用于在PC QQ的本地客户端中判断是否恶意登录。所有相关数据不会上传至云端,不会储存,也…

OCR系列——总体概述

最近参加了百度Paddle的动手学OCR课程,特此做一个学习总结。 1. 简介 OCR(Optical Character Recognition,光学字符识别)是计算机视觉重要方向,传统的OCR一般面向扫描文档类对象,现在的OCR是指场景文字识…

STM32——系统滴答定时器

STM32——系统滴答定时器 宗旨:技术的学习是有限的,分享的精神是无限的。 一、SysTick【内核中】 【风格:先描述一下库对寄存器的封装,再举例实现某些功能】 SysTick定时器被捆绑在NVIC中,用于产生SysTick异常&#…

你会用while(1)还是for(;;)写循环代码?

看代码看到for(;;)&#xff0c;然后觉得为什么不写成while(1)呢&#xff0c;所以就做了下面的测试。网上有解释&#xff0c;因为while需要做一次判断&#xff0c;理论上执行会花费的时间更久&#xff0c;for(;;)只是执行了两次空语句&#xff0c;执行会更快for.c#include <s…

OCR系列——文本检测任务

1. 简介 文本检测任务是找出图像或视频中的文字位置。不同于目标检测任务&#xff0c;目标检测不仅要解决定位问题&#xff0c;还要解决目标分类问题。 目标检测和文本检测同属于“定位”问题。但是文本检测无需对目标分类&#xff0c;并且文本形状复杂多样。 当前所说的文本…

关于ORACLE 语句中,IN 超过1000个的解决方法

在ORACLE SELECT 语句中 IN 的数据如果超过 1000&#xff0c;就会出错&#xff0c;解决方法也很简单&#xff0c;以C#代码为例&#xff1a; 1、先写一个方法&#xff0c;接收2个参数 参数1&#xff1a;接收 IN里面的数据&#xff0c;如&#xff1a;a1,a2,...a2000 &#xff1b;…

9个提高代码运行效率的小技巧你知道几个?

我们写程序的目的就是使它在任何情况下都可以稳定工作。一个运行的很快但是结果错误的程序并没有任何用处。在程序开发和优化的过程中&#xff0c;我们必须考虑代码使用的方式&#xff0c;以及影响它的关键因素。通常&#xff0c;我们必须在程序的简洁性与它的运行速度之间做出…

STM32——按键

STM32——按键 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 一、GPIO工作模式 1、当I/O端口配置为输入时&#xff1a; 输出缓冲器被禁止 施密特触发输入被激活 根据输入配置(上拉&#xff0c;下拉或浮动)的不同&#xff0c;弱上拉和下拉电阻被连接 …

深度学习——模型的压缩和加速

1. 简介 随着深度学习发展&#xff0c;越来越多的模型被发现和应用&#xff0c;模型的体量也越来越大&#xff0c;出现了模型过于庞大和参数冗余的问题。同时&#xff0c;移动端对模型的需求也是越轻量越好&#xff0c;因此&#xff0c;模型压缩和加速技术应运而生。 模型压缩…

干货,记一次解决录音杂音问题

最近在项目上遇到一个问题&#xff0c;也不能说是最近项目上的问题了&#xff0c;是之前一直存在的问题&#xff0c;但是对项目没什么影响&#xff0c;所以我就不怎么理会&#xff0c;直到最近&#xff0c;同事说这个杂音已经影响到了项目的开发&#xff0c;所以今天花了一天时…

3.5.2 冒泡排序类

那么&#xff0c;我们就以冒泡排序为例&#xff0c;把它改造成一个类。首先&#xff0c;单击菜单&#xff0c;“项目”&#xff0d;“添加类”&#xff0c;添加一个BubbleSort.cs类文件。IDE自动为我们创建如下代码&#xff1a; usingSystem;usingSystem.Collections.Generic;u…

STM32——串口通信

STM32——串口通信 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 一、异步串口通信协议 STM32 的串口非常强大&#xff0c;它不仅支持最基本的通用串口同步、异步通信&#xff0c;还具有 LIN 总线功能&#xff08;局域互联网&#xff09;、IRDA 功能&…