概述
主要功能
本文主要实现使用python编程实现对我上一个博客写的python编程读取wav文件数据得到的语音数据进行分帧,同时也编程实现将分帧后的数据还原为原始语音数据。
第一部分主要实现用python编程实现对语音数据进行分帧。
第二部分实现将分帧后的数据还原成原始语音数据,语音数据为单声道的。
输入输出数据文件均从命令行输入,分帧的帧长和帧移也从命令行输入。
附件包含两个程序,一个是语音数据分帧,另一个是分帧数据还原,其中分帧程序中English.txt
为分帧前的语音数据,Englishframe1.txt
为帧长为4,帧移为2进行分帧得到的结果。Englishframe2.txt
为为帧长为8,帧移为4进行分帧得到的结果。每个数据之间采用空格分隔,一行一帧数据。English.wav
为原始语音文件。
第一部分 分帧
对输入的语音数据进行分帧,语音数据文件,分帧数据文件(分帧后的数据保存在文件中),帧长,帧移均采用命令行方式输入。
程序
程序主要由两部分组成,一部分为main子函数部分,判断命令行参数,并读入数据文件,同时调用分帧函数,返回分帧后的数据,保存到文件中。另一部分为enframe分帧函数部分,主要对main函数部分传过来的语音数据进行分帧,返回分帧后的矩阵。
#将txt语音数据进行分帧
# -*- coding: utf-8 -*-
import numpy as np
import sys
import wave #语音文件处理包
import getopt
def enframe(data, wlen, inc): #data为语音数据,wlen为帧长,inc为帧移
data_length = len(data) # 信号总长度
if data_length <= wlen: # 若信号长度小于一个帧的长度,则帧数定义为1
nf = 1
else: # 否则,计算帧数
nf = int(np.ceil((1.0 * data_length - wlen + inc) / inc))
#np.ceil计算大于等于改值的最小整数,将小数点后部分删除
pad_length = int((nf - 1) * inc + wlen) # 所有帧加起来总的铺平后的长度
#zeros = np.zeros((pad_length - data_length,))
#pad_signal = np.concatenate((data, zeros)) # 补充完整的语音数据
pad_signal = np.pad(data, (0, pad_length - data_length), 'constant') # 用0填充最后不足一帧的数据
indices = np.tile(np.arange(0, wlen), (nf, 1)) + np.tile(np.arange(0, nf * inc, inc), (wlen, 1)).T #每帧的索引,将原矩阵横向、纵向地复制展开
#tile() 函数,就是将原矩阵横向、纵向地复制展开
indices = np.array(indices, dtype=np.int32) # 将indices转化为矩阵,数值类型为32位整型
frames = pad_signal[indices] # 得到帧信号, 用索引拿数据
return frames #返回分帧后的语音数据矩阵
def main(argv): #定义一个函数
try: #首先执行try后的程序,如果输入格式不对,则执行except getopt.GetoptError:后的程序
opts, args = getopt.getopt(argv, "i:o:-f:-l:h", ["input", "output","framelength=","overlap=","help"]) #命令行输入参数
except getopt.GetoptError:
print('输入参数错误,输入格式为:python wavtxtframe.py -i English.txt -o Englishframe.txt -f 4 -l 2,n其中wavtxtframe.py为程序文件名称,English.txt为语音数据文件,Englishframe.txt为分帧后的语音数据文件,n-f为分帧的帧长,-l为帧移')
sys.exit()
#global file
for opt, arg in opts:
if opt in ("-h", "--help"): #打印帮助
#test.wav为单声道语音文件,test2.wav为双声道语音文件
print('输入格式为:')
print('python wavtxtframe.py -i English.txt -o Englishframe.txt -f 4 -l 2')
print('或者:python wavtxtframe.py -i English.txt -o Englishframe.txt --framelength 4 --overlap 2')
print('其中wavtxtframe.py为程序文件名称,English.txt为语音数据文件,Englishframe.txt为分帧后的语音数据文件')
print('-f/-framenlength为分帧的帧长,-l/overlap为帧移' )
sys.exit()
elif opt in ("-i", "--input"):
input = arg #取命令行参数,即输入
file1 = open(input, 'rb') # 打开语音数据文件
elif opt in ("-o", "--output"):
output = arg #取命令行参数,即输出
file2 = open(output, 'w+') # 打开分帧后的数据保存的txt文件
elif opt in ("-f", "--framelength"):
framelength = arg #取命令行framelength后的参数,即帧长
framelength = int(framelength)
elif opt in ("-l", "--overlap"):
overlap = arg #取命令行overlap后的参数,即帧移
overlap = int(overlap)
line = file1.readline() # 每次读出txt文件中的一行内容
data = [] #初始化一个空矩阵
while line: #当未读到文件最后时
# 把切分出的列表的每个值, 把它们转成np.short型, 并返回迭代器
num = list(map(np.short, line.split())) # np.short
# 用list函数把map函数返回的迭代器遍历展开成一个列表
data.append(num)
line = file1.readline()
file1.close()
wavdata = np.array(data) # 将列表数据转换成数组
signal = wavdata.T #将列矩阵转为行矩阵
Frame = enframe(signal[0], framelength, overlap) # 调用分帧函数
#for i in Frame:
np.savetxt(file2, Frame, fmt='%d', delimiter=' ')
print(Frame)
file2.close()
'''
lines = f.readlines()
long = len(lines)
for line in lines:
for i in range(4):
line1 = line
file.write(line1)
print("t")
print("n")
data = np.reshape(line, [long, 4])
file.close() # 关闭输出文件
f.close() # 关闭输入的语音文件
exit()
'''
if __name__ == "__main__":
# sys.argv[1:]为要处理的参数列表,sys.argv[0]为脚本名,所以用sys.argv[1:]过滤掉脚本名。
main(sys.argv[1:]) #调用函数
#https://blog.csdn.net/luolinll1212/article/details/98940838
#python wavtxtframe.py -i English.txt -o Englishframe1.txt -f 4 -l 2
#python wavtxtframe.py -i English.txt -o Englishframe1.txt --framelength 4 --overlap 2
#python wavtxtframe.py -i English.txt -o Englishframe2.txt --framelength 8 --overlap 4
结果
1 查看帮助文档
python wavtxtframe.py -h
运行结果:
2 分帧,帧长为4,帧移为2
python wavtxtframe.py -i English.txt -o Englishframe1.txt -f 4 -l 2
运行结果:
另一种运行方式:
python wavtxtframe.py -i English.txt -o Englishframe1.txt --framelength 4 --overlap 2
运行结果:
分帧后,数据保存到文件中的结果:
3 分帧,帧长为8,帧移为4
python wavtxtframe.py -i English.txt -o Englishframe2.txt --framelength 8 --overlap 4
#或者:
python wavtxtframe.py -i English.txt -o Englishframe2.txt -f 8 -l 4
运行结果:
分帧后,数据保存文件结果:
查看文件中分帧后的数据,可以发现,分帧程序可以按照命令行输入的帧长和帧移进行分帧,且结果正确。
第二部分 分帧数据还原
程序
程序主要将分帧后的数据还原成原始语音数据。
#将分帧之后的语音数据还原为分帧之前的语音数据
import numpy as np
import sys
import wave #语音文件处理包
import getopt
import re
def main(argv): # 定义一个函数
try: # 首先执行try后的程序,如果输入格式不对,则执行except getopt.GetoptError:后的程序
opts, args = getopt.getopt(argv, "i:o:-f:-l:h",["input", "output", "framelength=", "overlap=", "help"]) # 命令行输入参数
except getopt.GetoptError:
print('输入参数错误,输入格式为:python frametxtwav.py -i Englishframe2.txt -o Englishframetxtwav.txt --framelength 8 --overlap 4,n其中frametxtwav.py为程序文件名称,程序功能是通过分帧后的数据得到原始语音数据,Englishframe2.txt为分帧后的数据文件, Englishframetxtwav.txt为还原的语音数据文件,n --framelength为分帧的帧长,--overlap为帧移')
sys.exit()
# global file
for opt, arg in opts:
if opt in ("-h", "--help"): # 打印帮助
# test.wav为单声道语音文件,test2.wav为双声道语音文件
print('输入格式为:')
print('python framtxtwave.py -i Englishframe1.txt -o Englishframetxtwav1.txt --framelength 4 --overlap 2')
print('或者:python framtxtwave.py -i Englishframe1.txt -o Englishframetxtwav1.txt -f 4 -l 2')
print('其中frametxtwav.py为程序文件名称,程序功能是通过分帧后的数据得到原始语音数据,Englishframe2.txt为分帧后的数据文件, Englishframetxtwav.txt为还原的语音数据文件')
print('-f/-framenlength为分帧的帧长,-l/overlap为帧移')
sys.exit()
elif opt in ("-i", "--input"):
input = arg # 取命令行参数,即输入
file1 = open(input, 'rb') # 打开分帧后的语音数据文件
elif opt in ("-o", "--output"):
output = arg # 取命令行参数,即输出
file2 = open(output, 'w+') # 打开用于保存分帧前的数据的txt文件
elif opt in ("-f", "--framelength"):
framelength = arg # 取命令行framelength后的参数,即帧长
framelength = int(framelength)
elif opt in ("-l", "--overlap"):
overlap = arg # 取命令行overlap后的参数,即帧移
overlap = int(overlap)
x = overlap #帧移,即每行中原始语音数据的长度
line1 = file1.readline() # 每次读出txt文件中的一行内容
#data = [] # 初始化一个空矩阵
print('txt文件中的数据的数据类型为:n', type(line1)) #返回从txt文件中得到的数据的数据类型
line = line1.decode(encoding='utf-8') #按utf-8的方式解码,解码成字符串,因为存入txt文件的数据为bytes型,要转为str
while line: #当未读到文件末尾
#for line in lines:
#x = re.split(r' ', line)[0] # 正则化以空格分割一行数据,取分割出来的第一个数据
#y = re.split(r' ', line)[1]
#line = str(x) + ' ' + str(y) + ' ' + 'n' # 重新写行数据
for i in range(x): #循环读取一行中的前x个数据
#content = str(re.split(r' ', line)[i]) + ' '
content = str(re.split(r' ', line)[i]) + 'n' #读取文件中的前overlap列数据,即未分帧前的数据,去掉了重复的数据
file2.write(content) #将数据写入另一个txt文件中
#content = str(re.split(r' ', line)[0]) + ' '+str(re.split(r' ', line)[1]) + ' ' +str(re.split(r' ', line)[i-1])+'n'
#line = str(x) + ' ' + 'n' # 重新写行数据
#file2.write(line)
#file2.write(content)
#content1 = 'n'
#file2.write(content1)
line1 = file1.readline() # 每次读出txt文件中的一行内容
line = line1.decode(encoding='utf-8') #按utf-8的方式解码,解码成字符串,因为存入txt文件的数据为bytes型,要转为str
file1.close()
#获取分帧数据文件的最后一帧的framelength-overlap长度的数据,并存入文件中
file1 = open(input, 'rb') # 打开分帧后的语音数据文件
line1 = file1.readlines()
long = len(line1)
print('文件行数为:',long)
print('txt文件中的数据的数据类型为:n', type(line1)) # 返回从txt文件中得到的数据的数据类型
last_line = line1[-1].decode('utf-8')
#line = last_line.decode(encoding='utf-8') # 按utf-8的方式解码,解码成字符串,因为存入txt文件的数据为bytes型,要转为str
for i in range(x,framelength): # 循环读取最后一行(即最后一帧)数据的framelength-overlap长度的数据
# content = str(re.split(r' ', line)[i]) + ' '
content = str(re.split(r' ', last_line)[i]) + 'n' # 读取文件中的前overlap列数据,即未分帧前的数据,去掉了重复的数据
file2.write(content) # 将数据写入另一个txt文件中
file1.close()
file2.close()
#with open(output, 'w+') as mon:
# mon.write(line)
'''
while line: # 当未读到文件最后时
# 把切分出的列表的每个值, 把它们转成np.short型, 并返回迭代器
num = list(map(np.short, line.split())) # np.short
# 用list函数把map函数返回的迭代器遍历展开成一个列表
data.append(num)
line = file1.readline()
# file2.close()
'''
'''
lines = f.readlines()
long = len(lines)
for line in lines:
for i in range(4):
line1 = line
file.write(line1)
print("t")
print("n")
data = np.reshape(line, [long, 4])
file.close() # 关闭输出文件
f.close() # 关闭输入的语音文件
exit()
'''
if __name__ == "__main__":
# sys.argv[1:]为要处理的参数列表,sys.argv[0]为脚本名,所以用sys.argv[1:]过滤掉脚本名。
main(sys.argv[1:]) # 调用函数
#命令行运行的命令
#python frametxtwav.py -i Englishframe1.txt -o Englishframetxtwav1.txt --framelength 4 --overlap 2
#python frametxtwav.py -i Englishframe2.txt -o Englishframetxtwav2.txt --framelength 8 --overlap 4
#python frametxtwav.py -i Englishframe1.txt -o Englishframetxtwav1.txt -f 4 -l 2
#python frametxtwav.py -i Englishframe2.txt -o Englishframetxtwav2.txt -f 8 -l 4
#python frametxtwav.py -h
1 帮助文档
python frametxtwav.py -h
结果:
C:UsersCLDesktop学习pythonwav>python frametxtwav.py -h
输入格式为:
python framtxtwave.py -i Englishframe1.txt -o Englishframetxtwav1.txt --framelength 4 --overlap 2
或者:python framtxtwave.py -i Englishframe1.txt -o Englishframetxtwav1.txt -f 4 -l 2
其中frametxtwav.py为程序文件名称,程序功能是通过分帧后的数据得到原始语音数据,Englishframe2.txt为分帧后的数据文件, Englishframetxtwav.txt为还原的语音数据文件
-f/-framenlength为分帧的帧长,-l/overlap为帧移
2 分帧数据还原,帧长为4,帧移为2
python frametxtwav.py -i Englishframe1.txt -o Englishframetxtwav1.txt --framelength 4 --overlap 2
结果:
C:UsersCLDesktop学习pythonwav>python frametxtwav.py -i Englishframe1.txt -o Englishframetxtwav1.txt --framelength 4 --overlap 2
txt文件中的数据的数据类型为:
<class 'bytes'>
文件行数为: 265651
txt文件中的数据的数据类型为:
<class 'list'>
还原的语音数据结果:
原语音数据:
对还原后的语音数据和原来的语音数据进行对比,结果一样(还原的语音数据最后多了一行0是因为分帧时最后不足一帧的补0所致,但0并不影响还原语音结果)。最后一帧数据还原正确。
3 分帧数据还原,帧长为8,帧移为4
python frametxtwav.py -i Englishframe2.txt -o Englishframetxtwav2.txt --framelength 8 --overlap 4
结果:
还原的语音数据结果:
原语音数据:
还原的语音数据最后多了一行0是因为分帧时最后不足一帧的补0所致,但0并不影响还原语音结果)。最后一帧数据还原正确。
附件:
本文章所有程序及文件:
链接:https://pan.baidu.com/s/1q_iFdQN94QHKuz773zPGVA
提取码:9k69
最后
以上就是香蕉猎豹为你收集整理的python编程实现语音数据分帧及分帧还原的全部内容,希望文章能够帮你解决python编程实现语音数据分帧及分帧还原所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复