語音處理

為單片機實驗服務的語音模塊
語音處理（Speech processing），又稱語音訊號處理、人聲處理，是研究語音信號及其處理方法的學科。通常，這些信號是以數字形式進行處理的，因此語音處理可以被視為數字信號處理的一個特殊案例，專門應用於語音信號。語音處理涉及語音信號的獲取、操控、存儲、傳輸和輸出等多個方面。不同的語音處理任務包括語音識別、語音合成、說話人分離、語音增強、說話人識別等。

**語音的相關常識**

**一般聲音檔格式**
取樣頻率：22050Hz
*單聲道或雙聲道
*每筆資料用8個bit來表示
*電腦中沒有經過任何壓縮的聲音檔：*.wav

**聲音的頻率**
頻率範圍
人耳可以辨識頻率：20Hz ~ 20000Hz
說話：150~2000Hz
電話系統頻域：小於3500Hz
電腦音效卡取樣頻率：44100Hz (最新技術可達192K)(一般用22050Hz、11025Hz 即可)
*超音波(ultrasound)與次聲波(infrasound)
超音波(ultrasound)：> 20000Hz
次聲波(infrasound)：>> fs
22050
>>> num_frame
122868

**讀取波形與數據**
要先import 相關模組: import numpy as np
*str_data = wavefile.readframes(num_frame)
*wave_data = np.frombuffer(str_data, dtype=np.int16) # 轉成整數型態
*wave_data = wave_data / max(abs(wave_data))  # normalization
*n_channel = 2
*wave_data = np.reshape(wave_data, (num_frame, n_channel)) # 若為雙聲道音檔需要做reshape

**畫出音訊波形圖**
要先import 相關模組: import matplotlib.pyplot as plt
*time = np.arange(0, num_frame)*1/fs
*plt.plot(time, wave_data)
*plt.show()

**畫出頻譜**
要先import 相關模組: from scipy.fftpack import fft
*fft_data = abs(fft(wave_data:,1))/fs # only choose the 1st channel # 注意要乘上1/fs
*n0=int(np.ceil(num_frame/2))
*fft_data1=np.concatenate(fft_datan0:num_frame,fft_data0:n0) # 將頻譜後面一半移到前面
*freq=np.concatenate(range(n0-num_frame,0),range(0,n0))*fs/num_frame # 頻率軸跟著調整
*plt.plot(freq,fft_data1)
*plt.xlim(-1000,1000) # 限制頻率的顯示範圍
*plt.show()

**播放聲音**
要先import 相關模組: import simpleaudio as sa
*n_bytes =2  # using two bytes to record a data
*wave_data = (2**15-1)* wave_data  # change the range to -215 ~ 215
*wave_data = wave_data.astype(np.int16)
*play_obj = sa.play_buffer(wave_data, n_channel, n_bytes, fs)
*play_obj.wait_done()

**製作音檔**
f = wave.open('testing.wav', 'wb')
*f.setnchannels(2) # 設定聲道數
*f.setsampwidth(2) # 每個samples 有幾個位元組
*f.setframerate(fs) # 設定取樣頻率
*f.writeframes(wave_data.tobytes())
*f.close()

**錄音**
要先import 相關模組: import pyaudio
import pyaudio
pa=pyaudio.PyAudio()
fs = 44100
chunk = 1024
stream = pa.open(format=pyaudio.paInt16, channels=1,rate=fs, input=True, frames_per_buffer=chunk)
vocal=
count=0

**時頻分析結果分析**

**Matlab**

**畫出時頻分析結果**
可採行兩種方式：
*使用mesh 指令畫出立體圖(但結果不一定清楚，且執行時間較久)
*將amplitude 變為gray-level，用顯示灰階圖的方法將結果表現出來
假設y 是時頻分析計算的結果
image(abs(y)/max(max(abs(y)))*C) % C 是一個常數，可以選C=400
或image(t, f, abs(y)/max(max(abs(y)))*C)
colormap(gray(256)) % 變成gray-level 的圖
set(gca,'Ydir','normal') % 若沒這一行, y-axis 的方向是倒過來的
set(gca,'Fontsize',12) % 改變橫縱軸數值的font sizes
xlabel('Time (Sec)','Fontsize',12) % x-axis
ylabel('Frequency (Hz)','Fontsize',12) % y-axis
title('STFT of x(t)','Fontsize',12) % title

**計算程式執行時間的指令**
tic (這指令如同按下碼錶)
toc (show 出碼錶按下後已經執行了多少時間)
註：通常程式執行第一次時，由於要做程式的編譯，所得出的執行時間會比較長。程式執行第二次以後所得出的執行時間，是較為正確的結果

**Python**

**事前安裝模組**
pip install numpy
*pip install matplotlib

**畫出時頻分析結果**
假設y為時頻分析結果(應為二維的矩陣數列)，將y 以灰階方式畫出來
import numpy as np
import matplotlib.pyplot as plt
C = 400
y = np.abs(y) / np.max(np.abs(y)) * C
plt.imshow(y, cmap='gray', origin='lower') # 加上origin='lower' 避免上下相反
plt.xlabel('Time (Sec)')
plt.ylabel('Frequency (Hz)')
plt.show()
若要加上座標軸數值(在plt.show()之前加上以下程式碼)
x_label = '0', '10', '20', '30' # 橫軸座標值
y_label = '-5', '0', '5' # 縱軸座標值
plt.xticks(np.arange(0, x_max, step=int(x_max/(len(x_label)-1)), x_label)
plt.yticks(np.arange(0, y_max, step=int(y_max/(len(y_label)-1)), y_label)

**語音訊號的來源**
人聲是由於聲帶震動，而產生聲音。當運動肌肉擠壓，使肺臟中的空氣通過聲帶時，空氣流動使得聲帶做週期性的震動，又再一次震動了空氣，接著，帶著動能的空氣離開氣管到達口腔或鼻腔，在腔室中震動，最後離開在嘴唇傳到人耳變成聲音。
若調整口腔中舌頭的位置，會產生不同種類的聲音，如果舌頭沒有做太多的動作，空氣只有在口腔中共振，接著直接流出嘴唇，會產生母音，若提起舌頭，使口鼻腔相通，則會出現鼻音。

**語音訊號分類**
從中文發音的觀點來說，聲音仍可分為子音與母音，母音和子音可以用兩種方式區分：- 發聲方式：一般而言，母音跟嘴唇形狀有關，而且不與鼻腔共振。相對而言，在發出子音時，就會運用到鼻腔配合發聲。- 頻譜分析：從頻譜上觀察可以發現子音的訊號頻率較高，持續時間較短，且會在母音之前出現。而母音的頻率較低，持續時間較長，在子音後或獨立出現，另外，母音的能量也會比子音大。
下面列出中文注音符號中的母音、子音及其拼音。
*母音：ㄚ ㄛ ㄜ ㄝ ㄞ ㄟ ㄠ ㄡ ㄢ ㄣ ㄤ ㄥ ㄦ 一 ㄨ ㄩ
*子音：ㄅ ㄆ ㄇ ㄈ ㄉ ㄊ ㄋ ㄌ ㄍ ㄎ ㄏ ㄐ ㄑ ㄒ ㄓ ㄔ ㄕ ㄖ ㄗ ㄘ ㄙ

**語音的架構**
要分析語音訊號前，必須先了解其架構，語音的要素從小到大分別是：音素→音節→詞彙→句子→整段話。
音素是聲音的最小單位，例如「呵」這個字的音素，就是「ㄏ」和「ㄜ」，但是音素和注音符號並不相等，例如「鷗」雖然只有「ㄡ」這個母音，但是由於是雙母音，所以會把他拆成兩個音素。音節在中文而言，就是隻一個字，例如：「天天開心」就有四個音節。詞彙是文字組成的有意義片段，各種不同的詞彙集結成句子，最後變成整段話，這就是語音的架構。

**語音處理方法**
用麥克風或其他裝置收到的類音聲音訊號，經由類比數位轉換裝置，將資料數據化進行處理，最後再經過數位類比轉換裝置輸出。因此，我們在處理時是針對數位訊號，語音訊號是一種離散時間訊號。其訊號處理流程如下：
# 收取並取樣訊號：利用麥克風或各種收音裝置，收取類比語音訊號，再用ADC裝置(如類比數位轉換卡)把類比訊號變成數位訊號，接著根據奈奎斯特理論作取樣，若不符合理論則會造成訊號失真。
# 量化及編碼：由於電腦中的記憶都是0和1，因此要將所收到的數據用一段適合的0跟1去儲存，這個動作就稱為量化，所使用的0與1越多，所需的記憶體越多。接著利用編碼器將數值以波形呈現，因此雖然是數位訊號，但是在電腦中所見到的是類比。
# 訊號標準化：將語音訊號標準化，使其數值都落在同一個範圍。
# 音框選擇：由於語音訊號是一段很長的訊號，因此會針對想要處理的部分取音框。
# 端點偵測：端點偵測的目的是使訊號處理的範圍更精確，只要設定一個音量閾值，若訊號小於閾值，則將其視為沒訊號，但是若雜訊過高，則會產生誤差。
# 去雜訊：由於雜訊多集中在高頻的部分，因此利用簡單的高頻濾波器，就可以去掉部分雜訊。

**基本處理方法**
語音訊號是屬於離散時間系統，因此會用離散時間的傅立葉轉換去做處理，除此之外，摺積、窗函數都是一定會使用到的處理方法。- 離散時間傅立葉轉換：

- 摺積：
兩訊號做convolution等於，兩訊號先做傅立葉轉換，相乘後再做反傅立葉轉換，藉此可以更快速的處理訊號。
 

**語音處理的應用**
語音處理主要有兩個目的：- 減少訊號雜訊，做出想要的訊號模組。- 進行語音辨識，使人可以利用語言與電腦溝通。

**參見**
 語音識別

**參考文獻**
 J. Benesty, M. M. Sondhi, Y. Huang (ed). Springer Handbook of Speech Processing. Springer, 2007. ISBN 978-3-540-49125-5.- J. Benesty, S. Makino, J. Chen (ed). Speech Enhancement. Springer, 2005. ISBN 978-3-540-24039-6.- Jian-Jiun Ding, “Advanced Digital Signal Processing”, NTU, 2021. - Jian-Jiun Ding, “Time Frequency Analysis and Wavelet Transforms ”, NTU, 2021.