librosa語音訊號處理
librosa是一個非常強大的python語音訊號處理的第三方庫,本文參考的是librosa的官方文件,本文主要總結了一些重要,對我來說非常常用的功能。學會librosa後再也不用用python去實現那些複雜的演算法了,只需要一句語句就能輕鬆實現。
先總結一下本文中常用的專業名詞:sr:取樣率、hop_length:幀移、overlapping:連續幀之間的重疊部分、n_fft:視窗大小、spectrum:頻譜、spectrogram:頻譜圖或叫做語譜圖、amplitude:振幅、mono:單聲道、stereo:立體聲
讀取音訊
librosa.load(path, sr=22050, mono=True, offset=0.0, duration=None)
讀取音訊檔案。預設取樣率是22050,如果要保留音訊的原始取樣率,使用sr = None。
引數:
- path :音訊檔案的路徑。
- sr :取樣率,如果為“None”使用音訊自身的取樣率
- mono :bool,是否將訊號轉換為單聲道
- offset :float,在此時間之後開始閱讀(以秒為單位)
- 持續時間:float,僅載入這麼多的音訊(以秒為單位)
返回:
- y :音訊時間序列
- sr :音訊的取樣率
重取樣
librosa.resample(y, orig_sr, target_sr, fix=True, scale=False)
重新取樣從orig_sr到target_sr的時間序列
引數:
- y :音訊時間序列。可以是單聲道或立體聲。
- orig_sr :y的原始取樣率
- target_sr :目標取樣率
- fix:bool,調整重取樣訊號的長度,使其大小恰好為 $\frac{len(y)}{orig\_sr}*target\_sr =t*target\_sr$
- scale:bool,縮放重新取樣的訊號,以使y和y_hat具有大約相等的總能量。
返回:
- y_hat :重取樣之後的音訊陣列
讀取時長
librosa.get_duration(y=None, sr=22050, S=None, n_fft=2048, hop_length=512, center=True, filename=None)
計算時間序列的的持續時間(以秒為單位)
引數:
- y :音訊時間序列
- sr :y的音訊取樣率
- S :STFT矩陣或任何STFT衍生的矩陣(例如,色譜圖或梅爾頻譜圖)。根據頻譜圖輸入計算的持續時間僅在達到幀解析度之前才是準確的。如果需要高精度,則最好直接使用音訊時間序列。
- n_fft :S的 FFT視窗大小
- hop_length :S列之間的音訊樣本數
- center :布林值
- 如果為True,則S [:, t]的中心為y [t * hop_length]
- 如果為False,則S [:, t]從y[t * hop_length]開始
- filename :如果提供,則所有其他引數都將被忽略,並且持續時間是直接從音訊檔案中計算得出的。
返回:
- d :持續時間(以秒為單位)
讀取取樣率
librosa.get_samplerate(path)
引數:
- path :音訊檔案的路徑
返回:音訊檔案的取樣率
寫音訊
librosa.output.write_wav(path, y, sr, norm=False)
將時間序列輸出為.wav檔案
引數:
- 路徑:儲存輸出wav檔案的路徑
- y :音訊時間序列。
- sr :y的取樣率
- norm:bool,是否啟用幅度歸一化。將資料縮放到[-1,+1]範圍。
過零率
計算音訊時間序列的過零率。
librosa.feature.zero_crossing_rate(y, frame_length = 2048, hop_length = 512, center = True)
引數:
- y :音訊時間序列
- frame_length :幀長
- hop_length :幀移
- center:bool,如果為True,則通過填充y的邊緣來使幀居中。
返回:
- zcr:zcr[0,i]是第i幀中的過零率
y, sr = librosa.load(librosa.util.example_audio_file()) print(librosa.feature.zero_crossing_rate(y)) # array([[ 0.134, 0.139, ..., 0.387, 0.322]])
波形圖
librosa.display.waveplot(y, sr=22050, x_axis='time', offset=0.0, ax=None)
繪製波形的幅度包絡線
引數:
- y :音訊時間序列
- sr :y的取樣率
- x_axis :str {'time','off','none'}或None,如果為“時間”,則在x軸上給定時間刻度線。
- offset:水平偏移(以秒為單位)開始波形圖
import librosa.display import matplotlib.pyplot as plt y, sr = librosa.load(librosa.util.example_audio_file(), duration=10) librosa.display.waveplot(y, sr=sr) plt.show()
短時傅立葉變換
librosa.stft(y, n_fft=2048, hop_length=None, win_length=None, window='hann', center=True, pad_mode='reflect')
短時傅立葉變換(STFT),返回一個複數矩陣使得D(f,t)
- 複數的實部:np.abs(D(f,t))頻率的振幅
- 複數的虛部:np.angle(D(f,t))頻率的相位
引數:
- y:音訊時間序列
- n_fft:FFT視窗大小,n_fft=hop_length+overlapping
- hop_length:幀移,如果未指定,則預設win_length / 4。
- win_length:每一幀音訊都由window()加窗。窗長win_length,然後用零填充以匹配N_FFT。預設
win_length=n_fft
。 - window:字串,元組,數字,函式 shape =(n_fft, )
- 視窗(字串,元組或數字);
- 窗函式,例如
scipy.signal.hanning
- 長度為n_fft的向量或陣列
- center:bool
- 如果為True,則填充訊號y,以使幀 D [:, t]以y [t * hop_length]為中心。
- 如果為False,則D [:, t]從y [t * hop_length]開始
- dtype:D的複數值型別。預設值為64-bit complex複數
- pad_mode:如果center = True,則在訊號的邊緣使用填充模式。預設情況下,STFT使用reflection padding。
返回:
- STFT矩陣,shape =(1 + $\frac{n_{fft} }{2}$,t)
短時傅立葉逆變換
librosa.istft(stft_matrix, hop_length=None, win_length=None, window='hann', center=True, length=None)
短時傅立葉逆變換(ISTFT),將複數值D(f,t)頻譜矩陣轉換為時間序列y,窗函式、幀移等引數應與stft相同
引數:
- stft_matrix :經過STFT之後的矩陣
- hop_length :幀移,預設為$\frac{win_{length}}{4}$
- win_length :窗長,預設為n_fft
- window:字串,元組,數字,函式或shape = (n_fft, )
- 視窗(字串,元組或數字)
- 窗函式,例如
scipy.signal.hanning
- 長度為n_fft的向量或陣列
- center:bool
- 如果為True,則假定D具有居中的幀
- 如果False,則假定D具有左對齊的幀
- length:如果提供,則輸出y為零填充或剪裁為精確長度音訊
返回:
- y :時域訊號
幅度轉dB
librosa.amplitude_to_db(S, ref=1.0)
將幅度頻譜轉換為dB標度頻譜。也就是對S取對數。與這個函式相反的是librosa.db_to_amplitude(S)
引數:
- S :輸入幅度
- ref :參考值,振幅abs(S)相對於ref進行縮放,$20*log_{10}(\frac{S}{ref})$
返回:
- dB為單位的S
功率轉dB
librosa.core.power_to_db(S, ref=1.0)
將功率譜(幅度平方)轉換為分貝(dB)單位,與這個函式相反的是librosa.db_to_power(S)
引數:
- S:輸入功率
- ref :參考值,振幅abs(S)相對於ref進行縮放,$10*log_{10}(\frac{S}{ref})$
返回:
- dB為單位的S
import librosa.display import numpy as np import matplotlib.pyplot as plt y, sr = librosa.load(librosa.util.example_audio_file()) S = np.abs(librosa.stft(y)) print(librosa.power_to_db(S ** 2)) # array([[-33.293, -27.32 , ..., -33.293, -33.293], # [-33.293, -25.723, ..., -33.293, -33.293], # ..., # [-33.293, -33.293, ..., -33.293, -33.293], # [-33.293, -33.293, ..., -33.293, -33.293]], dtype=float32) plt.figure() plt.subplot(2, 1, 1) librosa.display.specshow(S ** 2, sr=sr, y_axis='log') # 從波形獲取功率譜圖 plt.colorbar() plt.title('Power spectrogram') plt.subplot(2, 1, 2) # 相對於峰值功率計算dB, 那麼其他的dB都是負的,注意看後邊cmp值 librosa.display.specshow(librosa.power_to_db(S ** 2, ref=np.max), sr=sr, y_axis='log', x_axis='time') plt.colorbar(format='%+2.0f dB') plt.title('Log-Power spectrogram') plt.set_cmap("autumn") plt.tight_layout() plt.show()
功率譜和dB功率譜
頻譜圖
librosa.display.specshow(data, x_axis=None, y_axis=None, sr=22050, hop_length=512)
引數:
- data:要顯示的矩陣
- sr :取樣率
- hop_length :幀移
- x_axis 、y_axis :x和y軸的範圍
- 頻率型別
- 'linear','fft','hz':頻率範圍由FFT視窗和取樣率確定
- 'log':頻譜以對數刻度顯示
- 'mel':頻率由mel標度決定
- 時間型別
- time:標記以毫秒,秒,分鐘或小時顯示。值以秒為單位繪製。
- s:標記顯示為秒。
- ms:標記以毫秒為單位顯示。
- 所有頻率型別均以Hz為單位繪製
import librosa.display import numpy as np import matplotlib.pyplot as plt y, sr = librosa.load(librosa.util.example_audio_file()) plt.figure() D = librosa.amplitude_to_db(np.abs(librosa.stft(y)), ref=np.max) plt.subplot(2, 1, 1) librosa.display.specshow(D, y_axis='linear') plt.colorbar(format='%+2.0f dB') plt.title('線性頻率功率譜') plt.subplot(2, 1, 2) librosa.display.specshow(D, y_axis='log') plt.colorbar(format='%+2.0f dB') plt.title('對數頻率功率譜') plt.show()
Mel濾波器組
librosa.filters.mel(sr, n_fft, n_mels=128, fmin=0.0, fmax=None, htk=False, norm=1)
建立一個濾波器組矩陣以將FFT合併成Mel頻率
引數:
- sr :輸入訊號的取樣率
- n_fft :FFT元件數
- n_mels :產生的梅爾帶數
- fmin :最低頻率(Hz)
- fmax:最高頻率(以Hz為單位)。如果為None,則使用fmax = sr / 2.0
- norm:{None,1,np.inf} [標量]
- 如果為1,則將三角mel權重除以mel帶的寬度(區域歸一化)。否則,保留所有三角形的峰值為1.0
返回:Mel變換矩陣
melfb = librosa.filters.mel(22050, 2048) # array([[ 0. , 0.016, ..., 0. , 0. ], # [ 0. , 0. , ..., 0. , 0. ], # ..., # [ 0. , 0. , ..., 0. , 0. ], # [ 0. , 0. , ..., 0. , 0. ]]) import matplotlib.pyplot as plt plt.figure() librosa.display.specshow(melfb, x_axis='linear') plt.ylabel('Mel filter') plt.title('Mel filter bank') plt.colorbar() plt.tight_layout() plt.show()
計算Mel scaled 頻譜
librosa.feature.melspectrogram(y=None, sr=22050, S=None, n_fft=2048, hop_length=512, win_length=None, window='hann', center=True, pad_mode='reflect', power=2.0)
計算Mel scaled 頻譜,
如果提供了頻譜圖輸入S,則通過mel_f.dot(S)將其直接對映到mel_f上。
如果提供了時間序列輸入y,sr,則首先計算其幅值頻譜S,然後通過mel_f.dot(S ** power)將其對映到mel scale上 。預設情況下,power= 2在功率譜上執行。
引數:
- y :音訊時間序列
- sr :取樣率
- S :頻譜
- n_fft :FFT視窗的長度
- hop_length :幀移
- win_length :視窗的長度為win_length,預設
win_length = n_fft
- window :字串,元組,數字,函式或shape =(n_fft, )
- 視窗規範(字串,元組或數字);看到
scipy.signal.get_window
- 視窗函式,例如
scipy.signal.hanning
- 長度為n_fft的向量或陣列
- 視窗規範(字串,元組或數字);看到
- center:bool
- 如果為True,則填充訊號y,以使幀 t以y [t * hop_length]為中心。
- 如果為False,則幀t從y [t * hop_length]開始
- power:幅度譜的指數。例如1代表能量,2代表功率,等等
- n_mels:濾波器組的個數 1288
- fmax:最高頻率
返回:Mel頻譜shape=(n_mels, t)
import librosa.display import numpy as np import matplotlib.pyplot as plt y, sr = librosa.load(librosa.util.example_audio_file()) # 方法一:使用時間序列求Mel頻譜 print(librosa.feature.melspectrogram(y=y, sr=sr)) # array([[ 2.891e-07, 2.548e-03, ..., 8.116e-09, 5.633e-09], # [ 1.986e-07, 1.162e-02, ..., 9.332e-08, 6.716e-09], # ..., # [ 3.668e-09, 2.029e-08, ..., 3.208e-09, 2.864e-09], # [ 2.561e-10, 2.096e-09, ..., 7.543e-10, 6.101e-10]]) # 方法二:使用stft頻譜求Mel頻譜 D = np.abs(librosa.stft(y)) ** 2 # stft頻譜 S = librosa.feature.melspectrogram(S=D) # 使用stft頻譜求Mel頻譜 plt.figure(figsize=(10, 4)) librosa.display.specshow(librosa.power_to_db(S, ref=np.max), y_axis='mel', fmax=8000, x_axis='time') plt.colorbar(format='%+2.0f dB') plt.title('Mel spectrogram') plt.tight_layout() plt.show()
提取Log-Mel Spectrogram 特徵
Log-Mel Spectrogram特徵是目前在語音識別和環境聲音識別中很常用的一個特徵,由於CNN在處理影象上展現了強大的能力,使得音訊訊號的頻譜圖特徵的使用愈加廣泛,甚至比MFCC使用的更多。在librosa中,Log-Mel Spectrogram特徵的提取只需幾行程式碼:
import librosa y, sr = librosa.load('./train_nb.wav', sr=16000) # 提取 mel spectrogram feature melspec = librosa.feature.melspectrogram(y, sr, n_fft=1024, hop_length=512, n_mels=128) logmelspec = librosa.amplitude_to_db(melspec) # 轉換到對數刻度 print(logmelspec.shape) # (128, 65)
可見,Log-Mel Spectrogram特徵是二維陣列的形式,128表示Mel頻率的維度(頻域),64為時間幀長度(時域),所以Log-Mel Spectrogram特徵是音訊訊號的時頻表示特徵。其中,n_fft指的是窗的大小,這裡為1024;hop_length表示相鄰窗之間的距離,這裡為512,也就是相鄰窗之間有50%的overlap;n_mels為mel bands的數量,這裡設為128。
提取MFCC係數
MFCC特徵是一種在自動語音識別和說話人識別中廣泛使用的特徵。關於MFCC特徵的詳細資訊,有興趣的可以參考部落格http:// blog.csdn.net/zzc15806/article/details/79246716。在librosa中,提取MFCC特徵只需要一個函式:
librosa.feature.mfcc(y=None, sr=22050, S=None, n_mfcc=20, dct_type=2, norm='ortho', **kwargs)
引數:
- y:音訊資料
- sr:取樣率
- S:np.ndarray,對數功能梅爾譜圖
- n_mfcc:int>0,要返回的MFCC數量
- dct_type:None, or {1, 2, 3} 離散餘弦變換(DCT)型別。預設情況下,使用DCT型別2。
- norm: None or ‘ortho’ 規範。如果dct_type為2或3,則設定norm =’ortho’使用正交DCT基礎。 標準化不支援dct_type = 1。
返回:
M: MFCC序列
import librosa y, sr = librosa.load('./train_nb.wav', sr=16000) # 提取 MFCC feature mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=40) print(mfccs.shape) # (40, 65)
&n