# Input and output array for CMSIS DSP Real FFT Q15 functions

The first question:

in the documentations for CMSIS DSP real FFT functions, it is mentioned :

The FFT of a real N-point sequence has even symmetry in the frequency domain. The second half of the data equals the conjugate of the first half flipped in frequency. Looking at the data, we see that we can uniquely represent the FFT using only N/2 complex numbers. These are packed into the output array in alternating real and imaginary components:

X = { real[0], imag[0], real[1], imag[1], real[2], imag[2] ... real[(N/2)-1], imag[(N/2)-1 }


so an array of N samples, gives N parts (N/2 real parts and N/2 imaginary parts).

but in the description of arm_rfft_q15 function it is written :

If the input buffer is of length N, the output buffer must have length 2*N. The input buffer is modified by this function.

why is that ?

The second question:

the description of arm_rfft_q15 indicates that the input values should be in 1.15 fixed point values:

I understand the simple fixed point arithmetics, but how I'm supposed to convert my real int8_t values to 1.15 format? and what to do with the ouput type (let's say 256 points FFT which outputs values in the 8.8 fixed point format)? I guess some scaling should be done but I don't understand the upscale thing.

• You have "real int8_t values"? That doesn't make any sense. Commented May 4, 2020 at 22:21

why is that ?

It is possible that I am misunderstanding, but I think only the first N/2 complex samples are used. The other half may be used for scratch space, since it looks like it reuses part of the general FFT, which (looking at the documentation) is computed in place using a 2*N length buffer. I agree, the documentation could be more clear.

I understand the simple fixed point arithmetics, but how I'm supposed to convert my real int8_t values to 1.15 format?

Q15 means that you have a signed numbers in the range -1 -> ((2^15)-1)/(2^15) (very close to +1) stored as signed 16 bit integers (presumably). Essentially, you mentally divide each integer value by 2^15. Your int8_t values are -128 .. 127, or Q7.0. If you put cast them to int16_t (put them in the least significant byte of each Q15 sample), you can factor out that 128, and just call it a Q15 value.

and what to do with the ouput type (let's say 256 points FFT which outputs values in the 8.8 fixed point format)? I guess some scaling should be done but I don't understand the upscale thing.

Fixed point numbers have the problem that dynamic range is limited, so if the values get large, they become inaccurate. What that chart is telling you is that they have rescaled each number into a new format to maintain accuracy. So you will get an 8.8 number (value divided by 256 instead of 32768). To get the true value, divide by 128 (shift by 7), ideally using 32 bit value so you don't lose precision.

• for the Q7.0 to Q15, do I have to retain the sign bit? and put the remaining 7 bits into LSByte the way you said ? Commented May 5, 2020 at 5:12
• @Tirdad Sadri Nejad Sorry, that should have read "cast". The system should handle sign extending for you when you convert a signed number from 8 to 16 bit. Commented May 5, 2020 at 5:49