当前位置:   article > 正文

Python语音基础操作--3.1语音分帧与加窗_ython语音基础操作–3.1语音分帧与加窗

ython语音基础操作–3.1语音分帧与加窗

《语音信号处理试验教程》(梁瑞宇等)的代码主要是Matlab实现的,现在Python比较热门,所以把这个项目大部分内容写成了Python实现,大部分是手动写的。使用CSDN博客查看帮助文件:

Python语音基础操作–2.1语音录制,播放,读取
Python语音基础操作–2.2语音编辑
Python语音基础操作–2.3声强与响度
Python语音基础操作–2.4语音信号生成
Python语音基础操作–3.1语音分帧与加窗
Python语音基础操作–3.2短时时域分析
Python语音基础操作–3.3短时频域分析
Python语音基础操作–3.4倒谱分析与MFCC系数
Python语音基础操作–3.5线性预测分析
Python语音基础操作–4.1语音端点检测
Python语音基础操作–4.2基音周期检测
Python语音基础操作–4.3共振峰估计
Python语音基础操作–5.1自适应滤波
Python语音基础操作–5.2谱减法
Python语音基础操作–5.4小波分解
Python语音基础操作–6.1PCM编码
Python语音基础操作–6.2LPC编码
Python语音基础操作–6.3ADPCM编码
Python语音基础操作–7.1帧合并
Python语音基础操作–7.2LPC的语音合成
Python语音基础操作–10.1基于动态时间规整(DTW)的孤立字语音识别试验
Python语音基础操作–10.2隐马尔科夫模型的孤立字识别
Python语音基础操作–11.1矢量量化(VQ)的说话人情感识别
Python语音基础操作–11.2基于GMM的说话人识别模型
Python语音基础操作–12.1基于KNN的情感识别
Python语音基础操作–12.2基于神经网络的情感识别
Python语音基础操作–12.3基于支持向量机SVM的语音情感识别
Python语音基础操作–12.4基于LDA,PCA的语音情感识别

代码可在Github上下载busyyang/python_sound_open

一般来讲,语音信号的采样率是挺高的,而且认为语音信号在一定时间段的基本特性不会发生较大的变化,具有一定的短时平稳性。进行“短时分析”就行将信号分解成一段一段地来处理,每一段就叫一帧,大约10-30ms,也就是一秒钟大约33-100帧,对于通常10K的采样率来说,这样也能有一定的信息存在。分帧通常有一定的交叠部分,就是帧移。帧移与帧长的比通常为0~1/2。

分帧就是通过加窗函数实现的,假设原始信号为 s ( n ) s(n) s(n),窗函数为 w ( n ) w(n) w(n),那么分帧就是 s w ( n ) = s ( n ) ∗ w ( n ) s_w(n)=s(n)*w(n) sw(n)=s(n)w(n),窗函数需要满足1. 窗口两端不引起急剧变化,应该平滑过渡到0,2.在频域有较宽的3dB贷款以及较大的边带最大值。窗口的长度一般为10~20ms。有三种常见的窗函数为:

  • 矩形窗
    w ( n ) = { 1 , 0 ⩽ n ⩽ N − 1 0 , o t h e r s (矩形窗) w(n)=\left\{

    1,0nN10,others
    \right. \tag{矩形窗} w(n)={10,0nN1,others()

  • 汉明窗

w ( n ) = { 0.54 − 0.46 cos ⁡ [ 2 π n / ( N − 1 ) ] , 0 ⩽ n ⩽ N − 1 0 , o t h e r s (汉明窗) w(n)=\left\{

0.540.46cos[2πn/(N1)],0nN10,others
\right.\tag{汉明窗} w(n)={0.540.46cos[2πn/(N1)]0,0nN1,others()

  • 海宁窗

w ( n ) = { 0.5 ( 1 − cos ⁡ ( 2 π n / ( N − 1 ) ) ) , 0 ⩽ n ⩽ N − 1 0 , o t h e r s (汉明窗) w(n)=\left\{

0.5(1cos(2πn/(N1))),0nN10,others
\right.\tag{汉明窗} w(n)={0.5(1cos(2πn/(N1)))0,0nN1,others()

其图形如下:
在这里插入图片描述

import matplotlib.pyplot as plt
import numpy as np

plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']

N = 32
nn = [i for i in range(N)]
plt.subplot(3, 1, 1)
plt.stem(np.ones(N))
plt.title('(a)矩形窗')

w = 0.54 - 0.46 * np.cos(np.multiply(nn, 2 * np.pi) / (N - 1))
plt.subplot(3, 1, 2)
plt.stem(w)
plt.title('(b)汉明窗')

w = 0.5 * (1 - np.cos(np.multiply(nn, 2 * np.pi) / (N - 1)))
plt.subplot(3, 1, 3)
plt.stem(w)
plt.title('(c)海宁窗')
# plt.show()
plt.savefig('images/window.png')
plt.close()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

分帧操作,相当于将信号分解为若干个信号片段,并将片段与窗函数进行对应元素的乘法。

from scipy.io import wavfile
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False


def enframe(x, win, inc=None):
    nx = len(x)
    if isinstance(win, list):
        nwin = len(win)
        nlen = nwin  # 帧长=窗长
    elif isinstance(win, int):
        nwin = 1
        nlen = win  # 设置为帧长
    if inc is None:
        inc = nlen
    nf = (nx - nlen + inc) // inc
    frameout = np.zeros((nf, nlen))
    indf = np.multiply(inc, np.array([i for i in range(nf)]))
    for i in range(nf):
        frameout[i, :] = x[indf[i]:indf[i] + nlen]
    if isinstance(win, list):
        frameout = np.multiply(frameout, np.array(win))
    return frameout


fs, data = wavfile.read('C3_1_y.wav')
inc = 100
wlen = 200
en = enframe(data, wlen, inc)
i = input('起始帧(i):')
i = int(i)
tlabel = i
plt.subplot(4, 1, 1)
x = [i for i in range((tlabel - 1) * inc, (tlabel - 1) * inc + wlen)]
plt.plot(x, en[tlabel, :])
plt.xlim([(i - 1) * inc + 1, (i + 2) * inc + wlen])
plt.title('(a)当前波形帧号{}'.format(tlabel))

plt.subplot(4, 1, 2)
x = [i for i in range((tlabel + 1 - 1) * inc, (tlabel + 1 - 1) * inc + wlen)]
plt.plot(x, en[i + 1, :])
plt.xlim([(i - 1) * inc + 1, (i + 2) * inc + wlen])
plt.title('(b)当前波形帧号{}'.format(tlabel + 1))

plt.subplot(4, 1, 3)
x = [i for i in range((tlabel + 2 - 1) * inc, (tlabel + 2 - 1) * inc + wlen)]
plt.plot(x, en[i + 2, :])
plt.xlim([(i - 1) * inc + 1, (i + 2) * inc + wlen])
plt.title('(c)当前波形帧号{}'.format(tlabel + 2))

plt.subplot(4, 1, 4)
x = [i for i in range((tlabel + 3 - 1) * inc, (tlabel + 3 - 1) * inc + wlen)]
plt.plot(x, en[i + 3, :])
plt.xlim([(i - 1) * inc + 1, (i + 2) * inc + wlen])
plt.title('(d)当前波形帧号{}'.format(tlabel + 3))

# plt.show()
plt.savefig('images/en.png')
plt.close()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

在这里插入图片描述

另外,也可以直接使用numpy.hanning(N)来获得窗函数。其中N就是点数。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/236756
推荐阅读
相关标签
  

闽ICP备14008679号