1. 程式人生 > >基於eigen 實現mfcc提取特徵矩陣的實現

基於eigen 實現mfcc提取特徵矩陣的實現

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;

}