zoukankan      html  css  js  c++  java
  • 语音预处理(二):时域转频域

    一.时域转频域

    这节主要介绍如何经过傅里叶变换将音频转到频域,以便于后续的特征提取和识别。先后进行加窗、分帧、FFT和取log操作。
    输入:音频矩阵wavsignal ,帧率fs
    例:[[1507 1374 1218 ... -78 -127 -43]],16000
    输出:转成频域后的音频矩阵data_input

    二.代码:

    #coding=utf-8
    import os
    import wave
    import numpy as np
    import matplotlib.pyplot as plt
    import math 
    import time
    from python_speech_features import mfcc
    from python_speech_features import delta
    from python_speech_features import logfbank
    from scipy.fftpack import fft
    
    def read_wav_data(filename):
        """
        :param filename:输入音频的绝对路径(路径+文件名)例:D:\GitHub\wav\dae\train\A2_1.wav
        :return:wave_data,framerate:输出音频矩阵,帧率。例:A2_1 [[1507 1374 1218 ...  -78 -127  -43]]
        读取wav文件,返回声音信号的时域谱矩阵和播放时间
        """
        wav = wave.open(filename,"rb") #打开wav格式的声音文件filename
        audioname = filename.split('\')[-1] #音频名
        num_frame = wav.getnframes() #获取帧数
        #print("{}帧数为:{}".format(audioname,num_frame))
        num_channel = wav.getnchannels() #获取声道数
        #print("{}声道数为:{}".format(audioname,num_channel))
        framerate = wav.getframerate() # 获取帧率
        #print("{}帧率为:{}".format(audioname,framerate))
        num_sample_width = wav.getsampwidth() #获取每一帧的比特宽度
        #print("{}比特宽度为:{}".format(audioname,num_sample_width))
        str_data = wav.readframes(num_frame) # 读取全部的帧(二进制字符串)
        wav.close() # 关闭流
    
        wave_data = np.fromstring(str_data,dtype=np.short) # 将声音文件数据从字符串格式转换为数组矩阵形式
        # print("{} shape: {}".format("wave_data",wave_data.shape))
        # print("{} type: {}".format("wave_data",wave_data.dtype))
        # print("{}: {}".format("wave_data",wave_data))
        wave_data.shape = -1, num_channel #按照声道数将数组整形,单声道是一列,双声道是两列矩阵
        # print("{} shape(整形后): {}".format("wave_data",wave_data.shape))
        # print("{}(整形后): {}".format("wave_data",wave_data))
        wave_data = wave_data.T # 将wave_data矩阵转置
        # print("{} shape(转置后):{}".format("wave_data",wave_data.shape))
        # print("{}(转置后):{}".format("wave_data",wave_data))
        # print("{} len:{}".format("wave_data[0]",len(wave_data[0])))
    
        return wave_data, framerate
    x = np.linspace(0, 400 - 1, 400, dtype = np.int64)
    w = 0.54 - 0.46 * np.cos(2 * np.pi * (x) / (400 - 1) ) # 汉明窗
    
    def GetFrequencyFeature(wavsignal, fs):
        """
        :param wavsignal:音频矩阵 例:[[1507 1374 1218 ...  -78 -127  -43]]
        :param fs:帧率 例:16000
        :return data_input:转成频域后的音频矩阵
        """
        # wav波形 加时间窗以及时移10ms
        time_window = 25  # 单位ms
        window_length = fs / 1000 * time_window  # 计算窗长度的公式,目前全部为400固定值
        wav_arr = np.array(wavsignal)  # wav_arr:[[1507 1374 1218 ...  -78 -127  -43]]
        wav_length = wav_arr.shape[1]  # wav_arr.shape[0]:1,wav_arr.shape[1]:163000
        range0_end = int(len(wavsignal[0]) / fs * 1000 - time_window) // 10  # 计算循环终止的位置,也就是最终生成的窗数
        data_input = np.zeros((range0_end, 200), dtype=np.float)  # 用于存放最终的频率特征数据
        data_line = np.zeros((1, 400), dtype=np.float)
    
        for i in range(0, range0_end):
            p_start = i * 160  # 0,160,320,480
            p_end = p_start + 400  # 400,560,720,880
            data_line = wav_arr[0, p_start:p_end]  # 分帧
            data_line = data_line * w  # 加窗(这里是汉明窗)
            data_line = np.abs(fft(data_line)) / wav_length  # 傅里叶变换
            data_input[i] = data_line[0:200]  # 设置为400除以2的值(即200)是取一半数据,因为是对称的
        data_input = np.log(data_input + 1)  # 取log
        return data_input
    
    if(__name__=='__main__'):
           wave_data, fs = read_wav_data("D:\GitHub\wav\dae\train\A2_1.wav")
           print("wave_data:{}".format(wave_data))
           freimg = GetFrequencyFeature(wave_data, fs)
           print("freimg:{}".format(freimg))
           print("freimg shape:{}".format(freimg.shape))
    
    

    三.程序输出:

    wave_data:[[1507 1374 1218 ... -78 -127 -43]]
    freimg:
    [[2.42781686e-01 3.74806474e-01 1.57395831e-01 ... 2.44499564e-03 3.97955672e-03 2.58199104e-03]
    [4.53051376e-01 5.93472204e-01 2.75825723e-01 ... 4.04953736e-03 2.93284484e-03 2.91292203e-03]
    [7.36420845e-01 5.12987026e-01 3.08367617e-01 ... 3.05346426e-03 1.78931565e-03 1.43100353e-03]
    ...
    [2.66626609e-02 1.66521460e-01 1.30265491e-01 ... 3.11282926e-04 1.49347950e-03 2.64074732e-03]
    [3.03173655e-01 2.10056810e-01 5.29090247e-02 ... 2.23561051e-03 1.90130764e-03 2.44626778e-03]
    [2.42738928e-01 4.61532521e-02 1.34021807e-01 ... 7.12491485e-04 8.06380446e-04 1.50869641e-03]]
    freimg shape:(1016, 200)

  • 相关阅读:
    springboot2.0集成RestTemplate
    RestTemplate HttpMessageConverter报错的解决方案no suitable HttpMessageConverter
    vue条件渲染+列表渲染+事件处理器
    vue计算属性+vue中class与style绑定
    vue选项数据+vue模板语法
    vue安装配置+生命周期
    sass案例--实现高仿今日头条H5版新闻列表页
    sass内置函数
    sass继承+嵌套+条件控制
    sass常见的基本数据类型+加减乘除基本运算
  • 原文地址:https://www.cnblogs.com/jianxiong0117/p/9605089.html
Copyright © 2011-2022 走看看