Example #1
0
void scfft_doifft(scfft * f)
{
	#if SC_FFT_FFTW
		float *trbuf = f->trbuf;
		size_t bytesize = f->nfull * sizeof(float);
		memcpy(trbuf, f->indata, bytesize);
		trbuf[1] = 0.f;
		trbuf[f->nfull] = f->indata[1];  // Nyquist goes all the way down to the end of the line...
		trbuf[f->nfull+1] = 0.f;

		fftwf_execute(f->plan);
		// NB the plan already includes copying data to f->outbuf

	#elif SC_FFT_VDSP
		vDSP_ctoz((COMPLEX*) f->indata, 2, &splitBuf, 1, f->nfull >> 1);
		vDSP_fft_zrip(fftSetup[f->log2nfull], &splitBuf, 1, f->log2nfull, FFT_INVERSE);
		vDSP_ztoc(&splitBuf, 1, (DSPComplex*) f->outdata, 2, f->nfull >> 1);
	#elif SC_FFT_GREEN
		float *trbuf = f->trbuf;
		size_t bytesize = f->nfull * sizeof(float);
		memcpy(trbuf, f->indata, bytesize);
		// Green FFT is in-place
		riffts(trbuf, f->log2nfull, 1, cosTable[f->log2nfull]);
		// Copy to public buffer
		memcpy(f->outdata, trbuf, f->nwin * sizeof(float));
	#endif
	scfft_dowindowing(f->outdata, f->nwin, f->nfull, f->log2nwin, f->wintype, f->scalefac);
}
Example #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 );
}
Example #3
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];
	}
	
	
	
}
Example #4
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];
    }
}
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 );
     */
}
Example #6
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
		
}
Example #7
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);
    
}
Example #8
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);
}
Example #9
0
void FFTFrame::doInverseFFT(float* data) {
  vDSP_fft_zrip(m_FFTSetup, &m_frame, 1, m_log2FFTSize, FFT_INVERSE);
  vDSP_ztoc(&m_frame, 1, (DSPComplex*)data, 2, m_FFTSize / 2);

  // Do final scaling so that x == IFFT(FFT(x))
  float scale = 1.0f / m_FFTSize;
  VectorMath::vsmul(data, 1, &scale, data, 1, m_FFTSize);
}
Example #10
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);
}
Example #11
0
void FFT::performIFFT (float* fftBuffer)
{
    SplitComplex split;
    split.realp = fftBuffer;
	split.imagp = fftBuffer + properties.fftSizeHalved;

    jassert (split.realp != bufferSplit.realp); // These can't point to the same data!

	vDSP_fft_zrip (config, &split, 1, properties.fftSizeLog2, FFT_INVERSE);
    vDSP_ztoc (&split, 1, (COMPLEX*) buffer.getData(), 2, properties.fftSizeHalved);
}
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;
}
Example #13
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;
}
Example #14
0
void dm_fftSetupExecute(dm_fftSetup fftSetup_, unsigned long timeDomainLength_, float* timeDomain_, dm_fftComplexArrayT*  frequency_, unsigned long offset_) {
  fftsetup_internal* setup = (fftsetup_internal*)fftSetup_;
#ifdef DSP_USE_ACCELERATE
  if (setup->direction == DM_FFT_FORWARD) {
    frequency_->fillFromVector(timeDomain_, timeDomainLength_/2);
    vDSP_fft_zrip(setup->fftSetup, (DSPSplitComplex*)frequency_, 1, setup->logFftSize, FFT_FORWARD);
  } else {
    vDSP_fft_zrip(setup->fftSetup, (DSPSplitComplex*)frequency_, 1, setup->logFftSize, FFT_INVERSE);
    frequency_->toRealVector(timeDomain_, offset_, timeDomainLength_);
  }
#else
  
  if (setup->direction == DM_FFT_FORWARD) {
    memcpy(setup->temp, timeDomain_, sizeof(float) * timeDomainLength_);
    kiss_fftr(setup->fftSetup, (const kiss_fft_scalar *)setup->temp, (kiss_fft_cpx*)frequency_->data);
  } else {
    kiss_fftri(setup->fftSetup, (const kiss_fft_cpx*)frequency_->data, (kiss_fft_scalar *)setup->temp);
    memcpy(timeDomain_, setup->temp + offset_ * 2, timeDomainLength_ * sizeof(float));
    dm_vsfill(0, timeDomain_ + timeDomainLength_, frequency_->size());
  }
  
#endif
}
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 );;
}
Example #16
0
void ifft(FFT_FRAME* frame, float* outputBuffer)
{
    // get pointer to fft object
    FFT* fft = frame->fft;

    // perform in-place fft inverse
    vDSP_fft_zrip(fft->fftSetup, &frame->buffer, 1, fft->logTwo, FFT_INVERSE);
    
    // The output signal is now in a split real form.  Use the  function vDSP_ztoc to get a split real vector. 
    vDSP_ztoc(&frame->buffer, 1, (COMPLEX *)outputBuffer, 2, fft->sizeOverTwo);
    
    // This applies the windowing
    if (fft->window != NULL)
    	vDSP_vmul(outputBuffer, 1, fft->window, 1, outputBuffer, 1, fft->size);
}
Example #17
0
void scfft_dofft(scfft *f){
	// Data goes to transform buf
	memcpy(f->trbuf, f->indata, f->nwin * sizeof(float));
	scfft_dowindowing(f->trbuf, f->nwin, f->nfull, f->log2nfull, f->wintype, f->scalefac);
	#if SC_FFT_FFTW
		fftwf_execute(f->plan);
		// Rearrange output data onto public buffer
		memcpy(f->outdata, f->trbuf, f->nfull * sizeof(float));
		f->outdata[1] = f->trbuf[f->nfull]; // Pack nyquist val in
	#elif SC_FFT_VDSP
		// Perform even-odd split
		vDSP_ctoz((COMPLEX*) f->trbuf, 2, &splitBuf, 1, f->nfull >> 1);
		// Now the actual FFT
		vDSP_fft_zrip(fftSetup[f->log2nfull], &splitBuf, 1, f->log2nfull, FFT_FORWARD);
		// Copy the data to the public output buf, transforming it back out of "split" representation
		vDSP_ztoc(&splitBuf, 1, (DSPComplex*) f->outdata, 2, f->nfull >> 1);
	#endif
}
Example #18
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
}
Example #19
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;
}
Example #20
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]);
}
Example #21
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);
	
}
Example #22
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 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;
    }
}
Example #24
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);
}
//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;
}
Example #26
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);
}
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;
}
/*	Demonstrate the real-to-complex one-dimensional in-place FFT,
	vDSP_fft_zrip.

	The in-place FFT writes results into the same array that contains the
	input data.

	Applications may need to rearrange data before calling the
	real-to-complex FFT.  This is because the vDSP FFT routines currently
	use a separated-data complex format, in which real components and
	imaginary components are stored in different arrays.  For the
	real-to-complex FFT, real data passed using the same arrangements used
	for complex data.  (This is largely due to the nature of the algorithm
	used in performing in the real-to-complex FFT.) The mapping puts
	even-indexed elements of the real data in real components of the
	complex data and odd-indexed elements of the real data in imaginary
	components of the complex data.

	(It is possible to improve this situation by implementing
	interleaved-data complex format.  If you would benefit from such
	routines, please enter an enhancement request at
	http://developer.apple.com/bugreporter.)

	If an application's real data is stored sequentially in an array (as is
	common) and the design cannot be altered to provide data in the
	even-odd split configuration, then the data can be moved using the
	routine vDSP_ctoz.

	The output of the real-to-complex FFT contains only the first N/2
	complex elements, with one exception.  This is because the second N/2
	elements are complex conjugates of the first N/2 elements, so they are
	redundant.

	The exception is that the imaginary parts of elements 0 and N/2 are
	zero, so only the real parts are provided.  The real part of element
	N/2 is stored in the space that would be used for the imaginary part of
	element 0.

	See the vDSP Library manual for illustration and additional
	information.
*/
static void DemonstratevDSP_fft_zrip(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 *ObservedMemory = malloc(N * sizeof *ObservedMemory);

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

	// 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 = 79, Frequency1 = 296, Frequency2 = 143;
	const float Phase0 = 0, Phase1 = .2f, Phase2 = .6f;
	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, &Observed, 1, N/2);

	// Perform a real-to-complex FFT.
	vDSP_fft_zrip(Setup, &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_zrip 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*Stride] = 0;
	vDSP_ctoz((DSPComplex *) Signal, 2*Stride, &Observed, 1, N/2);

	// Time vDSP_fft_zrip by itself.

	t0 = Clock();

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

	t1 = Clock();

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

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

	// Time vDSP_fft_zrip with the vDSP_ctoz and vDSP_ztoc transformations.

	t0 = Clock();

	for (i = 0; i < Iterations; ++i)
	{
		vDSP_ctoz((DSPComplex *) Signal, 2*Stride, &Observed, 1, N/2);
		vDSP_fft_zrip(Setup, &Observed, 1, Log2N, FFT_FORWARD);
		vDSP_ztoc(&Observed, 1, (DSPComplex *) Signal, 2*Stride, N/2);
	}

	t1 = Clock();

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

	printf(
"\tvDSP_fft_zrip with vDSP_ctoz and vDSP_ztoc takes %g microseconds.\n",
		Time * 1e6);

	// Release resources.
	free(ObservedMemory);
	free(Signal);
}
Example #29
0
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];
                }
            }
        }
    }
}