《语音信号处理试验教程》(梁瑞宇等)的代码主要是Matlab实现的,现在Python比较热门,所以把这个项目大部分内容写成了Python实现,大部分是手动写的。使用CSDN博客查看帮助文件:

Python语音基础操作–2.1语音录制,播放,读取
Python语音基础操作–2.2语音编辑
Python语音基础操作–2.3声强与响度
Python语音基础操作–2.4语音信号生成
Python语音基础操作–3.1语音分帧与加窗
Python语音基础操作–3.2短时时域分析
Python语音基础操作–3.3短时频域分析
Python语音基础操作–3.4倒谱分析与MFCC系数
Python语音基础操作–4.1语音端点检测
Python语音基础操作–4.2基音周期检测
Python语音基础操作–4.3共振峰估计
Python语音基础操作–5.1自适应滤波
Python语音基础操作–5.2谱减法
Python语音基础操作–5.4小波分解
Python语音基础操作–6.1PCM编码
Python语音基础操作–6.2LPC编码
Python语音基础操作–6.3ADPCM编码
Python语音基础操作–7.1帧合并
Python语音基础操作–7.2LPC的语音合成
Python语音基础操作–10.1基于动态时间规整(DTW)的孤立字语音识别试验
Python语音基础操作–10.2隐马尔科夫模型的孤立字识别
Python语音基础操作–11.1矢量量化(VQ)的说话人情感识别
Python语音基础操作–11.2基于GMM的说话人识别模型
Python语音基础操作–12.1基于KNN的情感识别
Python语音基础操作–12.2基于神经网络的情感识别
Python语音基础操作–12.3基于支持向量机SVM的语音情感识别
Python语音基础操作–12.4基于LDA,PCA的语音情感识别

代码可在Github上下载:busyyang/python_sound_open

声道可以被看成一根具有非均匀截面的声管,在发音时将起共鸣器的作用。当声门处准周期脉冲激励进入声道时会引起共振特性,产生一组共振频率,这一组共振频率称为共振峰频率或简称为共振峰。共振峰参数包括共振峰频率、频带宽度和幅值,共振峰信息包含在语音频谱的包络中。因此共振峰参数提取的关键是估计语音频谱包络,并认为谱包络中的最大值就是共振峰。利用语音频谱傅里叶变换相应的低频部分进行逆变换,就可以得到语音频谱的包络曲线。依据频谱包络线各峰值能量的大小确定出第1-4共振峰.

在经典的语音信号模型中,共振峰等效为声道传输函数的复数极点对。对平均长度约为17cm声道(男性) ,在3kHz范围内大致包含三个或四个共振峰,而在5 kHz范围内包含四个或五个共振峰。高于5kHz的语音信号,能量很小。浊音信号最主要的是前三个共振峰。因此一切共振峰估计都是直接或间接地对频谱包络进行考察,关键是估计语音频谱包络,并认为谱包络中的最大值就是共振峰。

共振峰估计预处理

在估计之前需要进行预加重,对信号进行高频提升,还原声门的信号。
s′(n)=s(n)−a⋅s(n−1)s'(n)=s(n)-a·s(n-1)s′(n)=s(n)−a⋅s(n−1)

预加重有两个作用:

  • 增加一个零点:抵消声门脉冲引起的高端频谱幅度下跌,使信号频谱变得平坦且各共振峰幅度相接近;语音中只剩下声道部分的影响,所提取的特征更加符合原声道的模型。
  • 会削减低频信息,使有些基频幅值变大时,通过预加重后降低基频对共振峰检测的干扰,有利于共振峰的检测;同时减少频谱的动态范围。

另外,共振峰检测一般是分析韵母部分,所以还需要进行端点检测。可以使用基音周期检测相同的端点检测方法。

倒谱法共振峰估计

倒谱法共振峰估计的算法过程为:

  • 对语音信号x(i)x(i)x(i)进行预加重,并进行加窗,分帧,FFT处理
    Xi(k)=∑n=1Nxi(n)e−2πknjNX_i(k)=\sum_{n=1}^Nx_i(n)e^{-\frac{2\pi kn j}{N}}Xi​(k)=n=1∑N​xi​(n)e−N2πknj​
  • 取Xi(k)X_i(k)Xi​(k)的倒谱:
    x^i(n)=1N∑k=1Nlg⁡∣Xi(k)∣e−2πknjN\hat x_i(n)=\frac{1}{N}\sum_{k=1}^N\lg|X_i(k)|e^{-\frac{2\pi kn j}{N}}x^i​(n)=N1​k=1∑N​lg∣Xi​(k)∣e−N2πknj​
  • 给倒谱信号加窗得:hi(n)=x^i(n)×h(n)h_i(n)=\hat x_i(n)\times h(n)hi​(n)=x^i​(n)×h(n),这里的窗函数和倒谱的分辨率有关(和采样率和FFT长度有关):
    h(n)={1n⩽n0−1&n⩾N−n0+10n0−1<n<N−n0+1,n∈[0,N−1]h(n)=\left \{\begin{array}{lc} 1&n\leqslant n_0-1 \&n\geqslant N-n_0+1\\ 0& n_0-1<n<N-n_0+1 \end{array}\right.,n\in[0,N-1]h(n)={10​n⩽n0​−1&n⩾N−n0​+1n0​−1<n<N−n0​+1​,n∈[0,N−1]
  • 求hi(n)h_i(n)hi​(n)的包络线:Hi(k)=∑n=1Nhi(n)e−2πknjNH_i(k)=\sum\limits_{n=1}^{N}h_i(n)e^{-\frac{2\pi kn j}{N}}Hi​(k)=n=1∑N​hi​(n)e−N2πknj​
  • 在包络线张寻找极大值,获得相应共振峰参数。

LPC法共振峰估计

简化的语音产生模型是将辐射、声道以及声门激励的全部效应简化为一个时变的数字滤波器来等效,其传递函数为
H(z)=S(z)U(z)=G1−∑i=1paizi−1H(z)=\frac{S(z)}{U(z)}=\frac{G}{1-\sum\limits_{i=1}^pa_iz_i^{-1}}H(z)=U(z)S(z)​=1−i=1∑p​ai​zi−1​G​

令z−1=exp⁡(−j2πf/fs)z^{-1}=\exp(-j2\pi f/f_s)z−1=exp(−j2πf/fs​),则功率谱P(f)P(f)P(f)为:
P(f)=∣H(f)∣2=G2∣1−∑i=1paiexp⁡(−j2πif/fs)∣2P(f)=|H(f)|^2=\frac{G^2}{|1-\sum\limits_{i=1}^pa_i\exp(-j2\pi if/f_s)|^2}P(f)=∣H(f)∣2=∣1−i=1∑p​ai​exp(−j2πif/fs​)∣2G2​

利用FFT方法可对任意频率求得其功率谱幅值响应,并从幅值响应中找到共振峰,相应的求解方法有两种:抛物线内插法和线性预测系数求复数根法。

抛物线内插法

在任意共振峰频率FiF_iFi​的局部峰值频率mΔfm\Delta fmΔf(Δf\Delta fΔf为谱图的频率间隔),以及邻近的两个频率点(m−1)Δf(m-1)\Delta f(m−1)Δf,(m+1)Δf(m+1)\Delta f(m+1)Δf,以及他们的幅值分别为H(m−1),H(m),H(m+1)H(m-1),H(m),H(m+1)H(m−1),H(m),H(m+1),可以用二次方程aλ2+bλ+ca\lambda^2+b\lambda+caλ2+bλ+c来计算,求出更精确的中心频率FiF_iFi​和带宽BiB_iBi​。
为了方便计算,令mΔfm\Delta fmΔf处为零,对应于Δf,0,+Δf\Delta f,0,+\Delta fΔf,0,+Δf处的功率谱分别为H(m−1),H(m),H(m+1)H(m-1),H(m),H(m+1)H(m−1),H(m),H(m+1),由H=aλ2+bλ+cH=a\lambda^2+b\lambda+cH=aλ2+bλ+c有:
{H(m−1)=aΔ2−bΔ+cH(m)=cH(m+1)=aΔ2+bΔ+c\left \{\begin{array}{ll} H(m-1)=a\Delta^2-b\Delta+c\\ H(m)=c\\ H(m+1)=a\Delta^2+b\Delta+c \end{array}\right.⎩⎨⎧​H(m−1)=aΔ2−bΔ+cH(m)=cH(m+1)=aΔ2+bΔ+c​

假设Δf=1\Delta f=1Δf=1,则计算系数为:
{a=H(m−1)+H(m+1)2−H(m)b=H(m−1)+H(m+1)2c=H(m)\left \{\begin{array}{ll} a=\frac{H(m-1)+H(m+1)}{2}-H(m)\\ b=\frac{H(m-1)+H(m+1)}{2}\\ c=H(m) \end{array}\right.⎩⎨⎧​a=2H(m−1)+H(m+1)​−H(m)b=2H(m−1)+H(m+1)​c=H(m)​

极大值处中心频率为:λmax=−b/2a\lambda_{max}=-b/2aλmax​=−b/2a,实际共振峰中心频率为:Fi=λmaxΔf+mΔfF_i=\lambda_{max}\Delta f+m\Delta fFi​=λmax​Δf+mΔf,中心频率对应的功率谱HpH_pHp​为:
Hp=aλp2+bλp+c=−b24a+cH_p=a\lambda_p^2+b\lambda_p+c=-\frac{b^2}{4a}+cHp​=aλp2​+bλp​+c=−4ab2​+c

求带宽,就是在某个λ\lambdaλ处,使得谱值为最大值的一半:
aλ2+bλ+cHp=12\frac{a\lambda^2+b\lambda+c}{H_p}=\frac{1}{2}Hp​aλ2+bλ+c​=21​

解这个二次方程可以得到:
λroot=−b±b2−4a(c−0.5Hp)2a\lambda _{root}=\frac{-b±\sqrt{b^2-4a(c-0.5H_p)}}{2a}λroot​=2a−b±b2−4a(c−0.5Hp​)​​

实际带宽可以写成:
Bi=2λbΔfB_i=2\lambda_b\Delta fBi​=2λb​Δf

其中λb=−b2−4a(c−0.5Hp)2a\lambda_b=-\frac{b^2-4a(c-0.5H_p)}{2a}λb​=−2ab2−4a(c−0.5Hp​)​。

线性预测系数求根法

预测误差滤波器表示为:
A(z)=1−∑i=1paiz−iA(z)=1-\sum_{i=1}^pa_iz^{-i}A(z)=1−i=1∑p​ai​z−i

其多项式复根可以精确表示共振峰的中心频率与带宽。设zi=riejθiz_i=r_ie^{j\theta_i}zi​=ri​ejθi​为任意复根,其共轭值zi∗=rie−jθiz^*_i=r_ie^{-j\theta_i}zi∗​=ri​e−jθi​也是根,设ziz_izi​对应的共振峰频率为FiF_iFi​,3dB带宽为BiB_iBi​,那么有:
{2πFi/fs=θie−Biπ/fs−ri\left \{\begin{array}{ll} 2\pi F_i/f_s=\theta_i\\e^{-B_i\pi/f_s}-r_i \end{array} \right.{2πFi​/fs​=θi​e−Bi​π/fs​−ri​​

所以:
{Fi=θifs/2πBi=−ln⁡ri⋅fs/π\left \{\begin{array}{ll} F_i=\theta_if_s/2\pi\\B_i=-\ln r_i·f_s/\pi \end{array} \right.{Fi​=θi​fs​/2πBi​=−lnri​⋅fs​/π​

因为预测误差滤波器阶数p是预先设定的,所以复共辄对的数量最多是p/2。因为不属于共振峰的额外极点的带宽远大于共振峰带宽,所以比较容易剔除非共振峰极点。

# 共振峰估计函数
import numpy as np
from chapter3_分析实验.timefeature import *
from chapter3_分析实验.lpc import lpc_coeffdef local_maxium(x):"""求序列的极大值:param x::return:"""d = np.diff(x)l_d = len(d)maxium = []loc = []for i in range(l_d - 1):if d[i] > 0 and d[i + 1] <= 0:maxium.append(x[i + 1])loc.append(i + 1)return maxium, locdef Formant_Cepst(u, cepstL):"""倒谱法共振峰估计函数:param u::param cepstL::return:"""wlen2 = len(u) // 2U = np.log(np.abs(np.fft.fft(u)[:wlen2]))Cepst = np.fft.ifft(U)cepst = np.zeros(wlen2, dtype=np.complex)cepst[:cepstL] = Cepst[:cepstL]cepst[-cepstL + 1:] = Cepst[-cepstL + 1:]spec = np.real(np.fft.fft(cepst))val, loc = local_maxium(spec)return val, loc, specdef Formant_Interpolation(u, p, fs):"""插值法估计共振峰函数:param u::param p::param fs::return:"""ar, _ = lpc_coeff(u, p)U = np.power(np.abs(np.fft.rfft(ar, 2 * 255)), -2)df = fs / 512val, loc = local_maxium(U)ll = len(loc)pp = np.zeros(ll)F = np.zeros(ll)Bw = np.zeros(ll)for k in range(ll):m = loc[k]m1, m2 = m - 1, m + 1p = val[k]p1, p2 = U[m1], U[m2]aa = (p1 + p2) / 2 - pbb = (p2 - p1) / 2cc = pdm = -bb / 2 / aapp[k] = -bb * bb / 4 / aa + ccm_new = m + dmbf = -np.sqrt(bb * bb - 4 * aa * (cc - pp[k] / 2)) / aaF[k] = (m_new - 1) * dfBw[k] = bf * dfreturn F, Bw, pp, U, locdef Formant_Root(u, p, fs, n_frmnt):"""LPC求根法的共振峰估计函数:param u::param p::param fs::param n_frmnt::return:"""ar, _ = lpc_coeff(u, p)U = np.power(np.abs(np.fft.rfft(ar, 2 * 255)), -2)const = fs / (2 * np.pi)rts = np.roots(ar)yf = []Bw = []for i in range(len(ar) - 1):re = np.real(rts[i])im = np.imag(rts[i])fromn = const * np.arctan2(im, re)bw = -2 * const * np.log(np.abs(rts[i]))if fromn > 150 and bw < 700 and fromn < fs / 2:yf.append(fromn)Bw.append(bw)return yf[:min(len(yf), n_frmnt)], Bw[:min(len(Bw), n_frmnt)], U
from chapter2_基础.soundBase import *
from chapter4_特征提取.共振峰估计 import *
from scipy.signal import lfilterplt.figure(figsize=(14, 12))data, fs = soundBase('C4_3_y.wav').audioread()
# 预处理-预加重
u = lfilter([1, -0.99], [1], data)cepstL = 6
wlen = len(u)
wlen2 = wlen // 2
# 预处理-加窗
u2 = np.multiply(u, np.hamming(wlen))
# 预处理-FFT,取对数
U_abs = np.log(np.abs(np.fft.fft(u2))[:wlen2])
# 4.3.1
freq = [i * fs / wlen for i in range(wlen2)]
val, loc, spec = Formant_Cepst(u, cepstL)
plt.subplot(4, 1, 1)
plt.plot(freq, U_abs, 'k')
plt.title('频谱')
plt.subplot(4, 1, 2)
plt.plot(freq, spec, 'k')
plt.title('倒谱法共振峰估计')
for i in range(len(loc)):plt.subplot(4, 1, 2)plt.plot([freq[loc[i]], freq[loc[i]]], [np.min(spec), spec[loc[i]]], '-.k')plt.text(freq[loc[i]], spec[loc[i]], 'Freq={}'.format(int(freq[loc[i]])))
# 4.3.2
p = 12
freq = [i * fs / 512 for i in range(256)]
F, Bw, pp, U, loc = Formant_Interpolation(u, p, fs)plt.subplot(4, 1, 3)
plt.plot(freq, U)
plt.title('LPC内插法的共振峰估计')for i in range(len(Bw)):plt.subplot(4, 1, 3)plt.plot([freq[loc[i]], freq[loc[i]]], [np.min(U), U[loc[i]]], '-.k')plt.text(freq[loc[i]], U[loc[i]], 'Freq={:.0f}\nHp={:.2f}\nBw={:.2f}'.format(F[i], pp[i], Bw[i]))# 4.3.3p = 12
freq = [i * fs / 512 for i in range(256)]n_frmnt = 4
F, Bw, U = Formant_Root(u, p, fs, n_frmnt)plt.subplot(4, 1, 4)
plt.plot(freq, U)
plt.title('LPC求根法的共振峰估计')for i in range(len(Bw)):plt.subplot(4, 1, 4)plt.plot([freq[loc[i]], freq[loc[i]]], [np.min(U), U[loc[i]]], '-.k')plt.text(freq[loc[i]], U[loc[i]], 'Freq={:.0f}\nBw={:.2f}'.format(F[i], Bw[i]))plt.savefig('images/共振峰估计.png')
plt.close()

Python语音基础操作--4.3共振峰估计相关推荐

  1. Python语音基础操作--6.3ADPCM编码

    <语音信号处理试验教程>(梁瑞宇等)的代码主要是Matlab实现的,现在Python比较热门,所以把这个项目大部分内容写成了Python实现,大部分是手动写的.使用CSDN博客查看帮助文件 ...

  2. Python语音基础操作--2.3声强与响度

    <语音信号处理试验教程>(梁瑞宇等)的代码主要是Matlab实现的,现在Python比较热门,所以把这个项目大部分内容写成了Python实现,大部分是手动写的.使用CSDN博客查看帮助文件 ...

  3. Python语音基础操作--10.2隐马尔科夫模型的孤立字识别

    <语音信号处理试验教程>(梁瑞宇等)的代码主要是Matlab实现的,现在Python比较热门,所以把这个项目大部分内容写成了Python实现,大部分是手动写的.使用CSDN博客查看帮助文件 ...

  4. Python语音基础操作--5.1自适应滤波

    <语音信号处理试验教程>(梁瑞宇等)的代码主要是Matlab实现的,现在Python比较热门,所以把这个项目大部分内容写成了Python实现,大部分是手动写的.使用CSDN博客查看帮助文件 ...

  5. Python语音基础操作--10.1基于动态时间规整(DTW)的孤立字语音识别试验

    <语音信号处理试验教程>(梁瑞宇等)的代码主要是Matlab实现的,现在Python比较热门,所以把这个项目大部分内容写成了Python实现,大部分是手动写的.使用CSDN博客查看帮助文件 ...

  6. Python语音基础操作--3.5线性预测分析

    <语音信号处理试验教程>(梁瑞宇等)的代码主要是Matlab实现的,现在Python比较热门,所以把这个项目大部分内容写成了Python实现,大部分是手动写的.使用CSDN博客查看帮助文件 ...

  7. Python语音基础操作--3.2短时时域分析

    <语音信号处理试验教程>(梁瑞宇等)的代码主要是Matlab实现的,现在Python比较热门,所以把这个项目大部分内容写成了Python实现,大部分是手动写的.使用CSDN博客查看帮助文件 ...

  8. Python语音基础操作--11.2基于GMM的说话人识别模型

    <语音信号处理试验教程>(梁瑞宇等)的代码主要是Matlab实现的,现在Python比较热门,所以把这个项目大部分内容写成了Python实现,大部分是手动写的.使用CSDN博客查看帮助文件 ...

  9. python自相关函数提取基音周期_Python语音基础操作--4.2基音周期检测

    <语音信号处理试验教程>(梁瑞宇等)的代码主要是Matlab实现的,现在Python比较热门,所以把这个项目大部分内容写成了Python实现,大部分是手动写的.使用CSDN博客查看帮助文件 ...

最新文章

  1. 【读书笔记】《高性能JavaScript》
  2. oracle报错ora-12162,ORA-12162: TNS: 指定的 Net 服务名不正确
  3. 往hdfs写数据无权限
  4. .so 依赖目录 cmake_cmake浅析
  5. STM32F1笔记(二)GPIO输入
  6. Linux命令(三)
  7. 求周期字符串的最小子串
  8. 田渊栋团队新作:为什么非对比自监督学习效果好?
  9. 哪个Linux发行版运行kvm,如何在Linux发行版上安装和配置KVM和Open vSwitch
  10. UVa 1394 约瑟夫问题的变形
  11. 电脑怎么测试硬盘的读写速度_电脑硬盘这麽多到底该怎么选?硬盘的各类分类你知道吗...
  12. 五笔字根表识别码图_怎么学五笔 五笔字根表键盘图 【详细介绍】
  13. 腾讯一面+二面+三面+HR面
  14. 100个 ChatGPT 提示(Prompt)优化高质量提问案例
  15. 鞍山c语言培训,10_鞍山科技大学:C语言与数据结构_ppt_大学课件预览_高等教育资讯网...
  16. MT7603处理器性能,MT7603 wifi芯片介绍
  17. Spring Boot CORS跨域资源共享实现方案
  18. sqlitedeveloper数据库管理(SQLite Developer) v4.0.0.528 中文破解版
  19. 如何预防网站http劫持问题?
  20. ORA-01654: unable to extend index报错解决

热门文章

  1. 【Proe】三维模型转二维CAD图
  2. Thanos 与 VictoriaMetrics,谁才是打造大型 Prometheus 监控系统的王者?
  3. python抢优惠券程序_python3 优惠券查询GUI程序
  4. CentOS6.5挂载大于2TB的磁盘使用parted和GPT类型
  5. python中关系运算符惰性求值,lazy.js 惰性求值实现分析
  6. 旅行青蛙分析(Android篇)
  7. JAVA NIO:NIO与OIO的对比以及Channel通道、Selector选择器、Buffer缓冲区的介绍 高并发
  8. 我经历的日本东京交通
  9. Android Studio 使用本地gradle的配置
  10. 国科大学习资料--人工智能原理与算法-第七次作业解析(学长整理)