基於eigen 實現mfcc提取特徵矩陣的實現
阿新 • • 發佈:2018-11-10
MatrixXd mfcc_m(double *x, int length, int fs, int p, int framesize, int inc) { MatrixXd bank = melbankm(p, framesize, fs, 0, 0.5, 1); //bank.operator/=(splab::max(splab::max(bank))); bank = bank / bank.array().maxCoeff(); //DCT係數,p2*p int p2 = p / 2; //Vector<Type> n(p, splab::linspace((Type)0, (Type)(p - 1), p)); VectorXd n = VectorXd::LinSpaced(p, 0, p-1); MatrixXd dctcoef(p2, p); for (int k = 1; k < p2 + 1; k++) { //dctcoef.setRow(cos(((Type)2 * n + (Type)1)*(Type)k*PI / ((Type)2 * p)), k - 1); dctcoef.row(k - 1) = ((2 * n.array() + 1)*k*M_PI / (2 * p)).cos(); } //% 歸一化倒譜提升視窗 VectorXd w = 1 + 6 * sin(M_PI*VectorXd::LinSpaced(p2, 1, p2).array() / p2); w = w / w.maxCoeff(); //% 預加重濾波器 Type * yy = new Type[length]; yy = pre_emphasizing(x, length, 0.9375); //語音訊號分幀 MatrixXd xx = enframe(yy, length, framesize, inc); delete[] yy; Type n2 = (int)(framesize / 2) + 1; int xx_col_length = (int)xx.cols(); int xx_row_length = (int)xx.rows(); VectorXd s(xx_col_length); VectorXd y(xx_col_length); VectorXd t(xx_col_length); VectorXd c1(p2); VectorXd c2(p2); MatrixXd m(xx_row_length, p2); FFT<Type> fft; Eigen::VectorXcd tmpc(xx_col_length); // 計算每幀的MFCC引數 for (int i = 0; i < xx_row_length; i++) { y = xx.row(i); s=y.array()*gencoswin(framesize, 0, true).array(); fft.fwd(tmpc, s); t = abs(tmpc.array()).pow(2); c1 = dctcoef*(bank*t.head((int)n2)).array().log().matrix(); c2 = c1*w.transpose(); m.row(i) = c1.array()*w.array(); } //差分系數 //Matrix<Type>dtm(xx.dim(1), p2, (Type)0); MatrixXd dtm = MatrixXd::Zero(xx_row_length, p2); for (int i = 3; i < xx_row_length - 1; i++) { //dtm.setRow(-(Type)2 * m.getRow(i - 3) - m.getRow(i - 2) //+ m.getRow(i) + (Type)2 * m.getRow(i + 1), i - 1); dtm.row(i - 1) = -2 * m.row(i - 3) - m.row(i - 2) + m.row(i) + 2 * m.row(i + 1); } dtm = dtm /3; //dtm.operator/=((Type)3); //合併MFCC引數和一階差分MFCC引數 //去除首尾兩幀(共四幀),因為這兩幀的一階差分引數為0 //Matrix<Type> ccc(m.dim(1) - 4, p); MatrixXd ccc(xx_row_length-4, p); //ccc << m.rightCols(p2 - 2), dtm.leftCols(p2 - 2); ccc << m.middleRows(2, xx_row_length - 4), dtm.middleRows(2, xx_row_length - 4); return ccc; }