主要功能
本文主要实现使用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('输入格式为:'