Hello Kinetis users,
I am fairly new to Kinetis and brand new to CMSIS-DSP. I am trying to use the CMSIS-DSP arm_fir_q31 library function to filter an audio signal. When I try to use the arm_fir_q31 function I get an output signal with a lot of noise as shown below. When I remove the arm_fir_q31 function and just do a pass through, the signal looks ok. It also looks ok when I use the arm_negate_q31 function and I do see the negation.
Noisy output with arm_fir_q31 enabled. (Yellow=input, Green=output)
ok output signal with arm_fir_q31 disabled. (Yellow=input, Green=output)
Here are the details of my system:
The things I am unsure about are the conversion from raw ADC samples received over I2S (24 bit unsigned ADC value packed in 32 bit unsigned int) to Q31 format and the conversion back from Q31 to unsigned 24 bit value packed in 32 bit unsigned int after processing through arm_fir_q31 function.
My questions are:
Function called when I2S Rx buffer is filled. It converts raw samples to Q31, calls arm_fir_q31 function to process data block, converts back to 24 bit unsigned samples, and loads in I2S Tx buffer.
void vfnAudioBufferHandler_DMARxCallback (void){
static u8 bufIndx = 0;
u16 i,j;
GPIOA_PSOR |= 0x8000; //debug bit, PTA15 Set
//convert to Q31 format
for(i=0;i<AUDIO_NUM_CHANNELS;i++){ //loop through channels
for(j=0;j<AUDIO_SAMPLES_PER_BLOCK;j++){ //loop through samples
if(RxDMABuffer[i][bufIndx].samples[j] & 0x0080000){ //bit 23 is set
q31RxDMABuffer[i][bufIndx].samples[j] = RxDMABuffer[i][bufIndx].samples[j] & ~0xFF800000; //invert bit 23, sign extend zeros
}
else{ //bit 23 is clear
q31RxDMABuffer[i][bufIndx].samples[j] = RxDMABuffer[i][bufIndx].samples[j] | 0xFF800000; //invert bit 23, sign extend ones
}
}
}
for(i=0;i<AUDIO_NUM_CHANNELS;i++){
// arm_negate_q31(&q31RxDMABuffer[i][bufIndx].samples[0], &q31TxDMABuffer[i][bufIndx].samples[0],AUDIO_SAMPLES_PER_BLOCK);
arm_fir_q31(&S, &q31RxDMABuffer[i][bufIndx].samples[0], &q31TxDMABuffer[i][bufIndx].samples[0], AUDIO_SAMPLES_PER_BLOCK);
}
for(i=0;i<AUDIO_NUM_CHANNELS;i++){ //loop through channels
for(j=0;j<AUDIO_SAMPLES_PER_BLOCK;j++){ //loop through samples
if(q31TxDMABuffer[i][bufIndx].samples[j] & 0x8000000){ //bit 31 is set
TxDMABuffer[i][bufIndx].samples[j] = q31TxDMABuffer[i][bufIndx].samples[j] & ~0xFF800000; //stuff sign bit in bit 23
}
else{ //bit 31 is clear
TxDMABuffer[i][bufIndx].samples[j] = q31TxDMABuffer[i][bufIndx].samples[j] | 0xFF800000; //stuff sign bit in bit 23
}
}
}
bufIndx ^=1; //toggle buffer index for ping-pong buffering
GPIOA_PCOR |= 0x8000; //debug bit, PTA15 Clear
}
My code for converting fir filter coefficients from float to Q31 and initialization of fir filter:
NUM_TAPS = 10, AUDIO_SAMPLES_PER_BLOCK = 512
//convert FIR filter coefficients to Q31
arm_float_to_q31(&firCoeffF32[0], &firCoeffq31[0],NUM_TAPS);
//initialize fir filter instance
arm_fir_init_q31(&S, NUM_TAPS, &firCoeffq31[0], &firStateq31[0], AUDIO_SAMPLES_PER_BLOCK);
My fir filter coefficients (generated in MATLAB):
float32_t firCoeffF32[NUM_TAPS] = {
-0.0021610938, -0.0168824365, -0.0076310975, 0.1506507546, 0.3760238733,
0.3760238733, 0.1506507546, -0.0076310975, -0.0168824365, -0.0021610938
};
Thanks for any help!
Aaron
Solved! Go to Solution.
"if(RxDMABuffer[i][bufIndx].samples[j] & 0x0080000){ //bit 23 is set"
Are you checking 20th bit instead of 24th bit!
Here's how I converted my "uint16" to "int32" format
adc_RX_int32 = (int32_t) (adc_Rx_uint16)-0x00008000;
Hi,Aaron,
how about just left shifting 8 bit to convert from 24 bits fractional value to Q31 fraction value:
for example:
"if(RxDMABuffer[i][bufIndx].samples[j] & 0x0080000){ //bit 23 is set"
Are you checking 20th bit instead of 24th bit!
Thanks for catching that error, Nehal. It turned out, in addition to this error, I also had my codec configured incorrectly. The bit alignment was off, causing the sign bit to be shifted by one. Thish caused the random seeming noise and roll over observed when I applied the fir filter. After correcting the error you found and correcting the codec configuration all is working. Thank you.
You are right, checking wrong bit can't cause the signal(noise) that you posted. Noise was coming from multiple sources. But, I am glad to point out one error, while I am also new for CMSIS.