Beispiel #1
0
void bob::ap::Ceps::operator()(const blitz::Array<double,1>& input,
  blitz::Array<double,2>& ceps_matrix)
{

  // Get expected dimensionality of output array
  blitz::TinyVector<int,2> feature_shape = bob::ap::Ceps::getShape(input);
  // Check dimensionality of output array
  bob::core::array::assertSameShape(ceps_matrix, feature_shape);
  int n_frames=feature_shape(0);
  int shift_frame=0;
  double last_frame_elem=0;

  // Create the holder for the previous frame and make sure it's the same as the current frame
  // Used by SSFC features computation
  blitz::Array<double,1> _prev_frame_d;
  _prev_frame_d.resize(m_cache_frame_d.shape());
  // Create the temporary holder for SSFC features computation
  blitz::Array<double,1> _temp_frame_d;
  _temp_frame_d.resize(m_cache_frame_d.shape());

  if (m_ssfc_features) {
    //we are going to always process the next frame within the loop
    shift_frame = 1;
    // Init the first frame to the input
    extractNormalizeFrame(input, 0, _prev_frame_d);
    // Apply pre-emphasis
    pre_emphasis(_prev_frame_d, last_frame_elem);
    // Apply the Hamming window
    hammingWindow(_prev_frame_d);
    // Take the power spectrum of the first part of the FFT
    powerSpectrumFFT(_prev_frame_d);

  }

  blitz::Range r1(0,m_n_ceps-1);
  for (int i=0; i<n_frames; ++i)
  {
    // Init the current frame from the input, we process (i+1)th frame for SSFC features
    extractNormalizeFrame(input, i+shift_frame, m_cache_frame_d);

    // Update output with energy if required
    if (m_with_energy)
      ceps_matrix(i,(int)m_n_ceps) = logEnergy(m_cache_frame_d);

    // Apply pre-emphasis
    pre_emphasis(m_cache_frame_d, last_frame_elem);
    // Apply the Hamming window
    hammingWindow(m_cache_frame_d);
    // Take the power spectrum of the first part of the FFT
    // Note that after this call, we only operate on the first half of m_cache_frame_d array. The second half is ignored.
    // powerSpectrumFFT changes first half+1 elements of m_cache_frame_d array
    powerSpectrumFFT(m_cache_frame_d);

    if (m_ssfc_features)
    {
      // retrieve the previous frame into our temp
      _temp_frame_d = _prev_frame_d;
      // remember the current frame for the next round, before we change current frame
      _prev_frame_d = m_cache_frame_d;
      // Computation of SSFC features:
      // We take the previous frame and find the difference between values of current and previous frames
      m_cache_frame_d -= _temp_frame_d;
      // We compute norm2 for the difference as per SSFC features
      m_cache_frame_d = blitz::pow2(m_cache_frame_d);
      // Then, we can apply the filter and DCT later on
    }
    // Filter with triangular or rectangular filter bank (either in linear or Mel domain)
    filterBank(m_cache_frame_d);

    // Apply DCT kernel and update the output
    blitz::Array<double,1> ceps_matrix_row(ceps_matrix(i,r1));

    if (m_scfc_features)
      // do not apply DCT on SCFC features
      ceps_matrix_row = m_cache_filters(r1);
    else
      applyDct(ceps_matrix_row);
  }

  //compute the center of the cut-off frequencies
  const int n_coefs = (m_with_energy ?  m_n_ceps + 1 :  m_n_ceps);
  blitz::Range rall = blitz::Range::all();
  blitz::Range ro0(0,n_coefs-1);
  blitz::Range ro1(n_coefs,2*n_coefs-1);
  blitz::Range ro2(2*n_coefs,3*n_coefs-1);
  if (m_with_delta)
  {
    blitz::Array<double,2> ceps_matrix_0(ceps_matrix(rall,ro0));
    blitz::Array<double,2> ceps_matrix_1(ceps_matrix(rall,ro1));
    addDerivative(ceps_matrix_0, ceps_matrix_1);

    if (m_with_delta_delta)
    {
      blitz::Array<double,2> ceps_matrix_2(ceps_matrix(rall,ro2));
      addDerivative(ceps_matrix_1, ceps_matrix_2);
    }
  }
}
double * extractFeatures(short *samples)
{
	int N = firstPowerOfTwo(S);
	double *P;
	complex *x;
	complex *X;
	double *fftBins;
	double *filterBankEnergies;
	double *DCT;

	x = (complex *)malloc(sizeof(complex_t) * N);

	if (x == NULL)
	{
		Log("Error: memory allocation failed\n");
		
		return NULL;
	}

	for (int i = 0; i < S; i++)
	{
		x[i].re = (double)samples[i] * hammingWindow(i, N);
		x[i].im = 0;
	}

	for (int i = S; i < N; i++)
	{
		x[i].re = 0;
		x[i].im = 0;
	}
	
	X = fft(x, N);

	P = (double *)malloc(sizeof(double) * (N / 2 + 1));

	if (P == NULL)
	{
		Log("Error: memory allocation failed\n");

		return NULL;
	}

	for (int i = 0; i <= N / 2; i++)
	{
		P[i] = (1.0 / (double)N) * pow(magnitude(X[i]), 2);
	}

	double melLowerBound = 1125.0 * log(1.0 + ((double)MEL_LOWER_BOUND_HZ / 700.0));
	double melUpperBound = 1125.0 * log(1.0 + ((double)MEL_UPPER_BOUND_HZ / 700.0));

	fftBins = (double *)malloc(sizeof(double) * (FILTERBANKS + 2));
	
	if (fftBins == NULL)
	{
		Log("Error: memory allocation failed\n");

		return NULL;
	}
	
	double diff = (melUpperBound - melLowerBound) / ((double)FILTERBANKS + 1);
	double filter;

	for (int i = 0; i < FILTERBANKS + 2; i++)
	{
		filter = 700.0 * (exp((melLowerBound + (double)i * diff) / 1125.0) - 1.0);
		fftBins[i] = floor(filter * (N + 1) / SAMPLING_FREQ);
	}

	filterBankEnergies = (double *)malloc(sizeof(double) * FILTERBANKS);

	if (filterBankEnergies == NULL)
	{
		Log("Error: memory allocation failed\n");

		return NULL;
	}

	for (int m = 1; m <= FILTERBANKS; m++)
	{
		double result = 0;
		for (int k = 0; k <= N / 2; k++)
		{
			if (k >= fftBins[m - 1] && k <= fftBins[m])
			{
				result += P[k] * ((k - fftBins[m - 1]) / (fftBins[m] - fftBins[m - 1]));
			}
			else if (k >= fftBins[m] && k <= fftBins[m + 1])
			{
				result += P[k] * ((fftBins[m + 1] - k) / (fftBins[m + 1] - fftBins[m]));
			}
		}
		filterBankEnergies[m - 1] = log(result);
	}

	DCT = (double *)malloc(sizeof(double) * FILTERBANKS);

	if (DCT == NULL)
	{
		Log("Error: memory allocation failed\n");

		return NULL;
	}

	DCT[0] = 0.0;
	double N1 = (1 / sqrt((double)FILTERBANKS));
	for (int m = 0; m < FILTERBANKS; m++)
	{
		DCT[0] += N1 * filterBankEnergies[m];
	}

	N1 = sqrt(2.0 / (double)FILTERBANKS);

	for (int k = 1; k < FILTERBANKS; k++)
	{
		DCT[k] = 0.0;
		for (int m = 0; m < FILTERBANKS; m++)
		{
			DCT[k] += N1 * filterBankEnergies[m] * cos((M_PI * (double)k * (2.0 * (double)m + 1)) / (2.0 * (double)FILTERBANKS));
		}
	}

	/*for (int k = 0; k < FILTERBANKS; k++)
	{
		Log("%lf\n", DCT[k]);
	}*/

	free(P);
	free(x);
	free(X);
	free(fftBins);
	free(filterBankEnergies);
	return DCT;
}