Exemple #1
0
void AccelerateFFT<float>::performFFT (float* buffer, float* real, float* imag)
{
    vDSP_ctoz ((COMPLEX*)buffer, 2, &complexSplit, 1, fftSizeOver2);
    vDSP_fft_zrip (fftSetupFloat, &complexSplit, 1, log2n, FFT_FORWARD);
    
    complexSplit.realp[fftSizeOver2] = complexSplit.imagp[0];
    complexSplit.imagp[fftSizeOver2] = 0.0;
    complexSplit.imagp[0] = 0.0;
    
    for (size_t i = 0; i <= fftSizeOver2; i++)
    {
        complexSplit.realp[i] *= 0.5;
        complexSplit.imagp[i] *= 0.5;
    }
    
    for (size_t i = fftSizeOver2 - 1; i > 0; --i)
    {
        complexSplit.realp[2 * fftSizeOver2 - i] = complexSplit.realp[i];
        complexSplit.imagp[2 * fftSizeOver2 - i] = -1 * complexSplit.imagp[i];
    }
    
    for (size_t i = 0; i < fftSize; i++)
    {
        real[i] = complexSplit.realp[i];
        imag[i] = complexSplit.imagp[i];
    }
}
Exemple #2
0
void FFTAccelerate::doFFTReal(float samples[], float amp[], int numSamples)
{
	int i;
	vDSP_Length log2n = log2f(numSamples);
    int nOver2 = numSamples/2;
    //-- window
    //vDSP_blkman_window(window, windowSize, 0);
    vDSP_vmul(samples, 1, window, 1, in_real, 1, numSamples);

    //Convert float array of reals samples to COMPLEX_SPLIT array A
	vDSP_ctoz((COMPLEX*)in_real,2,&A,1,nOver2);

    //Perform FFT using fftSetup and A
    //Results are returned in A
	vDSP_fft_zrip(fftSetup, &A, 1, log2n, FFT_FORWARD);
    
    // scale by 1/2*n because vDSP_fft_zrip doesn't use the right scaling factors natively ("for better performances")
    {
        const float scale = 1.0f/(2.0f*(float)numSamples);
        vDSP_vsmul( A.realp, 1, &scale, A.realp, 1, numSamples/2 );
        vDSP_vsmul( A.imagp, 1, &scale, A.imagp, 1, numSamples/2 );
    }
    
    //Convert COMPLEX_SPLIT A result to float array to be returned
    /*amp[0] = A.realp[0]/(numSamples*2);
	for(i=1;i<numSamples/2;i++)
		amp[i]=sqrt(A.realp[i]*A.realp[i]+A.imagp[i]*A.imagp[i]);*/
    
    // collapse split complex array into a real array.
    // split[0] contains the DC, and the values we're interested in are split[1] to split[len/2] (since the rest are complex conjugates)
    vDSP_zvabs( &A, 1, amp, 1, numSamples/2 );
}
Exemple #3
0
void CMPerformFFT( CMFFT *fft, float *input, float *output )
{
	int i, n, nby2 ;
	
	n = fft->size ;
	nby2 = n/2 ;

	switch ( fft->style ) {
	case PowerSpectrum:
		vDSP_ctoz( ( COMPLEX* )input, 2, &fft->z, 1, nby2 ) ; 
		if ( fft->window ) {
			for ( i = 0; i < nby2; i++ ) {
				fft->z.realp[i] *= fft->window[i] ;
				fft->z.imagp[i] *= fft->window[i] ;
			}
		}
		vDSP_fft_zript( fft->vfft, &fft->z, 1, &fft->tempBuf, fft->log2n, FFT_FORWARD ) ;
		vDSP_vsq( fft->z.realp, 1, fft->z.realp, 1, nby2 ) ;
		vDSP_vsq( fft->z.imagp, 1, fft->z.imagp, 1, nby2 ) ;
		vDSP_vadd( fft->z.realp, 1, fft->z.imagp, 1,  &output[0], 1, nby2 ) ;
		break ;
	default:
		break ;
	}
}
Exemple #4
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);
    
}
Exemple #5
0
Cicm_Fft::Cicm_Fft(long aWindowSize)
{
	m_window_size	= Tools::clip_power_of_two(aWindowSize * 2);
	m_array_size	= m_window_size / 2;
	m_order			= Tools::log2(m_window_size);
	m_scale			= 1. / (double)(m_window_size * 2.);

#ifdef CICM_VDSP
	vDSP_ctoz((Cicm_Complex *)aRealVector, 2, &m_input_complexes, 1, m_array_size); 
	vDSP_fft_zrip(m_fft_setup, &m_input_complexes, 1, m_log2_size, FFT_FORWARD);
#endif
#ifdef CICM_IPPS
	Cicm_fft_get_size(m_order, &m_spec_size, &m_init_size, &m_buff_size);
	m_fft_buff = Cicm_buffer_malloc(m_buff_size);
	m_fft_init = Cicm_buffer_malloc(m_init_size);
	m_fft_spec = Cicm_buffer_malloc(m_spec_size);
	Cicm_fft_init_handle(&m_fft_handle, m_order, m_fft_spec, m_fft_init);
#endif
#ifdef CICM_FFTW_GSL
	m_real_vector		= (Cicm_Signal *)Cicm_signal_malloc(m_window_size);
	m_input_complexes	= (Cicm_Packed *)Cicm_packed_malloc(m_window_size);
	m_output_complexes	= (Cicm_Packed *)Cicm_packed_malloc(m_window_size);
	m_handle_forward	= Cicm_fft_init_handle_forward(m_window_size, m_real_vector, m_input_complexes);
	m_handle_inverse	= Cicm_fft_init_handle_inverse(m_window_size, m_input_complexes, m_real_vector);
#endif
		
}
Exemple #6
0
/*	Demonstrate using an FFT to detect telephone keys.

	Setup is the result of creating an FFT setup.

	F contains a pair of frequencies to inject into a signal.
*/
void Demonstrate(FFTSetup Setup, FrequencyPair F)
{
    float *Signal = malloc(SampleLength * sizeof *Signal);
    if (Signal == 0)
    {
        fprintf(stderr, "Error, unable to allocate memory.\n");
        exit(EXIT_FAILURE);
    }

    printf("\tGenerating signal with noise and DTMF tones...\n");

    // Initialize the signal with noise.
    for (int i = 0; i < SampleLength; ++i)
        Signal[i] = 4 * Random();

    // Add one of the tones to the signal.
    float Phase = Random();	// Start the tone at a pseudo-random time.
    for (int i = 0; i < SampleLength; ++i)
        Signal[i] += sin((i*F.Frequency[0] / SamplingFrequency + Phase)
                         * TwoPi);

    // Add the other tone.
    Phase = Random();	// Start the tone at a pseudo-random time.
    for (int i = 0; i < SampleLength; ++i)
        Signal[i] += sin((i*F.Frequency[1]/SamplingFrequency + Phase)
                         * TwoPi);

    // Rearrange the signal for vDSP_fft_zrip, using an auxiliary buffer.

    // Get enough memory for two halves.
    float *BufferMemory = malloc(SampleLength * sizeof *BufferMemory);
    if (BufferMemory == 0)
    {
        fprintf(stderr, "Error, unable to allocate memory.\n");
        exit(EXIT_FAILURE);
    }

    // Assign half the memory to reals and half to imaginaries.
    DSPSplitComplex Buffer
        = { BufferMemory, BufferMemory + SampleLength/2 };

    // Copy (and rearrange) the data to the buffer.
    vDSP_ctoz((DSPComplex *) Signal, 2, &Buffer, 1, SampleLength / 2);

    printf("\tAnalyzing signal...\n");

    // Compute the DFT of the signal.
    vDSP_fft_zrip(Setup, &Buffer, 1, Log2SampleLength, FFT_FORWARD);

    // Use the DFT results to identify the tones in the signal.
    int Tone0 = FindTone(Buffer, DTMF0, NumberOf(DTMF0));
    int Tone1 = FindTone(Buffer, DTMF1, NumberOf(DTMF1));

    printf("\tFound frequencies %g and %g for key %c.\n",
           DTMF0[Tone0], DTMF1[Tone1], Keys[Tone1*4 + Tone0]);

    // Release resources.
    free(BufferMemory);
    free(Signal);
}
Exemple #7
0
/* Calculate the power spectrum */
void fft::powerSpectrum_vdsp(int start, float *data, float *window, float *magnitude,float *phase) {
	
    uint32_t        i;
	
	//multiply by window
	vDSP_vmul(data, 1, window, 1, in_real, 1, n);

	//convert to split complex format - evens and odds
	vDSP_ctoz((COMPLEX *) in_real, 2, &A, 1, half);
	
	
	//calc fft
	vDSP_fft_zrip(setupReal, &A, 1, log2n, FFT_FORWARD);
	
	//scale by 2 (see vDSP docs)
	static float scale=0.5 ;
	vDSP_vsmul(A.realp, 1, &scale, A.realp, 1, half);
	vDSP_vsmul(A.imagp, 1, &scale, A.imagp, 1, half);

	//back to split complex format
	vDSP_ztoc(&A, 1, (COMPLEX*) out_real, 2, half);
	
	//convert to polar
	vDSP_polar(out_real, 2, polar, 2, half);
	
	for (i = 0; i < half; i++) {
		magnitude[i]=polar[2*i]+1.0;
		phase[i]=polar[2*i + 1];
	}
	
	
	
}
std::shared_ptr<float> FftProcessorImplAccelerate::process( const float * inData )
{
	mFftComplexBuffer.realp = (float *)memset( mFftComplexBuffer.realp, 0, mBandCount );
	mFftComplexBuffer.imagp = (float *)memset( mFftComplexBuffer.imagp, 0, mBandCount );
	
	vDSP_ctoz( (DSPComplex *)inData, 2 * sStride, &mFftComplexBuffer, 1, mBandCount );
	vDSP_fft_zrip( mFftSetup, &mFftComplexBuffer, 1, mLog2Size, FFT_FORWARD );
    
	float * outData = new float[mBandCount];
	for( int i = 0; i < mBandCount; i++ ) {
		outData[i] = sqrt( ( mFftComplexBuffer.realp[i] * mFftComplexBuffer.realp[i] ) + ( mFftComplexBuffer.imagp[i] * mFftComplexBuffer.imagp[i] ) );
	}
  
 	return std::shared_ptr<float>( outData, deleteFftBuffer );
    
    /*
    // apply window to fft data
//   vDSP_vmul( outData, 1, mWindow, 1, outData, 1, mBandCount );
    
    float* windowedOutData = new float[mBandCount];

//    for( int i = 0; i < mBandCount; i++ ) {
//        windowedOutData[i] = 0.0f;
//    }
    
    float val = 0.0f;
    vDSP_vsmul( outData, 1, &val, windowedOutData, 1, mBandCount );
    
    delete outData;
    
	return std::shared_ptr<float>( windowedOutData, deleteFftBuffer );
     */
}
Exemple #9
0
void FFTFrame::doFFT(const float* data) {
  AudioFloatArray scaledData(m_FFTSize);
  // veclib fft returns a result that is twice as large as would be expected.
  // Compensate for that by scaling the input by half so the FFT has the
  // correct scaling.
  float scale = 0.5f;
  VectorMath::vsmul(data, 1, &scale, scaledData.data(), 1, m_FFTSize);

  vDSP_ctoz((DSPComplex*)scaledData.data(), 2, &m_frame, 1, m_FFTSize / 2);
  vDSP_fft_zrip(m_FFTSetup, &m_frame, 1, m_log2FFTSize, FFT_FORWARD);
}
static void PerformFFT(float * input, float * window, COMPLEX_SPLIT &fftData, FFTSetup &setup, size_t N)
{	
	// windowing
	vDSP_vmul(input, 1, window, 1, input, 1, N);
	
	// FFT
	vDSP_ctoz((COMPLEX *) input, 2, &fftData, 1, N/2);
	vDSP_fft_zrip(setup, &fftData, 1, (size_t)ceilf(log2f(N)), kFFTDirection_Forward);
	
	// zero-ing out Nyquist freq
	fftData.imagp[0] = 0.0f;
}
Exemple #11
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;
}
shared_ptr<float> FftProcessorImplAccelerate::process( const float * inData )
{
	mFftComplexBuffer.realp = (float *)memset( mFftComplexBuffer.realp, 0, mBandCount );
	mFftComplexBuffer.imagp = (float *)memset( mFftComplexBuffer.imagp, 0, mBandCount );
	
	vDSP_ctoz( (DSPComplex *)inData, 2 * sStride, &mFftComplexBuffer, 1, mBandCount );
	vDSP_fft_zrip( mFftSetup, &mFftComplexBuffer, 1, mLog2Size, FFT_FORWARD );
	
	float * outData = new float[mBandCount];
	for( int i = 0; i < mBandCount; i++ ) {
		outData[i] = sqrt( ( mFftComplexBuffer.realp[i] * mFftComplexBuffer.realp[i] ) + ( mFftComplexBuffer.imagp[i] * mFftComplexBuffer.imagp[i] ) );
	}
	
	return shared_ptr<float>( outData, deleteFftBuffer );;
}
Exemple #13
0
Cicm_Fft::~Cicm_Fft()
{
#ifdef CICM_VDSP_FLOAT
	vDSP_ctoz((Cicm_Complex *)aRealVector, 2, &m_input_complexes, 1, m_array_size); 
	vDSP_fft_zrip(m_fft_setup, &m_input_complexes, 1, m_log2_size, FFT_FORWARD);
#endif
#ifdef CICM_IPPS
	Cicm_free(m_fft_buff);
	Cicm_free(m_fft_init);
	Cicm_free(m_fft_spec);
	Cicm_fft_free_handle(m_fft_handle);
#endif
#ifdef CICM_FFTW_GSL
	Cicm_free(m_real_vector);
	Cicm_free(m_input_complexes);
	Cicm_free(m_output_complexes);
	Cicm_fft_free_handle(m_handle_forward);
	Cicm_fft_free_handle(m_handle_inverse);
#endif
}
Exemple #14
0
void fft(FFT_FRAME* frame, float* audioBuffer)
{
	FFT* fft = frame->fft;
    
    // Do some data packing stuff
    vDSP_ctoz((COMPLEX*)audioBuffer, 2, &frame->buffer, 1, fft->sizeOverTwo);
    
    // This applies the windowing
    if (fft->window != NULL)
    	vDSP_vmul(audioBuffer, 1, fft->window, 1, audioBuffer, 1, fft->size);
    
    // Actually perform the fft
    vDSP_fft_zrip(fft->fftSetup, &frame->buffer, 1, fft->logTwo, FFT_FORWARD);
    
    // Do some scaling
    vDSP_vsmul(frame->buffer.realp, 1, &fft->normalize, frame->buffer.realp, 1, fft->sizeOverTwo);
    vDSP_vsmul(frame->buffer.imagp, 1, &fft->normalize, frame->buffer.imagp, 1, fft->sizeOverTwo);
    
    // Zero out DC offset
    frame->buffer.imagp[0] = 0.0;
}
Exemple #15
0
void FFTAccelerate::doFFTReal(float samples[], float amp[], int numSamples)
{
	int i;
	vDSP_Length log2n = log2f(numSamples);
    int nOver2 = numSamples/2;
    //-- window
    //vDSP_blkman_window(window, windowSize, 0);
    vDSP_vmul(samples, 1, window, 1, in_real, 1, numSamples);

    //Convert float array of reals samples to COMPLEX_SPLIT array A
	vDSP_ctoz((COMPLEX*)in_real,2,&A,1,nOver2);

    //Perform FFT using fftSetup and A
    //Results are returned in A
	vDSP_fft_zrip(fftSetup, &A, 1, log2n, FFT_FORWARD);
    
    //Convert COMPLEX_SPLIT A result to float array to be returned
    amp[0] = A.realp[0]/(numSamples*2);
	for(i=1;i<numSamples/2;i++)
		amp[i]=sqrt(A.realp[i]*A.realp[i]+A.imagp[i]*A.imagp[i]);
}
Exemple #16
0
void fft::inversePowerSpectrum_vdsp(int start, float *finalOut, float *window, float *magnitude,float *phase) {
	uint32_t i;
	
	for (i = 0; i < half; i++) {
//		polar[2*i] = pow(10.0, magnitude[i] / 20.0) - 1.0;
		polar[2*i] = magnitude[i] - 1.0;
		polar[2*i + 1] = phase[i];
	}	
	
	vDSP_rect(polar, 2, in_real, 2, half);
	
	vDSP_ctoz((COMPLEX*) in_real, 2, &A, 1, half);
	vDSP_fft_zrip(setupReal, &A, 1, log2n, FFT_INVERSE);
	vDSP_ztoc(&A, 1, (COMPLEX*) out_real, 2, half);
	
	static float scale = 1./n;
	vDSP_vsmul(out_real, 1, &scale, out_real, 1, n);

	//multiply by window
	vDSP_vmul(out_real, 1, window, 1, finalOut, 1, n);
	
}
Exemple #17
0
void fftIp(FFT* fftObject, float* audioBuffer)
{
    // Creating pointer of COMPLEX_SPLIT to use in calculations (points to same data as audioBuffer)
    COMPLEX_SPLIT* fftBuffer = (COMPLEX_SPLIT *)&audioBuffer[0];
    
    // Apply windowing
    if (fftObject->window != NULL)
        vDSP_vmul(audioBuffer, 1, fftObject->window, 1, audioBuffer, 1, fftObject->size);
    
    // This seems correct-ish TODO: check casting
    vDSP_ctoz((COMPLEX*)audioBuffer, 2, fftBuffer, 1, fftObject->sizeOverTwo);
    
    // Perform fft
    vDSP_fft_zrip(fftObject->fftSetup, fftBuffer, 1, fftObject->logTwo, FFT_FORWARD);
    
    // Do scaling
    vDSP_vsmul(fftBuffer->realp, 1, &fftObject->normalize, fftBuffer->realp, 1, fftObject->sizeOverTwo);
    vDSP_vsmul(fftBuffer->imagp, 1, &fftObject->normalize, fftBuffer->imagp, 1, fftObject->sizeOverTwo);
    
    // zero out DC offset
    fftBuffer->imagp[0] = 0.0;
}
void SignalProcessorAudioProcessor::computeFFT() {
    
    // Reinterpret the signal in fftBuffer as an interleaved-data complex vector and use vDSP_ctoz to move the data to a separated-data complex vector. The stride is equal to 2 because the imaginary elements are skipped
    vDSP_ctoz((DSPComplex *) fftBuffer, 2*Stride, &Buffer, 1, N/2);
    
    // Perform a real-to-complex DFT.
    vDSP_DFT_Execute(zrop_Setup,
                     Buffer.realp, Buffer.imagp,
                     Observed.realp, Observed.imagp);

    // If the FFT is set to logarithmic, transform the linear result array in a new log one
    if (logarithmicFFT) {
        computeLogFFT();
    }
    
    // Send the FFT message over the network
    sendFFTMsg();
    
    // Reinitialize fftBufferIndex to start writing the temp data back from the start of the table
    fftBufferIndex = 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);
}
Exemple #21
0
void FFTFrame::doFFT(const float* data)
{
    vDSP_ctoz((DSPComplex*)data, 2, &m_frame, 1, m_FFTSize / 2);
    vDSP_fft_zrip(m_FFTSetup, &m_frame, 1, m_log2FFTSize, FFT_FORWARD);
}
Exemple #22
0
ITunesPixelFormat ivis_render( ITunesVis* plugin, short audio_data[][512], float freq_data[][512],
                               void* buffer, long buffer_size, bool idle )
{
  ITunesPixelFormat format = ITunesPixelFormatUnknown;

  /* make sure we have a plugin and a visual handler */
  if ( !plugin || !plugin->imports.visual_handler )
    return format;

  int i=0, w=0;
  RenderVisualData visual_data;
  DSPSplitComplex splitComplex[2];
  float *data[2];

  /* perform FFT if we're not idling */
  if ( ! idle )
  {
    /* allocate some complex vars */
    for ( i = 0 ; i < 2 ; i++ )
    {
      splitComplex[i].realp = calloc( 512, sizeof(float) );
      splitComplex[i].imagp = calloc( 512, sizeof(float) );
      data[i] = calloc( 512, sizeof(float) );
    }

    /* 2 channels for spectrum and waveform data */
    visual_data.numWaveformChannels = 2;
    visual_data.numSpectrumChannels = 2;

    /* copy spectrum audio data to visual data strucure */
    for ( w = 0 ; w < 512 ; w++ )
    {
      /* iTunes visualizers expect waveform data from 0 - 255, with level 0 at 128 */
      visual_data.waveformData[0][w] = (UInt8)( (long)(audio_data[0][w]) / 128 + 128 );
      visual_data.waveformData[1][w] = (UInt8)( (long)(audio_data[1][w]) / 128 + 128 );

      /* scale to -1, +1 */
      *( data[0] + w ) = (float)(( audio_data[0][w]) / (2.0 * 8192.0) );
      *( data[1] + w ) = (float)(( audio_data[1][w]) / (2.0 * 8192.0) );
    }

    /* FFT scaler */
    float scale = ( 1.0 / 1024.0 ) ; /* scale by length of input * 2 (due to how vDSP does FFTs) */
    float nyq=0, dc=0, freq=0;

    for ( i = 0 ; i < 2 ; i++ )
    {
      /* pack data into format fft_zrip expects it */
      vDSP_ctoz( (COMPLEX*)( data[i] ), 2, &( splitComplex[i] ), 1, 256 );

      /* perform FFT on normalized audio data */
      fft_zrip( plugin->fft_setup, &( splitComplex[i] ), 1, 9, FFT_FORWARD );

      /* scale the values */
      vDSP_vsmul( splitComplex[i].realp, 1, &scale, splitComplex[i].realp, 1, 256 );
      vDSP_vsmul( splitComplex[i].imagp, 1, &scale, splitComplex[i].imagp, 1, 256 );

      /* unpack data */
      vDSP_ztoc( &splitComplex[i], 1, (COMPLEX*)( data[i] ), 2, 256 );

      /* ignore phase */
      dc = *(data[i]) = fabs( *(data[i]) );
      nyq = fabs( *(data[i] + 1) );

      for ( w = 1 ; w < 256 ; w++ )
      {
        /* don't use vDSP for this since there's some overflow */
        freq = hypot( *(data[i] + w * 2), *(data[i] + w * 2 + 1) ) * 256 * 16;
        freq = MAX( 0, freq );
        freq = MIN( 255, freq );
        visual_data.spectrumData[i][ w - 1 ] = (UInt8)( freq );
      }
      visual_data.spectrumData[i][256] = nyq;
    }

    /* deallocate complex vars */
    for ( i = 0 ; i < 2 ; i++ )
    {
      free( splitComplex[i].realp );
      free( splitComplex[i].imagp );
      free( data[i] );
    }

    /* update the render message with the new visual data and timestamp */
    plugin->visual_message.u.renderMessage.renderData = &visual_data;
    plugin->visual_message.u.renderMessage.timeStampID++;
  }

  /* update time */
  plugin->visual_message.u.renderMessage.currentPositionInMS =
    ivis_current_time() - plugin->start_time; // FIXME: real time

  /* save our GL context and send the vis a render message */
  CGLContextObj currentContext = CGLGetCurrentContext();
  if ( plugin->gl_context )
    aglSetCurrentContext( (AGLContext)(plugin->gl_context ) );

  /* call the plugin's render method */
  if ( idle )
  {
    /* idle message */
    if ( plugin->wants_idle )
      plugin->imports.visual_handler( kVisualPluginIdleMessage,
                                      &( plugin->visual_message ),
                                      plugin->vis_ref );
  }
  else
  {
    /* render message */
    plugin->imports.visual_handler( kVisualPluginRenderMessage,
                                    &( plugin->visual_message ),
                                    plugin->vis_ref );

    /* set position message */
    plugin->visual_message.u.setPositionMessage.positionTimeInMS
      = plugin->visual_message.u.renderMessage.currentPositionInMS;
    plugin->imports.visual_handler( kVisualPluginSetPositionMessage, &( plugin->visual_message ),
                                    plugin->vis_ref );
  }
  /* update message */
  plugin->imports.visual_handler( kVisualPluginUpdateMessage, NULL,
                                  plugin->vis_ref );

  /* read pixels and restore our GL context */
  CGLLockContext( CGLGetCurrentContext() );

  switch ( get_pixels( buffer, buffer_size, CGLGetCurrentContext() != currentContext ) )
  {
  case 3:
    format = ITunesPixelFormatRGB24;
    break;

  case 4:
    format = ITunesPixelFormatRGBA32;
    break;

  default:
    break;
  }

  CGLUnlockContext ( CGLGetCurrentContext() );

  /* restore our GL context */
  CGLSetCurrentContext( currentContext );
  return format;
}
void FFT::performFFT (float* samples)
{
	vDSP_ctoz ((COMPLEX*) samples, 2, &bufferSplit, 1, properties.fftSizeHalved);
	vDSP_fft_zrip (config, &bufferSplit, 1, properties.fftSizeLog2, FFT_FORWARD);
}
//get MVDR weighting matrix
void HiLight::get_MVDR_weighting(float grid_color_intensity_MVDR[grid_x*grid_x_MVDR][grid_y*grid_y_MVDR][MVDR_frame], float MVDR_weighting[grid_x*grid_x_MVDR][grid_y*grid_y_MVDR]){
    
    float brightness_mean[grid_x*grid_x_MVDR][grid_y*grid_y_MVDR];
    for (int j = 0; j < grid_x * grid_x_MVDR; j++){
        for (int k = 0; k < grid_y * grid_y_MVDR; k++){
            brightness_mean[j][k] = 0;
        }
    }
    
    for (int j = 0; j < grid_x*grid_x_MVDR; j++){
        for (int k = 0; k < grid_y*grid_y_MVDR; k++){
            for(int i = 0; i < MVDR_frame; i++){
                brightness_mean[j][k] = brightness_mean[j][k] + grid_color_intensity_MVDR[j][k][i];
            }
            brightness_mean[j][k] = brightness_mean[j][k]*1.0 / MVDR_frame;
            for(int i = 0; i < MVDR_frame; i++){
                grid_color_intensity_MVDR[j][k][i] = grid_color_intensity_MVDR[j][k][i] - brightness_mean[j][k];
            }
        }
    }
    
    // Set up a data structure with pre-calculated values for
    // doing a very fast FFT.
    float x[N];
    for (int j = 0; j < grid_x; j++){
        for (int k = 0; k < grid_y; k++){
            float x_MVDR[grid_x_MVDR * grid_y_MVDR][MVDR_frame/N][N];
            float r_MDVR[grid_x_MVDR * grid_y_MVDR][grid_x_MVDR * grid_y_MVDR];
            for (int frame_index = 0; frame_index < MVDR_frame/N;  frame_index++){
                for (int j1 = 0; j1 < grid_x_MVDR; j1++){
                    for (int k1 = 0; k1 < grid_y_MVDR; k1++){
                        for (int i = 0 ; i < N; i++){
                            x[i] = grid_color_intensity_MVDR[j1][k1][frame_index*N + i];
                        }
                        float fft_sum_N_over_2 = 0;
                        for (int i = 0; i < N/2; i++){
                            fft_sum_N_over_2 = fft_sum_N_over_2 + x[2*i] - x[2*i+1];
                        }
                        // We need complex buffers in two different formats!
                        DSPSplitComplex tempSplitComplex;
                        tempSplitComplex.realp = new float[N/2];
                        tempSplitComplex.imagp = new float[N/2];
                        
                        // ----------------------------------------------------------------
                        // Forward FFT
                        
                        // Scramble-pack the real data into complex buffer in just the way that's
                        // required by the real-to-complex FFT function that follows.
                        vDSP_ctoz((DSPComplex*)x, 2, &tempSplitComplex, 1, N/2);
                        
                        // Do real->complex forward FFT
                        vDSP_fft_zrip(fftSetup, &tempSplitComplex, 1, LOG_N, kFFTDirection_Forward);
                        
                        x_MVDR[j1*grid_y_MVDR + k1][frame_index][N/2] = fft_sum_N_over_2;
                        for (int i = 0; i < N/2; i++)
                        {
                            x_MVDR[j1*grid_y_MVDR + k1][frame_index][i] = tempSplitComplex.realp[i];
                            if (i>0){
                                x_MVDR[j1*grid_y_MVDR + k1][frame_index][N-i] = tempSplitComplex.realp[i];
                            }
                        }
                    }
                }
            }
            for (int r_j = 0; r_j < grid_x_MVDR * grid_y_MVDR; r_j++){
                for (int r_k = 0; r_k < grid_x_MVDR * grid_y_MVDR; r_k++){
                    float x_MVDR_sum = 0;
                    for (int row = 0; row != MVDR_frame/N; ++row)
                    {
                        for (int col = 0; col != N; ++col)
                        {
                            x_MVDR_sum = x_MVDR_sum + x_MVDR[r_j][row][col] * x_MVDR[r_k][row][col];
                        }
                    }
                    r_MDVR[r_j][r_k] = x_MVDR_sum;
                }
            }
            
            float w[grid_x_MVDR * grid_y_MVDR];
            float r_MVDR_inv[grid_x_MVDR * grid_y_MVDR][grid_x_MVDR * grid_y_MVDR];
            matrix <double> r_MDVR_tmp(grid_x_MVDR * grid_y_MVDR,grid_x_MVDR * grid_y_MVDR);
            for (int r_i=0; r_i < r_MDVR_tmp.getactualsize(); r_i++){
                for (int r_j=0; r_j < r_MDVR_tmp.getactualsize(); r_j++)
                {
                    r_MDVR_tmp.setvalue(r_i , r_j, r_MDVR[r_i][r_j]);
                }
            }
            r_MDVR_tmp.invert();
            bool invert_check;
            double inv_results;
            float r_MVDR_inv_sum = 0;
            float w_sum = 0;
            for (int r_i=0; r_i < r_MDVR_tmp.getactualsize(); r_i++){
                for (int r_j=0; r_j<r_MDVR_tmp.getactualsize(); r_j++)
                {
                    r_MDVR_tmp.getvalue(r_i, r_j, inv_results, invert_check);
                    r_MVDR_inv[r_i][r_j] = inv_results;
                    r_MVDR_inv_sum = r_MVDR_inv_sum + inv_results;
                }
            }
            for (int r_i = 0; r_i < grid_x_MVDR * grid_y_MVDR; r_i++){
                w[r_i] = 0;
                for (int r_j = 0; r_j < grid_x_MVDR * grid_y_MVDR; r_j++){
                    w[r_i] = w[r_i] + r_MVDR_inv[r_i][r_j];
                }
                w[r_i] = w[r_i]/r_MVDR_inv_sum;
                if (w[r_i] < 0){
                    w[r_i] = 0;
                }
                w_sum = w_sum + w[r_i];
            }
            for (int r_i = 0; r_i < grid_x_MVDR * grid_y_MVDR; r_i++){
                w[r_i] = w[r_i] / w_sum * grid_x_MVDR * grid_y_MVDR;
            }
            
            for(int w_i = 0; w_i < grid_x_MVDR; w_i++){
                for(int w_j = 0; w_j < grid_y_MVDR; w_j++){
                    MVDR_weighting[ j * grid_x_MVDR + w_i][ k * grid_y_MVDR + w_j] = w[w_i * grid_y_MVDR + w_j];
                }
            }
        }
    }
}
//Processes a frame and returns output image
bool HiLight::processFrame(const cv::Mat& inputFrame, int* screen_position, double current_timestamp, char *results, bool* denoise_check, bool* first_bit_check, int* hilight_line_index, char* hilight_results_tmp )
{
    *denoise_check = false;
    *first_bit_check = false;
    if(!initialized){
        initialized = true;
        for(int i = 0; i<grid_x; i++){
            for(int j = 0; j<grid_y; j++ ){
                for (int k = 0; k < first_bit_window; k++){
                    first_bit_color_window[i][j][k] = 0;
                }
                for (int k = 0; k < N; k++){
                    grid_color_intensity[i][j][k] = 0;
                    hilight_results_stack[i][j][k] = 0;
                }
                hilight_results[i][j] = 0;
            }
        }
        if (isImage){
            MVDR = true;
            first_2_ratio = 0.6;//0.8
            first_bit_voting = 0.5;//0.7
        }else{
            MVDR = false;
            first_2_ratio = 0.8; //0.7
            first_bit_voting = 0.7; //0.6
        }
        window_index = 0;
        first_bit_detected = false;
        first_bit_index = 0;
        hilight_stack_index = 0;
        start_time = current_timestamp;
        current_time = current_timestamp;
        denoise_start = false;
        MVDR_index = 0;
        bit_counter = 0;
        results_stack_counter = 0;
        fftSetup = vDSP_create_fftsetup(LOG_N, kFFTRadix2);
        start_receiving = false;
        counter_after_detect_1= 0;
        
        first_bit_1_detected = false;
        first_bit_2_detected = false;
        hilight_first_bit_index = 0;
        hilight_first_bit_counter = 0;
        hilight_first_bit_position = 0;
        
        if (screen_position[2] < screen_position[4]){
            image_ROI_position[0].y = screen_position[2];
        }else{
            image_ROI_position[0].y = screen_position[4];
        }
        
        if (screen_position[1] < screen_position[7]){
            image_ROI_position[0].x = screen_position[1];
        }else{
            image_ROI_position[0].x = screen_position[7];
        }
        
        if (screen_position[6] < screen_position[8]){
            image_ROI_position[1].y = screen_position[8];
        }else{
            image_ROI_position[1].y = screen_position[6];
        }
        
        if (screen_position[5] < screen_position[3]){
            image_ROI_position[1].x = screen_position[3];
        }else{
            image_ROI_position[1].x = screen_position[5];
        }
        
        if (isImage){
            // Set grids points to calculate the grid position
            for (int i = 0; i <= grid_x * grid_x_MVDR; i++){
                grids_points_top_image[i].x = screen_position[1] + (screen_position[3] - screen_position[1]) / grid_x / grid_x_MVDR * i;
                grids_points_top_image[i].y = screen_position[2] + (screen_position[4] - screen_position[2]) / grid_x / grid_x_MVDR * i;
                grids_points_bottom_image[i].x = screen_position[7] + (screen_position[5] - screen_position[7]) / grid_x / grid_x_MVDR * i;
                grids_points_bottom_image[i].y = screen_position[8] + (screen_position[6] - screen_position[8]) / grid_x / grid_x_MVDR * i;
            }
            
            for (int i = 0; i <= grid_y * grid_y_MVDR; i++){
                grids_points_left_image[i].x = screen_position[1] + (screen_position[7] - screen_position[1]) / grid_y / grid_y_MVDR * i;
                grids_points_left_image[i].y = screen_position[2] + (screen_position[8] - screen_position[2]) / grid_y / grid_y_MVDR * i;
                grids_points_right_image[i].x = screen_position[3] + (screen_position[5] - screen_position[3]) / grid_y / grid_y_MVDR * i;
                grids_points_right_image[i].y = screen_position[4] + (screen_position[6] - screen_position[4]) / grid_y / grid_y_MVDR * i;
            }
            
            for (int i = 0; i < grid_x * grid_x_MVDR; i++){
                for (int j = 0; j < grid_y * grid_y_MVDR; j++){
                    cv::Point2f r1;
                    cv::Point2f r2;
                    cv::Point2f r3;
                    cv::Point2f r4;
                    intersection(grids_points_top_image[i], grids_points_bottom_image[i], grids_points_left_image[j], grids_points_right_image[j], r1);//top left
                    intersection(grids_points_top_image[i+1], grids_points_bottom_image[i+1], grids_points_left_image[j], grids_points_right_image[j], r2);//top right
                    intersection(grids_points_top_image[i+1], grids_points_bottom_image[i+1], grids_points_left_image[j+1], grids_points_right_image[j+1], r3);// bottom right
                    intersection(grids_points_top_image[i], grids_points_bottom_image[i], grids_points_left_image[j+1], grids_points_right_image[j+1], r4);//bottom left
                    
                    //refine grid_position
                    if (r1.x <= r4.x){
                        grids_position_image[i][j][0].x = r4.x - image_ROI_position[0].x;
                    }else{
                        grids_position_image[i][j][0].x = r1.x - image_ROI_position[0].x;
                    }
                    
                    if (r1.y <= r2.y){
                        grids_position_image[i][j][0].y = r2.y - image_ROI_position[0].y;
                    }else{
                        grids_position_image[i][j][0].y = r1.y - image_ROI_position[0].y;
                    }
                    
                    if (r3.x <= r2.x){
                        grids_position_image[i][j][1].x = r3.x - image_ROI_position[0].x;
                    }else{
                        grids_position_image[i][j][1].x = r2.x - image_ROI_position[0].x;
                    }
                    
                    if (r3.y <= r4.y){
                        grids_position_image[i][j][1].y = r3.y - image_ROI_position[0].y;
                    }else{
                        grids_position_image[i][j][1].y = r4.y - image_ROI_position[0].y;
                    }
                }
            }
        }else{
            // Set grids points to calculate the grid position
            for (int i = 0; i <= grid_x; i++){
                grids_points_top_video[i].x = screen_position[1] + (screen_position[3] - screen_position[1]) / grid_x * i;
                grids_points_top_video[i].y = screen_position[2] + (screen_position[4] - screen_position[2]) / grid_x * i;
                grids_points_bottom_video[i].x = screen_position[7] + (screen_position[5] - screen_position[7]) / grid_x * i;
                grids_points_bottom_video[i].y = screen_position[8] + (screen_position[6] - screen_position[8]) / grid_x * i;
            }
            
            for (int i = 0; i <= grid_y; i++){
                grids_points_left_video[i].x = screen_position[1] + (screen_position[7] - screen_position[1]) / grid_y * i;
                grids_points_left_video[i].y = screen_position[2] + (screen_position[8] - screen_position[2]) / grid_y * i;
                grids_points_right_video[i].x = screen_position[3] + (screen_position[5] - screen_position[3]) / grid_y * i;
                grids_points_right_video[i].y = screen_position[4] + (screen_position[6] - screen_position[4]) / grid_y * i;
            }
            
            for (int i = 0; i < grid_x; i++){
                for (int j = 0; j < grid_y; j++){
                    cv::Point2f r1;
                    cv::Point2f r2;
                    cv::Point2f r3;
                    cv::Point2f r4;
                    intersection(grids_points_top_video[i], grids_points_bottom_video[i], grids_points_left_video[j], grids_points_right_video[j], r1);//top left
                    intersection(grids_points_top_video[i+1], grids_points_bottom_video[i+1], grids_points_left_video[j], grids_points_right_video[j], r2);//top right
                    intersection(grids_points_top_video[i+1], grids_points_bottom_video[i+1], grids_points_left_video[j+1], grids_points_right_video[j+1], r3);// bottom right
                    intersection(grids_points_top_video[i], grids_points_bottom_video[i], grids_points_left_video[j+1], grids_points_right_video[j+1], r4);//bottom left
                    
                    //refine grid_position
                    if (r1.x <= r4.x){
                        grids_position_video[i][j][0].x = r4.x - image_ROI_position[0].x;
                    }else{
                        grids_position_video[i][j][0].x = r1.x - image_ROI_position[0].x;
                    }
                    
                    if (r1.y <= r2.y){
                        grids_position_video[i][j][0].y = r2.y - image_ROI_position[0].y;
                    }else{
                        grids_position_video[i][j][0].y = r1.y - image_ROI_position[0].y;
                    }
                    
                    if (r3.x <= r2.x){
                        grids_position_video[i][j][1].x = r3.x - image_ROI_position[0].x;
                    }else{
                        grids_position_video[i][j][1].x = r2.x - image_ROI_position[0].x;
                    }
                    
                    if (r3.y <= r4.y){
                        grids_position_video[i][j][1].y = r3.y - image_ROI_position[0].y;
                    }else{
                        grids_position_video[i][j][1].y = r4.y - image_ROI_position[0].y;
                    }
                }
            }
        }
        
        srcTri[0] = cv::Point2f( screen_position[2],screen_position[1] );
        srcTri[1] = cv::Point2f( screen_position[4],screen_position[3] );
        srcTri[2] = cv::Point2f( screen_position[6],screen_position[5] );
        
        dist_top = sqrt(pow(screen_position[4]-screen_position[2],2.0) + pow(screen_position[3]-screen_position[1],2.0));
        dstTri[0] = cv::Point2f( screen_position[2],screen_position[1] );
        dstTri[1] = cv::Point2f( screen_position[2],screen_position[1] + dist_top );
        dstTri[2] = cv::Point2f( screen_position[2] + (int)(dist_top*transmitter_screen_ratio),screen_position[1] + dist_top);
        warp_mat = getAffineTransform( srcTri, dstTri );
    }else{
        current_time = current_timestamp;
    }
    
    //crop the transmitter screen from the captured image
    cv::Mat image_ROI = inputFrame(cv::Range(image_ROI_position[0].y, image_ROI_position[1].y), cv::Range(image_ROI_position[0].x, image_ROI_position[1].x));
    getGray_HiLight(image_ROI, grayImage);
    image_ROI.release();
    
    for (int c = 0; c < grid_x; c++){
        for (int r = 0; r < grid_y; r++){
            brightness[c][r] = 0;
        }
    }
    if (isImage){
        int brightness_c = 0;
        int brightness_r = 0;
        for (int c = 0; c < grid_x * grid_x_MVDR; c++){
            for (int r = 0; r < grid_y * grid_y_MVDR; r++)
            {
                cv::Mat tile = grayImage(cv::Range(grids_position_image[c][r][0].y + grid_margin, grids_position_image[c][r][1].y - grid_margin)
                                         , cv::Range(grids_position_image[c][r][0].x + grid_margin, grids_position_image[c][r][1].x - grid_margin));
                
                cv::Scalar pixel_scalar = cv::mean(tile);
                tile.release();
                float brightness_tmp =pixel_scalar[0];
                
                if (MVDR){
                    if(!denoise_start && MVDR_index < MVDR_frame){
                        grid_color_intensity_MVDR[c][r][MVDR_index] = brightness_tmp;
                        if ( c == grid_x * grid_x_MVDR -1 && r == grid_y * grid_y_MVDR - 1){
                            MVDR_index++;
                        }
                    }else if(!denoise_start && MVDR_index >= MVDR_frame){
                        denoise_start = true;
                        *denoise_check = true;
                        get_MVDR_weighting(grid_color_intensity_MVDR, MVDR_weighting);
                        
                        //print MVDR matrix
                        if (isDebug){
                            for (int i = 0; i < grid_x * grid_x_MVDR; i++){
                                for (int j = 0; j < grid_y * grid_y_MVDR; j++){
                                    printf("%f\t", MVDR_weighting[i][j]);
                                }
                                printf("\n");
                            }
                        }
                    }else{
                        brightness_c = floor(c*1.0/grid_x_MVDR);
                        brightness_r = floor(r*1.0/grid_y_MVDR);
                        brightness[brightness_c][brightness_r] = brightness[brightness_c][brightness_r] + brightness_tmp * MVDR_weighting[c][r];
                    }
                }else{
                    brightness_c = floor(c*1.0/grid_x_MVDR);
                    brightness_r = floor(r*1.0/grid_y_MVDR);
                    brightness[brightness_c][brightness_r] = brightness[brightness_c][brightness_r] + brightness_tmp;
                }
            }
        }
    }else{
        for (int c = 0; c < grid_x; c++){
            for (int r = 0; r < grid_y; r++)
            {
                cv::Mat tile = grayImage(cv::Range(grids_position_video[c][r][0].y + grid_margin, grids_position_video[c][r][1].y - grid_margin)
                                         , cv::Range(grids_position_video[c][r][0].x + grid_margin, grids_position_video[c][r][1].x - grid_margin));
                
                cv::Scalar pixel_scalar = cv::mean(tile);
                tile.release();
                float brightness_tmp =pixel_scalar[0];
                brightness[c][r] = brightness_tmp;
            }
        }
    }

    if (denoise_start || !MVDR){
        for (int c = 0; c < grid_x; c++){
            for (int r = 0; r < grid_y; r++){
                if (window_index<(N-1)) {
                    grid_color_intensity[c][r][window_index] = brightness[c][r];
                    window_index++;
                }else{
                    int i;
                    float fft_sum_N_over_2 = 0;
                    for (i = 1; i < N; i++){
                        grid_color_intensity[c][r][i-1] = grid_color_intensity[c][r][i];
                    }
                    grid_color_intensity[c][r][N-1] = brightness[c][r];
                    
                    for (i = 0; i < N/2; i++){
                        fft_sum_N_over_2 = fft_sum_N_over_2 + grid_color_intensity[c][r][2*i] - grid_color_intensity[c][r][2*i+1];
                    }

                    // Initialize the input buffer with a sinusoid
                    
                    // We need complex buffers in two different formats!
                    tempSplitComplex.realp = new float[N/2];
                    tempSplitComplex.imagp = new float[N/2];
                    
                    // ----------------------------------------------------------------
                    // Forward FFT
                    
                    // Scramble-pack the real data into complex buffer in just the way that's
                    // required by the real-to-complex FFT function that follows.
                    vDSP_ctoz((DSPComplex*)grid_color_intensity[c][r], 2, &tempSplitComplex, 1, N/2);
                    
                    // Do real->complex forward FFT
                    vDSP_fft_zrip(fftSetup, &tempSplitComplex, 1, LOG_N, kFFTDirection_Forward);
                    
                    int max_pulse_index = object_pulse_threashold;
                    float max_pulse = -100;
                    float object_pulse_power_1 = LinearToDecibel(pow (fft_sum_N_over_2, 2.0)/ N);
                    float object_pulse_power_2;
                    int object_pulse_force;
                    int object_pulse;
                    for (int k = object_pulse_threashold; k < N/2; k++)
                    {
                        float spectrum = LinearToDecibel((pow (tempSplitComplex.realp[k], 2.0) + pow (tempSplitComplex.imagp[k], 2.0))/ 4/ N);
                        if (max_pulse<spectrum){
                            max_pulse = spectrum;
                            max_pulse_index = k;
                        }
                        if(k == object_pulse_2){
                            object_pulse_power_2 = spectrum;
                        }
                    }
                    
                    delete tempSplitComplex.realp;
                    delete tempSplitComplex.imagp;
                    
                    if(max_pulse < object_pulse_power_1 && object_pulse_power_1 > -25){
                        object_pulse = 1;
                    }else if(max_pulse == object_pulse_power_2){
                        object_pulse = 2;
                    }else{
                        object_pulse = 0;
                    }
                    
                    if(object_pulse_power_1 >= object_pulse_power_2){
                        object_pulse_force = 1;
                    }else{
                        object_pulse_force = 2;
                    }
                    
                    //decode data by find the peak frequency power
                    if (first_bit_detected){
                        if (first_bit_1_detected && isCalibrate){
                            hilight_first_bit_stack[c][r][hilight_first_bit_index] = object_pulse_force;
                        }
                        if(current_time - start_time >= N / 60.0 * (bit_counter + 1)){
                            hilight_results[c][r] = get_hilight_results(hilight_results_stack[c][r], hilight_stack_index);
                            hilight_results_stack[c][r][0] = object_pulse_force;
                        }else{
                            hilight_results_stack[c][r][hilight_stack_index] = object_pulse_force;
                        }
                    }else{
                        first_bit_color_window[c][r][first_bit_index] = object_pulse;
                    }
                }
            }
        }

        if (first_bit_1_detected && isCalibrate){
            hilight_first_bit_timestamp[hilight_first_bit_index++] = current_time;
        }if(first_bit_2_detected && isCalibrate){
            first_bit_2_detected = false;
            hilight_first_bit_counter++;
            if (hilight_first_bit_counter == N/2){
                calibrate_first_bit_position();
            }
        }
        if (first_bit_detected){
            if(current_time - start_time >= N / 60.0 * (bit_counter + 1)){
                int counter_for_2 = 0;
                for (int i = 0; i < grid_x; i++){
                    for (int j = 0; j <  grid_y; j++){
                        if (isDebug || start_receiving){
                            printf("%d ",hilight_results[i][j]);
                        }
                        if (hilight_results[i][j] == 2){
                            counter_for_2++;
                        }
                    }
                }
                if (isDebug || start_receiving){
                    printf("\n");
                }
                hilight_stack_index = 1;
                bit_counter++;
                
                if (!start_receiving){
                    counter_after_detect_1++;
                    if (counter_after_detect_1 > 3){
                        reset();
                    }else{
                        if(counter_for_2 >= (double)grid_x * grid_y * first_2_ratio){
                            first_bit_2_detected = true;
                            start_receiving = true;
                            *first_bit_check = true;
                            if (isDebug){
                                printf("\n");
                            }
                        }
                    }
                    return false;
                }else{
                    int results_counter_tmp =0;
                    for (int i = 0; i < grid_x; i++){
                        for (int j = 0; j <  grid_y; j++){
                            output_bit_stack[results_stack_counter++] = hilight_results[i][j];
                            hilight_results_tmp[results_counter_tmp++] = hilight_results[i][j] + '0' - 1;
                        }
                    }
                    hilight_line_index[0] = results_stack_counter/grid_x/grid_y;
                    
                    if (results_stack_counter == output_bit_stck_length){
                        results_stack_counter = 0;
                        get_char_from_bits(output_bit_stack, results);
                        
                        printf("%s\n",results);
                        
                        if (demo){
                            debug_reset();
                            return true;
                        }else{
                            debug_reset();
                            return false;
                        }
                    }else{
                        return false;
                    }
                }
            }else{
                hilight_stack_index++;
            }
        }else{
            if(first_bit_index<first_bit_window-1){
                first_bit_index++;
            }else{
                first_bit_detected = detect_first_bit(first_bit_color_window);
                if (first_bit_detected){
                    if (isCalibrate){
                        first_bit_1_detected = true;
                    }
                    start_time = current_time;
                }
            }
        }
    }
    return false;
}
/*	Demonstrate the real-to-complex one-dimensional out-of-place FFT,
	vDSP_fft_zrop.

	The out-of-place FFT writes results into a different array than the
	input.  If you are using vDSP_ctoz to reformat the input, you do not
	need vDSP_fft_zrop because you move the data from an input array to an
	output array when you call vDSP_ctoz.  vDSP_fft_zrop may be useful when
	incoming data arrives in the format used by vDSP_fft_zrop, and you want
	to simultaneously perform an FFT and store the results in another array.
*/
static void DemonstratevDSP_fft_zrop(FFTSetup Setup)
{
	/*	Define a stride for the array be passed to the FFT.  In many
		applications, the stride is one and is passed to the vDSP
		routine as a constant.
	*/
	const vDSP_Stride Stride = 1;

	// Define a variable for a loop iterator.
	vDSP_Length i;

	// Define some variables used to time the routine.
	ClockData t0, t1;
	double Time;

	printf("\n\tOne-dimensional real FFT of %lu elements.\n",
		(unsigned long) N);

	// Allocate memory for the arrays.
	float *Signal = malloc(N * Stride * sizeof Signal);
	float *BufferMemory = malloc(N * sizeof *BufferMemory);
	float *ObservedMemory = malloc(N * sizeof *ObservedMemory);

	if (ObservedMemory == NULL || BufferMemory == NULL || Signal == NULL)
	{
		fprintf(stderr, "Error, failed to allocate memory.\n");
		exit(EXIT_FAILURE);
	}

	// Assign half of BufferMemory to reals and half to imaginaries.
	DSPSplitComplex Buffer = { BufferMemory, BufferMemory + N/2 };

	// Assign half of ObservedMemory to reals and half to imaginaries.
	DSPSplitComplex Observed = { ObservedMemory, ObservedMemory + N/2 };

	/*	Generate an input signal.  In a real application, data would of
		course be provided from an image file, sensors, or other source.
	*/
	const float Frequency0 = 48, Frequency1 = 243, Frequency2 = 300;
	const float Phase0 = 1.f/3, Phase1 = .82f, Phase2 = .5f;
	for (i = 0; i < N; ++i)
		Signal[i*Stride] =
			  cos((i * Frequency0 / N + Phase0) * TwoPi)
			+ cos((i * Frequency1 / N + Phase1) * TwoPi)
			+ cos((i * Frequency2 / N + Phase2) * TwoPi);

	/*	Reinterpret the real signal as an interleaved-data complex
		vector and use vDSP_ctoz to move the data to a separated-data
		complex vector.  This puts the even-indexed elements of Signal
		in Observed.realp and the odd-indexed elements in
		Observed.imagp.

		Note that we pass vDSP_ctoz two times Signal's normal stride,
		because ctoz skips through a complex vector from real to real,
		skipping imaginary elements.  Considering this as a stride of
		two real-sized elements rather than one complex element is a
		legacy use.

		In the destination array, a stride of one is used regardless of
		the source stride.  Since the destination is a buffer allocated
		just for this purpose, there is no point in replicating the
		source stride.
	*/
	vDSP_ctoz((DSPComplex *) Signal, 2*Stride, &Buffer, 1, N/2);

	// Perform a real-to-complex FFT.
	vDSP_fft_zrop(Setup, &Buffer, 1, &Observed, 1, Log2N, FFT_FORWARD);

	/*	Prepare expected results based on analytical transformation of
		the input signal.
	*/
	float *ExpectedMemory = malloc(N * sizeof *ExpectedMemory);
	if (ExpectedMemory == NULL)
	{
		fprintf(stderr, "Error, failed to allocate memory.\n");
		exit(EXIT_FAILURE);
	}

	// Assign half of ExpectedMemory to reals and half to imaginaries.
	DSPSplitComplex Expected = { ExpectedMemory, ExpectedMemory + N/2 };

	for (i = 0; i < N/2; ++i)
		Expected.realp[i] = Expected.imagp[i] = 0;

	// Add the frequencies in the signal to the expected results.
	Expected.realp[(int) Frequency0] = N * cos(Phase0 * TwoPi);
	Expected.imagp[(int) Frequency0] = N * sin(Phase0 * TwoPi);

	Expected.realp[(int) Frequency1] = N * cos(Phase1 * TwoPi);
	Expected.imagp[(int) Frequency1] = N * sin(Phase1 * TwoPi);

	Expected.realp[(int) Frequency2] = N * cos(Phase2 * TwoPi);
	Expected.imagp[(int) Frequency2] = N * sin(Phase2 * TwoPi);

	// Compare the observed results to the expected results.
	CompareComplexVectors(Expected, Observed, N/2);

	// Release memory.
	free(ExpectedMemory);

	/*	The above shows how to use the vDSP_fft_zrop routine.  Now we
		will see how fast it is.
	*/

	/*	Zero the signal before timing because repeated FFTs on non-zero
		data can cause abnormalities such as infinities, NaNs, and
		subnormal numbers.
	*/
	for (i = 0; i < N; ++i)
		Signal[i] = 0;
	vDSP_ctoz((DSPComplex *) Signal, 2*Stride, &Observed, 1, N/2);

	// Time vDSP_fft_zrop by itself.

	t0 = Clock();

	for (i = 0; i < Iterations; ++i)
		vDSP_fft_zrop(Setup, &Buffer, 1, &Observed, 1, Log2N,
			FFT_FORWARD);

	t1 = Clock();

	// Average the time over all the loop iterations.
	Time = ClockToSeconds(t1, t0) / Iterations;

	printf("\tvDSP_fft_zrop on %lu elements takes %g microseconds.\n",
		(unsigned long) N, Time * 1e6);

	/*	Unlike the vDSP_fft_zrip example, we do not time vDSP_fft_zrop
		in conjunction with vDSP_ctoz and vDSP_ztoc.  If your data
		arrangement requires you to use vDSP_ctoz, then you are already
		making a copy of the input data.  So you would just do the FFT
		in-place in that copy; you would call vDSP_fft_zrip and not
		vDSP_fft_zrop.
	*/

	// Release resources.
	free(ObservedMemory);
	free(BufferMemory);
	free(Signal);
}
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;
}