I have read about spectral leakages in other posts here. From what i understand, it occurs because you dont have an integer number of time periods in your sampled data. By default a rectangular window (=no window) is used and it corresponds to a sinc function in the frequency domain. If we have an integer number of time periods in our data the zeros of the sinc cancel out every other frequency component giving us the correct value. If however we dont have an integer number of time periods in our sample, that corresponds to a shifted sinc and this is convolved with the frequency spectrum of the original resulting in leakage. In essence there is always leakage but it is masked by carefully choosing the number of samples to be an integer number of time-periods.
I wrote a simple program in scilab to see if i can remove this leakage with windowing. f(x) = Asin(20*pi*X). Maximum frequency = 10, sampling rate Fs = 30. I use a sinc window. A finite sinc window leaks in the frequency domain. For n samples the FFT(sinc) = (m1, m2, m3,...mn), m2 to mn are mirrored about the center. I changed the FFT(sinc) to FFTnew = (-m1, m2/abs(m2)-m2,-m3,-m4,...,mn/abs(mn)-mn) so that abs(FFT + FFTnew) = (0,1,0,...,1). I now create a new window called modifiedSincWindow = sinc + InvFFT(FFTnew). (in scilab invFFT(FFT(f(x)) = f(x), no scaling issues). the abs(FFT(modifiedSincWindow)) has all 0s except for 2 1s as expected. This is obvious from the linearity property of the DFT.
a) NumSamples = 30. FFT(f(x) x modifiedSincWindow) gives me the correct amplitude A.
b) NumSamples = 31. FFT(f(x) x modifiedSincWindow) does not give me the correct amplitude A. it doesnt even look anything like in (a). why is this? if we are convolving the frequency spectrum of the signal with the spectrum of the modifiedSincWindow and since the component falls in some bin shouldnt we get the same result as in (a). the spectrum for the modifiedSincWindow is exactly 1 for a particular bin and zero for the rest. And convolving this with the spectrum of f(x) should get me the same result as (a) but it isnt. Can anyone help me understand what exactly is happening here? why is it not working as expected? thanks for your comments.
EDIT: Added scilab code below.
My question basically boils down to if we are getting leakage because of the convolution by the sinc function, why not multiply the signal with a window whose magnitude response is 1 for one bin and zero for the rest. This should give us the right amplitude value irrespective of whether the number of samples is an integer number of time periods or not. right?
maxFreq = 10;
T = 3*maxFreq;
numSamples = T; %%(b) numSamples = T+1
timeRes = 1/T;
%%sampling the sinc function
sincVals = zeros(numSamples);
for i = 1:1:numSamples
xval = (i - numSamples/2) * timeRes;
if(xval == 0) %%then
sincVals(i) = 1;
else
sincVals(i) = sinc(xval);
end
end
fftVals = fft(sincVals);
modifiedFFTArray = zeros(numSamples);
for i = 1:1:numSamples
modifiedFFTArray(i) = -fftVals(i);
end
modifiedFFTArray(2) = fftVals(2)/abs(fftVals(2)) - fftVals(2);
modifiedFFTArray(numSamples) = fftVals(numSamples)/abs(fftVals(numSamples)) - fftVals(numSamples);
invModified = ifft(modifiedFFTArray);
%%sincDiffs magnitude response is 0 for all bins except for 2 bins where it is 1
sincDiff = sincVals + (invModified);
signal = zeros(numSamples);
for i = 1:1:numSamples
xval = i * timeRes;
signal(i) = 1.5*cos(2*pi*maxFreq*xval) * (sincDiff(i));
end
binRes = T/numSamples;
%%disp(binRes)
binID = 1+floor(maxFreq/binRes); %%indexing is from 1 so add 1
%%disp(binID)
fftVals = fft(signal);
plot(abs(fftVals))