Hi I tested arm_rfft_fast_f32 function from CMSIS-DSP 1.4.4 with generated 50hz sine wave at 1000Hz sample rate using 1024 samples, but i get peek value at 102, not 51 which i should get 1000/1024 ~0,97 * 51 = 50Hz:
uint16_t i;
float32_t khz10[1024];
float32_t maxvalue;
uint32_t maxindex;
//float32_t output2[1024];
arm_rfft_fast_instance_f32 S;
arm_rfft_fast_init_f32(&S, 1024);
printf("Input=[");
for(i=0; i<1024; i++){
khz10[i] = 1.2f*arm_sin_f32(2*3.1415926f*50*i/1000)+1;
printf("%f,",khz10[i]);
}
printf("]\r\n");
arm_rfft_fast_f32(&S, khz10,khz10,0);
arm_abs_f32(khz10, khz10, 1024);
arm_max_f32(khz10+1, 1023, &maxvalue, &maxindex);
printf("Max:[%ld]:%f Output=[",maxindex,maxvalue);
I later tested this function with real data from adc and I can only get 1/4 of frequency spectrum
not about 1/2 as I expected. Can anyone could me explain this ?
My previous reply is for your previous post containing the plot for the real and imaginary parts. I wonder why I didn't see your follow-up post and prior to my posting of this reply, it was your post that was shown as latest in the welcome page.
Hi, i find what was wrong. We can't just use the same buffer for input and output in function arm_rfft_fast_f32
I pondered if it is possible to use the same buffer in arm_rfft_fast_f32. My attention was diverted from it because the signal and the spur has an interesting relationship. The frequency bin of the spur, 460, is equal to 511 - 51. Fortunately, you decided to restore the output buffer and found the trouble.
There is still a minor problem with the output spectrum. Earlier I stated that the CMSIS-DSP real FFT functions pack the data for frequency bins 0 (DC) and N/2 (Nyquist frequency) at the beginning of the output array. So if the output array is passed to arm_cmplx_mag_f32 right after arm_rfft_fast_f32, the magnitude for DC will be erroneous and the Nyquist frequency will be missing in the spectrum. We can have it corrected in two ways.
First, we use a temporary variable to save the Nyquist frequency data, later the saved data will be reinserted to the output array.
float32_t output[1024];
float32_t saveNyquist; // Variable for saving the Nyquist frequency data
arm_rfft_fast_f32(&S, khz10,output,0);
// Take the absolute value of the Nyquist frequency data and save it to saveNyquist
arm_abs_f32(output+1, &saveNyquist, 1);
// Convert real DC data to complex number with imaginary part = 0,
// this 0 obliterates the Nyquist frequency data at index=1
// so it was saved in the preceding function call
output[1] = 0;
arm_cmplx_mag_f32(output,output, 512);
// Append the saved Nyquist frequency data
output[512] = saveNyquist;
// There are now 513 frequency bins because of the Nyquist frequency
// and it should be included in the search for the bin with maximum magnitude
arm_max_f32(output+1, 512, &maxvalue, &maxindex);
maxindex++;
printf("Max Value:[%ld]:%f Output=[",maxindex,maxvalue);
for(i=0; i<513; i++){
printf("%f,",output[i]);
Second, instead of using a temporary variable, we extend the length of the output array to hold one more complex number. The Nyquist frequency data will be copied into the extended location.
float32_t output[1026];
// Unpack the DC and Nyquist frequency data
//
// Copy the Nyquist frequency data to the end of the buffer
output[1024] = output[1];
// Convert the DC and Nyquist frequency data to complex numbers
// with imaginary parts = 0
output[1] = output[1025] = 0;
arm_cmplx_mag_f32(output,output, 513);
Note: The corrections are with respect to the latest code that you posted, the one which you described as correct version.