python分割语音端点检测
发布日期:2022/10/23 18:40:16 浏览量:
一、语音信号的分帧处理
语音信号是时序信号,其具有长时随机性和短时平稳性。长时随机性指语音信号随时间变化是一个随机过程,短时平稳性指在短时间内其特性基本不变,因为人说话是肌肉具有惯性,从一个状态到另一个状态不可能瞬时完成。语音通常在10-30ms之间相对平稳,因此语音信号处理的第一步基本都是对语音信号进行分帧处理,帧长度一般取10-30ms。
语音信号的分帧处理通常采用滑动窗的方式,窗口可以采用直角窗、Hamming窗等。窗口长度决定每一帧信号中包含原始语音信号中信息的数量,窗口每次的滑动距离等于窗口长度时,每一帧信息没有重叠,当窗口滑动距离小于窗口长度时帧信息有重合。本博文采用直角窗进行语音信号的分帧处理:
直角窗:
h(n)={1,0≤n≤N−10,other{\rm{h}}(n) = \left\{ {\begin{matrix}
{1, 0\le n \le N - 1}\\
{0,{\rm{other}}}
\end{matrix}} \right.h(n)={1,0≤n≤N−10,other
二、端点检测方法
端点检测是指找出人声开始和结束的端点。利用人声信号短时特性与非人声信号短时特性的差异可以有效地找出人声开始和结束的端点,本博文介绍短时能量和短时过零率结合进行端点检测的方法。
2.1、短时能量
第n帧信号的短时平均能量定义为:
En=∑m=n−N+1n[x(m)w(n−m)]2{E_n} = \sum\limits_{m = n - N + 1}^n {{{\left[ {x\left( m \right)w\left( {n - m} \right)} \right]}^2}}En=m=n−N+1∑n[x(m)w(n−m)]2
包含人声信号的帧的短时平均能量大于非人声信号的帧。
2.2、短时过零率
过零信号指通过零值,相邻取样值改变符号即过零,过零数是样本改变符号的数量。
第n帧信号的平均短时过零数为:
Zn=∑m=n−N+1n∣sgn[x(m)]−sgn[x(m−1)]∣w(n−m){Z_n} = \sum\limits_{m = n - N + 1}^n {\left| {{\mathop{\rm sgn}} \left[ {x\left( m \right)} \right] - {\mathop{\rm sgn}} \left[ {x\left( {m - 1} \right)} \right]} \right|w\left( {n - m} \right)}Zn=m=n−N+1∑n∣sgn[x(m)]−sgn[x(m−1)]∣w(n−m)
w(n)={1/(2N),0≤n≤N−10,otherw\left( n \right) = \left\{ {\begin{matrix}
{1/\left( {2N} \right),0 \le n \le N - 1}\\
{0,other}
\end{matrix}} \right.w(n)={1/(2N),0≤n≤N−10,other
三、Python实现
import wave
import numpy as np
import matplotlib.pyplot as plt
def read(data_path):
’’’读取语音信号
’’’
wavepath = data_path
f = wave.open(wavepath,’rb’)
params = f.getparams()
nchannels,sampwidth,framerate,nframes = params[:4] #声道数、量化位数、采样频率、采样点数
str_data = f.readframes(nframes) #读取音频,字符串格式
f.close()
wavedata = np.fromstring(str_data,dtype = np.short) #将字符串转化为浮点型数据
wavedata = wavedata * 1.0 / (max(abs(wavedata))) #wave幅值归一化
return wavedata,nframes,framerate
def plot(data,time):
plt.plot(time,data)
plt.grid(’on’)
plt.show()
def enframe(data,win,inc):
’’’对语音数据进行分帧处理
input:data(一维array):语音信号
wlen(int):滑动窗长
inc(int):窗口每次移动的长度
output:f(二维array)每次滑动窗内的数据组成的二维array
’’’
nx = len(data) #语音信号的长度
try:
nwin = len(win)
except Exception as err:
nwin = 1
if nwin == 1:
wlen = win
else:
wlen = nwin
nf = int(np.fix((nx - wlen) / inc) + 1) #窗口移动的次数
f = np.zeros((nf,wlen)) #初始化二维数组
indf = [inc * j for j in range(nf)]
indf = (np.mat(indf)).T
inds = np.mat(range(wlen))
indf_tile = np.tile(indf,wlen)
inds_tile = np.tile(inds,(nf,1))
mix_tile = indf_tile + inds_tile
f = np.zeros((nf,wlen))
for i in range(nf):
for j in range(wlen):
f[i,j] = data[mix_tile[i,j]]
return f
def point_check(wavedata,win,inc):
’’’语音信号端点检测
input:wavedata(一维array):原始语音信号
output:StartPoint(int):起始端点
EndPoint(int):终止端点
’’’
#1.计算短时过零率
FrameTemp1 = enframe(wavedata[0:-1],win,inc)
FrameTemp2 = enframe(wavedata[1:],win,inc)
signs = np.sign(np.multiply(FrameTemp1,FrameTemp2)) # 计算每一位与其相邻的数据是否异号,异号则过零
signs = list(map(lambda x:[[i,0] [i>0] for i in x],signs))
signs = list(map(lambda x:[[i,1] [i<0] for i in x], signs))
diffs = np.sign(abs(FrameTemp1 - FrameTemp2)-0.01)
diffs = list(map(lambda x:[[i,0] [i<0] for i in x], diffs))
zcr = list((np.multiply(signs, diffs)).sum(axis = 1))
#2.计算短时能量
amp = list((abs(enframe(wavedata,win,inc))).sum(axis = 1))
# # 设置门限
# print(’设置门限’)
ZcrLow = max([round(np.mean(zcr)*0.1),3])#过零率低门限
ZcrHigh = max([round(max(zcr)*0.1),5])#过零率高门限
AmpLow = min([min(amp)*10,np.mean(amp)*0.2,max(amp)*0.1])#能量低门限
AmpHigh = max([min(amp)*10,np.mean(amp)*0.2,max(amp)*0.1])#能量高门限
# 端点检测
MaxSilence = 8 #最长语音间隙时间
MinAudio = 16 #最短语音时间
Status = 0 #状态0:静音段,1:过渡段,2:语音段,3:结束段
HoldTime = 0 #语音持续时间
SilenceTime = 0 #语音间隙时间
print(’开始端点检测’)
StartPoint = 0
for n in range(len(zcr)):
if Status ==0 or Status == 1:
if amp[n] > AmpHigh or zcr[n] > ZcrHigh:
StartPoint = n - HoldTime
Status = 2
HoldTime = HoldTime + 1
SilenceTime = 0
elif amp[n] > AmpLow or zcr[n] > ZcrLow:
Status = 1
HoldTime = HoldTime + 1
else:
Status = 0
HoldTime = 0
elif Status == 2:
if amp[n] > AmpLow or zcr[n] > ZcrLow:
HoldTime = HoldTime + 1
else:
SilenceTime = SilenceTime + 1
if SilenceTime < MaxSilence:
HoldTime = HoldTime + 1
elif (HoldTime - SilenceTime) < MinAudio:
Status = 0
HoldTime = 0
SilenceTime = 0
else:
Status = 3
elif Status == 3:
break
if Status == 3:
break
HoldTime = HoldTime - SilenceTime
EndPoint = StartPoint + HoldTime
return StartPoint,EndPoint,FrameTemp1
if __name__ == ’__main__’:
data_path = ’audio_data.wav’
win = 240
inc = 80
wavedata,nframes,framerate = read(data_path)
time_list = np.array(range(0,nframes)) * (1.0 / framerate)
plot(wavedata,time_list)
StartPoint,EndPoint,FrameTemp = point_check(wavedata,win,inc)
checkdata,Framecheck = check_signal(StartPoint,EndPoint,FrameTemp,win,inc)
————————————————
版权声明:本文为CSDN博主「weixin_39710106」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_39710106/article/details/111444972
马上咨询: 如果您有业务方面的问题或者需求,欢迎您咨询!我们带来的不仅仅是技术,还有行业经验积累。
QQ: 39764417/308460098 Phone: 13 9800 1 9844 / 135 6887 9550 联系人:石先生/雷先生