python pyaudio对音频进行端点检测,检测出说话区间

python pyaudio对音频进行端点检测,检测出说话区间

主要采用过零率和语音能量来进行检测,并设置双阈值。
代码如下:

# -*- coding: utf-8 -*-
import wave
import os
import matplotlib.pyplot as plt
import numpy as np# 判断是否变号
def sgn(data):if data >= 0:return 1else:return 0# 计算每一帧的能量,设定每 256 个采样点为一帧,一帧就是一个语音块
def calEnergy(wave_data):energy = []sum = 0for i in range(len(wave_data)):sum = sum + (int(wave_data[i]) * int(wave_data[i]))if (i + 1) % 256 == 0:energy.append(sum)sum = 0elif i == len(wave_data) - 1:energy.append(sum)return energy# 计算过零率
def calZeroCrossingRate(wave_data):zeroCrossingRate = []sum = 0for i in range(len(wave_data)):# 判断当前索引 i 是否是 256 的倍数,为了避免从音频数据的开头和上一帧最后一个采样点计算过零率if i % 256 == 0:continuesum = sum + np.abs(sgn(wave_data[i]) - sgn(wave_data[i - 1]))if (i + 1) % 256 == 0:zeroCrossingRate.append(float(sum) / 255)sum = 0elif i == len(wave_data) - 1:zeroCrossingRate.append(float(sum) / 255)return zeroCrossingRate"""
当使用双门限法进行语音端点检测时,可以按照以下步骤实现:
计算语音信号的短时能量和过零率。可以使用算法或库函数来计算短时能量和过零率。
初始化参数。设定较高和较低能量阈值、过零率阈值等参数。
根据能量阈值进行初步检测。遍历短时能量序列,当能量超过较高能量阈值时,标记为起始点;
当能量低于较低能量阈值时,标记为结束点。
根据过零率阈值进行进一步检测。遍历起始点和结束点之间的时间窗口,在时间窗口内计算过零率,
并判断是否超过过零率阈值。若超过阈值,说明该点为语音信号的起始或结束点;
若未超过阈值,说明该点为语音信号的过渡点。
根据检测到的起始和结束点,得到语音信号的分段结果。
"""# 利用短时能量,短时过零率,使用双门限法进行端点检测
def endPointDetect(wave_data, energy, zeroCrossingRate):sum = 0energyAverage = 0# 短时能量平均数for en in energy:sum = sum + enenergyAverage = sum / len(energy)#    print(energyAverage)# 首先计算语音前一段的静音部分的能量均值(前5帧)sum = 0for en in energy[:5]:sum = sum + enML = sum / 5# 将能量均值的1/4作为MHMH = energyAverage / 4  # 较高的能量阈值# 将静音部分的能量均值和MH的平均数的1/4作为ML。ML = (ML + MH) / 4  # 较低的能量阈值# 计算前5帧的过零率sum = 0for zcr in zeroCrossingRate[:5]:sum = float(sum) + zcrZs = sum / 5  # 过零率阈值A = []B = []C = []# 首先利用较大能量阈值 MH 进行初步检测flag = 0for i in range(len(energy)):if len(A) == 0 and flag == 0 and energy[i] > MH:A.append(i)flag = 1# 如果当前点与上一个浊音的结束点之间的距离大于阈值(这里设为21),则将当前点设为新的浊音的起始点elif flag == 0 and energy[i] > MH and i - 21 > A[len(A) - 1]:A.append(i)flag = 1# 如果当前能量超过 MH,但当前点与上一个浊音的结束点之间的距离小于等于阈值 21,则将上一个浊音的结束点舍弃elif flag == 0 and energy[i] > MH and i - 21 <= A[len(A) - 1]:A = A[:len(A) - 1]flag = 1# 拿到结束点if flag == 1 and energy[i] < MH:A.append(i)flag = 0print("较高能量阈值,计算后的浊音A:" + str(A))# 根据较低能量阈值,在基础 A 上增加一段语音for j in range(len(A)):i = A[j]if j % 2 == 1:  # 奇数下标为结束点while i < len(energy) and energy[i] > ML:i = i + 1B.append(i)else:  # 偶数下标为起始点while i > 0 and energy[i] > ML:i = i - 1B.append(i)print("较低能量阈值,增加一段语言B:" + str(B))# 利用过零率进行最后一步检测,过零率高表示活跃语音print(B)for j in range(len(B)):i = B[j]if j % 2 == 1:  # 奇数下标为结束点while i < len(zeroCrossingRate) and zeroCrossingRate[i] >= 3 * Zs:i = i + 1C.append(i)else:  # 偶数下标为起始点while i > 0 and zeroCrossingRate[i] >= 3 * Zs:i = i - 1C.append(i)print("过零率阈值,最终语音分段C:" + str(C))return Cf = wave.open("./output.wav", "rb")
# getparams() 一次性返回所有的WAV文件的格式信息
params = f.getparams()
# nframes 采样点数目 帧数
nchannels, sampwidth, framerate, nframes = params[:4]
# readframes() 按照采样点读取数据
str_data = f.readframes(nframes)  # str_data 是二进制字符串# 以上可以直接写成 str_data = f.readframes(f.getnframes())# 转成二字节数组形式(每个采样点占两个字节)
wave_data = np.fromstring(str_data, dtype=np.short)
f.close()# 转成双声道
wave_data.shape = -1, 2
wave_data = wave_data.Ttime = np.arange(0, nframes) * (1.0 / framerate)  # 每个采样点对应的时间,单位是 s
waveDate = wave_data[0]  # 提取一个声道的数据
print("采样点数目:" + str(len(waveDate)))  # 输出一个声道应为采样点数目
print("采样率:" + str(framerate))
plt.plot(waveDate)
plt.ylabel("voiceprint")
plt.xlabel("nframes")
plt.show()minvalue = min(waveDate)
maxvalue = max(waveDate)
energy = calEnergy(waveDate)  # 每 256 为一帧,energy 为语音块的能量
plt.subplot(211)
plt.plot(energy)
plt.ylabel("energy")
plt.xlabel("frame")# 保存 energy
with open("./energy/1_en.txt", "w") as f:for en in energy:f.write(str(en) + "\n")zeroCrossingRate = calZeroCrossingRate(waveDate)
plt.subplot(212)
plt.plot(zeroCrossingRate)  # 同样是以帧为单位的过零率
plt.ylabel("zeroCrossingRate")
plt.xlabel("frame")
plt.show()# 保存过零率
with open("./zero/1_zero.txt", "w") as f:for zcr in zeroCrossingRate:f.write(str(zcr) + "\n")# 双门限法进行端点检测
N = endPointDetect(waveDate, energy, zeroCrossingRate)plt.plot(waveDate)
for i in range(0,len(N),2):print(i)x = [N[i] * 256, N[i] * 256]  # * 256 放大到原来的采样点上x1 = [N[i+1] * 256, N[i+1] * 256]y = [minvalue, maxvalue]plt.plot(x, y, "-g")plt.plot(x1, y, "-r")plt.plot()plt.ylabel("voiceprint")plt.xlabel("nframes")plt.show()# 输出为 pcm 格式
with open("./corpus/1.pcm", "wb") as f:i = 0while i < len(N):for num in waveDate[N[i] * 256: N[i + 1] * 256]:f.write(num)i = i + 2

运行结果如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/196973.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MysqlCluster集群部署

1.引言 1.1目的 部署MysqlCluster集群环境 1.2 MySQL集群Cluster原理 1. 数据分片 MySQL集群Cluster将数据分成多个片段&#xff0c;每个片段存储在不同的服务器上。这样可以将数据负载分散到多个服务器上&#xff0c;提高系统的性能和可扩展性。 2. 数据同步 MySQL集群…

layui+ssm实现数据表格双击编辑更新数据

layui实现数据表格双击编辑数据更新 在使用layui加载后端数据请求时&#xff0c;对数据选项框进行双击即可实现数据的输入编辑更改 代码块 var form layui.form, table layui.table,layer parent.layer undefined ? layui.layer : parent.layer,laypage layui.laypag…

ElasticSearch学习笔记(一)

计算机软件的学习&#xff0c;最重要的是举一反三&#xff0c;只要大胆尝试&#xff0c;认真验证自己的想法就能收到事办功倍的效果。在开始之前可以看看别人的教程做个快速的入门&#xff0c;然后去官方网站看看官方的教程&#xff0c;有中文教程固然是好&#xff0c;没有中文…

备忘录不小心删了怎么办?如何找回我的备忘录?

如果你的记性不太好&#xff0c;或者每天需要记住、完成的事情很多&#xff0c;那么养成随手记事的好习惯是非常有必要的。因为手机是每个成年人都会随身携带的电子设备&#xff0c;所以直接在手机上记录事情比较简单、便捷。而手机备忘录、便签、笔记等工具类软件&#xff0c;…

简单的界面与数据分离的架构

草图绘制于2021年2月19日 当时用到了&#xff1a;qt的子项目、delegate、view和widget的关系&#xff0c;有感而写的小备忘&#xff0c;2022年底考的软件设计师里面的设计模式虽然可能早已包含&#xff0c;但自己也得有自己啊&#xff0c;要把自己哪怕不成熟的东西也记录下来&…

HDFS客户端及API操作实验

实验二 HDFS客户端及API操作 实验目的&#xff1a; 1.掌握HDFS的客户端操作&#xff0c;包括上传文件、下载文件、重命名、查看目录等&#xff1b; 2.掌握HDFS的Java API使用&#xff0c;能够利用Java API实现上传、下载等常用操作&#xff1b; 实验内容&#xff1a; HDF…

fastadmin权限树。树形下拉框

fastadmin 笔记 权限树 在构造方法中编写相应的代码 值得一提的是&#xff0c;你的表必须有 id 字段以及 pid 字段。 // 必须将结果集转换为数组$ruleList \think\Db::name("state_list")->field(createtime,updatetime, true)->order(id ASC)->select();…

FTP服务文件上传失败,错误码553的排故过程

本文主要记录文件上传失败&#xff0c;错误码553的排故过程。 1 背景 树莓派通过FTP给嵌入式板卡传输文件&#xff0c;好几套设备&#xff0c;发现有的能传输成功&#xff0c;有的传输不成功。树莓派和嵌入式板卡都一样的&#xff0c;出现问题时感觉很懵。 2 逐项对比 2.1 自…

AF自动登录应用--实现无源码系统单点登录

在企业信息化的进程中&#xff0c;许多组织拥有一系列的老应用系统&#xff0c;这些系统在多年的运行中积累了大量的业务数据和流程。然而&#xff0c;这些老应用系统往往没有设计或实现单点登录&#xff08;SSO&#xff09;功能&#xff0c;用户需要在不同系统之间频繁输入账号…

C语言--每日选择题--Day35

第一题 1. 有如下定义&#xff1a;(x y) % 2 (int) a / (int) b 的值是&#xff08;&#xff09; int x 3; int y 2;float a 2.5; float b 3.5; A&#xff1a;0 B&#xff1a;2 C&#xff1a;1.5 D&#xff1a;1 答案及解析 D 本题是考查强制类型转换和操作符优先级 操作…

Figma安装指南:新手入门必看!

如果您想下载Figma客户端&#xff0c;可以直接在Figma官网Products>Downloads页面下载。 如果你不能访问Figma的官方网站&#xff0c;即使下载到客户端&#xff0c;你的网络环境也不能正常使用。 因为Figma的服务器在国外&#xff0c;在国内访问时经常会遇到网络不稳定的情…

SAP 生产订单状态控制

对于生产订单状态&#xff0c;我们经常会对状态进行控制&#xff0c;比如说已领料报工的生产订单就不允许做重读主数据 或者是部分入库不允许做TECO等等 可以通过一个标准的事物代码进行对生产订单状态的一个控制 Tcode&#xff1a;BS22 选择你需要你控制的订单的状态编号双击…

西南科技大学模拟电子技术实验六(BJT电压串联负反馈放大电路)预习报告

一、计算/设计过程 BJT电压串联负反馈放大电路图1-1-1-1为BJT电压串联负反馈放大实验电路,若需稳定输出电压,减小从信号源所取电流,可引入电压串联负反馈闭合开关。 图1-1-1-1 理论算法公式(1)闭环电压放大倍数 (2)反馈系数 (3)输入电阻 (4)输出电阻 计算过程。开环…

51综合程序03-DS1302时钟

文章目录 DS1302时钟芯片一、DS1302时钟芯片的工作原理1. 芯片特点2. 引脚说明3. 寄存器地址4. 读数据的时序图5. 写数据的时序图 二、综合实例LCD1602显示 DS1302时钟芯片 一、DS1302时钟芯片的工作原理 1. 芯片特点 实时计算年、月、日、时、分、秒、星期&#xff0c;直到2…

FacetWP Hierarchy Select网站内容层次结构选择插件

点击阅读FacetWP Hierarchy Select网站内容层次结构选择插件原文 FacetWP Hierarchy Select网站内容层次结构选择插件可让您基于分层分类法创建引导下拉菜单。 FacetWP Hierarchy Select网站内容层次结构选择插件功能 通过引导式下拉菜单过滤结果&#xff0c;一次一个深度级…

【从零开始学习Redis | 第六篇】爆改Setnx实现分布式锁

前言&#xff1a; 在Java后端业务中&#xff0c; 如果我们开启了均衡负载模式&#xff0c;也就是多台服务器处理前端的请求&#xff0c;就会产生一个问题&#xff1a;多台服务器就会有多个JVM&#xff0c;多个JVM就会导致服务器集群下的并发问题。我们在这里提出的解决思路是把…

卷积神经网络(CNN):艺术作品识别

文章目录 一、前言一、设置GPU二、导入数据1. 导入数据2. 检查数据3. 配置数据集4. 数据可视化 三、构建模型四、编译五、训练模型六、评估模型1. Accuracy与Loss图2. 混淆矩阵3. 各项指标评估 一、前言 我的环境&#xff1a; 语言环境&#xff1a;Python3.6.5编译器&#xf…

HarmonyOS开发员,月薪过万不是梦

最近爆出消息&#xff0c;安卓与鸿蒙将不再兼容&#xff01;这意味着华为已经搭建了完整的鸿蒙生态&#xff0c;不再需要依赖于安卓生态。据统计&#xff0c;鸿蒙生态设备已经达到了7亿台&#xff0c;开发者人数也达到了220万人 此外&#xff0c;华为对鸿蒙系统的性能和体验有…

语音识别从入门到精通——1-基本原理解释

文章目录 语音识别算法1. 语音识别简介1.1 **语音识别**1.1.1 自动语音识别1.1.2 应用 1.2 语音识别流程1.2.1 预处理1.2.2 语音检测和断句1.2.3 音频场景分析1.2.4 识别引擎(**语音识别的模型**)1. 传统语音识别模型2. 端到端的语音识别模型基于Transformer的ASR模型基于CNN的…

unity学习笔记18

模型文件属性简介 1.动画类型&#xff1a;一共有四种&#xff1a;无 表示没有动画&#xff0c;旧版 就表示这个模型文件里面的动画片段可以用animation组件来播放的&#xff0c;最后两个 ”泛型“和“人形”都是animator组件来播放的。区别是泛型支持所有类型的动画播放&#x…