语音短时过零率计算——Python实现

概念

上一篇文章介绍了语音短时能量,这篇介绍一下语音的短时过零率。短时过零率也是一个比较基础的语音时域特征,下面就来介绍一下。

短时过零率就是单位时间穿过坐标系横轴的次数,计算公式如下:

Z n = ∑ m = − ∞ ∞ ∣ s g n [ x ( m ) ] − s g n [ x ( m − 1 ) ] ∣ w ( m ) Z_n = \sum_{m = -\infty}^\infty|sgn[x(m)] - sgn[x(m - 1)]|w(m) Zn=m=sgn[x(m)]sgn[x(m1)]w(m)

其中, s g n ( n ) sgn(n) sgn(n)为符号函数:

s g n [ x ( n ) ] = { 1 x ( n ) ≥ 0 − 1 x ( n ) &lt; 0 sgn[x(n)] = \begin{cases} 1 &amp; x(n) \ge 0 \\ -1 &amp; x(n) &lt; 0 \end{cases} sgn[x(n)]={11x(n)0x(n)<0

w ( n ) w(n) w(n) 函数用来计算比:

w ( n ) = { 1 / 2 N 0 ≤ n ≤ N − 1 0 其它 w(n) = \begin{cases} 1/2N &amp; 0 \le n \le N -1 \\ 0 &amp; \text{其它} \end{cases} w(n)={1/2N00nN1其它

我们可以通过计算每一帧时间内穿过的横轴的次数,然后除以每帧内采样点的数目,就可以得到语音每帧内的短时过零率。

门限过零率

由于短时过零率很容易受到低频的干扰,因此,在计算时,加上门限,来过滤掉低频带来的影响,如图所示:

在这里插入图片描述

计算公式如下:

Z n = ∑ m = − ∞ ∞ ∣ s g n [ x ( m ) − T ] − s g n [ x ( m − 1 ) − T ] ∣ + ∣ s g n [ x ( m ) + T ] − s g n [ x ( m − 1 ) + T ] ∣ w ( m ) Z_n = \sum_{m = -\infty}^\infty{|sgn[x(m) - T] - sgn[x(m - 1) - T]| + |sgn[x(m) + T] - sgn[x(m - 1) + T]|}w(m) Zn=m=sgn[x(m)T]sgn[x(m1)T]+sgn[x(m)+T]sgn[x(m1)+T]w(m)

这样,利用添加门限的方式,就可以过滤掉低频带来的影响。

Python 实现

首先,还是先要读取语音文件:

f = wave.open("./语料/" + str(i + 1) + ".wav","rb")
# getparams() 一次性返回所有的WAV文件的格式信息
params = f.getparams()
# nframes 采样点数目
nchannels, sampwidth, framerate, nframes = params[:4]
# readframes() 按照采样点读取数据
str_data = f.readframes(nframes)            # str_data 是二进制字符串

# 以上可以直接写成 str_data = f.readframes(f.getnframes())

# 转成二字节数组形式(每个采样点占两个字节)
wave_data = np.fromstring(str_data, dtype = np.short)
print( "采样点数目:" + str(len(wave_data)))          #输出应为采样点数目
f.close()

写一个计算短时过零率的函数,我这里的语音,每帧有个采样点:

# 自定义函数,计算数值的符号。
def sgn(data):
    if data >= 0 :
        return 1
    else :
        return 0
#计算过零率
def calZeroCrossingRate(wave_data) :
    zeroCrossingRate = []
    sum = 0
    for i in range(len(wave_data)) :
        if i % 256 == 0:
            continue
        sum = sum + np.abs(sgn(wave_data[i]) - sgn(wave_data[i - 1]))
        if (i + 1) % 256 == 0 :
            zeroCrossingRate.append(float(sum) / 255)
            sum = 0
        elif i == len(wave_data) - 1 :
            zeroCrossingRate.append(float(sum) / 255)
    return zeroCrossingRate

最后,调用即可:

zeroCrossingRate = calZeroCrossingRate(wave_data)

所有过零率数据都存储在 zeroCrossingRate 数组里了 。

写在最后

由于本人刚开始学习语音部分,学的还很有限,如有书写错误的地方,希望大家帮助改正,十分感谢。

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值