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 fft::convToDB_vdsp(float *in, float *out) { float ref = 1.0; vDSP_vdbcon(in, 1, &ref, out, 1, half, 1); //get rid of any -infs float vmin=0.0; float vmax=9999999.0; vDSP_vclip(out, 1, &vmin, &vmax, out, 1, half); }
Pitch PitchDetector::process(float *input, unsigned int numberOfSamples) { assert(this->numberOfSamples==numberOfSamples); int n = numberOfSamples; float *originalReal = this->FFTBuffer; // 1.1.时域上加窗 vDSP_vmul(input, 1, this->windowFunc, 1, originalReal, 1, n); // 分前后加窗没什么不一样啊 // vDSP_vmul(input, 1, this->windowFunc, 1, originalReal+(n/2), 1, n/2); // vDSP_vmul(input+(n/2), 1, this->windowFunc+(n/2), 1, originalReal, 1, n/2); // 2.拆成复数形似{1+2i, 3+4i, ..., 1023+1024i} 原始数组可以认为是(COMPLEX*)交错存储 现在拆成COMPLEX_SPLIT非交错(分轨式)存储 vDSP_ctoz((COMPLEX*)originalReal, 2, &this->A, 1, n/2); // 读取originalReal以2的步长塞进A里面 // // 3.fft变换的预设 float originalRealInLog2 = log2f(n); // FFTSetup setupReal = vDSP_create_fftsetup(originalRealInLog2, FFT_RADIX2); // 4.傅里叶变换 vDSP_fft_zrip(this->setupReal, &this->A, 1, originalRealInLog2, FFT_FORWARD); // 5.转换成能量值 vDSP_zvabs(&this->A, 1, this->magnitudes, 1, n/2); Float32 one = 1; vDSP_vdbcon(this->magnitudes, 1, &one, this->magnitudes, 1, n/2, 0); // 6.获取基频f0 float maxValue; vDSP_Length index; vDSP_maxvi(this->magnitudes, 1, &maxValue, &index, n/2); // 6.1.微调参数 double alpha = this->magnitudes[index - 1]; double beta = this->magnitudes[index]; double gamma = this->magnitudes[index + 1]; double p = 0.5 * (alpha - gamma) / (alpha - 2 * beta + gamma); // 7.转换为频率 indexHZ = index * (SampleRate / (n/2)) float indexHZ = (index+p) * ((this->sampleRate*1.0) / n); // 8.乐理信息生成 Pitch pitch; pitch.frequency = indexHZ; pitch.amplitude = beta; pitch.key = 12 * log2(indexHZ / 127.09) + 28.5; pitch.octave = (pitch.key - 3.0) / 12 + 1; calStep(&pitch); pitch.stepString = calStep(indexHZ); return pitch; }
/******************************************************************************* VectorDbConvert */ Error_t VectorDbConvert(float* dest, const float* in, unsigned amplitude_flag, unsigned length) { #ifdef __APPLE__ float one = 1.0; vDSP_vdbcon(in, 1, &one, dest, 1, length, amplitude_flag); #else float scale = 10.0 + 10 * amplitude_flag; for (unsigned i = 0; i < length; ++i) { dest[i] = scale * log10f(in[i]); } #endif return NOERR; }
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; }