DSPRelated.com
Forums

Accuracy of FFT/iFFT on the C55x?

Started by alec...@gmail.com May 13, 2007
Hello all,

I'm trying to implement a frequency-domain filter on the TI C55x and
encountered some problems with accuracy.  My code takes the FFT of the
input and the coefficients, multiply them, and applies iFFT to get the
time-domain output back.  However, when I tested the algorithm with
random data, the error (compared to Matlab convolution) is not
centered at zero for the last few samples of every run.  (see the plot
here: http://picasaweb.google.com/alecwei/UntitledAlbum/photo#5063913366565937794)
I've check the FFT and complex multiplication routines and they seemed
to work fine, and the deviation appears to occur at the iFFT following
multiplication.  Can someone please comment on what might be causing
the problem (probably scaling)?  Thanks in advance.

My code looks like this:

        form_x();
	cfft(x1, NX, SCALE);
	cbrev(x1, x1, NX);
	cfft(x2, NX, SCALE);
	cbrev(x2, x2, NX);
	complex_multiply();

	asm("\tBSET SATD");
	cifft(x1, NX, NOSCALE);
	asm("\tBCLR SATD");
	cbrev(x1, x1, NX);
	asm("\tBSET SATD");
	cifft(x2, NX, NOSCALE);
	asm("\tBCLR SATD");
	cbrev(x2, x2, NX);
	form_y();

alecwei@gmail.com wrote:
> Hello all, > > I'm trying to implement a frequency-domain filter on the TI C55x and > encountered some problems with accuracy. My code takes the FFT of the > input and the coefficients, multiply them, and applies iFFT to get the > time-domain output back. However, when I tested the algorithm with > random data, the error (compared to Matlab convolution) is not > centered at zero for the last few samples of every run. (see the plot > here: http://picasaweb.google.com/alecwei/UntitledAlbum/photo#5063913366565937794) > I've check the FFT and complex multiplication routines and they seemed > to work fine, and the deviation appears to occur at the iFFT following > multiplication. Can someone please comment on what might be causing > the problem (probably scaling)? Thanks in advance. > > My code looks like this: > > form_x(); > cfft(x1, NX, SCALE); > cbrev(x1, x1, NX); > cfft(x2, NX, SCALE); > cbrev(x2, x2, NX); > complex_multiply(); > > asm("\tBSET SATD"); > cifft(x1, NX, NOSCALE); > asm("\tBCLR SATD"); > cbrev(x1, x1, NX); > asm("\tBSET SATD"); > cifft(x2, NX, NOSCALE); > asm("\tBCLR SATD"); > cbrev(x2, x2, NX); > form_y();
The mask coefficients that you use to alter the frequency distribution imply an impulse response. If that impulse response is longer than IFFT you use, distortions are inevitable. If you repeat the process on successive blocks, those blocks need to be properly stitched together. FFT -- multiply -- IFFT achieves circular convolution, not linear convolution. To simulate linear convolution, you need to pad with enough zeros to keep the snake's tail out of its mouth, then discard the wrapped beginning and end of the result. Jerry -- Engineering is the art of making what you want from things you can get. ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Jerry,

Thanks for the reply.  My code does integrate the overlap-save method
to extract linear convolution results from circular convolution.  It's
hidden in the form_x() and form_y() routines.  I verified simple loop-
back using just a cfft followed by cifft and it worked - the error was
centered at 0 and on the order of 16-bit precision.  The
complex_multiply() routine was also verified independently, but
somehow things just won't work together.

Right now I'm replacing the complex FFT routines with their real
counters parts rfft and rifft, which are able to remove the periodic
peaks but the error is larger because of a scaling by 4 issue.  This
is part of a real-time code for audio processing, could this be an
issue with the the dsp library and DSP/BIOS?

On May 15, 10:28 am, Jerry Avins <j...@ieee.org> wrote:
> alec...@gmail.com wrote: > > Hello all, > > > I'm trying to implement a frequency-domain filter on the TI C55x and > > encountered some problems with accuracy. My code takes the FFT of the > > input and the coefficients, multiply them, and applies iFFT to get the > > time-domain output back. However, when I tested the algorithm with > > random data, the error (compared to Matlab convolution) is not > > centered at zero for the last few samples of every run. (see the plot > > here:http://picasaweb.google.com/alecwei/UntitledAlbum/photo#5063913366=
565...)
> > I've check the FFT and complex multiplication routines and they seemed > > to work fine, and the deviation appears to occur at the iFFT following > > multiplication. Can someone please comment on what might be causing > > the problem (probably scaling)? Thanks in advance. > > > My code looks like this: > > > form_x(); > > cfft(x1, NX, SCALE); > > cbrev(x1, x1, NX); > > cfft(x2, NX, SCALE); > > cbrev(x2, x2, NX); > > complex_multiply(); > > > asm("\tBSET SATD"); > > cifft(x1, NX, NOSCALE); > > asm("\tBCLR SATD"); > > cbrev(x1, x1, NX); > > asm("\tBSET SATD"); > > cifft(x2, NX, NOSCALE); > > asm("\tBCLR SATD"); > > cbrev(x2, x2, NX); > > form_y(); > > The mask coefficients that you use to alter the frequency distribution > imply an impulse response. If that impulse response is longer than IFFT > you use, distortions are inevitable. If you repeat the process on > successive blocks, those blocks need to be properly stitched together. > > FFT -- multiply -- IFFT achieves circular convolution, not linear > convolution. To simulate linear convolution, you need to pad with enough > zeros to keep the snake's tail out of its mouth, then discard the > wrapped beginning and end of the result. > > Jerry > -- > Engineering is the art of making what you want from things you can get. > =AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=
=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF= =AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF
Problem solved.  There was an issue with setting/resetting the status
register bits on return from the complex multiply routine.  I forgot
to clear the FRCT and SATD bits which apparently caused problems in
the real-time code.

On May 15, 3:06 pm, "alec...@gmail.com" <alec...@gmail.com> wrote:
> Jerry, > > Thanks for the reply. My code does integrate the overlap-save method > to extract linear convolution results from circular convolution. It's > hidden in the form_x() and form_y() routines. I verified simple loop- > back using just a cfft followed by cifft and it worked - the error was > centered at 0 and on the order of 16-bit precision. The > complex_multiply() routine was also verified independently, but > somehow things just won't work together. > > Right now I'm replacing the complex FFT routines with their real > counters parts rfft and rifft, which are able to remove the periodic > peaks but the error is larger because of a scaling by 4 issue. This > is part of a real-time code for audio processing, could this be an > issue with the the dsp library and DSP/BIOS? > > On May 15, 10:28 am, Jerry Avins <j...@ieee.org> wrote: > > > alec...@gmail.com wrote: > > > Hello all, > > > > I'm trying to implement a frequency-domain filter on the TI C55x and > > > encountered some problems with accuracy. My code takes the FFT of the > > > input and the coefficients, multiply them, and applies iFFT to get the > > > time-domain output back. However, when I tested the algorithm with > > > random data, the error (compared to Matlab convolution) is not > > > centered at zero for the last few samples of every run. (see the plot > > > here:http://picasaweb.google.com/alecwei/UntitledAlbum/photo#50639133=
66565...)
> > > I've check the FFT and complex multiplication routines and they seemed > > > to work fine, and the deviation appears to occur at the iFFT following > > > multiplication. Can someone please comment on what might be causing > > > the problem (probably scaling)? Thanks in advance. > > > > My code looks like this: > > > > form_x(); > > > cfft(x1, NX, SCALE); > > > cbrev(x1, x1, NX); > > > cfft(x2, NX, SCALE); > > > cbrev(x2, x2, NX); > > > complex_multiply(); > > > > asm("\tBSET SATD"); > > > cifft(x1, NX, NOSCALE); > > > asm("\tBCLR SATD"); > > > cbrev(x1, x1, NX); > > > asm("\tBSET SATD"); > > > cifft(x2, NX, NOSCALE); > > > asm("\tBCLR SATD"); > > > cbrev(x2, x2, NX); > > > form_y(); > > > The mask coefficients that you use to alter the frequency distribution > > imply an impulse response. If that impulse response is longer than IFFT > > you use, distortions are inevitable. If you repeat the process on > > successive blocks, those blocks need to be properly stitched together. > > > FFT -- multiply -- IFFT achieves circular convolution, not linear > > convolution. To simulate linear convolution, you need to pad with enough > > zeros to keep the snake's tail out of its mouth, then discard the > > wrapped beginning and end of the result. > > > Jerry > > -- > > Engineering is the art of making what you want from things you can get. > > =AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=
=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF= =AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF=AF
alecwei@gmail.com wrote:
> Problem solved. There was an issue with setting/resetting the status > register bits on return from the complex multiply routine. I forgot > to clear the FRCT and SATD bits which apparently caused problems in > the real-time code.
Thanks for the update. Please accept my apologies for having misinterpreted what you wrote and thereby underestimating the level of your understanding. Jerry -- Engineering is the art of making what you want from things you can get. &macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;