⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fe_basic.cpp

📁 这是一个语音特征提取的程序源码
💻 CPP
字号:
///////////////////////////////////////////////////////////////////////////////
// This is a part of the Feature program.
// Version: 1.0
// Date: February 22, 2003
// Programmer: Oh-Wook Kwon
// Copyright(c) 2003 Oh-Wook Kwon. All rights reserved. owkwon@ucsd.edu
///////////////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "FE_feature.h"


typedef CPolynomial<float> Polynomial;
typedef Complex<float> CComplex;


int Fe::fftcep_spectrum_basic(short *sample, int frameSize, float *spectrum, int fftSize, int cepFilterLen)
{
	_fft_spectrum_basic(sample, frameSize, spectrum, fftSize, 1, cepFilterLen);
	return 1;
}


int Fe::lpc_basic(short *sample, int frameSize, float *acf, int norder, float *G)
{
	vector<float> frameA(frameSize);
	preprocessing(sample, frameSize, &frameA[0]);
	m_window.Windowing(&frameA[0], frameSize, WIN_HAMMING);
	_lpc_basic(&frameA[0], frameSize, acf, norder, G);
	return(1);
}


int Fe::lpc_cov_basic(short *sample, int frameSize, float *acf, int norder, float *G)
{
	vector<float> frameA(frameSize);
	for(int i=0;i<frameSize;i++) frameA[i]=sample[i];
	FeMatrix<float> cov(norder+1, norder+1);
	lpc_cov(&frameA[0], frameSize, cov, acf, norder, G);
	return(1);
}


int Fe::parcor_basic(short *sample, int frameSize, float *kcf, int norder)
{
	float G;
	vector<float> acf(norder+1);
	vector<float> frameA(frameSize);
	preprocessing(sample, frameSize, &frameA[0]);
	m_window.Windowing(&frameA[0], frameSize, WIN_HAMMING);
	_lpc_parcor_basic(&frameA[0], frameSize, &acf[0], kcf, norder, &G);
	return(1);
}


int	Fe::lar_basic(short *sample, int frameSize, float *lar, int norder)
{
	float G;
	vector<float> acf(norder+1);
	vector<float> kcf(norder+1);
	vector<float> frameA(frameSize);
	preprocessing(sample, frameSize, &frameA[0]);
	m_window.Windowing(&frameA[0], frameSize, WIN_HAMMING);
	_lpc_parcor_basic(&frameA[0], frameSize, &acf[0], &kcf[0], norder, &G);
	lar[0] = 0;
	for(int i=1; i<= norder; i++){
		lar[i] = (float)log((1-kcf[i])/(1+kcf[i]));
	}
	return(1);
}


int	Fe::lpc_spectrum_basic(short *sample, int frameSize, int norder, float *spectrum, int fftSize)
{
	int i;
	float G;
	vector<float> acf(fftSize);
	lpc_basic(sample, frameSize, &acf[0], norder, &G);
	int log2fftsize = (int)(log(fftSize)/log(2)+0.5);
	float logGdb = (G>0 ? 20*LOG10(G) : FE_MIN_LOG_ENERGY);	/* power spectrum */
	acf[0] = 1;
	/* Note that the definition of a[] is y(n) = a(1)y(n-1) + a(2)y(n-2) + ... */
	for(i=1;i<=norder;i++) acf[i] = -acf[i];
	
	compute_spectrum(&acf[0], spectrum, norder+1, log2fftsize);
	
	/* Note that spectrum is in the power domain. */
	for(i=0;i<fftSize;i++){
		float db=(spectrum[i]>FE_MIN_ENERGY ? 10*LOG10(spectrum[i]) : 10*LOG10(FE_MIN_ENERGY));
		spectrum[i] = (float)(logGdb-db);
	}
	
	return(1);
}


int	Fe::lpccep_spectrum_basic(short *sample, int frameSize, int ceporder, int norder, float *spectrum, int fftSize)
{
	int i;
	float G;
	vector<float> acf(fftSize);
	lpc_basic(sample, frameSize, &acf[0], norder, &G);
	vector<float> lpc_cep(fftSize);

	lpc_to_cepstrum(&acf[0], norder, &lpc_cep[0], ceporder, G);

	lpc_cep[0] = 0.5*lpc_cep[0]; /* we need log magnitude because fft_pow will give power spectrum */
	int log2fftsize = (int)(log(fftSize)/log(2)+0.5);
	compute_spectrum(&lpc_cep[0], spectrum, ceporder+1, log2fftsize);

	/* need 10/log(10) to get dB scale because lpc_cep is in the natural log scale. */
	float log10db=(float)(10/log(10));
	for(i=0;i<fftSize;i++){
		spectrum[i] = log10db*spectrum[i];
	}
	return(1);
}


int	Fe::melcep_spectrum_basic(short *sample, int frameSize, int ceporder, float *spectrum, int fftSize)
{
	int i,k;
	vector<float> mel_cep(ceporder+1);
	mel_cepstrum_basic(sample, frameSize, &mel_cep[0], ceporder, fftSize);
	MfccIDCT (&mel_cep[0], &m_idctMatrix[0], ceporder, m_fbOrder, spectrum);

	/* scale up to be consistent with other kinds of cepstrum coefficients */
	float g=2*fftSize/(float)m_fbOrder;
	for(i=0;i<m_fbOrder;i++) spectrum[i] *= g;

	float log10db=(float)(10/log(10));
	for(i=m_fbOrder;i>=1;i--){
		int kmin=(m_MelCenterIdx[i-1]+m_MelCenterIdx[i])/2;
		int kmax=(m_MelCenterIdx[i]+m_MelCenterIdx[i+1])/2;
		for(k=kmin;k<kmax;k++) spectrum[k]=log10db*spectrum[i-1];
	}
	{
		int kmax=(m_MelCenterIdx[0]+m_MelCenterIdx[1])/2;
		for(k=0;k<kmax;k++) spectrum[k]=spectrum[m_MelCenterIdx[1]];
		int kmin=(m_MelCenterIdx[m_fbOrder]+m_MelCenterIdx[m_fbOrder+1])/2;
		for(k=kmin;k<=fftSize/2;k++) spectrum[k]=spectrum[m_MelCenterIdx[m_fbOrder]];
	}
	return(1);
}


int	Fe::lpc_error_basic(short *sample, int frameSize, float *acf, int norder, float* residual)
{
	int i,n;
	for(n=0;n<norder && n<frameSize;n++){
		short si;
		residual[n] = sample[n];	
		for(i=1;i<=norder;i++){
			si = (n-i>=0) ? sample[n-i] : 0;
			residual[n] -= acf[i]*si;
		}
	}
	for(n=norder;n<frameSize;n++){
		residual[n] = sample[n];
		for(i=1;i<=norder;i++){
			residual[n] -= acf[i]*sample[n-i];
		}
	}
	return(1);
}


int	Fe::formant_basic(short *sample, int frameSize, float *formant, int formantN, int norder)
{
	float G;
	vector<float> acf(norder+1);
	lpc_basic(sample, frameSize, &acf[0], norder, &G);
	vector<CComplex> rootsA;
	int nf = lpc_to_formant(&acf[0], norder, formant, formantN, rootsA);
	for(int i=0; i<nf; i++)
		formant[i] *= (m_sampleRate/(float)(2*M_PI));
	return(1);
}


/*
sigma2 = r[0] - sum_{k=1}^N {a[k]*r[k]}
return value = G = sqrt(sigma2)
*/
float Fe::calc_lpc_gain_basic(float *r, float *acf, int norder)
{
	int i;
	float sigma2 = r[0];
	for(i=1; i<=norder; i++){
		sigma2 -= acf[i]*r[i];
	}
	return (float)sqrt(sigma2);
}


int	Fe::_lpc_parcor_basic(float *sample, int frameSize, float *acf, float *kcf, int norder, float *G)
{
	int		i, winSize;
	vector<float> r(norder+1);
	vector<float> rorg(norder+1);
	winSize = frameSize;
	{
		auto_correlation(sample, &r[0], frameSize, norder);
		
		for(i=0; i<=norder; i++) rorg[i] = r[i];
		
		/* solving the autocorrelation matrix */
		levins(&r[0], kcf, acf, norder);
		
		/* just for completeness */
		kcf[0] = 0;
		acf[0] = 1;
		
		/* G denotes LPC gain G */
		if(G) (*G) = calc_lpc_gain_basic(&rorg[0], acf, norder);
	}
	
	return(1);
}


/*
H(z) = G / (1 - sum_{i=1}^N {a[i]*z^{-i}} )
acf[0] = G, acf[i] = a[i], i=1,...,N
*/
int	Fe::_lpc_basic(float *sample, int frameSize, float *acf, int norder, float *G)
{
	int		i, winSize;
	vector<float> r(norder+1);
	vector<float> rorg(norder+1);
	vector<float> kcf(norder+1);
	winSize = frameSize;
	{
		auto_correlation(sample, &r[0], frameSize, norder);
		
		for(i=0; i<=norder; i++) rorg[i] = r[i];
		
		/* solving the autocorrelation matrix */
		levins(&r[0], &kcf[0], acf, norder);
		
		/* just for completeness */
		kcf[0] = 0; 
		acf[0] = 1;
		
		/* G denotes LPC gain G */
		if(G) (*G) = calc_lpc_gain_basic(&rorg[0], acf, norder);
	}
	
	return(1);
}


int	Fe::_lpc_error_basic(float *sample, int frameSize, float *acf, int norder, float* residual)
{
	int i,n;
	for(n=0;n<norder && n<frameSize;n++){
		float si;
		residual[n] = sample[n];	
		for(i=1;i<=norder;i++){
			si = (n-i>=0) ? sample[n-i] : 0;
			residual[n] -= acf[i]*si;
		}
	}
	for(n=norder;n<frameSize;n++){
		residual[n] = sample[n];
		for(i=1;i<=norder;i++){
			residual[n] -= acf[i]*sample[n-i];
		}
	}
	return(1);
}


/* preprocessing */
int Fe::preprocessing(short *sample, int sampleN, float *out)
{
	for(int i=0;i<sampleN;i++) out[i]=sample[i];
	if (m_dither) Dither(out, sampleN);
	preemphasize(out, sampleN, m_emphFac);
	return 1;
}


/* energy */
float Fe::compute_energy(float *sample, int sampleN, float mean)
{
	float sum = 0;
	for(int i=0; i<sampleN; i++){
		sum += (sample[i]-mean)*(sample[i]-mean);
	}
	float v=((sampleN>0) ? sum/sampleN : (float)0);
	v = v+1; /* to make happy feature extraction and analysis routines */
	return v;
}


/* zero crossing rate */
int Fe::compute_zero_cross_rate(float *sample, int sampleN, int level, int dc_bias)
{
	if(sampleN<1) return 0;
	int zcr=0;	
	float prev = sample[0]-dc_bias-level;
	for(int i=1; i<sampleN; i++) {
		float val  = sample[i]-dc_bias-level;
		float ztmp=val*prev;
		if(ztmp<0) zcr++;
		prev=val;
	}
	return zcr;
}


/* cepstral weighting */
/* cepstral coefficients are ordered as [c0, c1, c2, ..., c12] */
int	Fe::cepstral_window(float *cep, int ceporder, FeLifter lifter)
{
	int i;
	switch(lifter){
	case LIFT_NO:
		break;
	case LIFT_SIN:
		for (i=0; i<=ceporder; i++)
			cep[i] *= (float)(1. + (float)ceporder/2. * sin((M_PI*(i+1))/(float)ceporder));
		break;
	case LIFT_LINEAR:
		for (i=0; i<=ceporder; i++)
			cep[i] *= (i+1);
		break;
	case LIFT_SQRT:
		for (i=0; i<=ceporder; i++)
			cep[i] *= (float)sqrt(i+1);
		break;
	case LIFT_CUBE_ROOT:
		for (i=0; i<=ceporder; i++)
			cep[i] *= (float)pow(i+1,1/3.0);
		break;
	}
	return(1);
}


/* in-place preemphasis */
int Fe::preemphasize(float *sample, int sampleN, float emphFac)
{
	/* Setting emphFac=0 turns off preemphasis. */
	int	i;
	for (i = sampleN-1; i > 0; i--) {
		sample[i] = sample[i] - emphFac * sample[i-1];
	}
	sample[0] = (float)(1.0 - emphFac) * sample[0];
	return(1);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -