Estoy muestreando una señal de rango de audio con un ancho de banda de 3100Hz y luego aplico una FFT utilizando el ejemplo de la biblioteca DSP de Microchip para determinar la frecuencia más dominante de la señal.
En el último paso en el que se supone que debo recuperar la frecuencia con la energía más alta, todo lo que obtengo son ceros.
El primer paso, que consiste en muestrear la señal analógica, está funcionando bien, ya que he exportado los valores de matriz a Excel y graficado el gráfico.
El código es el siguiente:
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();
}
}
Variables externas
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};
ACTUALIZACIÓN:
Ahora estoy obteniendo un valor, 16640 Hz para la frecuencia dominante.
Cuando exporto los datos generados a dsPICWorks, obtengo esto:
Parece que la función está devolviendo el valor correcto pero la FFT no está funcionando correctamente, ya que debería obtener otra cosa, ¿no?