音频静音检测算法

1、简介

        Voice Activity Detector, 即语音动态检测;静音检测对于实时通话有着很重要的作用,什么是静默检测?顾名思义就是检测语音的状态,静默状态还是激活状态,这里存在一个问题,就是多长时间的静默状态才当作语音的结束,以及大的语音能量以及多长时间的状态持续才当作语音激活的开始,通常这个需要一个经验值。

2、静音检测的应用:

1、节省带宽:

        用来检测发送端是否有人在讲话,来决定是否发送语音数据,当检测到用户没有讲话,即静音状态时,发送端可以不发送语音报文,只发送静音指示报文,从而降低语音报文占用的带宽。如下所示,正常的语音包负载占据160字节(G711U编码);

而静音帧只有几个字节,如下所示:

        这种情况把VAD阈值设置的要低一些,否则会影响音频的质量,如果阈值过高的话,有可能在开始讲话的时候会丢失几个字,需要注意;

3、展示收发话状态:

        检测语音流是否有声音,来展示收发话状态 ,如果感觉不准的话,可以累积一秒的音频包,然后算比例再进行决策,比如在一秒内超过80%的数据包都是静音包,则可以视为无人说话状态,否则,反之,实测效果还是比较准;

以下是我基于webrtc写的一个代码调用示例:

#define FRAMESIZE 160

int main(int argc, char** argv)
{
	FILE *fpInput = NULL, *fpOutput = NULL;
	VadInst * handle = NULL;
	int status;
	int fs = 8000;
	short audioFrame[FRAMESIZE];
	handle = NULL;

	status = WebRtcVad_Create(&handle);
	if (status != 0)
	{
		printf("Create is error \n");
		return -1;
	}

	status = WebRtcVad_Init(handle);
	if (status != 0)
	{
		printf("Init is error\n");
		return -1;
	}

	fpInput = fopen("original_8k.raw", "rb");
	fpOutput = fopen("result.txt", "wb");
	if (fpInput == NULL)
	{
		printf("open file failure\n");
		return -1;
	}

	status = WebRtcVad_set_mode(handle, 2);
	if (status != 0)
	{
		printf("set mode is error\n");
		return -1;
	}

	while (!feof(fpInput))
	{
		fread(audioFrame, sizeof(short), FRAMESIZE, fpInput);

		status = WebRtcVad_Process(handle, fs, audioFrame, FRAMESIZE);
		if (status == -1)
		{
			printf("WebRtcVad_Process is error\n");
			return -1;
		}
		else if (status == 1)
		{
			printf("Active Voice\n");
			
		}
		else
		{
			printf("Non-active Voice\n");
		}

		fprintf(fpOutput, "%2d", status);
	}

	fclose(fpInput);
	fclose(fpOutput);
	status = WebRtcVad_Free(handle);
	if (status != 0)
	{
		printf("Free is failure\n");
		return -1;
	}

	printf("Finished \n");
	getchar();
	
	return 0;
}

项目地址https://download.csdn.net/download/unique_no1/83209937

        里面包含测试程序和可执行文件,windows平台和linux平台的我都已经编译好了,大家可以测试看下效果,接口调用也比较简单,欢迎沟通、交流。

tel:18108010758

vx:unique_no_1


-------------------------------------------------------------------------------------------------------------------------------

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是代码实现: ```python import librosa import soundfile as sf import numpy as np import matplotlib.pyplot as plt # 加载音频文件 audio_file = 'example.wav' y, sr = librosa.load(audio_file, sr=None) # 计算短时能量特征 frame_length = int(0.02 * sr) energy = librosa.feature.rms(y, frame_length=frame_length, hop_length=frame_length, center=True) # 计算谱质心特征 spec_cent = librosa.feature.spectral_centroid(y, sr=sr, n_fft=frame_length, hop_length=frame_length, freq=None) # 绘制短时能量与谱质心特征 plt.figure(figsize=(10, 6)) plt.subplot(2, 1, 1) plt.plot(np.arange(len(y)) / sr, y) plt.plot(np.arange(len(energy[0])) * frame_length / sr, energy[0], color='r') plt.ylabel('Energy') plt.subplot(2, 1, 2) plt.plot(np.arange(len(y)) / sr, y) plt.plot(np.arange(len(spec_cent[0])) * frame_length / sr, spec_cent[0], color='r') plt.ylabel('Spectral Centroid') plt.xlabel('Time (s)') plt.show() # 端点检测 threshold_energy = 0.1 # 短时能量阈值 threshold_spec_cent = 1000 # 谱质心阈值 endpoints = [] is_speech = False for i in range(len(energy[0])): if energy[0][i] > threshold_energy and spec_cent[0][i] > threshold_spec_cent: if not is_speech: endpoints.append(i * frame_length) is_speech = True else: if is_speech: endpoints.append(i * frame_length) is_speech = False if is_speech: endpoints.append(len(y)) # 绘制端点检测结果与静音区域标记 plt.figure(figsize=(10, 6)) plt.plot(np.arange(len(y)) / sr, y) for i in range(0, len(endpoints), 2): plt.axvspan(endpoints[i] / sr, endpoints[i+1] / sr, color='r', alpha=0.2) plt.xlabel('Time (s)') plt.show() # 去除静音 y_new = np.array([]) for i in range(0, len(endpoints), 2): y_new = np.concatenate((y_new, y[endpoints[i]:endpoints[i+1]])) sf.write('example_no_silence.wav', y_new, sr) # 绘制去静音前后的端点检测对比图 plt.figure(figsize=(10, 6)) plt.subplot(2, 1, 1) plt.plot(np.arange(len(y)) / sr, y) for i in range(0, len(endpoints), 2): plt.axvspan(endpoints[i] / sr, endpoints[i+1] / sr, color='r', alpha=0.2) plt.xlabel('Time (s)') plt.title('Before Removing Silence') plt.subplot(2, 1, 2) plt.plot(np.arange(len(y_new)) / sr, y_new) plt.xlabel('Time (s)') plt.title('After Removing Silence') plt.show() ``` 上述代码中,我们首先使用 `librosa.load` 函数加载音频文件,并计算出短时能量和谱质心特征。然后,我们绘制出短时能量和谱质心特征的示意图。 接着,我们使用一个简单的算法进行端点检测。具体来说,当短时能量和谱质心同时超过一定阈值时,我们认为这是语音信号,否则就是静音区域。我们将检测到的端点信息保存在 `endpoints` 列表中,并绘制出端点检测结果和静音区域标记的示意图。 然后,我们使用 `numpy.concatenate` 函数将去除静音后的音频片段拼接起来,并使用 `soundfile.write` 函数将音频保存在本地文件夹中。最后,我们绘制出去静音前后的端点检测对比图。 需要注意的是,上述代码中的阈值和算法只是一个示例,实际应用中需要根据具体情况进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

音视频工具站

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值