Python語音基礎操作--7.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語音基礎操作–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

語音合成主要可分爲波形合成法,參數合成法,規則合成法。

  • 波形合成法
    • 波形編碼合成,直接把需要合成的語音通過編碼的形式進行存儲,稱爲PCM合成。
    • 波形編輯合成,通過在音庫中採取語音的合成單元波形,對這些波形進行編輯拼接後輸出。
  • 參數合成法
    • 分析法:提取語音參數,壓縮存儲量,然後人工控制這些參數的生成。
  • 規則法
    • 通過語音學規則產生語音。系統中最小語音單位的聲學參數,以及由音素組成音節,由音節組成詞,由詞組成句子。

幀合併

分幀處理後,需要將多個幀合併起來,涉及的操作有去創函數和去交疊操作。方法爲:

  • 通過IFFT把一幀頻域數據轉化爲時域數據。
  • 將一組激勵脈衝通過一個濾波器。

常用的三種數據疊加方法爲重疊相加法,重疊存儲法,線性比例重疊相加法。

重疊相加法

假設信號長度爲N1N_1,窗函數h(n)h(n)的長度爲NN,每幀的信號xi(n)x_i(n)長度爲MM,將每幀信號與窗函數後面補零,使得長度都爲N+M1N+M-1,得到x^i(n)\hat x_i(n)h^(n)\hat h(n)。計算x^i(n)\hat x_i(n)h^(n)\hat h(n)的卷積結果,可以使用FFT和IFFT來計算結果。卷積結果y(n)y(n)的長度爲N+M-1,把重疊部分相加,與不重疊部分共同構成輸出。把重疊相加推廣到時域,信號x(n)x(n)是分幀的,每幀爲:
xi(m)={x(n),(i1)ΔL+1niΔL+L0,,m[1,L]x_i(m)=\left \{\begin{array}{ll} x(n)&,(i-1)\Delta L+1 \leqslant n \leqslant i\Delta L +L\\ 0&,其他 \end{array} \right.,m\in [1,L]

yi1(m)y_{i-1}(m)yi(m)y_{i}(m)有M個樣點重疊,重疊部分爲(i1)ΔL+1(i1)ΔL+M(i-1)\Delta L+1 到 (i-1)\Delta L +M,輸出爲:
y(n)={y(n),n(i1)ΔLy(n)+yi(m),(i1)ΔL+1n(i1)ΔL+M,M[1,M]yi(m),(i1)ΔL+1+Mn(i1)ΔL+L,M[M+1,L]y(n)=\left \{\begin{array}{ll} y(n)&,n\leqslant (i-1)\Delta L\\ y(n)+y_i(m)&,(i-1)\Delta L+1 \leqslant n \leqslant (i-1)\Delta L +M,M\in[1,M]\\ y_i(m)&,(i-1)\Delta L+1+M \leqslant n \leqslant (i-1)\Delta L+L,M\in[M+1,L] \end{array} \right.

重疊存儲法

重疊存儲法是分幀數據在前面補零達到N+M-1的長度。FFT後只取後面M個樣本點,輸出到輸出序列上。
y(n)={y(n),n(i1)ΔLyi(m),(i1)ΔL+1n(i1)ΔL+M,M[1,ΔL]y(n)=\left \{\begin{array}{ll} y(n)&,n\leqslant (i-1)\Delta L\\ y_i(m)&,(i-1)\Delta L+1 \leqslant n \leqslant (i-1)\Delta L +M,M\in[1,\Delta L]\\ \end{array} \right.

線性比例重疊相加

如果前一幀和下一幀的變化較大,那麼用重疊相加法就不合適了。可以將重疊部分進行比例計權後相加。假設重疊部分長度爲M,兩個斜三角的窗函數w1(n)=(n1)/Mw_1(n)=(n-1)/Mw2(n)=(Mn)/Mw_2(n)=(M-n)/Mn[1,M]n\in [1,M]

如果前一幀的重疊部分爲y1y_1,後一幀的重疊部分爲y2y_2。那麼y(n)=y1(n)w1(n)+y2(n)w2(n)y(n)=y_1(n)w_1(n)+y_2(n)w_2(n)

y(n)={y(n),n(i1)ΔLy(n)w2(n)+yi(m)w1(n),(i1)ΔL+1n(i1)ΔL+M,M[1,M]yi(m),(i1)ΔL+1+Mn(i1)ΔL+L,M[M+1,L]y(n)=\left \{\begin{array}{ll} y(n)&,n\leqslant (i-1)\Delta L\\ y(n)w_2(n)+y_i(m)w_1(n)&,(i-1)\Delta L+1 \leqslant n \leqslant (i-1)\Delta L +M,M\in[1,M]\\ y_i(m)&,(i-1)\Delta L+1+M \leqslant n \leqslant (i-1)\Delta L+L,M\in[M+1,L] \end{array} \right.

import numpy as np


def Filpframe_OverlapA(x, win, inc):
    """
    基於重疊相加法的信號還原函數
    :param x: 分幀數據
    :param win: 窗
    :param inc: 幀移
    :return:
    """
    nf, slen = x.shape
    nx = (nf - 1) * inc + slen
    frameout = np.zeros(nx)
    x = x / win
    for i in range(nf):
        start = i * inc
        frameout[start:start + slen] += x[i, :]
    return frameout


def Filpframe_OverlapS(x, win, inc):
    """
    基於重疊存儲法的信號還原函數
    :param x: 分幀數據
    :param win: 窗
    :param inc: 幀移
    :return:
    """
    nf, slen = x.shape
    nx = (nf - 1) * inc + slen
    frameout = np.zeros(nx)
    x = x / win
    for i in range(nf):
        frameout[slen + (i - 1) * inc:slen + i * inc] += x[i, slen - inc:]
    return frameout


def Filpframe_LinearA(x, win, inc):
    """
    基於比例重疊相加法的信號還原函數
    :param x: 分幀數據
    :param win: 窗
    :param inc: 幀移
    :return:
    """
    nf, slen = x.shape
    nx = (nf - 1) * inc + slen
    frameout = np.zeros(nx)
    overlap = len(win) - inc
    x = x / win
    w1 = [i / overlap for i in range(overlap)]
    w2 = [i / overlap for i in range(overlap - 1, -1, -1)]
    for i in range(nf):
        if i == 0:
            frameout[:slen] = x[i, :]
        else:
            M = slen + (i - 1) * inc
            y = frameout[M - overlap:M] * w2 + x[i, :overlap] * w1
            xn = x[i, overlap:]
            yy = np.hstack((y, xn))
            frameout[M - overlap:M - overlap + slen] += yy
    return frameout

from chapter2_基礎.soundBase import *
from chapter7_語音合成.flipframe import *
from chapter3_分析實驗.C3_1_y_1 import enframe

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

data, fs = soundBase('C7_1_y.wav').audioread()

wlen = 256
wnd = np.hamming(wlen)
overlap = 100
f = enframe(data, wnd, overlap)
plt.figure(figsize=(14, 12))
# 7.1.1
fn_overlap = Filpframe_OverlapA(f, wnd, overlap)
plt.subplot(3, 2, 1)
plt.plot(data / np.max(np.abs(data)), 'k')
plt.title('原始信號')
plt.subplot(3, 2, 2)
plt.title('還原信號-重疊相加法')
plt.plot(fn_overlap / np.max(np.abs(fn_overlap)), 'c')

# 7.1.2
fn_s = Filpframe_OverlapS(f, wnd, overlap)
plt.subplot(3, 2, 3)
plt.plot(data / np.max(np.abs(data)), 'k')
plt.title('原始信號')
plt.subplot(3, 2, 4)
plt.title('還原信號-重疊存儲法')
plt.plot(fn_s / np.max(np.abs(fn_s)), 'c')

# 7.1.3
fn_l = Filpframe_LinearA(f, wnd, overlap)
plt.subplot(3, 2, 5)
plt.plot(data / np.max(np.abs(data)), 'k')
plt.title('原始信號')
plt.subplot(3, 2, 6)
plt.title('還原信號-線性疊加法')
plt.plot(fn_l / np.max(np.abs(fn_l)), 'c')

plt.savefig('images/flipframe.png')
plt.close()

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章