void ofxFFT::calc() { //Generate a split complex vector from the real data vDSP_ctoz((COMPLEX *)input, 2, &mDspSplitComplex, 1, mFFTLength); //Take the fft and scale appropriately vDSP_fft_zrip(mSpectrumAnalysis, &mDspSplitComplex, 1, log2n, FFT_FORWARD); // vDSP_fft_zrip(mSpectrumAnalysis, &mDspSplitComplex, 1, log2n, FFT_INVERSE); vDSP_vsmul(mDspSplitComplex.realp, 1, &mFFTNormFactor, mDspSplitComplex.realp, 1, mFFTLength); vDSP_vsmul(mDspSplitComplex.imagp, 1, &mFFTNormFactor, mDspSplitComplex.imagp, 1, mFFTLength); // /* The output signal is now in a split real form. Use the function // * vDSP_ztoc to get a split real vector. */ // vDSP_ztoc(&mDspSplitComplex, 1, (COMPLEX *) output, 2, mFFTLength); // //Zero out the nyquist value mDspSplitComplex.imagp[0] = 0.0; //Convert the fft data to dB vDSP_zvmags(&mDspSplitComplex, 1, amplitude, 1, mFFTLength); //In order to avoid taking log10 of zero, an adjusting factor is added in to make the minimum value equal -128dB float mAdjust0DB = ADJUST_0_DB; vDSP_vsadd(amplitude, 1, &mAdjust0DB, power, 1, mFFTLength); float one = 1; vDSP_vdbcon(power, 1, &one, power, 1, mFFTLength, 0); }
void FFTHelper::ComputeFFT(Float32* inAudioData, Float32* outFFTData) { if (inAudioData == NULL || outFFTData == NULL) return; //Generate a split complex vector from the real data vDSP_ctoz((COMPLEX *)inAudioData, 2, &mDspSplitComplex, 1, mFFTLength); //Take the fft and scale appropriately vDSP_fft_zrip(mSpectrumAnalysis, &mDspSplitComplex, 1, mLog2N, kFFTDirection_Forward); vDSP_vsmul(mDspSplitComplex.realp, 1, &mFFTNormFactor, mDspSplitComplex.realp, 1, mFFTLength); vDSP_vsmul(mDspSplitComplex.imagp, 1, &mFFTNormFactor, mDspSplitComplex.imagp, 1, mFFTLength); //Zero out the nyquist value mDspSplitComplex.imagp[0] = 0.0; //Convert the fft data to dB vDSP_zvmags(&mDspSplitComplex, 1, outFFTData, 1, mFFTLength); //In order to avoid taking log10 of zero, an adjusting factor is added in to make the minimum value equal -128dB vDSP_vsadd(outFFTData, 1, &kAdjust0DB, outFFTData, 1, mFFTLength); Float32 one = 1; vDSP_vdbcon(outFFTData, 1, &one, outFFTData, 1, mFFTLength, 0); Float32 max = -100; int index = -1; for(unsigned long i = 0; i < mFFTLength; i++){ if(outFFTData[i] > max){ max = outFFTData[i]; index = i; } } if(max > -40){ // Filter out anything else, as it is unlikely to be the microwave beep recentMaxIndex = index; //if(index == 181){ // We found the microwave beep //printf("%d %f\n", index, max); }else{ recentMaxIndex = 0; } }
void FFTHelper::ComputeFFT(Float32* inAudioData, Float32* outFFTData) { if (inAudioData == NULL || outFFTData == NULL) return; //Generate a split complex vector from the real data vDSP_ctoz((COMPLEX *)inAudioData, 2, &mDspSplitComplex, 1, mFFTLength); //Take the fft and scale appropriately vDSP_fft_zrip(mSpectrumAnalysis, &mDspSplitComplex, 1, mLog2N, kFFTDirection_Forward); vDSP_vsmul(mDspSplitComplex.realp, 1, &mFFTNormFactor, mDspSplitComplex.realp, 1, mFFTLength); vDSP_vsmul(mDspSplitComplex.imagp, 1, &mFFTNormFactor, mDspSplitComplex.imagp, 1, mFFTLength); //Zero out the nyquist value mDspSplitComplex.imagp[0] = 0.0; //Convert the fft data to dB vDSP_zvmags(&mDspSplitComplex, 1, outFFTData, 1, mFFTLength); //In order to avoid taking log10 of zero, an adjusting factor is added in to make the minimum value equal -128dB vDSP_vsadd(outFFTData, 1, &kAdjust0DB, outFFTData, 1, mFFTLength); Float32 one = 1; vDSP_vdbcon(outFFTData, 1, &one, outFFTData, 1, mFFTLength, 0); }
Boolean FFTBufferManager::ComputeFFT(int32_t *outFFTData) { if (HasNewAudioData()) { // for(int i=0;i<mFFTLength;i++) // { // if(mAudioBuffer[i]>0.15) // printf("%f\n",mAudioBuffer[i]); // } //Generate a split complex vector from the real data # define NOISE_FILTER 0.01; for(int i=0;i<4096;i++) { //DENOISE if(mAudioBuffer[i]>0) { mAudioBuffer[i] -= NOISE_FILTER; if(mAudioBuffer[i] < 0) { mAudioBuffer[i] = 0; } } else if(mAudioBuffer[i]<0) { mAudioBuffer[i] += NOISE_FILTER; if(mAudioBuffer[i]>0) { mAudioBuffer[i] = 0; } } else { mAudioBuffer[i] = 0; } } vDSP_ctoz((COMPLEX *)mAudioBuffer, 2, &mDspSplitComplex, 1, mFFTLength); //Take the fft and scale appropriately vDSP_fft_zrip(mSpectrumAnalysis, &mDspSplitComplex, 1, mLog2N, kFFTDirection_Forward); vDSP_vsmul(mDspSplitComplex.realp, 1, &mFFTNormFactor, mDspSplitComplex.realp, 1, mFFTLength); vDSP_vsmul(mDspSplitComplex.imagp, 1, &mFFTNormFactor, mDspSplitComplex.imagp, 1, mFFTLength); //Zero out the nyquist value mDspSplitComplex.imagp[0] = 0.0; //Convert the fft data to dB Float32 tmpData[mFFTLength]; vDSP_zvmags(&mDspSplitComplex, 1, tmpData, 1, mFFTLength); //In order to avoid taking log10 of zero, an adjusting factor is added in to make the minimum value equal -128dB vDSP_vsadd(tmpData, 1, &mAdjust0DB, tmpData, 1, mFFTLength); Float32 one = 1; vDSP_vdbcon(tmpData, 1, &one, tmpData, 1, mFFTLength, 0); //Convert floating point data to integer (Q7.24) vDSP_vsmul(tmpData, 1, &m24BitFracScale, tmpData, 1, mFFTLength); for(UInt32 i=0; i<mFFTLength; ++i) outFFTData[i] = (SInt32) tmpData[i]; for(int i=0;i<mFFTLength/4;i++) { printf("%i:::%i\n",i,outFFTData[i]/16777216+120); } OSAtomicDecrement32Barrier(&mHasAudioData); OSAtomicIncrement32Barrier(&mNeedsAudioData); mAudioBufferCurrentIndex = 0; return true; } else if (mNeedsAudioData == 0) OSAtomicIncrement32Barrier(&mNeedsAudioData); return false; }
bool ofxAudioUnitFftNode::getAmplitude(std::vector<float> &outAmplitude) { getSamplesFromChannel(_sampleBuffer, 0); // return empty if we don't have enough samples yet if(_sampleBuffer.size() < _N) { outAmplitude.clear(); return false; } // normalize input waveform if(_outputSettings.normalizeInput) { float timeDomainMax; vDSP_maxv(&_sampleBuffer[0], 1, &timeDomainMax, _N); vDSP_vsdiv(&_sampleBuffer[0], 1, &timeDomainMax, &_sampleBuffer[0], 1, _N); } PerformFFT(&_sampleBuffer[0], _window, _fftData, _fftSetup, _N); // get amplitude vDSP_zvmags(&_fftData, 1, _fftData.realp, 1, _N/2); // normalize magnitudes float two = 2.0; vDSP_vsdiv(_fftData.realp, 1, &two, _fftData.realp, 1, _N/2); // scale output according to requested settings if(_outputSettings.scale == OFXAU_SCALE_LOG10) { for(int i = 0; i < (_N / 2); i++) { _fftData.realp[i] = log10f(_fftData.realp[i] + 1); } } else if(_outputSettings.scale == OFXAU_SCALE_DECIBEL) { float ref = 1.0; vDSP_vdbcon(_fftData.realp, 1, &ref, _fftData.realp, 1, _N / 2, 1); float dbCorrectionFactor = 0; switch (_outputSettings.window) { case OFXAU_WINDOW_HAMMING: dbCorrectionFactor = DB_CORRECTION_HAMMING; break; case OFXAU_WINDOW_HANNING: dbCorrectionFactor = DB_CORRECTION_HAMMING; break; case OFXAU_WINDOW_BLACKMAN: dbCorrectionFactor = DB_CORRECTION_HAMMING; break; } vDSP_vsadd(_fftData.realp, 1, &dbCorrectionFactor, _fftData.realp, 1, _N / 2); } // restrict minimum to 0 if(_outputSettings.clampMinToZero) { float min = 0.0; float max = INFINITY; vDSP_vclip(_fftData.realp, 1, &min, &max, _fftData.realp, 1, _N / 2); } // normalize output between 0 and 1 if(_outputSettings.normalizeOutput) { float max; vDSP_maxv(_fftData.realp, 1, &max, _N / 2); if(max > 0) { vDSP_vsdiv(_fftData.realp, 1, &max, _fftData.realp, 1, _N / 2); } } outAmplitude.assign(_fftData.realp, _fftData.realp + _N/2); return true; }