Beispiel #1
0
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);
    
}
Beispiel #2
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);
}
Beispiel #3
0
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;
}
Beispiel #4
0
/*******************************************************************************
 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;
}