概念
上一篇文章介绍了语音短时能量,这篇介绍一下语音的短时过零率。短时过零率也是一个比较基础的语音时域特征,下面就来介绍一下。
短时过零率就是单位时间穿过坐标系横轴的次数,计算公式如下:
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(m−1)]∣w(m)
其中, s g n ( n ) sgn(n) sgn(n)为符号函数:
s g n [ x ( n ) ] = { 1 x ( n ) ≥ 0 − 1 x ( n ) < 0 sgn[x(n)] = \begin{cases} 1 & x(n) \ge 0 \\ -1 & x(n) < 0 \end{cases} sgn[x(n)]={1−1x(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 & 0 \le n \le N -1 \\ 0 & \text{其它} \end{cases} w(n)={1/2N00≤n≤N−1其它
我们可以通过计算每一帧时间内穿过的横轴的次数,然后除以每帧内采样点的数目,就可以得到语音每帧内的短时过零率。
门限过零率
由于短时过零率很容易受到低频的干扰,因此,在计算时,加上门限,来过滤掉低频带来的影响,如图所示:
计算公式如下:
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(m−1)−T]∣+∣sgn[x(m)+T]−sgn[x(m−1)+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
数组里了 。
写在最后
由于本人刚开始学习语音部分,学的还很有限,如有书写错误的地方,希望大家帮助改正,十分感谢。