音频处理四:(音频的分帧)

程序设计四:音频的分帧

一:需求分析

为了分析读人数据,通常进行分帧处理。在分帧中,往往设置在相邻两帧之间有一部分重叠。其原因是:语音信号是时变的,在短时范围内特征变化较小,所以作为稳态来处理;但超出这短时范围语音信号就有变化了。在相邻两帧之间基音发生了变化,如正好是两个音节之间, 或正好是声母向韵母过渡,等等,这时,其特征参数有可能变化较大,但为了使特征参数平滑地变化,在两个不重叠的帧之间插一些帧来提取特征参数,这就形成了相邻帧之间有重叠部分。

将本地的采样数据.txt读出,分帧以后保存到另一个.txt文件,需要考虑单声道和双声道

wavtxtframe -i yyy.txt -o zzz.txt -framelength 4 -overlap 2

二:参考知识

1.文件知识

本地.txt信息

lanTian2.txt 声道数1 采样率8000 量化位数2的lanTian2.mav的采样值 
BAC009S0003W0121.txt 声道数1 采样率16000 量化位数2的BAC009S0003W0121.wav的采样值
2.分帧介绍

wlen为帧长,inc为帧移,重叠部分为overlap,overlap=wlen - inc

信号帧数为:
n f = ( N −  overlap)  /  inc  = ( N − w l e n ) / i n c + 1 n f=(N-\text { overlap) } / \text { inc }=(N-w l e n) / i n c+1 nf=(N overlap) / inc =(Nwlen)/inc+1

nf = int(np.ceil((1.0 * signal_length - wlen + inc) / inc))

np.ceil向上取整,所以会导致实际分帧后的长度大于信号本身的长度,所以要对原来的信号进行补零,类似与FFT变换中的数据点不够补零达到采样点的数量。

pad_length = int((nf - 1) * inc + wlen)  # 所有帧加起来总的铺平后的长度
zeros = np.zeros((pad_length - signal_length,))  # 不够的长度使用0填补,类似于FFT中的扩充数组操作#np.concatenate()连接两个维度相同的矩阵
pad_signal = np.concatenate((signal, zeros))  # 填补后的信号记为pad_signal

三:python代码

holiday04.py
import wave
import numpy as np
import sys
import getopt


def enframe(signal, wlen, inc):
    '''
    参数含义:
    signal:原始音频型号
    nw:每一帧的长度
    inc:相邻帧的间隔
    '''
    signal_length = len(signal)  # 信号总长度
    if signal_length <= wlen:  # 若信号长度小于一个帧的长度,则帧数定义为1
        nf = 1
    else:  # 否则,计算帧数
        nf = int(np.ceil((1.0 * signal_length - wlen + inc) / inc))
        #np.ceil计算大于等于改值的最小整数,将小数点后部分删除
    pad_length = int((nf - 1) * inc + wlen)  # 所有帧加起来总的铺平后的长度
    zeros = np.zeros((pad_length - signal_length,))  # 不够的长度使用0填补,类似于FFT中的扩充数组操作
    #np.concatenate()连接两个维度相同的矩阵
    pad_signal = np.concatenate((signal, zeros))  # 填补后的信号记为pad_signal
    indices = np.tile(np.arange(0, wlen), (nf, 1)) + np.tile(np.arange(0, nf * inc, inc), (wlen, 1)).T
    # 相当于对所有帧的时间点进行抽取,得到nf*nw长度的矩阵
    #tile() 函数,就是将原矩阵横向、纵向地复制展开
    indices = np.array(indices, dtype=np.int32)  # 将indices转化为矩阵
    frames = pad_signal[indices]  # 得到帧信号

    return frames#返回帧信号矩阵


def main(argv):
    try:

        #opts, args = getopt.getopt(argv, "-h-i:-f:-o:", ["help", "input=", "framelength", "overlap"])
         opts, args = getopt.getopt(argv, "-h-i:-o:-f:-l:", ["help", "input=", "output=","framelength=","overlap="])
    except getopt.GetoptError:
        print('Error: python holiday04.py -i BAC009S0003W0121.txt -o frame02.txt --framelength 200 --overlap 100')
        print('   or: python holiday04.py -i BAC009S0003W0121.txt -o frame01.txt -f 200 -l 100')
        sys.exit(2)

    # 处理 返回值options是以元组为元素的列表。
    for opt, arg in opts:
        if opt in ("-h", "--help"):
            print("为真实还原,输入的参数尽量和原语音一致")
            print('python holiday04.py -i BAC009S0003W0121.txt -o frame02.txt --framelength 200 --overlap 100')
            print('or: python holiday04.py -i BAC009S0003W0121.txt -o frame01.txt -f 200 -l 100')
            sys.exit()
        elif opt in ("-i", "--input"):
            input = arg
        elif opt in ("-o", "--output"):
            output = arg

        elif opt in ("-f", "--framelength"):
            framelength = int(arg)
            print(framelength)

        elif opt in ("-l", "--overlap"):
            overlap = int(arg)

            f = open(input)
            # f = open("wavData(left).txt")
            # f = open("lanTian2.txt")
            # wavData(left)
            line = f.readline()
            data_list = []
            while line:
                # 把切分出的列表的每个值, 把它们转成np.short型, 并返回迭代器
                num = list(map(np.short, line.split()))  # np.short
                # 用list函数把map函数返回的迭代器遍历展开成一个列表
                data_list.append(num)
                line = f.readline()
            f.close()
            wave_data = np.array(data_list)
            signal = wave_data.T

            Frame = enframe(signal[0], framelength, overlap)  # signal[0]是为了保证维度一致

            file = open(output, 'w+')

            np.savetxt(file,Frame, fmt='%d', delimiter=' ')
            file.close()


if __name__ == "__main__":
    # sys.argv[1:]为要处理的参数列表,sys.argv[0]为脚本名,所以用sys.argv[1:]过滤掉脚本名。
    main(sys.argv[1:])


#python holiday04.py -i BAC009S0003W0121.txt -o frame02.txt --framelength 200 --overlap 100
#python holiday04.py -i BAC009S0003W0121.txt -o frame01.txt -f 200 -l 100
#python holiday04.py -i lanTian2.txt -o frame01.txt -f 200 -l 100

四:实现结果

1.请求帮助
python holiday04.py -h

在这里插入图片描述

2.单参数分帧
  • -i 输入采样值点的文件
  • -o 保存的文件
  • -f 帧长
  • -l 帧移
python holiday04.py -i BAC009S0003W0121.txt -o frame01.txt -f 200 -l 100

在这里插入图片描述

3.多参数分帧
  • -i 输入采样值点的文件
  • -o 保存的文件
  • –framelength 帧长
  • –overlap 帧移
python holiday04.py -i BAC009S0003W0121.txt -o frame02.txt --framelength 200 --overlap 100

在这里插入图片描述

五:结果分析

以BAC009S0003W0121.txt的内容用本程序将结果保存,再用matlab直接读取原语音BAC009S0003W0121.wav进行对比,结果为一致

1.matlab对比程序

程序4对比.m

%实验要求一:语音分帧显示
clc
clear all
close all

[x,Fs]=audioread('G:\python\holiday\BAC009S0003W0121.wav','native');       % 读入数据文件
wlen=200; inc=100;          % 给出帧长和帧移
N=length(x);                    % 信号长度
time=(0:N-1)/Fs;                % 计算出信号的时间刻度
signal=enframe(x,wlen,inc)';     % 分帧
signal=signal';

2.显示结果

2.1 matlab结果

2.2 python生成的frame01.txt
在这里插入图片描述

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

唐维康

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

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

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

打赏作者

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

抵扣说明:

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

余额充值