微立顶科技

新闻资讯

创新 服务 价值

  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     联系人:石先生/雷先生