AnsweredAssumed Answered

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

Question asked by Aaron Cramer on Jun 10, 2015
Latest reply on Jul 23, 2015 by Nehal Patel

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

Outcomes