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

《语音信号处理试验教程》(梁瑞宇等)的代码主要是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语音基础操作–3.5线性预测分析
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. 短时能量与短时平均幅度

设第 n n n帧语音信号 x n ( m ) x_n(m) xn(m)的短时能量用 E n E_n En表示:
E n = ∑ m = 1 N x n 2 ( m ) E_n=\sum\limits_{m=1}^Nx_n^2(m) En=m=1Nxn2(m)

E n E_n En是度量语音信号幅度值变化的函数,对高电平非常敏感(用平方计算的)。可以用短时平均幅度函数 M n M_n Mn:
M n = ∑ m = 1 N ∣ x n ( m ) ∣ M_n=\sum\limits_{m=1}^N|x_n(m)| Mn=m=1Nxn(m)

M n M_n Mn也是一帧语音信号的能量大小的表征,不会应该平方造成较大差异。

  1. 短时过零率

表示一帧语音信号波形穿过横轴的次数。也就是前后一个样本点符号变化的次数。
Z n = 1 2 ∑ m = 1 N ∣ s g n [ x n ( m ) ] − s g n [ x n ( m − 1 ) ] ∣ Z_n=\frac{1}{2}\sum\limits_{m=1}^N|sgn[x_n(m)]-sgn[x_n(m-1)]| Zn=21m=1Nsgn[xn(m)]sgn[xn(m1)]

在实际计算那种,由于信号中可能有50Hz的工频干扰或偏移量,计算的过零率参数往往不准确,所以在A/D转换前的防混叠带通滤波器的低端截止频率要高于50Hz,抑制电源干扰。在软件上去质量偏量,或者采用低直流漂移量元件。实际在计算过零率时候,还可以使用 x i ( m ) ∗ x i ( m + 1 ) < 0 x_i(m)*x_i(m+1)<0 xi(m)xi(m+1)<0来判断。

  1. 短时自相关

自相关函数具有一些性质(如偶函数,如果序列是有周期性,自相关函数也有周期性)。对于浊音可以用自相关函数求出基音周期。在进行语音信号的预测分析时,也要用到自相关函数。语音信号 x n ( m ) x_n(m) xn(m)的自相关函数 R n ( k ) R_n(k) Rn(k)可以表示为:
R n ( k ) = ∑ m = 1 N − k x n ( m ) x n ( m + k ) , 其 中 ( 0 ⩽ k ⩽ K ) R_n(k)=\sum\limits_{m=1}^{N-k}x_n(m)x_n(m+k),其中(0\leqslant k \leqslant K) Rn(k)=m=1Nkxn(m)xn(m+k)(0kK)

K为最大延迟点数。短时自相关函数的性质有:

  • 如果 x n ( m ) x_n(m) xn(m)是周期的,假设周期为 N p N_p Np,则自相关函数是同周期的周期函数,即 R n ( k ) = R n ( k + N p ) R_n(k)=R_n(k+N_p) Rn(k)=Rn(k+Np)
  • R n ( k ) R_n(k) Rn(k)是偶函数,即 R n ( k ) = R n ( − k ) R_n(k)=R_n(-k) Rn(k)=Rn(k)
  • k = 0 k=0 k=0时,自相关函数具有最大值,即 R n ( 0 ) ⩾ ∣ R n ( k ) ∣ R_n(0)\geqslant |R_n(k)| Rn(0)Rn(k),并且 R n ( 0 ) R_n(0) Rn(0)等于确定性信号序列的能量或随机性序列的平均功率。
  1. 短时平均幅度差

短时自相关函数是语言信号分析的重要参量,但是计算自相关喊得运算非常大,为了避免乘法,一个简单的方法就是利用差值,即短时平均幅度差函数。因为如果信号是周期(周期为 N p N_p Np)的,则相距的周期的整数倍的样本点的幅值是相等的,差值为0。
d ( n ) = x ( n ) − x ( n + k ) = 0 , ( k = 0 , ± N p , ± 2 N p , . . . ) d(n)=x(n)-x(n+k)=0,(k=0,±N_p,±2N_p,...) d(n)=x(n)x(n+k)=0,(k=0,±Np,±2Np,...)

实际语音信号 d ( n ) d(n) d(n)不为零,是一个很小的值。可定义短时平均幅度差为:
F n ( k ) = ∑ m = 1 N − k ∣ x n ( m ) − x n ( m + k ) ∣ F_n(k)=\sum\limits_{m=1}^{N-k}|x_n(m)-x_n(m+k)| Fn(k)=m=1Nkxn(m)xn(m+k)

如果 x ( n ) x(n) x(n)在窗口范围内,具有周期性,则 F n ( k ) F_n(k) Fn(k) k = 0 , ± N p , ± 2 N p , . . . k=0,±N_p,±2N_p,... k=0,±Np,±2Np,...时将出现极小值。平均幅度差函数与自相关喊得关系为:
F n ( k ) = 2 β ( k ) [ R n ( 0 ) − R n ( k ) ] 1 / 2 F_n(k)=\sqrt{2}\beta(k)[R_n(0)-R_n(k)]^{1/2} Fn(k)=2 β(k)[Rn(0)Rn(k)]1/2

其中 β ( k ) \beta(k) β(k)在不同的语音段在0.6~1.0之间变化,但是对一个特定的语音段,他随着 k k k值的变化并不明显。


# timefeature.py
import numpy as np
from .C3_1_y_1 import enframe


def STAc(x):
    """
    计算短时相关函数
    :param x:
    :return:
    """
    para = np.zeros(x.shape)
    fn = x.shape[1]
    for i in range(fn):
        R = np.correlate(x[:, i], x[:, i], 'valid')
        para[:, i] = R
    return para


def STEn(x, win, inc):
    """
    计算短时能量函数
    :param x:
    :param win:
    :param inc:
    :return:
    """
    X = enframe(x, win, inc)
    s = np.multiply(X, X)
    return np.sum(s, axis=1)


def STMn(x, win, inc):
    """
    计算短时平均幅度计算函数
    :param x:
    :param win:
    :param inc:
    :return:
    """
    X = enframe(x, win, inc)
    s = np.abs(X)
    return np.mean(s, axis=1)


def STZcr(x, win, inc):
    """
    计算短时过零率
    :param x:
    :param win:
    :param inc:
    :return:
    """
    X = enframe(x, win, inc)
    X1 = X[:, :-1]
    X2 = X[:, 1:]
    s = np.multiply(X1, X2)
    sgn = np.where(s < 0, 1, 0)
    return np.sum(sgn, axis=1)


def STAmdf(X):
    """
    计算短时幅度差,好像有点问题
    :param X:
    :return:
    """
    # para = np.zeros(X.shape)
    fn = X.shape[1]
    wlen = X.shape[0]
    para = np.zeros((wlen, wlen))
    for i in range(fn):
        u = X[:, i]
        for k in range(wlen):
            en = len(u)
            para[k, :] = np.sum(np.abs(u[k:] - u[:en - k]))
    return para


def FrameTimeC(frameNum, frameLen, inc, fs):
    ll = np.array([i for i in range(frameNum)])
    return ((ll - 1) * inc + frameLen / 2) / fs

# C3_2_y.py
from scipy.io import wavfile
import matplotlib.pyplot as plt
from chapter3_分析实验.windows import *
from chapter3_分析实验.timefeature import *
from chapter2_基础.soundBase import *

data, fs = soundBase('C3_2_y.wav').audioread()
inc = 100
wlen = 200
win = hanning_window(wlen)
N = len(data)
time = [i / fs for i in range(N)]

EN = STEn(data, win, inc)  # 短时能量
Mn = STMn(data, win, inc)  # 短时平均幅度
Zcr = STZcr(data, win, inc)  # 短时过零率

X = enframe(data, win, inc)
X = X.T
Ac = STAc(X)
Ac = Ac.T
Ac = Ac.flatten()

Amdf = STAmdf(X)
Amdf = Amdf.flatten()

fig = plt.figure(figsize=(14, 13))
plt.subplot(3, 1, 1)
plt.plot(time, data)
plt.title('(a)语音波形')
plt.subplot(3, 1, 2)
frameTime = FrameTimeC(len(EN), wlen, inc, fs)
plt.plot(frameTime, Mn)
plt.title('(b)短时幅值')
plt.subplot(3, 1, 3)
plt.plot(frameTime, EN)
plt.title('(c)短时能量')
plt.savefig('images/energy.png')

fig = plt.figure(figsize=(10, 13))
plt.subplot(2, 1, 1)
plt.plot(time, data)
plt.title('(a)语音波形')
plt.subplot(2, 1, 2)
plt.plot(frameTime, Zcr)
plt.title('(b)短时过零率')
plt.savefig('images/Zcr.png')

fig = plt.figure(figsize=(10, 13))
plt.subplot(2, 1, 1)
plt.plot(time, data)
plt.title('(a)语音波形')
plt.subplot(2, 1, 2)
plt.plot(Ac)
plt.title('(b)短时自相关')
plt.savefig('images/corr.png')

fig = plt.figure(figsize=(10, 13))
plt.subplot(2, 1, 1)
plt.plot(time, data)
plt.title('(a)语音波形')
plt.subplot(2, 1, 2)
plt.plot(Amdf)
plt.title('(b)短时幅度差')
plt.savefig('images/Amdf.png')

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 5
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值