но эти значения получаются после цикла со сдвигом,
for( i = 0; i < N_FFT; i++ )
{
out_cfft.re = out_cfft.re << 6; /* log2(N_FFT) = 6 */
out_cfft.im = out_cfft.im << 6;
}
а до этого цикла(сдвига), т.е. сразу после прямого преобразования в массиве out_cfft[0].re = 0x100 все остальное нули, в out_cfft.im все нули
БПФ
Re: БПФ
Я провел эксперимент: при значениях входного сигнала ( массив in[] ) <= 0x100 (т.е. половине разрядной сетки - 256) для 16-разрядных значений с фиксированной точкой, надо делать масштабирование (сдвигать влево, т.е. умножать значения в частотной области на log2(N_FFT) = 6 - массив out_cfft[] после прямого преобразования). Если все значения входного сигнала > 0x100, то масштабирование надо делать после обратного преобразования ( тоже сдвигать влево, но уже во временной области на log2(N_FFT) = 6 - массив out_ifft[] ). Только так получается такая же амплитуда сигнала.
Потом я провел такой же эксперимент с гармоникой. При амплитудах входного сигнала <= 0x400 (1024), надо делать масштабирование спектра - после прямого преобразования, если значения > 0x400, то после обратного преобразования.
/*****************************************************************************
* NewProject.c
*****************************************************************************/
/* Compute IFFT( CFFT( X ) ) = X */
#include <filter.h>
#include <math.h>
#include <fract.h>
#include <fract2float_conv.h>
#include <fract_typedef.h>
#include <math_const.h>
#define N_FFT 64
complex_fract16 in[N_FFT];
complex_fract16 out_cfft[N_FFT];
complex_fract16 out_ifft[N_FFT];
complex_fract16 twiddle[N_FFT/2];
int blk_exp;
void main(void)
{
int i;
float x;
/* Generate AC signal */
/* Generate DC signal
for( i = 0; i < N_FFT; i++ )
{
in.re = 0x200;
in.im = 0x0;
}
*/
/* Generate AC signal */
x = (float) (TWO_PI*750/48000);
for( i = 0; i < N_FFT; i++ )
{
in.re = (fract16) (sinf(i*x)*1024);
in.im = 0x0;
}
/* Populate twiddle table */
twidfftrad2_fr16(twiddle, N_FFT);
/* Compute Fast Fourier Transform */
cfft_fr16(in, out_cfft, twiddle, 1, N_FFT, &blk_exp, 0);
/* Reverse static scaling applied by cfft_fr16() function
Apply the shift operation before the call to the
ifft_fr16() function only if all the values in out_cfft
= 0x100. Otherwise, perform the shift operation after the
ifft_fr16() function has been computed.
*/
for( i = 0; i < N_FFT; i++ )
{
out_cfft.re = out_cfft.re << 6; // log2(N_FFT) = 6
out_cfft.im = out_cfft.im << 6;
}
/* обнулили старшую часть спектра
for( i = N_FFT/2; i < N_FFT; i++ ) {
out_cfft.re = 0x0;
out_cfft.im = 0x0;
}*/
// постоянная составляющая спектра - первый элемент массива out[0] не удваивается
/* удвоили младшую часть спектра начиная со второго элемента (out[1])
for( i = 1; i < N_FFT/2; i++ ) {
out_cfft[i] = cadd_fr16(out_cfft[i], out_cfft[i]);
}
*/
/* Compute Inverse Fast Fourier Transform
The output signal from the ifft function will be the same
as the DC signal of magnitude 0x100 which was passed into
the cfft function.
*/
ifft_fr16(out_cfft, out_ifft, twiddle, 1, N_FFT, &blk_exp, 0);
/*
for( i = 0; i < N_FFT; i++ )
{
out_ifft[i].re = out_ifft[i].re << 6; // log2(N_FFT) = 6
out_ifft[i].im = out_ifft[i].im << 6;
}
*/
}
Потом я провел такой же эксперимент с гармоникой. При амплитудах входного сигнала <= 0x400 (1024), надо делать масштабирование спектра - после прямого преобразования, если значения > 0x400, то после обратного преобразования.
/*****************************************************************************
* NewProject.c
*****************************************************************************/
/* Compute IFFT( CFFT( X ) ) = X */
#include <filter.h>
#include <math.h>
#include <fract.h>
#include <fract2float_conv.h>
#include <fract_typedef.h>
#include <math_const.h>
#define N_FFT 64
complex_fract16 in[N_FFT];
complex_fract16 out_cfft[N_FFT];
complex_fract16 out_ifft[N_FFT];
complex_fract16 twiddle[N_FFT/2];
int blk_exp;
void main(void)
{
int i;
float x;
/* Generate AC signal */
/* Generate DC signal
for( i = 0; i < N_FFT; i++ )
{
in.re = 0x200;
in.im = 0x0;
}
*/
/* Generate AC signal */
x = (float) (TWO_PI*750/48000);
for( i = 0; i < N_FFT; i++ )
{
in.re = (fract16) (sinf(i*x)*1024);
in.im = 0x0;
}
/* Populate twiddle table */
twidfftrad2_fr16(twiddle, N_FFT);
/* Compute Fast Fourier Transform */
cfft_fr16(in, out_cfft, twiddle, 1, N_FFT, &blk_exp, 0);
/* Reverse static scaling applied by cfft_fr16() function
Apply the shift operation before the call to the
ifft_fr16() function only if all the values in out_cfft
= 0x100. Otherwise, perform the shift operation after the
ifft_fr16() function has been computed.
*/
for( i = 0; i < N_FFT; i++ )
{
out_cfft.re = out_cfft.re << 6; // log2(N_FFT) = 6
out_cfft.im = out_cfft.im << 6;
}
/* обнулили старшую часть спектра
for( i = N_FFT/2; i < N_FFT; i++ ) {
out_cfft.re = 0x0;
out_cfft.im = 0x0;
}*/
// постоянная составляющая спектра - первый элемент массива out[0] не удваивается
/* удвоили младшую часть спектра начиная со второго элемента (out[1])
for( i = 1; i < N_FFT/2; i++ ) {
out_cfft[i] = cadd_fr16(out_cfft[i], out_cfft[i]);
}
*/
/* Compute Inverse Fast Fourier Transform
The output signal from the ifft function will be the same
as the DC signal of magnitude 0x100 which was passed into
the cfft function.
*/
ifft_fr16(out_cfft, out_ifft, twiddle, 1, N_FFT, &blk_exp, 0);
/*
for( i = 0; i < N_FFT; i++ )
{
out_ifft[i].re = out_ifft[i].re << 6; // log2(N_FFT) = 6
out_ifft[i].im = out_ifft[i].im << 6;
}
*/
}
- Бахурин Сергей
- Администратор
- Сообщения: 1116
- Зарегистрирован: 05 окт 2010, 19:55
- Контактная информация:
Re: БПФ
А после ifft что в массиве на выходе лежит?mbk писал(а):Да, все верно, в массиве out_cfft[0].re = 0x4000 все остальное нули, в out_cfft.im все нули.
Re: БПФ
в out_ifft[] лежит 0ч100
Re: БПФ
в out_ifft[].re все значения равны 0x100 как и на входе в in[].re
- Бахурин Сергей
- Администратор
- Сообщения: 1116
- Зарегистрирован: 05 окт 2010, 19:55
- Контактная информация:
Re: БПФ
ну значит все в порядке выход ifft равен входу fft