语音端点检测之相关法、谱熵法、比例法(python版)

文章介绍了语音端点检测的四种方法:双门限法、自相关函数最大值法、谱熵法和比例法。自相关法利用信号的周期性差异来识别语音;谱熵法通过分析信号的谱熵特性来区分语音和噪声;比例法则关注能零比和能熵比。这些方法都在Python中实现,用于识别语音信号的开始和结束点。
摘要由CSDN通过智能技术生成

一、相关法

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)
#数据归一化

双门限点检测是一种常用的信号处理算法,用于检测信号中的边界点。以下是一段用Python实现的双门限点检测代码。 首先,我们需要导入必要的库: ```python import numpy as np import matplotlib.pyplot as plt ``` 然后,定义一个函数来实现双门限点检测: ```python def double_threshold_detection(signal, low_threshold, high_threshold): low_indices = np.where(signal < low_threshold)[0] high_indices = np.where(signal > high_threshold)[0] start_indices = [low_indices[0]] end_indices = [] for i in range(1, len(low_indices)): if low_indices[i] - low_indices[i-1] > 1: start_indices.append(low_indices[i]) for i in range(0, len(high_indices)-1): if high_indices[i+1] - high_indices[i] > 1: end_indices.append(high_indices[i]) end_indices.append(high_indices[-1]) return start_indices, end_indices ``` 在这段代码中,我们指定了两个起始阈值:low_threshold和high_threshold。首先,我们使用np.where函数找到低于低阈值的索引和高于高阈值的索引。然后,我们根据低索引的连续性找到信号的起始位置,根据高索引的连续性找到信号的结束位置。最后,我们将起始位置和结束位置作为结果返回。 接下来,我们可以使用这段代码来检测一个示例信号的边界点: ```python # 定义一个示例信号 signal = np.array([1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 5, 4, 3, 2]) # 调用双门限点检测函数 start_indices, end_indices = double_threshold_detection(signal, 1, 4) # 绘制信号及检测结果 plt.plot(signal) plt.scatter(start_indices, [signal[i] for i in start_indices], color='r') plt.scatter(end_indices, [signal[i] for i in end_indices], color='g') plt.show() ``` 以上代码将绘制这段示例信号,并在检测到的起始位置处用红色圆点标记,结束位置处用绿色圆点标记。 这就是双门限点检测Python代码实现。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值