一、相关法
1、短时自相关
自相关函数具有一些性质,如它是偶函数;假设序列具有周期性,则其自相关函数也是同周期的周期函数等。对于浊音语音可以用自相关函数求出语音波形序列的基音周期。此外, 在进行语音信号的线性预测分析时,也要用到自相关函数
2、自相关函数最大值法
图
4‐2
和图 4‐3 分别是噪声信号和含噪语音的自相关函数。从图可知,两种信号的自 相关函数存在极大的差异,因此可利用这种差别来提取语音端点。根据噪声的情况,设置两个阈值
T1
和
T2
,当相关函数最大值大于
T2 时,便判定是语音;当相关函数最大值大于或小于
T1
时,则判定为语音信号的端点。
3.代码运行
from speechlib import *
(fs, data) = wavfile.read('C4_1_y.wav')
data = data - np.mean(data)
data = data / np.max(data)
IS = 0.25
wlen = 200
inc = 80
N = len(data)
time = [i / fs for i in range(N)]
wnd = np.hamming(wlen) #使用汉明窗
NIS = int((IS * fs - wlen) // inc + 1)
thr1 = 1.1
thr2 = 1.3
voiceseg, vsl, SF, NF, Rum = vad_corr(data, wnd, inc, NIS, thr1, thr2)
fn = len(SF)
frameTime = FrameTimeC(fn, wlen, inc, fs)
plt.subplot(2, 1, 1)
plt.plot(time, data)
plt.title('纯语音波形')
plt.ylabel('幅值')
plt.subplot(2, 1, 2)
plt.plot(frameTime, Rum)
plt.title('短时自相关函数')
plt.xlabel('时间/s')
plt.ylabel('幅值')
for i in range(vsl):
nx1=voiceseg[i]['start']
nx2=voiceseg[i]['end']
plt.subplot(2, 1, 1)
plt.axvline(frameTime[nx1], np.min(data), np.max(data), color='blue', linestyle='--')
plt.axvline(frameTime[nx2], np.min(data), np.max(data), color='red', linestyle='-')
plt.legend(['波形', '起点', '终点'])
plt.subplot(2, 1, 2)
plt.axvline(frameTime[nx1], np.min(Rum), np.max(Rum), color='blue', linestyle='--')
plt.axvline(frameTime[nx2], np.min(Rum), np.max(Rum), color='red', linestyle='-')
plt.legend(['短时自相关', '起点', '终点'])
plt.show()
核心代码解释:
名称:vad_corr
功能:用自相关函数最大值法进行端点检测。
调用格式:[voiceseg,vsl,SF,NF,Rum]=vad_corr(x,wnd,inc,NIS,th1,th2)
说明:输入参数 x 是输入的语音数据;wnd 是窗函数或窗长;inc 是帧移;th1 是端点检
测阈值;th2 是语音检测阈值;NIS 是无声段的帧数,用来计算阈值。输出参数 voiceseg 是
一个数据结构,记录了语音端点的信息;vsl 是 voiceseg 的长度;SF 是语音帧标志(SF=1 表
示该帧是语音段);NF 是噪声/无声帧标志(NF=1 表示该帧是噪声/无声段);Rum 是返回的
短时自相关序列的最大值。
二、谱熵法
还是理论(不想写)
1.谱熵特征
(1)语音信号的谱熵不同于噪声信号的谱熵。
(2)理论上,如果谱的分布保持不变,语音信号幅值的大小不会影响归一化。但实际上,
语音谱熵随语音随机性而变化,与能量特征相比,谱熵的变化是很小的。
(3)在某种程度上讲,谱熵对噪声具有一定的稳健性,在相同的语音信号当信噪比降
低时,语音信号的谱熵值的形状大体保持不变,这说明谱熵是一个比较稳健性的特征参数。
(4)语音谱熵只与语音信号的随机性有关,而与语音信号的幅度无关,理论上认为只
要语音信号的分布不发生变化,那么语音谱熵不会受到语音幅度的影响。另外,由于每个频
率分量在求其概率密度函数的时侯都经过了归一化处理,所以从这一方面也证明了语音信号
的谱熵只会与语音分布有关,而不会与幅度大小有关。
2.谱熵检测大致思路
(1)首先对语音信号进行分帧加窗、取 FFT 变换的点数;
(2)计算出每一帧的谱的能量;
(3)计算出每一帧中每个样本点的概率密度函数;
(4)计算出每一帧的谱熵值;
(5)设置判决门限;
(6)根据各帧的谱熵值进行端点检测。
from speechlib import *
(fs, data) = wavfile.read('C4_1_y.wav')
data = data - np.mean(data)
data = data / np.max(data)
IS = 0.25
wlen = 200
inc = 80
N = len(data)
time = [i / fs for i in range(N)]
wnd = np.hamming(wlen)
overlap = wlen - inc
NIS = int((IS * fs - wlen) // inc + 1)
thr1 = 0.99
thr2 = 0.96
voiceseg, vsl, SF, NF, Enm = vad_specEN(data, wnd, inc, NIS, thr1, thr2, fs)
fn = len(SF)
frameTime = FrameTimeC(fn, wlen, inc, fs)
plt.subplot(2, 1, 1)
plt.plot(time, data)
plt.title('纯语音波形')
plt.ylabel('幅值')
plt.subplot(2, 1, 2)
plt.plot(frameTime, Enm)
plt.title('短时谱熵')
plt.xlabel('时间/s')
plt.ylabel('幅值')
for i in range(vsl):
nx1=voiceseg[i]['start']
nx2=voiceseg[i]['end']
plt.subplot(2, 1, 1)
plt.axvline(frameTime[nx1], np.min(data), np.max(data), color='blue', linestyle='--')
plt.axvline(frameTime[nx2], np.min(data), np.max(data), color='red', linestyle='-')
plt.legend(['波形', '起点', '终点'])
plt.subplot(2, 1, 2)
plt.axvline(frameTime[nx1], np.min(Enm), np.max(Enm), color='blue', linestyle='--')
plt.axvline(frameTime[nx2], np.min(Enm), np.max(Enm), color='red', linestyle='-')
plt.legend(['短时谱熵', '起点', '终点'])
plt.show()
核心代码解释
名称:vad_specEn
功能:用谱熵法进行端点检测。
调用格式:[voiceseg,vsl,SF,NF,Enm]=vad_specEn(x,wnd,inc,NIS,th1,th2,fs)
说明:输入参数 x 是输入的语音数据;wnd 是窗函数或窗长;inc 是帧移;th1 是端点检
测阈值;th2 是语音检测阈值;NIS 是无声段的帧数,用来计算阈值;fs 是采样频率。输出参
数 voiceseg 是一个数据结构,记录了语音端点的信息;vsl 是 voiceseg 的长度;SF 是语音帧
标志(SF=1 表示该帧是语音段);NF 是噪声/无声帧标志(NF=1 表示该帧是噪声/无声段);
Enm 是计算的谱熵
结果
三、比例法
from speechlib import *
(fs, data) = wavfile.read('C4_1_y.wav')
data = data - np.mean(data)
data = data / np.max(data)
IS = 0.25
wlen = 200
inc = 80
N = len(data)
time = [i / fs for i in range(N)]
wnd = np.hamming(wlen)
overlap = wlen - inc
NIS = int((IS * fs - wlen) // inc + 1)
mode = 1
if mode == 1:
thr1 = 3
thr2 = 4
tlabel = '能零比'
elif mode == 2:
thr1 = 0.05
thr2 = 0.1
tlabel = '能熵比'
voiceseg, vsl, SF, NF, Epara = vad_pro(data, wnd, inc, NIS, thr1, thr2, mode)
fn = len(SF)
frameTime = FrameTimeC(fn, wlen, inc, fs)
plt.subplot(2, 1, 1)
plt.plot(time, data)
plt.title('纯语音波形')
plt.ylabel('幅值')
plt.subplot(2, 1, 2)
plt.plot(frameTime, Epara)
plt.title(tlabel)
plt.xlabel('时间/s')
plt.ylabel('幅值')
for i in range(vsl):
nx1=voiceseg[i]['start']
nx2=voiceseg[i]['end']
plt.subplot(2, 1, 1)
plt.axvline(frameTime[nx1], np.min(data), np.max(data), color='blue', linestyle='--')
plt.axvline(frameTime[nx2], np.min(data), np.max(data), color='red', linestyle='-')
plt.legend(['波形', '起点', '终点'])
plt.subplot(2, 1, 2)
plt.axvline(frameTime[nx1], np.min(Epara), 1.0, color='blue', linestyle='--')
plt.axvline(frameTime[nx2], np.min(Epara), 1.0, color='red', linestyle='-')
plt.legend([tlabel, '起点', '终点'])
plt.show()
名称:vad_pro
功能:用比例法进行端点检测。
调用格式:[voiceseg,vsl,SF,NF,Epara]=vad_pro(x,wnd,inc,NIS,th1,th2,mode);
说明:输入参数 x 是输入的语音数据;wnd 是窗函数或窗长;inc 是帧移;th1 是端点检
测阈值;th2 是语音检测阈值;NIS 是无声段的帧数,用来计算阈值;mode 是算法模式,1
代表能零比,2 代表能熵比。输出参数 voiceseg 是一个数据结构,记录了语音端点的信息;
vsl 是 voiceseg 的长度;SF 是语音帧标志(SF=1 表示该帧是语音段);NF 是噪声/无声帧标志
(NF=1 表示该帧是噪声/无声段);Epara 是计算的能零比或能熵比。
四、总结
语音端点检测一共介绍了4种,双门限法、相关法、谱熵法、比例法
双门限法:(10条消息) 语音端点检测之双门限法(python版)_X在敲AI代码的博客-CSDN博客
核心参数部分:
1.双门限法
名称:vad_TwoThr
功能:用双门限法进行端点检测。
调用格式:[voiceseg,vsl,SF,NF,amp,zcr]=vad_TwoThr(x,wlen,inc,NIS)
2.相关法
名称:vad_corr
功能:用自相关函数最大值法进行端点检测。
调用格式:[voiceseg,vsl,SF,NF,Rum]=vad_corr(x,wnd,inc,NIS,th1,th2)
Rum 是返回的短时自相关序列的最大值。
3.谱熵法:
名称:vad_specEn
功能:用谱熵法进行端点检测。
调用格式:[voiceseg,vsl,SF,NF,Enm]=vad_specEn(x,wnd,inc,NIS,th1,th2,fs)
Enm 是计算的谱熵
4.比例法:
名称:vad_pro
功能:用比例法进行端点检测。
调用格式:[voiceseg,vsl,SF,NF,Epara]=vad_pro(x,wnd,inc,NIS,th1,th2,mode);
mode 是算法模式,1代表能零比,2 代表能熵比。 Epara 是计算的能零比或能熵比。
共同参数解释:输出参数 voiceseg 是一个数据结构,记录了语音端点的信息;
vsl 是 voiceseg 的长度;SF 是语音帧标志(SF=1 表示该帧是语音段);NF 是噪声/无声帧标志
输入参数 x 是输入的语音数据;wnd 是窗函数或窗长;inc 是帧移;th1 是端点检
测阈值;th2 是语音检测阈值;NIS 是无声段的帧数,用来计算阈值;fs 是采样频率。
数据处理部分:
(fs, data) = wavfile.read('XXXXX.wav') #数据读入
data = data - np.mean(data) #np.mean 求平均数
data = data / np.max(data)
#数据归一化