CMSIS DSP fixed point FFT wrong output

I'm trying to use the fixed point FFT transforms in the CMSIS DSP library. My target is the STM32L476, and I'm using STM32Cube_FW_L4_V1.7.0 - which includes CMSIS DSP lib 1.4.7 .

I simulated a single real valued tone at a precise frequency bin in the time domain, and then performed the transforms.

Using the floating point arm_rfft_fast_f32(), I get the result as expected - the correct amplitude in the correct output bin.

However, when using arm_rfft_q31(), or arm_rfft_q15() - I don't even get a peak in the correct frequency bin!

 

Here is the output from arm_rfft_q15():

[16381,0,-1,0,709,-1983,2222,4415,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-5119,-2577,2186,-784,-1,0]

Here is the output from arm_rfft_q31():

[536870944,0,-15,-19,23240802,-64953733,72831748,144691785,51,-2,8,-15,-15,22,29,-4,-28,-43,-45,-9,-2,-36,71,50,48,54,20,-12,6,-12,-13,-18,-31,-22,-11,-3,-33,4,-8,-47,-26,-25,13,-12,4,-85,9,20,7,14,-43,5,-89,39,-36,51,-30,-9,-33,0,9,7,25,3,-13,-5,-33,8,-36,-7,35,-6,21,-1,-10,-31,-92,-1,0,8,91,-5,1,-7,68,-26,45,79,-50,68,-2,-17,1,-27,-9,-18,-15,-9,34,-11,8,-33,-3,-84,93,-49,47,56,12,-52,-18,5,-28,61,-1,13,18,-13,-12,5,-9,40,-167738039,-84432181,71665411,-25642316,53,16]

Here is the output from arm_rfft_f32():

[64,3.81469727e-006,-1.30165176e-008,2.78808875e-006,-2.63608308e-006,-1.43498551e-006,-2.20025822e-006,1.55988891e-006,-3.17734111e-006,2.28971089e-006,-4.13359703e-006,-3.99351165e-006,3.3615288e-006,-6.35730567e-006,-1.83613133e-006,1.4832101e-006,8.42540203e-007,-8.34117913e-008,1.19015112e-007,-3.54151325e-007,-4.52007998e-006,-1.87770434e-006,1.33076787e-006,-4.27001032e-006,3.85652584e-006,-6.87715158e-007,-7.24427537e-007,3.24526695e-007,2.41454723e-006,-1.10006795e-006,-4.33748028e-007,-2.1075698e-006,-2.86102295e-006,-32,2.47405137e-006,-5.26619988e-006,4.35172797e-006,1.06991661e-006,-1.56049498e-006,-4.68452345e-006,8.2863553e-006,-8.3584564e-006,1.36473163e-005,6.01639476e-006,1.50150754e-008,1.29226264e-005,-6.07512538e-006,4.92575919e-006,-2.85533275e-007,4.21643904e-007,2.05122728e-006,-5.45398507e-007,-5.33170237e-007,2.84525072e-007,1.11498127e-006,3.02459739e-006,-2.57460715e-006,1.09262567e-006,-2.07302446e-006,6.56729242e-007,1.46118708e-008,-1.71687179e-006,2.87481407e-006,3.05214257e-007,3.81469727e-006,5.7220459e-006,-1.86521504e-006,2.85848864e-006,-4.34889489e-006,-1.13131955e-006,-4.21444702e-006,2.13638464e-006,2.42501983e-006,-3.95507141e-006,-4.21646382e-006,9.35715434e-008,1.05906965e-005,-2.36277538e-006,-9.27502515e-006,6.53561801e-006,7.62370405e-007,4.21643904e-007,2.22225162e-006,2.78844391e-006,-8.44451733e-006,2.69385669e-006,-2.64457799e-006,-3.37315555e-006,2.35364951e-006,-1.96206065e-006,-3.07793698e-006,-4.43971885e-007,2.61880075e-007,-2.0395504e-007,-8.26422877e-007,1.10286078e-006,-6.67572021e-006,-1.90734863e-006,2.08137703e-006,-8.47662977e-006,2.19906019e-006,1.73804125e-007,-3.91400454e-006,-3.91602498e-006,6.78347851e-006,-7.08411062e-006,9.67197047e-006,5.11953931e-006,-3.90942205e-006,8.35106584e-006,-3.97188887e-006,1.78316373e-006,-3.65703016e-007,-8.34117913e-008,-5.38766744e-006,-5.59780528e-006,6.69599831e-006,-3.71000579e-006,1.03211437e-006,-1.06248524e-006,3.02775379e-006,7.33740762e-006,-4.08721326e-006,8.02330362e-008,-1.69819941e-006,-2.02053729e-006,1.02261538e-006,2.34814749e-007]

 

Below is the code I used:

arm_rfft_fast_init_f32(&sRfftMathObj128_f32, 128);
arm_rfft_init_q15(&sRfftMathObj128_q15, 128, 0, 0);
arm_rfft_init_q15(&sRifftMathObj128_q15, 128, 1, 0);
arm_rfft_init_q31(&sRfftMathObj128_q31, 128, 0, 0);
arm_rfft_init_q31(&sRifftMathObj128_q31, 128, 1, 0);

arm_fill_q15(0, t1_q15, 128);
arm_fill_q15(0, t2_q15, 128);
arm_fill_q31(0, t1_q31, 128);
arm_fill_q31(0, t2_q31, 128);
arm_fill_f32(0, t1_f32, 128);

for (int i = 0; i < 128; i++)
{
    in_f32[i] = sinf(M_TWOPI * ((16.0f/128.0f)*400e3) * i / 400e3)/2.0f + 0.5f;
    in_q15[i] = (int16_t)((sinf(M_TWOPI * ((16.0f/128.0f)*400e3) * i / 400e3)/2.0f + 0.5f) * ((1L<<15)-1));
    in_q15_cmplx[2*i] = (int16_t)((sinf(M_TWOPI * ((16.0f/128.0f)*400e3) * i / 400e3)/2.0f + 0.5f) * ((1L<<15)-1));
    in_q15_cmplx[2*i+1] = 0;
    in_q31[i] = (int32_t)((sinf(M_TWOPI * ((16.0f/128.0f)*400e3) * i / 400e3)/2.0f + 0.5f) * ((1LL<<30)-1));
}

arm_rfft_fast_f32(&sRfftMathObj128_f32, in_f32, t1_f32, 0);
arm_rfft_q15(&sRfftMathObj128_q15, in_q15, t1_q15);
arm_rfft_q31(&sRfftMathObj128_q31, in_q31, t1_q31);
arm_cfft_q15(&arm_cfft_sR_q15_len128, in_q15_cmplx, 0, 0);

  • Hi faisalshah!

    I'm having a similar problem. With floating function everything works fine. But, when I'm using arm_rfft_q15(), the result seems weird.

    Below is the code I used:

    int16_t vibdata[8192], fftvibout[8192];
    arm_rfft_instance_q15   RealFFT_Instance;
     
    //Create a signal array with two frequencies (75 e 150)
    for (int n=0; n<8192; n++)
          {
                vibdata[n]=(int16_t)(16384*sin(2*75*PI*n/8191)+8192*sin(2*150*PI*n/8191));
          }
    //Calculates FFT
    arm_rfft_init_q15(&RealFFT_Instance,8192,0,1);
    arm_rfft_q15(&RealFFT_Instance,(q15_t *)vibdata,(q15_t *)fftvibout);
    arm_cmplx_mag_q15((q15_t *)fftvibout,(q15_t *)vibdata,4096);

    Below, you could see the result. As was expected, there are two frequencies (75 and 150). But, besides that, two frequencies (3946 and 4021) appears in the end of the spectrum.

    Did you solve your problem? Could you share with me?

    Regards,

    Lucas