예제 #1
0
/*********************
*
*	FUNCTION: cross_power
*
*	DESCRIPTION:
*		Calculate the cross power between the 2 input arrays.
*		If the size of both input arrays is not a power of two they are padded to the next power of 2.
*		If input arrays have different size, the minimum is kept as being the size of both arrays.
*
***********************/
void cross_power(INT16 *x, INT32 x_Nelements, INT16 *y, INT32 y_Nelements, FLOAT **mag, INT32 *mag_Nelements)
{
	FLOAT *tempx = NULL;
	FLOAT *tempy = NULL;
	FLOAT tmp1,tmp2;
	INT32 count,count1;

	tempx = zeropad(x,&x_Nelements);
	tempy = zeropad(y,&y_Nelements);

	if (x_Nelements>y_Nelements) x_Nelements = y_Nelements;
	RealFFT(tempy,y_Nelements);
	RealFFT(tempx,x_Nelements);

	if ((*mag)==NULL) (*mag) = (FLOAT*) malloc( (x_Nelements/2) * sizeof(FLOAT));

	for (count=0, count1=0; count<x_Nelements-1; count+=2,count1++)
	{
		tmp1 = tempx[count]*tempy[count]+tempx[count+1]*tempy[count+1];
		tmp2 = tempx[count]*tempy[count+1]-tempx[count+1]*tempy[count];
		(*mag)[count1] = (FLOAT) sqrt(tmp1*tmp1 + tmp2*tmp2);

		(*mag)[count1]/= (x_Nelements*x_Nelements);
	}

	*mag_Nelements = count1;

	free(tempx);
	free(tempy);

}
예제 #2
0
/*********************
*
*	FUNCTION: cross_power_ratio
*
*	DESCRIPTION:
*		Compute the cross power correlation	and a ratio at the end. 
*
***********************/
FLOAT cross_power_ratio(INT16 *x, INT32 x_Nelements, INT16 *y, INT32 y_Nelements)
{
	FLOAT *tempx;
	FLOAT *tempy;
	FLOAT a=0,b=0,tmp1,tmp2;
	INT32 count;

	tempx = zeropad(x,&x_Nelements);
	tempy = zeropad(y,&y_Nelements);

	if (x_Nelements>y_Nelements) x_Nelements = y_Nelements;

	RealFFT(tempx,x_Nelements);
	RealFFT(tempy,y_Nelements);

	for (count=0; count<(x_Nelements*0.15); count+=2)
	{
		tmp1 = tempx[count]*tempy[count]+tempx[count+1]*tempy[count+1]; 
		tmp2 = tempx[count]*tempy[count+1]-tempx[count+1]*tempy[count]; 
		a+= (FLOAT) sqrt(tmp1*tmp1 + tmp2*tmp2);
	}

	for (count=(INT32)(x_Nelements*0.15); count<x_Nelements; count+=2)
	{
		tmp1 = tempx[count]*tempy[count]+tempx[count+1]*tempy[count+1]; 
		tmp2 = tempx[count]*tempy[count+1]-tempx[count+1]*tempy[count]; 
		b+= (FLOAT) sqrt(tmp1*tmp1 + tmp2*tmp2);
	}

	free(tempx);
	free(tempy);

	if (b!=0) return a/b;
	else return 0;
}
/* Calculate the power spectrum */
void fft::powerSpectrum(int start, int half, float *data, int windowSize,float *magnitude,float *phase, float *power, float *avg_power) {
	int i;
	int windowFunc = 3;
	float total_power = 0.0f;
	
	/* processing variables*/
	float *in_real = new float[windowSize];
	float *in_img = new float[windowSize];
	float *out_real = new float[windowSize];
	float *out_img = new float[windowSize];
	
	for (i = 0; i < windowSize; i++) {
		in_real[i] = data[start + i];
	}
	
	WindowFunc(windowFunc, windowSize, in_real);
	RealFFT(windowSize, in_real, out_real, out_img);
	
	for (i = 0; i < half; i++) {
		/* compute power */
		power[i] = out_real[i]*out_real[i] + out_img[i]*out_img[i];
		total_power += power[i];
		/* compute magnitude and phase */
		magnitude[i] = 2.0*sqrt(power[i]);
		phase[i] = atan2(out_img[i],out_real[i]);
	}
	/* calculate average power */
	*(avg_power) = total_power / (float) half;
	
	delete[]in_real;
	delete[]in_img;   
	delete[]out_real;
	delete[]out_img;
}
예제 #4
0
void ofxFftBasic::fft(float *input, float *output)
{ 
    int Half = bins/2;
    if(!ready) {
		ofLog(OF_LOG_ERROR, "setup() must be called before fft()\n");
		return;
	}

    /* processing variables*/
    float *in_real  = new float[bins];
    float *in_img   = new float[bins];
    float *out_real = new float[bins];
    float *out_img  = new float[bins];

	for (int i = 0; i < bins; i++) {
      in_real[i] = input[i];
	}

   	runWindow(in_real);
	RealFFT(bins, in_real, out_real, out_img);

   	float normalizer = 2. / windowSum;

	for(int i = 1; i < Half; i++) {
        output[i] = cartesianToAmplitude(out_real[i], out_img[i]) * normalizer;
	}

   delete [] in_real;
   delete [] in_img;
   delete [] out_real;
   delete [] out_img;
}
예제 #5
0
void
RevTransform(FFT_DATA_TYPE *ddata,size_t NumLen)
{
StartTimer(FFTTime);
RealFFT(ddata,CalcFFTLen(NumLen),-1);
StopTimer(FFTTime);
}
예제 #6
0
파일: fft.cpp 프로젝트: arturoc/Maximilian
/* Calculate the power spectrum */
void fft::powerSpectrum(int start, float *data, float *window, float *magnitude,float *phase) {
	int i;
	
	//windowing
	for (i = 0; i < n; i++) {
		in_real[i] = data[start + i] * window[i];
	}
	
	
	RealFFT(n, in_real, out_real, out_img);
	
	for (i = 0; i < half; i++) {
		/* compute power */
		float power = out_real[i]*out_real[i] + out_img[i]*out_img[i];
		/* compute magnitude and phase */
		magnitude[i] = sqrt(power);
		phase[i] = atan2(out_img[i],out_real[i]);
		
//		if (magnitude[i] < 0.000001){ // less than 0.1 nV
//			magnitude[i] = 0; // out of range
//		} else {
//			magnitude[i] = 20.0*log10(magnitude[i] + 1);  // get to to db scale
//		}
	}
	
}
예제 #7
0
void
FwdTransform(FFT_DATA_TYPE *ddata,BigInt Num,size_t NumLen)
{
PutNumIntoFFTNum(ddata, Num, NumLen);
StartTimer(FFTTime);
RealFFT(ddata,CalcFFTLen(NumLen),1);
StopTimer(FFTTime);
}
예제 #8
0
/* Calculate the power spectrum */
void fft::powerSpectrum (float *data, int windowSize, float *magnitude) {
	
   int windowFunc = 3;
   float total_power = 0.0f;
   
	/* processing variables*/
	float *out_real = new float[windowSize];
	float *out_img = new float[windowSize];
   
    WindowFunc(windowFunc, windowSize, data);
	RealFFT(windowSize, data, out_real, out_img);

	for (int i=0; i<windowSize/2; i++) {
		/* compute magnitude and phase */
		magnitude[i] = 1000.0*sqrt(out_real[i]*out_real[i] + out_img[i]*out_img[i])/windowSize;
		//phase[i] = atan2(out_img[i],out_real[i]);
	}
	
	delete[]out_real;
    delete[]out_img;
}
예제 #9
0
/* Calculate the power spectrum */
void ofxFftBasic::powerSpectrum(int start, int half, float *data, int bins,float *magnitude,float *phase, float *power, float *avg_power) {
    if(!ready) {
		ofLog(OF_LOG_ERROR, "setup() must be called first!\n");
		return;
	}

    int i;
    float total_power = 0.0f;

    /* processing variables*/
    float *in_real = new float[bins];
    float *in_img = new float[bins];
    float *out_real = new float[bins];
    float *out_img = new float[bins];

    for (i = 0; i < bins; i++) {
      in_real[i] = data[start + i];
    }

   	runWindow(in_real);
	RealFFT(bins, in_real, out_real, out_img);

    for (i = 0; i < half; i++) {
        /* compute power */
        power[i] = out_real[i]*out_real[i] + out_img[i]*out_img[i];
        total_power += power[i];
        /* compute magnitude and phase */
        magnitude[i] = 2.0*sqrt(power[i]);
        phase[i] = atan2(out_img[i],out_real[i]);
    }

   /* calculate average power */
   *(avg_power) = total_power / (float) half;

   delete[]in_real;
   delete[]in_img;
   delete[]out_real;
   delete[]out_img;
}
예제 #10
0
void FreqWindow::Recalc()
{
   wxLogMessage(wxT("Starting FreqWindow::Recalc()"));
   if (mProcessed)
      delete[] mProcessed;
   mProcessed = NULL;

   if (!mData) {
      mFreqPlot->Refresh(true);
      return;
   }

   int alg = mAlgChoice->GetSelection();
   int windowFunc = mFuncChoice->GetSelection();
   long windowSize = 0;
   (mSizeChoice->GetStringSelection()).ToLong(&windowSize);

   int f = NumWindowFuncs();

   if (!(windowSize >= 32 && windowSize <= 65536 &&
         alg >= 0 && alg <= 4 && windowFunc >= 0 && windowFunc < f)) {
      mFreqPlot->Refresh(true);
      return;
   }

   mWindowSize = windowSize;

   if (mDataLen < mWindowSize) {
      mFreqPlot->Refresh(true);
      return;
   }

   mProcessed = new float[mWindowSize];

   int i;
   for (i = 0; i < mWindowSize; i++)
      mProcessed[i] = float(0.0);
   int half = mWindowSize / 2;

   float *in = new float[mWindowSize];
   float *in2 = new float[mWindowSize];
   float *out = new float[mWindowSize];
   float *out2 = new float[mWindowSize];
   float *win = new float[mWindowSize];

   // initialize the window
   for(int i=0; i<mWindowSize; i++)
      win[i] = 1.0;
   WindowFunc(windowFunc, mWindowSize, win);
   // Scale window such that an amplitude of 1.0 in the time domain
   // shows an amplitude of 0dB in the frequency domain
   double wss = 0;
   for(int i=0; i<mWindowSize; i++)
      wss += win[i];
   if(wss > 0)
      wss = 4.0 / (wss*wss);
   else
      wss = 1.0;

   //Progress dialog over FFT operation
   wxLogMessage(wxT("Starting progress dialogue in FreqWindow::Recalc()"));
   ProgressDialog *mProgress = new ProgressDialog(_("FreqWindow"),_("Drawing Spectrum"));

   int start = 0;
   int windows = 0;
   while (start + mWindowSize <= mDataLen) {
      for (i = 0; i < mWindowSize; i++)
         in[i] = win[i] * mData[start + i];

      switch (alg) {
      case 0:                  // Spectrum
         PowerSpectrum(mWindowSize, in, out);

         for (i = 0; i < half; i++)
            mProcessed[i] += out[i];
         break;

      case 1:
      case 2:
      case 3:   // Autocorrelation, Cuberoot AC or Enhanced AC

         // Take FFT
#ifdef EXPERIMENTAL_USE_REALFFTF
         RealFFT(mWindowSize, in, out, out2);
#else
         FFT(mWindowSize, false, in, NULL, out, out2);
#endif
         // Compute power
         for (i = 0; i < mWindowSize; i++)
            in[i] = (out[i] * out[i]) + (out2[i] * out2[i]);

         if (alg == 1) {
            for (i = 0; i < mWindowSize; i++)
               in[i] = sqrt(in[i]);
         }
         if (alg == 2 || alg == 3) {
            // Tolonen and Karjalainen recommend taking the cube root
            // of the power, instead of the square root

            for (i = 0; i < mWindowSize; i++)
               in[i] = pow(in[i], 1.0f / 3.0f);
         }
         // Take FFT
#ifdef EXPERIMENTAL_USE_REALFFTF
         RealFFT(mWindowSize, in, out, out2);
#else
         FFT(mWindowSize, false, in, NULL, out, out2);
#endif

         // Take real part of result
         for (i = 0; i < half; i++)
            mProcessed[i] += out[i];
         break;

      case 4:                  // Cepstrum
#ifdef EXPERIMENTAL_USE_REALFFTF
         RealFFT(mWindowSize, in, out, out2);
#else
         FFT(mWindowSize, false, in, NULL, out, out2);
#endif

         // Compute log power
         // Set a sane lower limit assuming maximum time amplitude of 1.0
         float power;
         float minpower = 1e-20*mWindowSize*mWindowSize;
         for (i = 0; i < mWindowSize; i++)
         {
            power = (out[i] * out[i]) + (out2[i] * out2[i]);
            if(power < minpower)
               in[i] = log(minpower);
            else
               in[i] = log(power);
         }
         // Take IFFT
#ifdef EXPERIMENTAL_USE_REALFFTF
         InverseRealFFT(mWindowSize, in, NULL, out);
#else
         FFT(mWindowSize, true, in, NULL, out, out2);
#endif

         // Take real part of result
         for (i = 0; i < half; i++)
            mProcessed[i] += out[i];

         break;
      }                         //switch

      start += half;
      windows++;
      // only update the progress dialogue infrequently to reduce it's overhead
      // If we do it every time, it spends as much time updating X11 as doing
      // the calculations. 10 seems a reasonable compromise on Linux that
      // doesn't make it unresponsive, but avoids the slowdown.
      if ((windows % 10) == 0)
         mProgress->Update(1 - static_cast<float>(mDataLen - start) / mDataLen);
   }

   wxLogMessage(wxT("Finished updating progress dialogue in FreqWindow::Recalc()"));
   switch (alg) {
   double scale;
   case 0:                     // Spectrum
      // Convert to decibels
      mYMin = 1000000.;
      mYMax = -1000000.;
      scale = wss / (double)windows;
      for (i = 0; i < half; i++)
      {
         mProcessed[i] = 10 * log10(mProcessed[i] * scale);
         if(mProcessed[i] > mYMax)
            mYMax = mProcessed[i];
         else if(mProcessed[i] < mYMin)
            mYMin = mProcessed[i];
      }
      if(mYMin < -dBRange)
         mYMin = -dBRange;
      if(mYMax <= -dBRange)
         mYMax = -dBRange + 10.; // it's all out of range, but show a scale.
      else
         mYMax += .5;

      mProcessedSize = half;
      mYStep = 10;
      break;

   case 1:                     // Standard Autocorrelation
   case 2:                     // Cuberoot Autocorrelation
      for (i = 0; i < half; i++)
         mProcessed[i] = mProcessed[i] / windows;

      // Find min/max
      mYMin = mProcessed[0];
      mYMax = mProcessed[0];
      for (i = 1; i < half; i++)
         if (mProcessed[i] > mYMax)
            mYMax = mProcessed[i];
         else if (mProcessed[i] < mYMin)
            mYMin = mProcessed[i];

      mYStep = 1;

      mProcessedSize = half;
      break;

   case 3:                     // Enhanced Autocorrelation
      for (i = 0; i < half; i++)
         mProcessed[i] = mProcessed[i] / windows;

      // Peak Pruning as described by Tolonen and Karjalainen, 2000

      // Clip at zero, copy to temp array
      for (i = 0; i < half; i++) {
         if (mProcessed[i] < 0.0)
            mProcessed[i] = float(0.0);
         out[i] = mProcessed[i];
      }

      // Subtract a time-doubled signal (linearly interp.) from the original
      // (clipped) signal
      for (i = 0; i < half; i++)
         if ((i % 2) == 0)
            mProcessed[i] -= out[i / 2];
         else
            mProcessed[i] -= ((out[i / 2] + out[i / 2 + 1]) / 2);

      // Clip at zero again
      for (i = 0; i < half; i++)
         if (mProcessed[i] < 0.0)
            mProcessed[i] = float(0.0);

      // Find new min/max
      mYMin = mProcessed[0];
      mYMax = mProcessed[0];
      for (i = 1; i < half; i++)
         if (mProcessed[i] > mYMax)
            mYMax = mProcessed[i];
         else if (mProcessed[i] < mYMin)
            mYMin = mProcessed[i];

      mYStep = 1;

      mProcessedSize = half;
      break;

   case 4:                     // Cepstrum
      for (i = 0; i < half; i++)
         mProcessed[i] = mProcessed[i] / windows;

      // Find min/max, ignoring first and last few values
      int ignore = 4;
      mYMin = mProcessed[ignore];
      mYMax = mProcessed[ignore];
      for (i = ignore + 1; i < half - ignore; i++)
         if (mProcessed[i] > mYMax)
            mYMax = mProcessed[i];
         else if (mProcessed[i] < mYMin)
            mYMin = mProcessed[i];

      mYStep = 1;

      mProcessedSize = half;
      break;
   }

   delete[]in;
   delete[]in2;
   delete[]out;
   delete[]out2;
   delete[]win;

   wxLogMessage(wxT("About to draw plot in FreqWindow::Recalc()"));
   DrawPlot();
   mFreqPlot->Refresh(true);
   delete mProgress;
}
예제 #11
0
bool SpectrumAnalyst::Calculate(Algorithm alg, int windowFunc,
                                size_t windowSize, double rate,
                                const float *data, size_t dataLen,
                                float *pYMin, float *pYMax,
                                FreqGauge *progress)
{
   // Wipe old data
   mProcessed.resize(0);
   mRate = 0.0;
   mWindowSize = 0;

   // Validate inputs
   int f = NumWindowFuncs();

   if (!(windowSize >= 32 && windowSize <= 65536 &&
         alg >= SpectrumAnalyst::Spectrum &&
         alg < SpectrumAnalyst::NumAlgorithms &&
         windowFunc >= 0 && windowFunc < f)) {
      return false;
   }

   if (dataLen < windowSize) {
      return false;
   }

   // Now repopulate
   mRate = rate;
   mWindowSize = windowSize;
   mAlg = alg;

   auto half = mWindowSize / 2;
   mProcessed.resize(mWindowSize);

   Floats in{ mWindowSize };
   Floats out{ mWindowSize };
   Floats out2{ mWindowSize };
   Floats win{ mWindowSize };

   for (size_t i = 0; i < mWindowSize; i++) {
      mProcessed[i] = 0.0f;
      win[i] = 1.0f;
   }

   WindowFunc(windowFunc, mWindowSize, win.get());

   // Scale window such that an amplitude of 1.0 in the time domain
   // shows an amplitude of 0dB in the frequency domain
   double wss = 0;
   for (size_t i = 0; i<mWindowSize; i++)
      wss += win[i];
   if(wss > 0)
      wss = 4.0 / (wss*wss);
   else
      wss = 1.0;

   if (progress) {
      progress->SetRange(dataLen);
   }

   size_t start = 0;
   int windows = 0;
   while (start + mWindowSize <= dataLen) {
      for (size_t i = 0; i < mWindowSize; i++)
         in[i] = win[i] * data[start + i];

      switch (alg) {
         case Spectrum:
            PowerSpectrum(mWindowSize, in.get(), out.get());

            for (size_t i = 0; i < half; i++)
               mProcessed[i] += out[i];
            break;

         case Autocorrelation:
         case CubeRootAutocorrelation:
         case EnhancedAutocorrelation:

            // Take FFT
            RealFFT(mWindowSize, in.get(), out.get(), out2.get());
            // Compute power
            for (size_t i = 0; i < mWindowSize; i++)
               in[i] = (out[i] * out[i]) + (out2[i] * out2[i]);

            if (alg == Autocorrelation) {
               for (size_t i = 0; i < mWindowSize; i++)
                  in[i] = sqrt(in[i]);
            }
            if (alg == CubeRootAutocorrelation ||
                alg == EnhancedAutocorrelation) {
               // Tolonen and Karjalainen recommend taking the cube root
               // of the power, instead of the square root

               for (size_t i = 0; i < mWindowSize; i++)
                  in[i] = pow(in[i], 1.0f / 3.0f);
            }
            // Take FFT
            RealFFT(mWindowSize, in.get(), out.get(), out2.get());

            // Take real part of result
            for (size_t i = 0; i < half; i++)
               mProcessed[i] += out[i];
            break;

         case Cepstrum:
            RealFFT(mWindowSize, in.get(), out.get(), out2.get());

            // Compute log power
            // Set a sane lower limit assuming maximum time amplitude of 1.0
            {
               float power;
               float minpower = 1e-20*mWindowSize*mWindowSize;
               for (size_t i = 0; i < mWindowSize; i++)
               {
                  power = (out[i] * out[i]) + (out2[i] * out2[i]);
                  if(power < minpower)
                     in[i] = log(minpower);
                  else
                     in[i] = log(power);
               }
               // Take IFFT
               InverseRealFFT(mWindowSize, in.get(), NULL, out.get());

               // Take real part of result
               for (size_t i = 0; i < half; i++)
                  mProcessed[i] += out[i];
            }

            break;

         default:
            wxASSERT(false);
            break;
      }                         //switch

      // Update the progress bar
      if (progress) {
         progress->SetValue(start);
      }

      start += half;
      windows++;
   }

   if (progress) {
      // Reset for next time
      progress->Reset();
   }

   float mYMin = 1000000, mYMax = -1000000;
   double scale;
   switch (alg) {
   case Spectrum:
      // Convert to decibels
      mYMin = 1000000.;
      mYMax = -1000000.;
      scale = wss / (double)windows;
      for (size_t i = 0; i < half; i++)
      {
         mProcessed[i] = 10 * log10(mProcessed[i] * scale);
         if(mProcessed[i] > mYMax)
            mYMax = mProcessed[i];
         else if(mProcessed[i] < mYMin)
            mYMin = mProcessed[i];
      }
      break;

   case Autocorrelation:
   case CubeRootAutocorrelation:
      for (size_t i = 0; i < half; i++)
         mProcessed[i] = mProcessed[i] / windows;

      // Find min/max
      mYMin = mProcessed[0];
      mYMax = mProcessed[0];
      for (size_t i = 1; i < half; i++)
         if (mProcessed[i] > mYMax)
            mYMax = mProcessed[i];
         else if (mProcessed[i] < mYMin)
            mYMin = mProcessed[i];
      break;

   case EnhancedAutocorrelation:
      for (size_t i = 0; i < half; i++)
         mProcessed[i] = mProcessed[i] / windows;

      // Peak Pruning as described by Tolonen and Karjalainen, 2000

      // Clip at zero, copy to temp array
      for (size_t i = 0; i < half; i++) {
         if (mProcessed[i] < 0.0)
            mProcessed[i] = float(0.0);
         out[i] = mProcessed[i];
      }

      // Subtract a time-doubled signal (linearly interp.) from the original
      // (clipped) signal
      for (size_t i = 0; i < half; i++)
         if ((i % 2) == 0)
            mProcessed[i] -= out[i / 2];
         else
            mProcessed[i] -= ((out[i / 2] + out[i / 2 + 1]) / 2);

      // Clip at zero again
      for (size_t i = 0; i < half; i++)
         if (mProcessed[i] < 0.0)
            mProcessed[i] = float(0.0);

      // Find NEW min/max
      mYMin = mProcessed[0];
      mYMax = mProcessed[0];
      for (size_t i = 1; i < half; i++)
         if (mProcessed[i] > mYMax)
            mYMax = mProcessed[i];
         else if (mProcessed[i] < mYMin)
            mYMin = mProcessed[i];
      break;

   case Cepstrum:
      for (size_t i = 0; i < half; i++)
         mProcessed[i] = mProcessed[i] / windows;

      // Find min/max, ignoring first and last few values
      {
         size_t ignore = 4;
         mYMin = mProcessed[ignore];
         mYMax = mProcessed[ignore];
         for (size_t i = ignore + 1; i + ignore < half; i++)
            if (mProcessed[i] > mYMax)
               mYMax = mProcessed[i];
            else if (mProcessed[i] < mYMin)
               mYMin = mProcessed[i];
      }
      break;

   default:
      wxASSERT(false);
      break;
   }

   if (pYMin)
      *pYMin = mYMin;
   if (pYMax)
      *pYMax = mYMax;

   return true;
}
예제 #12
0
void PaulStretch::process(float *smps, size_t nsmps)
{
   //add NEW samples to the pool
   if ((smps != NULL) && (nsmps != 0)) {
      if (nsmps > poolsize) {
         nsmps = poolsize;
      }
      int nleft = poolsize - nsmps;

      //move left the samples from the pool to make room for NEW samples
      for (int i = 0; i < nleft; i++)
         in_pool[i] = in_pool[i + nsmps];

      //add NEW samples to the pool
      for (size_t i = 0; i < nsmps; i++)
         in_pool[i + nleft] = smps[i];
   }

   //get the samples from the pool
   for (size_t i = 0; i < poolsize; i++)
      fft_smps[i] = in_pool[i];
   WindowFunc(eWinFuncHanning, poolsize, fft_smps.get());

   RealFFT(poolsize, fft_smps.get(), fft_c.get(), fft_s.get());

   for (size_t i = 0; i < poolsize / 2; i++)
      fft_freq[i] = sqrt(fft_c[i] * fft_c[i] + fft_s[i] * fft_s[i]);
   process_spectrum(fft_freq.get());


   //put randomize phases to frequencies and do a IFFT
   float inv_2p15_2pi = 1.0 / 16384.0 * (float)M_PI;
   for (size_t i = 1; i < poolsize / 2; i++) {
      unsigned int random = (rand()) & 0x7fff;
      float phase = random * inv_2p15_2pi;
      float s = fft_freq[i] * sin(phase);
      float c = fft_freq[i] * cos(phase);

      fft_c[i] = fft_c[poolsize - i] = c;

      fft_s[i] = s; fft_s[poolsize - i] = -s;
   }
   fft_c[0] = fft_s[0] = 0.0;
   fft_c[poolsize / 2] = fft_s[poolsize / 2] = 0.0;

   FFT(poolsize, true, fft_c.get(), fft_s.get(), fft_smps.get(), fft_tmp.get());

   float max = 0.0, max2 = 0.0;
   for (size_t i = 0; i < poolsize; i++) {
      max = std::max(max, fabsf(fft_tmp[i]));
      max2 = std::max(max2, fabsf(fft_smps[i]));
   }


   //make the output buffer
   float tmp = 1.0 / (float) out_bufsize * M_PI;
   float hinv_sqrt2 = 0.853553390593f;//(1.0+1.0/sqrt(2))*0.5;

   float ampfactor = 1.0;
   if (rap < 1.0)
      ampfactor = rap * 0.707;
   else
      ampfactor = (out_bufsize / (float)poolsize) * 4.0;

   for (size_t i = 0; i < out_bufsize; i++) {
      float a = (0.5 + 0.5 * cos(i * tmp));
      float out = fft_smps[i + out_bufsize] * (1.0 - a) + old_out_smp_buf[i] * a;
      out_buf[i] =
         out * (hinv_sqrt2 - (1.0 - hinv_sqrt2) * cos(i * 2.0 * tmp)) *
         ampfactor;
   }

   //copy the current output buffer to old buffer
   for (size_t i = 0; i < out_bufsize * 2; i++)
      old_out_smp_buf[i] = fft_smps[i];
}
예제 #13
0
bool ComputeSpectrum(const float * data, int width,
                     int windowSize,
                     double WXUNUSED(rate), float *output,
                     bool autocorrelation, int windowFunc)
{
   if (width < windowSize)
      return false;

   if (!data || !output)
      return true;

   float *processed = new float[windowSize];

   int i;
   for (i = 0; i < windowSize; i++)
      processed[i] = float(0.0);
   int half = windowSize / 2;

   float *in = new float[windowSize];
   float *out = new float[windowSize];
   float *out2 = new float[windowSize];

   int start = 0;
   int windows = 0;
   while (start + windowSize <= width) {
      for (i = 0; i < windowSize; i++)
         in[i] = data[start + i];

      WindowFunc(windowFunc, windowSize, in);

      if (autocorrelation) {
         // Take FFT
         RealFFT(windowSize, in, out, out2);
         // Compute power
         for (i = 0; i < windowSize; i++)
            in[i] = (out[i] * out[i]) + (out2[i] * out2[i]);

         // Tolonen and Karjalainen recommend taking the cube root
         // of the power, instead of the square root

         for (i = 0; i < windowSize; i++)
            in[i] = powf(in[i], 1.0f / 3.0f);

         // Take FFT
         RealFFT(windowSize, in, out, out2);
      }
      else
         PowerSpectrum(windowSize, in, out);

      // Take real part of result
      for (i = 0; i < half; i++)
        processed[i] += out[i];

      start += half;
      windows++;
   }

   if (autocorrelation) {

      // Peak Pruning as described by Tolonen and Karjalainen, 2000
      /*
       Combine most of the calculations in a single for loop.
       It should be safe, as indexes refer only to current and previous elements,
       that have already been clipped, etc...
      */
      for (i = 0; i < half; i++) {
        // Clip at zero, copy to temp array
        if (processed[i] < 0.0)
            processed[i] = float(0.0);
        out[i] = processed[i];
        // Subtract a time-doubled signal (linearly interp.) from the original
        // (clipped) signal
        if ((i % 2) == 0)
           processed[i] -= out[i / 2];
        else
           processed[i] -= ((out[i / 2] + out[i / 2 + 1]) / 2);

        // Clip at zero again
        if (processed[i] < 0.0)
            processed[i] = float(0.0);
      }

      // Reverse and scale
      for (i = 0; i < half; i++)
         in[i] = processed[i] / (windowSize / 4);
      for (i = 0; i < half; i++)
         processed[half - 1 - i] = in[i];
   } else {
      // Convert to decibels
      // But do it safely; -Inf is nobody's friend
      for (i = 0; i < half; i++){
         float temp=(processed[i] / windowSize / windows);
         if (temp > 0.0)
            processed[i] = 10*log10(temp);
         else
            processed[i] = 0;
      }
   }

   for(i=0;i<half;i++)
      output[i] = processed[i];
   delete[]in;
   delete[]out;
   delete[]out2;
   delete[]processed;

   return true;
}