/********************* * * 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); }
/********************* * * 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; }
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; }
void RevTransform(FFT_DATA_TYPE *ddata,size_t NumLen) { StartTimer(FFTTime); RealFFT(ddata,CalcFFTLen(NumLen),-1); StopTimer(FFTTime); }
/* 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 // } } }
void FwdTransform(FFT_DATA_TYPE *ddata,BigInt Num,size_t NumLen) { PutNumIntoFFTNum(ddata, Num, NumLen); StartTimer(FFTTime); RealFFT(ddata,CalcFFTLen(NumLen),1); StopTimer(FFTTime); }
/* 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; }
/* 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; }
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; }
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; }
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]; }
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; }