Help converting raw ADC data to Q31 and using CMSIS-DSP arm_fir_q31?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Help converting raw ADC data to Q31 and using CMSIS-DSP arm_fir_q31?

Jump to solution
3,479 Views
aaroncramer
Contributor I

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)

scope_6.bmp

ok output signal with arm_fir_q31 disabled.  (Yellow=input, Green=output)

scope_5.bmp

Here are the details of my system:

  • Kinetis K70 MCU in tower system
  • Custom tower module with TI TLV320AIC3007 CODEC, configured as I2S slave, 48kHz sample rate, 24bit samples packed in 32 bit words
  • I2S communication between Codec and K70.
  • DMA handles data transfer in "ping-pong" buffering scheme.  512 samples per block, stereo audio data.

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:

  1. Is my method correct for converting the raw ADC samples received from the codec to Q31 format? (lines 08 - 17)
  2. Is my method correct for converting from Q31 format back to a 24 bit unsigned value? (lines 26 - 35)
  3. Do you see where I am going wrong?

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

1 Solution
1,913 Views
nehalpatel
Contributor II

"if(RxDMABuffer[i][bufIndx].samples[j] & 0x0080000){ //bit 23 is set"

Are you checking 20th bit instead of 24th bit!

View solution in original post

5 Replies
1,913 Views
nehalpatel
Contributor II

Here's how I converted my "uint16" to "int32" format

adc_RX_int32 = (int32_t) (adc_Rx_uint16)-0x00008000;

0 Kudos
1,913 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,Aaron,

how about just left shifting 8 bit to convert from 24 bits fractional value to Q31 fraction value:

for example:

  1.     for(i=0;i<AUDIO_NUM_CHANNELS;i++)
  2. //loop through channels 
  3.         for(j=0;j<AUDIO_SAMPLES_PER_BLOCK;j++)
  4.              { //loop through samples 
  5.                            q31RxDMABuffer[i][bufIndx].samples[j] = RxDMABuffer[i][bufIndx].samples[j]<<8;
  6.              }
  7. }
  8. BR
  9. XiangJun Rong
1,914 Views
nehalpatel
Contributor II

"if(RxDMABuffer[i][bufIndx].samples[j] & 0x0080000){ //bit 23 is set"

Are you checking 20th bit instead of 24th bit!

1,913 Views
aaroncramer
Contributor I

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.

1,913 Views
nehalpatel
Contributor II

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.

0 Kudos