1
$\begingroup$

I am sampling an audio range signal with a bandwidth of 3100Hz and then applying a FFT using the DSP library example from Microchip to determine the most dominant frequency of the signal.

On the last step where I am supposed to get back the frequency with the highest energy, all I am getting are zeros.

The first step, which is sampling the analogue signal is working well as I have exported the array values into excel and plotted the graph.

The code is as follows:

void alarmFreq (void) //Detect the dominant frequency of the audio picked by the microphone
    {    
    int i = 0;
    fractional *p_real = &sigCmpx[0].real;
    fractcomplex *p_cmpx = &sigCmpx[0];
    readMic();
    for (ix_MicADCbuff=0;ix_MicADCbuff<FFT_BLOCK_LENGTH;ix_MicADCbuff++)
    {
        sigCmpx[ix_MicADCbuff].real = Float2Fract(micADCbuff[ix_MicADCbuff]);   // replace real part with ADC value
        sigCmpx[ix_MicADCbuff].imag = 0;                                        // set imaginary part with 0
    }
    /*for (ix_MicADCbuff=0;ix_MicADCbuff<FFT_BLOCK_LENGTH;ix_MicADCbuff++)
    {
        *p_real = micADCbuff[ix_MicADCbuff];   // replace real part with ADC value
        *p_real++;                                        
    }*/
    for ( i = 0; i < FFT_BLOCK_LENGTH; i++ )//The FFT function requires input data to be in the fractional fixed-point range [-0.5, +0.5]
        {                   
            *p_real = *p_real >>1 ;         //So, we shift all data samples by 1 bit to the right.
            *p_real++;                      //Should you desire to optimize this process, perform data scaling when first obtaining the time samples or within the BitReverseComplex function source code
        }                   
    p_real = &sigCmpx[(FFT_BLOCK_LENGTH/2)-1].real; //Set up pointers to convert real array to a complex array. The input array initially has all the real input samples followed by a series of zeros
    p_cmpx = &sigCmpx[FFT_BLOCK_LENGTH-1] ;                     
    for ( i = FFT_BLOCK_LENGTH; i > 0; i-- )        //Convert the Real input sample array to a Complex input sample array
        {                   
            (*p_cmpx).real = (*p_real--);   //We will simply zero out the imaginary part of each data sample
            (*p_cmpx--).imag = 0x0000;  
        }
    FFTComplexIP (LOG2_BLOCK_LENGTH, &sigCmpx[0], (fractcomplex *) __builtin_psvoffset(&twiddleFactors[0]), (int) __builtin_psvpage(&twiddleFactors[0]));// Perform FFT operation
    BitReverseComplex (LOG2_BLOCK_LENGTH, &sigCmpx[0]);// Store output samples in bit-reversed order of their addresses   
    SquareMagnitudeCplx(FFT_BLOCK_LENGTH, &sigCmpx[0], &sigCmpx[0].real);//Compute the square magnitude of the complex FFT output array so we have a Real output vector
    VectorMax(FFT_BLOCK_LENGTH/2, &sigCmpx[0].real, &peakFrequencyBin);//Find the frequency Bin ( = index into the SigCmpx[] array) that has the largest energy 
    peakFrequency = peakFrequencyBin*(AUDIO_FS/FFT_BLOCK_LENGTH); //Compute the frequency (in Hz) of the largest spectral component 
}

void readMic (void) //Sample microphone input
    {
    ADC1_ChannelSelectSet(ADC1_AI_MIC);
    ix_MicADCbuff=0;
    for(ix_MicADCbuff=0;ix_MicADCbuff<FFT_BLOCK_LENGTH;ix_MicADCbuff++)
        {
            //delay_ms(1);          //FS without waiting time 66790 Hz
            ADC1_SamplingStop();
            while(!ADC1_IsConversionComplete()){}
            micADCbuff[ix_MicADCbuff] = ADC1_Channel0ConversionResultGet();
        }
}

External variables

extern const fractcomplex twiddleFactors[FFT_BLOCK_LENGTH/2]    
__attribute__ ((space(auto_psv), aligned (FFT_BLOCK_LENGTH*2)));

fractcomplex sigCmpx[FFT_BLOCK_LENGTH] __attribute__ ((section (".ydata, data, ymemory"), 
    aligned (FFT_BLOCK_LENGTH * 2 *2))) ={0};

UPDATE:

I am now getting a value, 16640 Hz for dominant frequency.

When I export the data generated to dsPICWorks I get this:

enter image description here

Seems like the function is returning the correct value but the FFT is not working properly as I should get something else right?

UPDATE 2

So I got it working! It was a data type issue. What I did was to change the ADC output data type bits from decimal to fractional and I loaded the samples directly into the array that the FFT function uses. However, I am still having strange behaviours.

The frequency bins are 66790/512 = 130Hz

Sometimes, when I pass a signal which dominant frequency is not a multiple of 130Hz, I get as a result the dominant frequency multiplied times 3. So I have added a divide by 3 instruction in case the result is too high. Luckily I only have two expected frequencies which are 520Hz and 3100 Hz so I can truncate the results, however, I would like to know what the issue is here.

$\endgroup$
  • $\begingroup$ Hi! Can you upload the captured audio data of 3100 Hz bandwidth ? Also, what's the sampling rate and bit resolution of ADC? $\endgroup$ – Fat32 Oct 15 '18 at 0:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.