python提取时长2s以内的单词音频的韵母基频,以及单词词长信息

提取信息自动存入当前工作空间中的excel文件,包括文件名、前字时长、后字时长、两字总时长、前字韵母基频、后字韵母基频。(10个点,9段,采用自相关法)

音频源文件为.wav和.textgrid文件。如gong1_yuan2.wav、gong1_yuan2.textgrid,其中gong1_yuan2代表单词“公园”,1、2代表声平前字为1声,后字为2声。

使用代码时,文件夹格式建议如下,要有M001这个二级目录。(M为male性别,001代表说话人编号。)若你的代码无男女区别,则也建议新建一个M001子目录。
参考数据链接:
https://pan.baidu.com/s/1Sdymm3XYD9uXKGoD8UYoDg
提取码:d851

如需要多次处理音频,将旧音频文件删除,复制新的进去就行。

基本算法思想

根据textgrid文件标注的单词的韵头、韵母、以及中间silence段的时间序列,计算出每个韵头、韵母左右端点。在textgrid文件中,以gong1_yuan2.textgrid为例,前后字的Intervals为 ( 0.5,1.0,T1) 、( 1.,2,1.9,T12。 韵头为(0.5,0.6,g),韵母为(0.6,1.0,ong),其他依次类推。两字之间可能存在silence段:(1.0,1.2,sil)。

关于Textgrid文件格式的参考:https://blog.csdn.net/duxin_csdn/article/details/88966295

根据文件采样频率计算出离散时间序列横坐标,根据韵头韵母的左右端点,计算出时间序列横坐标区间,即为韵头or韵母所在的区间。 如时间序列为 0.1 0.2 0.3 0.4 0.5,韵母左端点标注为0.25,则取左区间端点为0.3.其他同理。

根据时间区间即可得到对应数字信号序列,将其输入自相关算法即可计算基频。

若需要提取韵头基频,根据算法修改即可。本文所建立的韵母、韵头表,未必对所有使用者的textgrid的标注都适用。

import textgrid
import xlwt
import os
import re
import wave
import numpy as np
import math
#gong1_yuan2.TextGrid
from matplotlib import pyplot as plt
import scipy.io.wavfile as wavbook = xlwt.Workbook()  # 创建Workbook,相当于创建Excel encoding='utf-8'
# 创建sheet,Sheet1为表的名字,cell_overwrite_ok为是否覆盖单元格
sheet1 = book.add_sheet('Sheet1')
D1=D2=D3=D4=0
def getparam(file_name):#此函数获取2个单字的时长、总长、第一个字韵母时间区间(D1,D2)、第二个字韵母时间区间 (D3,D4)#第一个单字时间总长T1 第二个单字时间总长T2 ,全长时间T3tg = textgrid.TextGrid()tg.read(file_name)  # 'file.TextGrid' 是文件名sylset = {'b', 'p', 'm', 'f', 'd', 't', 'n', 'l', 'g', 'k', 'h', 'j', 'q', 'x', 'zh', 'ch', 'sh', 'z', 'c', 's','y', 'w', 'r','e'}sylmset={'a','ai','an','ang','ao','e','ei','en','eng','er','o','ong','ou','iu','i','ia','ian','iang','iao','ie','in','ing','iong','iou','u','un','ui','ua','uai','uan','uang','uei','uen','ueng','uo','v','van','ve','vn','R','iii','ii','eR'}#根据文件名处理标记twonum=re.findall("\d+", file_name)#'1'代表韵头,'0'代表韵母syltag=''num=1b = 1a = []  # 韵母区间c = []  # 韵母标记 注意可能出现3个韵母,则有6个区间数字,需要修改成4个for i in range(0, len(tg.tiers)):for j in range(0, len(tg.tiers[i])):
##############################################求韵母区间##############################################if (((tg.tiers[i][j].mark != 'None') & (tg.tiers[i][j].mark != 'sil') & (tg.tiers[i][j].mark != ''))):if (tg.tiers[i][j].mark in sylmset  ):a.append(tg.tiers[i].intervals[j].minTime)a.append(tg.tiers[i].intervals[j].maxTime)c.append(tg.tiers[i].intervals[j].mark)
#############################################↑↑↑求韵母区间↑↑↑############################################################################################求词时长##############################################if (twonum[0] != twonum[1]):if ((tg.tiers[i][j].mark == 'T' + twonum[0])):T1time = round(tg.tiers[i].intervals[j].maxTime - tg.tiers[i].intervals[j].minTime, 5)  # 第一个词时长A1 = round(tg.tiers[i].intervals[j].minTime,5)if ((tg.tiers[i][j].mark == 'T' + twonum[1])):T2time = round(tg.tiers[i].intervals[j].maxTime - tg.tiers[i].intervals[j].minTime, 5)  # 第2个词时长A2 = round(tg.tiers[i].intervals[j].maxTime,5)else:if ((tg.tiers[i][j].mark == 'T' + twonum[0])):if (b == 1):T1time = round(tg.tiers[i].intervals[j].maxTime - tg.tiers[i].intervals[j].minTime, 5)  # 第一个词时长A1=round(tg.tiers[i].intervals[j].minTime,5)b = b + 1else:T2time = round(tg.tiers[i].intervals[j].maxTime - tg.tiers[i].intervals[j].minTime, 5)  # 第2个词时长A2 = round(tg.tiers[i].intervals[j].maxTime,5)##############################################↑↑↑求词时长↑↑↑##############################################if(len(a)>4 and c[0]=='e'):a.pop(0)a.pop(0)else:if(len(a)>4 and c[1]=='e'):a.pop(2)a.pop(2)D1 = a[0]D2 = a[1]D3 = a[2]D4 = a[3]T3time = A2 - A1print( str(T1time)+'---'+ str(T2time)+'---'+str(T3time)+'-/-/D1:'+str(D1)+'---D2:'+str(D2)+'--//-D3:'+str(D3)+'---D4:'+str(D4)  )return [T1time,T2time,T3time,D1,D2,D3,D4]def write_file(file_name,file_name_wav,file_pre,j):#此函数将第j个文件写入excel第j行 (从0开始数par=getparam(file_name)#向表中添加数据sheet1.write(j, 0, file_pre[0]+'/'+file_name.split('.',1)[0]) #写入第一列文件名#sheet1.write(j, 8,file_pre )  # 写入第一列文件名for i in range(0,len(par)):sheet1.write(j, i+1, str(par[i]))    #写入时间数据。# 获取10个点的基频。根据time数据和wavedata数据.wav_data, time,fs = read_wav_data(file_name_wav)# 找到大于D1 小于D2的点。为前字区间。命名为L1,L2。# 找到大于D1的点。L1=0L2=0L3=0L4=0for i in range(0, len(wav_data), 1):if (time[i] >par[3]):#D1)L1 = i;break# 找到小于D2的点。for i in range(0, len(wav_data), 1):if (time[i] >par[4]):L2 = i - 1;break# 找到大于D3 小于D4的点。为前字区间。命名为L3,L4。# 找到大于D3的点。for i in range(0, len(wav_data), 1):if (time[i] >par[5]):L3 = i;break# 找到小于D2的点。for i in range(0, len(wav_data), 1):if (time[i] >par[6]):L4 = i - 1;break# 在L1--L2 L3--L4之间取10个点。if(L3>L2):global fre1fre1 = np.arange(0, 10, 1)global fre2fre2 = np.arange(0, 10, 1)m1=0;m2=0;for i in range(L1, L2, math.ceil((L2 - L1 + 1)/10)):k=i+math.ceil((L2 - L1 + 1)/10)fre1[m1]=find_pitch(wav_data[i:k],fs)m1=1+m1if(m1>=9):breakfor i in range(L3, L4, math.ceil((L4 - L3 + 1) / 10)):k = i + math.ceil((L4 - L3 + 1) / 10)fre2[m2] = find_pitch(wav_data[i:k],fs)m2 = 1 + m2if (m2 >= 9):break# 将基频写入for i in range(9, 18):sheet1.write(j, i, str(fre1[i-9]))for i in range(20, 29):sheet1.write(j, i, str(fre2[i-20]))print(file_pre[0] + '/' + file_name.split('.', 1)[0] + '->>>' + str(L1) + '---' + str(L2) + '---' + str(L3) + '---' + str(L4) +'->par5==' + str(par[3]) + '->par6==' + str(par[4]) +'->par5==' + str(par[5]) + '->par6==' + str(par[6]))#print(fre1)book.save('adata1.xls')def file_name(file_dir):#此函数从路径下文件中获取所有textgrid文件的名字L=[]for root, dirs, files in os.walk(file_dir):for file in files:if os.path.splitext(file)[1] == '.TextGrid':L.append(os.path.join(root, file))for i in range(0,len(L)):L[i]=os.path.basename(L[i])return Ldef file_name_wave(file_dir):# 此函数从路径下文件中获取所有wave文件的名字L=[]for root, dirs, files in os.walk(file_dir):for file in files:if os.path.splitext(file)[1] == '.wav':L.append(os.path.join(root, file))for i in range(0,len(L)):L[i]=os.path.basename(L[i])return Ldef file_pre_name(file_dir):# 此函数从路径下文件中获取所有文件的上级目录名L=[]for root, dirs, files in os.walk(file_dir):for file in files:if os.path.splitext(file)[1] == '.wav':L.append(os.path.join(root, file))for i in range(0,len(L)):L[i]=re.findall("\w\d\d\d",L[i])return Ldef read_wav_data(filename):fs, wavdata = wav.read(filename)time=np.arange(0,len(wavdata))/fsreturn  wavdata,time,fsdef find_pitch(x,fs):ms20 = int((fs / 50))ms2 = int(fs / 500)#print('--ms20='+str(ms20)+'--ms2='+str(ms2)+'--fs='+str(fs))x = [i / 32767 for i in x]y = plt.acorr(x, maxlags=110, normed=True)y = y[1]z = y[round(len(y) / 2):]z = z[ms2:ms20]zmax = max(z)index = np.where(z == zmax)index = index[0][0]pitch = fs / (ms2 + index + 2)#plt.show()return pitch# 下面是自己的文件夹地址
FileNameset = file_name(r'F:\PythonVirtualEnv\wuxiaoxin_para\音频')
FileNameset_wave = file_name_wave(r'F:\PythonVirtualEnv\wuxiaoxin_para\音频')
FileNameset_pre=file_pre_name(r'F:\PythonVirtualEnv\wuxiaoxin_para\音频')# excel第一行
markname = ['文件の名', '首字时长', '次字时长', '两字总时长', '首字韵母左端点', '首字韵母右端点', '次字韵母左端点', '次字韵母右端点']
for i in range(0, len(markname)):sheet1.write(0, i, markname[i])
sheet1.write(0, 9, '前字基频')
sheet1.write(0, 20,'后字基频')
# 将T1time至D4数据输入excel
for i in range(0, len(FileNameset)):write_file(FileNameset[i],FileNameset_wave[i],FileNameset_pre[i], i+1)if(i==len(FileNameset)-1):print('process finished')#write_file('ban1_fa1.TextGrid','ban1_fa1.wav', 2)

python提取时长2s以内的单词音频的韵母基频,以及单词词长信息相关推荐

  1. Praat脚本提取时长及基频并示例如何绘制声调图

    Praat脚本提取时长及基频并示例如何绘制声调图 2016年03月29日 17:21:04 不太会编程 阅读数:13986 标签: Praat脚本声调图汉字声调五度值 更多 个人分类: Praat 版 ...

  2. Praat脚本-022 | 提取时长和音强

    目录 引题 操作解释 运行脚本 获取脚本 关注 版权说明 引题 提取基频Praat脚本-009 | 提取时长和基频,提取共振峰Praat脚本-010 | 提取时长和共振峰,提取音强,这大概是最常用的三 ...

  3. python中排序英文单词怎么写_Python 排序最长英文单词链(列表中前一个单词末字母是下一个单词的首字母)...

    本文主要介绍排序最长的单词链的方法,列表中每个元素相当于一个单词,要实现列表中前一个单词末字母是下一个单词的首字母,并且这个链是最长的. 使用递归实现 words = ['giraffe', 'ele ...

  4. python实现时频谱,语谱图,mel语谱倒谱等

    python实现时频谱,语谱图,mel语谱倒谱等 可以和理论相结合学习:https://blog.csdn.net/qq_36002089/article/details/108378796 语音信号 ...

  5. python编辑时怎样换行_python怎么换行

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! windows换行符是'rn',unixlinux的换行符为'n',mac的换行 ...

  6. 【影像组学】用3Dslicer或Python提取影像组学特征

    文章目录 1. 利用 3Dslicer 软件提取影像组学特征 2. 利用 python 提取影像组学特征 1. 利用 3Dslicer 软件提取影像组学特征 安装插件:SlicerRadiomics ...

  7. python取特定年份的数据_python,_怎样用python提取不同股票csv里特定时间段的数据,python - phpStudy...

    怎样用python提取不同股票csv里特定时间段的数据 我有几千只股票的csv数据,需要算所有股票在特定时间段内的收益率. 但是数据里的日期信息并不统一,有的csv到2011年就没有了之后的信息了,有 ...

  8. Algorithm:C++/python语言实现之求旋转数组最小值、求零子数组、求最长公共子序列和最长公共子串、求LCS与字符串编辑距离

    Algorithm:C++/python语言实现之求旋转数组最小值.求零子数组.求最长公共子序列和最长公共子串.求LCS与字符串编辑距离 目录 一.求旋转数组最小值 1.分析问题 2.解决思路 二.求 ...

  9. python提取html正文为txt,python 提取html文本的方法

    假设我们需要从各种网页中提取全文,并且要剥离所有HTML标记.通常,默认解决方案是使用BeautifulSoup软件包中的get_text方法,该方法内部使用lxml.这是一个经过充分测试的解决方案, ...

最新文章

  1. Linux redis安装教程,Linux 下redis5.0.0安装教程详解
  2. 集合Gk表示这样一堆数字,该集合内的数字有k个1
  3. b站编程课程资源汇总
  4. 程序设计语言python语言概述
  5. 高校胜负欲PK合辑,看看你的母校在拼什么?最服的还是它!
  6. Apache Kylin的核心概念
  7. 图书管理系统html_结自主可控数字化硕果,同方鼎欣推进基于OFD技术的数字档案管理系统研发...
  8. DNN深度神经网络、RBM受限玻尔兹曼机、DBN深度置信网络
  9. 数据结构代码学习笔记(持续更新中)
  10. python request 接口自动化设计
  11. IOS UIAlertView 提示视图
  12. 下载各种版本的weblogic
  13. 2.aop原理:@EnableAspectJAutoProxy
  14. macbook终端打开jupyter notebook
  15. 计算两点间距离C++
  16. 163邮箱登陆入口展示,企业邮箱电脑版登陆入口
  17. 【英文论文写作经验分享】1、Abstract 怎么写?
  18. html5玻璃下雨,下雨天外后视镜总是沾满水珠 6个妙招帮你解决这个难题
  19. oracle 视图的写法,Oracle视图基础详解与实例
  20. 关于cesm中寻找浮力频率N的记录

热门文章

  1. 从0开始实现一个合成大西瓜
  2. 6iypl8php,无线超方便 YPL TL-1/TL-3蓝牙音箱新品上市
  3. [python]打日语
  4. 编程达人海哥c语言,编程达人 我在写海哥初级班39课作业的时候遇到了问题,希望有兄弟帮忙解答一下...
  5. vue中实现 楼层效果
  6. NPDP知识推送-第一章新产品开发战略(2)
  7. google计费接入,Billing结算库支付
  8. SQL注入漏洞-SQL注入原理与实践
  9. HTML如何使用隐藏图片,css3如何隐藏图片?
  10. python的time模块使用