Python語音基礎操作--6.1PCM編碼

《語音信號處理試驗教程》(梁瑞宇等)的代碼主要是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

脈衝編碼調製(Pulse Code Modulation, PCM)是語音信號的重要編碼方式之一。語音編碼是將模擬信號轉爲數字信號的語音通信技術,分爲波形編碼、參量編碼和混合編碼等類型。波形編碼針對語音波形進行,在降低量化樣本比特數的同時保持了良好的語音質量。PCM編碼就是一種波形編碼方法,通過每隔一段時間對模擬語音信號採樣,將其取整量化,用二進制碼錶示抽樣量化的隔值,實現將語音數字化的編碼調製。
PCM是現代數字傳輸系統普遍採用的調製方式。PCM可以向用戶提供多種業務,包括2M-155Mbit/s速率的數字數據專線業務和語音、圖像、遠程教學等業務,適用於傳輸速率要求高、需要更高帶寬的應用,在語音信號處理中有着廣泛的運用。PCM 分爲抽樣、量化和編碼三個步驟。

在這裏插入圖片描述
抽樣過程就是抽取某點的頻率值的過程。顯然,在1 s 內抽取的點越多,獲取的頻率信息越豐富。爲了復原波形, 一次振動中必須有2 個點的採樣,人耳能夠感覺到的最高頻率爲20 kHz ,因此要滿足人耳的聽覺要求,則需要至少每秒進行40000 次採樣,即採樣率爲44.1 kHz 。光有頻率信息是不夠的,還必須獲得該頻率的能量值並量化,用於表示信號強度。量化電平數爲2 的整數次幕,常用16 bit 的採樣大小即2162^{16}。例如對一個語音信號進行8次採樣,採樣點分別對應的能量值分別爲A1-A8,使用2 bit的採樣大小隻能保留A1-A8中4個點,而進行3 bit的採樣則剛好記錄下8 點的所有信息。採樣率和採樣大小的值越大,記錄的波形越接近原始信號。

抽樣量化就是常規A/D的過程,量化後的抽樣信號在一定範圍內僅有有限個可取的樣值,且信號正負幅度分佈的對稱性使正負樣值個數相等,若將有限個量化樣值絕對值從小到大排列,依次賦予十進制數字,以﹢、﹣號爲前綴,則量化後的抽樣信號就轉化爲按時序排列的十進制數字碼流。將數字轉化爲二進制編碼,根據十進制代碼總個數確定二進制位數,即字長。這樣將量化的抽樣信號變成給定字長的二進制碼流的過程就是編碼。

import numpy as np


def PCM_encode(x):
    n = len(x)
    out = np.zeros((n, 8))
    for i in range(n):
        # 符號位
        if x[i] > 0:
            out[i, 0] = 1
        else:
            out[i, 0] = 0
        # 數據位
        if abs(x[i]) < 32:
            out[i, 1], out[i, 2], out[i, 3], step, st = 0, 0, 0, 2, 0
        elif abs(x[i]) < 64:
            out[i, 1], out[i, 2], out[i, 3], step, st = 0, 0, 1, 2, 32
        elif abs(x[i]) < 128:
            out[i, 1], out[i, 2], out[i, 3], step, st = 0, 1, 0, 4, 64
        elif abs(x[i]) < 256:
            out[i, 1], out[i, 2], out[i, 3], step, st = 0, 1, 1, 8, 128
        elif abs(x[i]) < 512:
            out[i, 1], out[i, 2], out[i, 3], step, st = 1, 0, 0, 16, 256
        elif abs(x[i]) < 1024:
            out[i, 1], out[i, 2], out[i, 3], step, st = 1, 0, 1, 32, 512
        elif abs(x[i]) < 2048:
            out[i, 1], out[i, 2], out[i, 3], step, st = 1, 1, 0, 64, 1024
        else:
            out[i, 1], out[i, 2], out[i, 3], step, st = 1, 1, 1, 128, 2048

        if abs(x[i]) >= 4096:
            out[i, 1:] = np.array([1, 1, 1, 1, 1, 1])
        else:
            tmp = bin(int((abs(x[i]) - st) / step)).replace('0b', '')
            tmp = '0' * (4 - len(tmp)) + tmp
            t = [int(k) for k in tmp]
            out[i, 4:] = t
    return out.reshape(8 * n)


def PCM_decode(ins, v):
    inn = ins.reshape(len(ins) // 8, 8)
    slot = np.array([0, 32, 64, 128, 256, 512, 1024, 2048])
    step = np.array([2, 2, 4, 8, 16, 32, 64, 128])
    out = np.zeros(len(ins) // 8)
    for i in range(inn.shape[0]):
        sgn = 2 * inn[i, 0] - 1
        tmp = int(inn[i, 1] * 4 + inn[i, 2] * 2 + inn[i, 3])
        st = slot[tmp]
        dt = (inn[i, 4] * 8 + inn[i, 5] * 4 + inn[i, 6] * 2 + inn[i, 7]) * step[tmp] + 0.5 * step[tmp]
        out[i] = sgn * (st + dt) / 4096 * v
    return out

from chapter2_基礎.soundBase import *
from chapter6_語音編碼.PCM import *

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

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

sxx = np.array(list(map(int, data * 4096)))

y = PCM_encode(sxx)

yy = PCM_decode(y, 1)

plt.subplot(3, 1, 1)
plt.plot(data)
plt.title('編碼前')

plt.subplot(3, 1, 2)
plt.plot(yy)
plt.title('解碼後')

plt.subplot(3, 1, 3)
plt.plot(yy - data)
plt.title('誤差')

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

在這裏插入圖片描述

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