簡介
以前參與過114對話系統的項目,中間擱置好久,如今把以前作過的內容整理一下,一是爲本身回顧,二是也但願分享本身看的內容,中間也遇到一些問題,若是您能夠提一些建議將不勝感激.
114查詢主要分爲4個任務,該對話系統但願經過構建神經網絡學習模型,以實現將傳統的須要接線員回覆用戶問題的方式,轉換爲能夠實現機器自動回覆用戶問題的智能對話。因爲拿到的是114電話錄音數據,並無標記好的文本,加上語音中有當地方言、特定字母數字在現有商用轉錄識別效果差等問題,因此須要本身實現語音識別的模塊,以便後期能夠針對咱們數據集的特定進行訓練優化。這篇blog將介紹語音預處理內容。
因爲本人研究生階段研究方向是NLP,未系統學習信號內容,因此專業知識有所欠缺,如下資料是在項目過程當中查閱資料等整理的,若有不當,還望指教~javascript
參考連接:php
from IPython.display import Image
Image(filename = "/home/lsy/project/dialogue/ASR_test/preprocess/window_func_img/freq_amplitude.png", width = 400, height = 400)
A/D轉換就是把模擬信號轉換爲數字信號的過程,模擬電信號變爲了由"0","1"組成的bit信號。
A/D轉換關鍵步驟是聲音的採樣和量化和編碼。html
爲實現A/D轉換,須要把模擬音頻信號波形進行分割,這種方法稱爲採樣(Sampling)。 採樣的過程是每隔一個時間間隔在模擬聲音的波形上取一個幅度值,把時間上的連續信號變成時間上的離散信號。 該時間間隔稱爲採樣週期, 其倒數爲採樣頻率,表示計算機每秒中採集多少聲音樣本。html5
奈奎斯特(Nyquist)理論
採樣頻率與聲音頻率之間有着必定的關係,根據奈奎斯特理論,只有採樣頻率高於聲音信號最高頻率的兩倍時,才能把數字信號表示的聲音還原爲原來的聲音。$$f_s >= 2f$$java
採樣的方式有不少,這裏再也不贅述,能夠參考連接1學習瞭解。python
採樣只解決了音頻波形信號在時間座標上(橫軸) 把一個波形切成若干個等分的數字化問題,可是還須要用某種數字化的方法來反映某一瞬間聲波幅度的電壓值大小,該值的大小影響音量的高低。 咱們把對聲波波形幅度的數字化表示稱之爲"量化"。
量化的過程是將採樣後的信號按照整個聲波的幅度劃分爲有限個區段的集合,把落入某個區段內的樣值歸爲一類,並賦予相同的量化值。jquery
如何分割採樣信號的幅度呢?
採起二進制的方式,以8bit或16bit的方式劃分縱軸。也就是說在一個以8位爲記錄模式的音效中,其縱軸將會被劃分爲$2^8 = 256$個量化等級,用以記錄其幅值大小。也即爲若每一個量化級用長度爲b比特的二進制表示,那麼量化級n的個數爲 $n = 2^b$
以下圖所示,b = 3時的量化方式,其前三個採樣值能夠用二進制序列」100 110 111「表示。linux
因此能夠簡單理解:採樣是橫軸對時間分段,量化是縱軸對振幅分段。android
from IPython.display import Image
Image(filename = "/home/lsy/project/dialogue/ASR_test/preprocess/window_func_img/quantizing_enc.png", width = 300, height = 300)
模擬信號量通過採樣和量化後,造成一系列的離散信號——脈衝數字信號。這些脈衝數字信號能夠以必定的方式進行編碼,造成計算機內部運行的數據。
編碼就是按照必定的格式把通過採樣和量化獲得的離散數據記錄下來,並在有用的數據中加入一些用於糾錯、同步和控制的數據。 在數據回放時,能夠根據所記錄的糾錯數據判別讀出的聲音數據是否有錯,如在必定範圍內有錯,能夠加以糾正。
編碼的形式有不少,經常使用的編碼方式是脈衝編碼調製(PCM).在wav中也有采用ADPCM的編碼方式,這裏主要對這兩種進行介紹。
若是咱們對一個聲音信號進行採樣,採用16位量化,好比採集53個點.若是咱們直接存儲每個點的16位的採樣值,這樣就須要53X16=848位,大約是106字節。以下圖:
from IPython.display import Image
Image(filename = "/home/lsy/project/dialogue/ASR_test/preprocess/window_func_img/pcm.png", width = 300, height = 300)
但咱們換個思路,咱們不存儲採樣值,而存儲採樣點兩兩之間的差值(採樣值可能會很大,須要更多的位數來表達,好比16個位,可是兩點之間通常來講是比較連續的,差值不會太大,因此這個差值只須要不多的幾個位便可表達,好比4個位)。這樣,咱們只須要知道前一個點的值,又知道它與下一個點的差值,就能夠計算獲得下一個點了。這個差值就是所謂的「差分」。DPCM即爲差分脈衝編碼調製。 這樣對於1.2.3.1中用16位表示53個點,DPCM只須要4位,這樣存儲大小減爲原來的 1/4。
ADPCM爲自適應差分脈衝編碼調製。自適應體如今哪裏呢?
考慮DPCM存儲的是兩點之差,但對於有的差值大,有的差值小;若是差值大過有限位數可表示的範圍,那麼數據就會丟失,形成失真。如何更好的保存原始音頻的信息呢?
若是有一種方法,能夠把兩點之間的差值變換到固定的幾個位便可表達的範圍內,那就行了。並且這種變換是實時的,而且具備自適應性和預測能力的。這就是ADPCM的基本思想。它定義了一些因子,這種算法若是發現兩點之間差值變大以後,就會用差值去和相應的因子做除法,從而減少了差值,讓它能夠減小到幾個位可表達的數值範圍內。而選擇哪個因子來除它,這就是ADPCM編碼要做的事情了。
ADPCM算法巧妙的利用了音頻信號的特色,也就是音頻信號上的點與它前面的若干個點是有必定的相關性的,從而能夠對下一個點進行預測,從而預先估計這個差值,從而選取相應的除數因子,去把差值歸化到數值範圍內.
from IPython.display import Image
Image(filename = "/home/lsy/project/dialogue/ASR_test/preprocess/window_func_img/adpcm.png", width = 300, height = 300)
114的電話錄音數據是.V3格式的,通常播放器是不支持的,而且也沒有見到直接用該數據格式進行音頻處理的。音頻處理經常使用是轉換爲.wav格式。在轉格式時,注意幾個點,編碼格式、採樣率、編碼位數、通道數、文件頭。
本實驗中採用的是https://mox-sir.iteye.com/blog/2181641 中的代碼。本實驗中採用的ADPCM編碼,單通道,對於採樣率和編碼位數則須要看V3文件中是如何採樣的。本實驗中試了幾種方式,但只有6khz採樣率,uint8編碼合適。轉換時也嘗試採用了8k採樣率和16bit編碼,但效果不好,基本聽不清楚。採用8k採樣率,8-bit編碼的效果是:說話人聲音很尖,語速被加快;採用8k採樣率,16-bit編碼的效果是:說話人聲音很低,很粗,徹底不像女聲了;而且語速很是慢,以致於轉換後只有前部分的語音被轉換來,後部分的都丟失了。
在文件格式轉換過程當中,文件頭信息設置很重要。(固然上面連接的代碼中都寫好了,但仍是能夠了解一下)。
Digital Audio - Creating a WAV (RIFF) file http://www.topherlee.com/software/pcm-tut-wavformat.html 中有對wav的文件頭信息的詳盡介紹。 這裏涉及到一個點就是RIFF.
RIFF
在windows環境下,大部分的多媒體文件都依循着一些通用的結構來存放,這些結構稱爲「資源互換文件格式」(Resources Interchange File Format),簡稱RIFF。RIFF能夠看做一種樹狀結構,其基本構成單位是塊(chunk)。每一個塊由「辨別碼」、「數據大小」及「數據」等構成。 RIFF文件的前4字節爲其辨別碼「RIFF"的ASCII字符碼,緊跟其後的雙字節數據則標示整個文件大小(單位爲字節Byte)。因爲表示文件長度或塊長度的」數據大小「信息佔用4Byte,因此,事實上一個WAVE文件或文件中塊的長度爲數據大小加8。
WAVE
wav文件又稱波形文件,來源於對聲音模擬波形的採樣,並以不一樣的量化位數把這些採樣點的值輪換成二進制數,而後存入磁盤,這就產生了波形文件。wav聲音文件是使用RIFF的格式描述的,它由文件頭和波形音頻文件數據塊組成。文件頭包括標識符、語音特徵值、聲道特徵以及PCM格式類型標誌等、WAV數據塊是由數據字塊標記、數據子塊長度和波形音頻數據3個數據字塊組成。
在WAVE文件中,所採用的編碼方式有PCM(Pulse Code Modulation-脈衝編碼調製)和ADPCM(Adaptive Differential Pulse Code Modulation-自適應差分脈衝編碼調製)兩種。
WAVE文件是很是簡單的一種RIFF文件,它的格式類型爲"WAVE"。RIFF塊包含兩個子塊,這兩個子塊的ID分別是"fmt"和"data",其中"fmt"子塊由結構PCMWAVEFORMAT所組成,其子塊的大小就是sizeofof(PCMWAVEFORMAT),數據組成就是PCMWAVEFORMAT結構中的數據。
參考連接:https://blog.csdn.net/cwfjimogudan/article/details/71112171
https://wenku.baidu.com/view/614101450722192e4536f6bc.html
from IPython.display import Image
Image(filename = "/home/lsy/project/dialogue/ASR_test/preprocess/window_func_img/canonical_wave_file_format.png", width = 500, height = 500)
以上圖示顯示了一個wave file format的格式,簡潔形象。
那麼根據這個圖示,再看V3轉wav的代碼就很明瞭了。其中
int wFormatTag = 1; // format tag (01 = Windows PCM)
tmpArr = new byte[2];
toShortBinary(wFormatTag, tmpArr, 0);
filewriter.write(tmpArr);// format tag (01 = Windows PCM)
表示了轉換後的wav文件是採用的PCM編碼。
爲何要強調看這個信息呢?由於下面須要對採樣位數、採樣率進行轉換,不一樣的編碼格式顯然須要不一樣的轉換方式。
import scipy.io.wavfile as wav
import matplotlib.pyplot as plt
import os
import numpy as np
經過plot顯示wavsignal
# load the china-unicom test data
filepath = "/home/lsy/project/dialogue/ASR_test/preprocess/test_6kuint8/0747033-6k-uint8.wav"
fs, wavsignal = wav.read(filepath)
plt.plot(wavsignal)
plt.show()
爲了與訓練數據集中數據的格式統一,須要將uint8轉換爲int16.除了使用經常使用的sox等開源工具,想可否本身代碼實現轉換。轉換前首先要考慮wav文件的編碼格式,在2中介紹了,本實驗中採用的PCM編碼方式,也就是非壓縮格式,那麼存儲的直接是8位採樣值。那麼這就簡單一些了。
思路是將uint8數據範圍scale到int16範圍內,如如下convert_scale函數所示. 因爲uint8是無符號類型的,int16有符號,因此應先減去中值再擴展。
(可是若是採用的其餘編碼方式,好比ADPCM編碼,則不能夠用這種轉換方式,由於ADPCM存儲的信息並非本來的採樣量化後的值,而是差分值。若是直接將uint8 scale到int16空間,至關於將原音頻的採樣點之間的差值人爲放大,這會形成失真。)
固然用c++的話,能夠直接用移位實現,https://stackoverflow.com/questions/24449957/converting-a-8-bit-pcm-to-16-bit-pcm
INT16 sample16 = (INT16)(sample8 - 0x80) << 8;
def convert_scale(x):
return (int)(x - 128) * 256
w = [convert(x) for x in wavsignal]
plt.plot(w)
plt.show()
嘗試了sox轉換,scipy.signal.resample轉換等方式,但都有高頻部分丟失的問題。(雖然轉換後人耳聽是正常的,可是看文末的語譜圖便發現高頻部分信息都丟失了)目前這個問題並無很好的解決,若是您有很好的resample的方法歡迎指導交流~
首先查看本身的音頻的採樣率
print(fs)# sample rate
因爲訓練集中採用的是16kHz的採樣率,爲了與其保持一致,這裏將本身的語音數據由6kHz重採樣到16kHz.
不少開源工具提供該功能,好比使用sox, 或ffmpeg等,這裏直接使用的scipy.signal.resample函數。https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.resample.html
scipy.signal.resample(x, num, t=None, axis=0, window=None)
Resample x to num samples using Fourier method along the given axis. 固然採起這種重採樣方式多是形成高頻信息丟失的緣由,具體分析見文末語譜圖的分析部分。
from scipy import signal
wavsignal = signal.resample(w, (int)(len(w) / 6 * 16))
wavsignal = np.clip(wavsignal, a_min = -32768, a_max = 32767)
plt.plot(wavsignal)
plt.show()
print(len(wavsignal))
從上圖看出,其噪聲是很是明顯的,以致於人聲的特徵並不清晰。因此咱們須要將其中的細節plot出來進行分析,以方便以後的處理。
plt.plot(wavsignal[12000:14000])
plt.show()
如下幾幅plots將不一樣階段的wavsignal表現出來。最後三張圖的波形分佈與以前有明顯的不一樣,能夠認爲是噪聲。
start = 12000
step = 1000
for i in range(5):
fig = plt.figure(figsize=(20,3))
plt.plot(wavsignal[start + i * step: start + (i+1)*step])
plt.show()
這個wav是經過v3直接轉換過來的,爲了使語音更加乾淨,還須要預處理。
預加劇是一種在發送端對輸入信號高頻份量進行補償的信號處理方式。隨着信號速率的增長,信號在傳輸過程當中受損很大,爲了在接收終端能獲得比較好的信號波形,就須要對受損的信號進行補償,預加劇技術的思想就是在傳輸線的始端加強信號的高頻成分,以補償高頻份量在傳輸過程當中的過大衰減。而預加劇對噪聲並無影響,所以有效地提升了輸出信噪比。
參考:
1) https://blog.csdn.net/xiaoyaoren3134/article/details/48678553
2) https://blog.csdn.net/cwfjimogudan/article/details/71112171
3) https://haythamfayek.com/2016/04/21/speech-processing-for-machine-learning.html
(1) 平衡頻譜,由於高頻相較於低頻一般具備較小的幅度。聲道的終端爲口和脣。從聲道輸出的是速度波,而語音信號是聲壓波,兩者之比的倒數稱爲輻射阻抗。它表徵口和脣和輻射效應,也包括圓形頭部的繞射效應等。語音信號s(n)的平均功率譜受聲門激勵和口鼻輻射的影響,高頻端大約在800Hz以上按6dB/oct (倍頻程)衰減,頻率越高相應的成分越小,爲此要在對語音信號s(n)進行分析以前對其高頻部分加以提高。
(2) 避免在傅里葉變換操做期間的數值問題;
(3) 改善信噪比
備註:在現代的ASR系統中,預加劇並無很是大的影響,由於其大部分做用能夠經過下文所講的mean normalization實現。雖然預加劇能夠避免FFT中的數值問題,可是在現代的FFT實現中,這並非大問題。
通常採用一階FIR高通數字濾波器來實現預加劇,公式爲
$H(z) = 1 - uz^{-1}$
設n時刻的語音採樣值爲$s(n)$,通過預加劇處理後的結果爲
$y(t) = x(t) - \alpha x(t - 1)$
其中a爲預加劇係數,$0.9 < a < 1.0$,通常取值0.95或者0.97.
# origin plot
plt.plot(wavsignal)
plt.show()
# pre-emphasised plot
pre_emphasis = 0.97
wavsignal = np.append([wavsignal[0]], [(wavsignal[i + 1] - pre_emphasis * wavsignal[i]) for i in range(len(wavsignal) - 1)])
# clip to int16
wavsignal = np.clip(wavsignal, a_min = -32768, a_max = 32767)
plt.plot(wavsignal)
plt.show()
首先須要瞭解當前的算法是如何處理語音信號的。通常首先採用的是傅里葉變化,將語音信號由時域轉換到頻域空間。傅里葉變化是針對周期函數的,這是它的限制所在。語音信號,其頻率是不斷變化的,也就是「非週期性」的。若是直接將這樣長的語音信號進行傅里葉變換,是很難得到其信號頻率的良好近似的。那麼如何採用傅里葉變化對語音信號進行處理呢?
這就須要考慮到語音的特性了。語音在較短的時間內變化是平穩的,即具備」短時平穩性「(10-30ms內能夠認爲語音信號近似不變),所以能夠將長語音截斷爲短的片斷,進行「短時分析」。咱們能夠認爲這段短時語音是具備週期性的,能夠對其進行週期延拓。這樣就獲得了一個周期函數,能夠進行傅里葉變換了。 上面中」短的片斷「,每個短的片斷稱爲」一幀「。將不定長的音頻切分紅固定長度的小段,這一步稱爲分幀。
幀長就是每一幀的時間長度,通常取20mx-40ms.
幀移就是每次處理完一幀後向後移動的步長,通常設置與幀長有 50%(+/-10%)的重疊。
在上面進行分幀後,須要對幀加窗函數。
(1) 截取一小段音頻以便進行週期性延拓與傅里葉變換
(2) 不一樣的窗函數的頻譜泄漏不一樣,能夠根據數據與任務要求進行選擇
仍然承接以上分幀的思路,運用計算機實現工程測試信號處理時,不可能對無限長的信號進行測量和運算,而是取其有限的時間片斷進行分析。作法是從信號中截取一個時間片斷,而後用截取的信號時間片斷進行週期延拓處理,獲得虛擬的無限長的信號,而後就能夠對信號進行傅里葉變換、相關分析等數學處理。那麼窗函數就須要是在某一區間內有非零值,而在其他區間值幾乎爲0,那麼用該函數f, 乘以任何一個其餘函數g, f * g只有一部分有非零值。這裏的f即爲窗函數,g即爲咱們的音頻,這樣就能夠截取出一小段音頻了。
無限長的信號被截斷之後,其頻譜發生了畸變,原來集中在f(0)處的能量被分散到兩個較寬的頻帶中去了(這種現象稱之爲頻譜能量泄漏)。
也能夠想象成,若是將原波形在窗口兩端直接截斷,使其取值爲0,這就爲在進行傅里葉變換,也就是進行時域到頻域的變換時,爲了要擬合這個忽然降爲0的波形,須要引入高頻成分,那麼這樣進行傅里葉變換的結果並不能很好的反應原音頻的真實狀況了。
爲了減小頻譜能量泄漏,因此須要用這種在兩端平滑變爲0的窗函數,以免譜泄露。
不一樣的窗函數對信號頻譜的影響是不同的,這主要是由於不一樣的窗函數,產生泄漏的大小不同,頻率分辨能力也不同。信號的截斷產生了能量泄漏,而用FFT算法計算頻譜又產生了柵欄效應,從原理上講這兩種偏差都是不能消除的,可是咱們能夠經過選擇不一樣的窗函數對它們的影響進行抑制。(矩形窗主瓣窄,旁瓣大,頻率識別精度最高,幅值識別精度最低;布萊克曼窗主瓣寬,旁瓣小,頻率識別精度最低,但幅值識別精度最高)。
https://baike.baidu.com/item/%E7%AA%97%E5%87%BD%E6%95%B0/3497822?fr=aladdin 中對矩形窗、三角窗、漢寧窗(Hanning)、海明窗(Hamming)、高斯窗進行了比較。
https://blog.csdn.net/juhou/article/details/81194566 中則顯示了窗函數及其主旁瓣衰減的圖示。
這種窗的優勢是主瓣比較集中,缺點是旁瓣較高,並有負旁瓣,致使變換中帶進了高頻干擾和泄漏,甚至出現負譜現象。
from IPython.display import Image
Image(filename = "/home/lsy/project/dialogue/ASR_test/preprocess/window_func_img/rect.png", width = 400, height = 400)
漢寧窗主瓣加寬並下降,旁瓣則顯著減少,從減少泄漏觀點出發,漢寧窗優於矩形窗.但漢寧窗主瓣加寬,至關於分析帶寬加寬,頻率分辨力降低。
from IPython.display import Image
Image(filename = "/home/lsy/project/dialogue/ASR_test/preprocess/window_func_img/hanning.png", width = 400, height = 400)
海明窗與漢寧窗都是餘弦窗,只是加權係數不一樣。海明窗加權的係數能使旁瓣達到更小。分析代表,海明窗的第一旁瓣衰減爲一42dB.海明窗旁瓣衰減速度爲20dB/(10oct),這比漢寧窗衰減速度慢。海明窗與漢寧窗都是頗有用的窗函數。
在Scipy.signal.hamming中對Hamming window有簡要的介紹: $$ w(n) = 0.54 + 0.46cos(\frac{2\pi n}{M - 1}), 0 <= n <= M- 1$$ 其中,M是輸出窗口內點的個數;w是窗,最大值被歸一化爲1. 本實驗中選擇的是海明窗。
from IPython.display import Image
Image(filename = "/home/lsy/project/dialogue/ASR_test/preprocess/window_func_img/hamming.png", width = 400, height = 400)
x=np.linspace(0, 400 - 1, 400, dtype = np.int64)
w = 0.54 - 0.46 * np.cos(2 * np.pi * (x) / (400 - 1) ) # hamming window
fs= 16000
# wav波形 加時間窗以及時移10ms
time_window = 25 # 單位ms
window_length = fs / 1000 * time_window # 計算窗長度的公式,目前所有爲400固定值
print('window_length = ', window_length)
wav_arr = np.array(wavsignal)
wav_length = len(wavsignal)
print(wav_length)
這裏直接調用的scipy.fftpack進行傅里葉變換,並將變換後的結果用語譜圖表示。
語譜圖就是語音頻譜圖。 https://wenku.baidu.com/view/30c1ae2da517866fb84ae45c3b3567ec112ddc14.html
語音的時域分析和頻域分析是語音分析的兩種重要方法,但各有侷限性:
(1) 時域分析對語音信號的頻率特性沒有直觀的瞭解;
(2) 頻域特性中又沒有語音信號隨時間的變化關係。
所以人們研究語音的時頻分析特性,把和時序相關的傅里葉分析的顯示圖形稱爲語譜圖。
語譜圖用三維的方式表示語音頻譜特性,縱軸表示頻率,橫軸表示時間,顏色的深淺表示特定頻帶的能量大小,顏色深,表示該點的語音能量越強。 它綜合了頻譜圖和時域波形的特色,明顯的顯示處語音頻譜隨時間的變化狀況,或者能夠說是一種動態的頻譜。
from scipy.fftpack import fft
# 獲取信號的時頻圖
# 計算循環終止的位置,也就是最終生成的窗數 = (總的ms - 最後一個窗口ms) / 窗口移動步長
# 10爲幀移
range0_end = (int)((len(wavsignal)/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 # 16khz/s --> 16hz/ms --> 10ms * 16hz/ms = 160hz
p_end = p_start + 400 # 16hz/ms * 25ms = 400
data_line = wav_arr[p_start:p_end]
data_line = data_line * w # 加窗
data_line = np.abs(fft(data_line)) # 傅里葉變換
data_input[i]=data_line[0:200] # 設置爲400除以2的值(即200)是取一半數據,由於是對稱的
data_input = np.log(data_input + 1)
#data_input = data_input[::]
fig = plt.figure(figsize=(20,10))
plt.imshow(data_input.T, origin = 'lower')
plt.show()
上圖是音頻通過傅里葉變換以後獲得的語譜圖。能夠看到在縱軸75以上的部分信息是丟失很是嚴重的。該信息的丟失是在由6k->16k採樣率變化時丟掉的。(對於6k採樣率,每一個窗口中的數據爲 6 * 25 = 150, 因爲對稱保留一半,因此留下 150/2 = 75,也就是上圖所示的0-75的低頻部分。) 我試過用sox修改採樣率,可是也會產生一樣的問題。爲何會有這樣的問題呢?
對於整數倍的上採樣或降採樣其效果較好,可是對於分數倍數,則會在插值時有一些問題.
https://blog.csdn.net/longbei9029/article/details/81237335 中用圖示給出了形象的解釋。(以44.1khz->48khz爲例)
從圖中能夠看出,原始波形分4段5個採樣點(包括首尾),若是整數倍轉換,採用了8個分段9個採樣點(採樣率翻倍),波形是沒有改變的。
可是,若是新的採樣率是原來的1.5倍,採用6個分段7個採樣點,新的波形就會和原波形相差很遠,形成很大的偏差,換言之,這是一個有損轉換過程。一樣,44.1KHz和48KHz之間的轉換也是屬於非整數倍轉換,會帶來可觀的音質損失。
from IPython.display import Image
Image(filename = "/home/lsy/project/dialogue/ASR_test/preprocess/window_func_img/fraction_sample_rate.png", width = 400, height = 400)
另外,在http://forum.doom9.org/archive/index.php/t-131642.html 中」Terranigma「提出相似的問題:
」Does resampling from lets say, 44100 to 48000khz = loss of quality, or perhaps it may seem that way since 48000khz can hold higher frequencies than 44100khz?「
一位名爲」3dsnar「的用戶給出的解釋是:從resample時採用的FIR做爲一個低通濾波器的工做原理出發給出的解釋. ( 至於爲何須要低通濾波器:「因爲抽取可能產生混疊,內插可能產生鏡像,所以須要在抽取前進行抗混疊濾波,在內插後進行抗鏡像濾波。抗混疊濾波和抗鏡像濾波都是使用低通濾波器實現。」)
」To clarify. resampling applies an anti-aliasing (lowpass) FIR filter to the input signal during the resampling process. This causes some errors, including Gibbs effect in the time domain, and some frequency domain distortions (since the frequency characteristics of these filters is inperfect)
Resampling 44,1 -> 48 is possible, because you upsample 160 times and than downsample 147 time. This normally would be very ineficient, however something called polyphase filterbank and polyphase filtering routine is used, which applies both in one shot.
Anyway, this is still pretty computationally complex (44,1 -> 48), hence older resamplers used to use shorter FIR impulse responces for constructing the polyphse matrix, and therefore this particular convertion had alwas (than e.g. 44,1 -> 88,2) been viewed as more problematic and results of lower quality.
Today, a good resampler can make this conversion nearly perfectly (i.e. errors are inaudible, although present).「
目前我還在諮詢並尋找更好的resample的方法,若是您有相關的建議歡指導交流!
from IPython.display import Image
Image(filename = "/home/lsy/Downloads/zhifubao.png", width = 200, height = 200)
[支付寶] 若是您願意送我一個小禮物~ O(∩_∩)O
The scientist does not study nature because it is useful to do so. He studies it because he takes pleasure in it, and he takes pleasure in it because it is beautiful. If nature were not beautiful it would not be worth knowing, and life would not be worth living. ~ Henri Poincare