Does anybody know anything about the Mayer FFT implementation (without me having to take quite a bit of time to study the code)?
I am attempting to perform a convolution, and the ifft appears to produce what I would call a "mirrored" output. In other words, my kernel+signal length is limited to N/2 and whatever occupies n=0...N/2 is mirrored about n=N...N/2. It sort of looks like what I would expect from an FFT in terms of negative frequencies...except it's like a mirror in negative time.
Here is my convolution code:
void convolve(struct cxType* data, struct cxType* kernel, int size)
{
int i,j;
int wrksz = size;
float gain = 1.0f/((float) wrksz);
mayer_fft(wrksz, data->re, data->im);
mayer_fft(wrksz, kernel->re, kernel->im);
for(i=0;i<wrksz;i++)
{
data->re[i]*=kernel->re[i]*gain;
data->im[i]*=kernel->im[i]*gain;
}
mayer_ifft(wrksz, data->re, data->im);
}
Doing essentially the same thing using gnu Octave (MATLAB syntax equivalent for you who are unfamiliar) produces the expected results, including allowing me to occupy M+N-1 in the signal output:
fs=48000;
Ts = 1/fs;
NN = 1024
sincsz = floor(NN/4);
sigstart = floor(NN/16);
sigend = floor(NN/2);
dpi=2*pi;
%window func
tau=(1:sincsz)/sncsz;
window=0.5*(1.0 - cos(dpi*tau));
%plot(tau,window)
%sinc filter kernel
fc=5050;
wc=dpi*fc;
Ts=1/fs;
segTime=Ts*sincsz;
t0=-segTime/2;
t=Ts*((1:sincsz) - 1) + t0 ;
s=zeros(1,sincsz);
s=window.*sin(wc*t)./(wc*t);
s(sincsz/2+1) = 1;
%plot(t,s)
fund = 1650;
tt = (1:NN)*Ts;
signal = sin(dpi*tt*fund) + sin(dpi*tt*2*fund) + sin(dpi*tt*3*fund) + sin(dpi*tt*4*fund) + sin(dpi*tt*5*fund);
signal(1:sigstart) = signal(1:sigstart)*0;
signal(sigend:NN) = signal(sigend:NN)*0;
%plot(tt,signal)
h=zeros(1,NN);
h(1:sincsz) = s(1:sincsz);
H=fft(h);
X=fft(signal);
Y=H.*X;
y=ifft(Y);
plot(real(y))
The equivalent signal and FIR kernel synthesis are implemented in C (not shown). I am using gnuplot to display the results of the C implementation of this, so I know the filter kernel and the signal are implemented identically to what I did with Octave.
The only difference in what is being done as far as I can tell is the FFT implementation. Does somebody know if these results are a fundamental problem with my understanding of the FFT algorithm in general, or with the FHT-based implementation from this archaic code written by Ron Mayer? You can go to his archived web site to get the code I am using: http://reocities.com/researchtriangle/8869/fft_summary.html
Now, if I perform an FFT on a block of data and then perform the ifft, I get back the original data as I would expect. If I modify the data spectrally in any way, I get results that I don't expect.
I once tried to use this mayer FFT algorithm to replace that used in S. Bernsee's pitch shift algorithm, and this did not work at all. I used fftw3, and that code worked as I expected. I am curious to try this same basic algorithm with fftw3 to see what happens.
What I don't know is if I misunderstand something fundamental which is causing me to mis-apply rmayer's implementation, or if this is just a simple artifact I have to work around (that is, using an FFT size double of what I expect).