MFCC特徵提取--基於kaldi裁剪

0. 前言

關於MFCC相關原理,這裏就不過多敘述了,網上的參考資料也比較多,自己對MFCC原理理解也不是很深刻(方向不一樣),主要介紹本人對kaldi mfcc特徵提取代碼裁剪後的接口,此處開源的MFCC不含pitch特徵提取。

詳細代碼

1. Github代碼結構介紹

在介紹之前,提及一點,若要運行,請先閱讀README.md編譯外部庫。

特徵提取的代碼在src/feat目錄下,測試代碼在src/main/feat-test.cc
MFCC最後提交commit 1d1d3fef56b3325352f29e1e08c78516a5ba12f5,切換到commit後,可以知道調用了哪些數學運算,其中openblas調用了兩個接口:**cblas_sdot **、cblas_sgemv
文件源程序結構:
在這裏插入圖片描述
如果想要編譯測試代碼src/main/feat-test.cc,請修改src/build/Makefile

以上代碼文件中,計算特徵的接口在compute-feat.h中,其他mel-banks和srfft相關操作可以不用管。

關於mfcc參數設置,代碼中採用的宏定義的方式,具體的配置在feat-params.h中,需要特別注意的是如果改變了窗函數的大小,需要手動計算一下 PADDING_WINDOWS_SIZE, 計算PADDING_WINDOWS_SIZE方式如下:

// 計算窗函數方式, 傳入參數爲WINDOW_SIZE
static inline int32 RoundUpToNearestPowerOfTwo(int32 n)
{
  n--;
  n |= n >> 1;
  n |= n >> 2;
  n |= n >> 4;
  n |= n >> 8;
  n |= n >> 16;
  return n+1;
}

#define WINDOW_SHIFT          (static_cast<int32> ((SAMPLEING_RATE) * 0.001f * (FRAME_SHIFT_MS)))
#define WINDOW_SIZE           (static_cast<int32> ((SAMPLEING_RATE) * 0.001f * (FRAME_LENGHT_MS)))
//#define PADDING_WINDOWS_SIZE  ((RoundUpToNearestPowerOfTwo(WINDOW_SIZE)))
#define PADDING_WINDOWS_SIZE  (512)  // 此處手動填入的計算值

因爲在程序中使用PADDING_WINDOWS_SIZE來創建一個全局數組,而用函數時是在運行時才確定數組大小,所以編譯會報錯,怎麼寫帶返回值的RoundUpToNearestPowerOfTwo宏定義函數,歡迎大佬指點一下,不勝感激!

2. APIs說明

Api 說明
ComputeFeatInit() 初始化特徵提取的一些變量及mel-banks、srfft
ComputeFeatures(const vector &waveform, vector<BaseFloat* > &feats) 計算mfcc特徵,傳入音頻文件data段(原始PCM流),輸出的結果存在feats中
NumFramesReady(const vector<BaseFloat* > &feats) 獲取當前音頻提取完有多少幀MFCC特徵
IsLastFrame(const vector<BaseFloat* > &feats, const int32 frame) 判斷當前幀是否是最後一幀
GetFrame(const vector<BaseFloat* > &feats, const int32 frame) 根據frame獲得一行mfcc特徵
FeatsFree() 釋放當前音頻文件計算mfcc特徵過程中申請的內存
FeatDestroy() 釋放所有的特徵提取申請的內存, 除featsFree()外還包括mel-banks、srfft申請的內存

如果需要修改成C語言,只需要替換掉vector即可,特徵feats可以定義成如下結構體:

typedef struct 
{
	int32 frames;
	BaseFloat**feat;
} MfccFeats;

3. 調用流程

在這裏插入圖片描述

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