# FFT interpolation Matlab

Started by March 6, 2019
```Hi,
I am trying to use interpolation to detect an FFT peak between bins however my interpolation results in the same peak as the FFT.  I am inputting a 50Hz sine wave.. Sampling freq is 6500hz and I have 2048 sample points.  There fore my bin freq is 3.17hz which multipled out gives me a 50.8hz nearest bin frequency which is what my code is giving me.  I am trying to see where my interpolation code is going wrong and not giving me a peak at 50hz

//Code:

Fs =6500;            % Sampling frequency
Y=SINWAVTest;
T = 1/Fs;             % Sampling period
L = length(Y);             % Length of signal
t = (0:L-1)*T;        % Time vector
t2 = flipud(rot90(t));
y2 = Y; %+ 2*randn(size(t2));
y2 = y2;% - mean(y2);
y3 = fft((y2))
P2 = abs(y3/L);
P1 = P2(1:L/2+1);
P1(2:end-1) = 2*P1(2:end-1);
f = Fs*(0:(L/2))/L;
%%Interpolated
T_mean = (t(L)-t(1))/(L-1);
t_u = t(1):T_mean:t(L);
yy = interp1(t,Y,t_u,'spline');
y4 = fft(yy)
Psd_i=abs(fft(yy)).^2/(L*T_mean)
fr=[-ceil((L-1)/2):floor((L-1)/2)]/(L*T_mean);
Psd_a=abs(nedft(Y,t2,fr)).^2/(L*T_mean);
P1I = Psd_i(1:L/2+1);
P1I(2:end-1) = 2*P1I(2:end-1);
%Plot time-domain signal
subplot(4,1,1);
plot(t, Y);
ylabel('Amplitude'); xlabel('Time (secs)');
axis tight;
title('Shaker Input Signal');
subplot(4,1,2);
plot(1000*t(1:1000),y2(1:1000))
title('Signal Corrupted with Zero-Mean Random Noise')
xlabel('t (milliseconds)')
ylabel('X(t)')
subplot(4,1,3);
plot(f,P1)

title('Single-Sided Amplitude Spectrum of X(t)')
xlabel('f (Hz)')
ylabel('|P1(f)|')
%ylim([0,2000]);
subplot(4,1,4);
plot(f,P1I,'r')
title('Interpolated FFT')
xlabel('f (Hz)')
ylabel('|P1(f)|')
%ylim([0,2000]);

//Code
```
```Well... I apologize if I say something wrong, but I hope I do not.

So... first, to put the terms right, what you are doing is DFT (discrete
fourier transform), and FFT (fast fourier transform) is how you are
doing it.

Second, when you do a DFT of a peak that doesn't exactly coincide with
one of your DFT bins, you don't only get a single peak in that bin, but
also a number of smaller peaks in other bins. Which is the source of
your error. To reduce the number of bins containing any of the peaks,
you need to multiply your signal by the window function prior to the
DFT. That should massively reduce the error, and let you obtain much
more accurate results.

Third, there's a bunch of window functions to choose from. I suggest you
to start with something as simple as hamming window:
https://www.mathworks.com/help/signal/ref/hamming.html
After that you might try one of the more complicated windows such as
Chebushev or Kaiser which allow you to control the magnitude of
sidelobes, and see if it works better for you.

Fourth, at this point you might wonder, why does the lack of a window
function affect your results at all? Without a window function (or, to
put it in more precise terms, with a rectangular window function), you
get noticeable sidelobes across all your DFT bins, but that shouldn't,
in principle, affect the main peak, so you still should be able to get
the correct result. Well, the problem here is that your signal contains
not one complex sinusoid but two -- one at 50 Hz and the other at -50
Hz. With a rectangular window function the sidelobes from either peak
contaminate the other peak which results in a measurable error while
determining its position.

Fifth, I hope my input was helpful, but you would be much better off if
you read the first three chapters of "Understanding Digital Signal
Processing" by Richard Lyons, that is the major source of my insight on
the problem.

Hope that helps!

Gene.

On 07.03.2019 2:57, Michael R wrote:
> Hi,
> I am trying to use interpolation to detect an FFT peak between bins however my interpolation results in the same peak as the FFT.  I am inputting a 50Hz sine wave.. Sampling freq is 6500hz and I have 2048 sample points.  There fore my bin freq is 3.17hz which multipled out gives me a 50.8hz nearest bin frequency which is what my code is giving me.  I am trying to see where my interpolation code is going wrong and not giving me a peak at 50hz
> Thanks in advance!
>
> //Code:
>
> Fs =6500;            % Sampling frequency
> Y=SINWAVTest;
> T = 1/Fs;             % Sampling period
> L = length(Y);             % Length of signal
> t = (0:L-1)*T;        % Time vector
> t2 = flipud(rot90(t));
> y2 = Y; %+ 2*randn(size(t2));
> y2 = y2;% - mean(y2);
> y3 = fft((y2))
> P2 = abs(y3/L);
> P1 = P2(1:L/2+1);
> P1(2:end-1) = 2*P1(2:end-1);
> f = Fs*(0:(L/2))/L;
> %%Interpolated
> T_mean = (t(L)-t(1))/(L-1);
> t_u = t(1):T_mean:t(L);
> yy = interp1(t,Y,t_u,'spline');
> y4 = fft(yy)
> Psd_i=abs(fft(yy)).^2/(L*T_mean)
> fr=[-ceil((L-1)/2):floor((L-1)/2)]/(L*T_mean);
> Psd_a=abs(nedft(Y,t2,fr)).^2/(L*T_mean);
> P1I = Psd_i(1:L/2+1);
> P1I(2:end-1) = 2*P1I(2:end-1);
> %Plot time-domain signal
> subplot(4,1,1);
> plot(t, Y);
> ylabel('Amplitude'); xlabel('Time (secs)');
> axis tight;
> title('Shaker Input Signal');
> subplot(4,1,2);
> plot(1000*t(1:1000),y2(1:1000))
> title('Signal Corrupted with Zero-Mean Random Noise')
> xlabel('t (milliseconds)')
> ylabel('X(t)')
> subplot(4,1,3);
> plot(f,P1)
>
> title('Single-Sided Amplitude Spectrum of X(t)')
> xlabel('f (Hz)')
> ylabel('|P1(f)|')
> %ylim([0,2000]);
> subplot(4,1,4);
> plot(f,P1I,'r')
> title('Interpolated FFT')
> xlabel('f (Hz)')
> ylabel('|P1(f)|')
> %ylim([0,2000]);
>
> //Code
>

```
```Also, I haven't seen you doing any interpolation in the code, which is
why you might end up getting an integer multiple of a frequency bin as
the output.

In that regard, it's essential to note that interpolation is to be done
in the frequency domain, which could be achieved by either zero-padding
of the time-domain series, or any conventional interpolation algorithms
in the frequency domain (such as any kind of 3-point frequency
estimation algorithms, which have been discussed extensively in this
group in the past).

Best regards,
Gene.

On 07.03.2019 8:42, Gene Filatov wrote:
> Well... I apologize if I say something wrong, but I hope I do not.
>
> So... first, to put the terms right, what you are doing is DFT (discrete
> fourier transform), and FFT (fast fourier transform) is how you are
> doing it.
>
> Second, when you do a DFT of a peak that doesn't exactly coincide with
> one of your DFT bins, you don't only get a single peak in that bin, but
> also a number of smaller peaks in other bins. Which is the source of
> your error. To reduce the number of bins containing any of the peaks,
> you need to multiply your signal by the window function prior to the
> DFT. That should massively reduce the error, and let you obtain much
> more accurate results.
>
> Third, there's a bunch of window functions to choose from. I suggest you
> to start with something as simple as hamming window:
> https://www.mathworks.com/help/signal/ref/hamming.html
> After that you might try one of the more complicated windows such as
> Chebushev or Kaiser which allow you to control the magnitude of
> sidelobes, and see if it works better for you.
>
> Fourth, at this point you might wonder, why does the lack of a window
> function affect your results at all? Without a window function (or, to
> put it in more precise terms, with a rectangular window function), you
> get noticeable sidelobes across all your DFT bins, but that shouldn't,
> in principle, affect the main peak, so you still should be able to get
> the correct result. Well, the problem here is that your signal contains
> not one complex sinusoid but two -- one at 50 Hz and the other at -50
> Hz. With a rectangular window function the sidelobes from either peak
> contaminate the other peak which results in a measurable error while
> determining its position.
>
> Fifth, I hope my input was helpful, but you would be much better off if
> you read the first three chapters of "Understanding Digital Signal
> Processing" by Richard Lyons, that is the major source of my insight on
> the problem.
>
> Hope that helps!
>
> Gene.
>
>
> On 07.03.2019 2:57, Michael R wrote:
>> Hi,
>> I am trying to use interpolation to detect an FFT peak between bins
>> however my interpolation results in the same peak as the FFT.  I am
>> inputting a 50Hz sine wave.. Sampling freq is 6500hz and I have 2048
>> sample points.  There fore my bin freq is 3.17hz which multipled out
>> gives me a 50.8hz nearest bin frequency which is what my code is
>> giving me.  I am trying to see where my interpolation code is going
>> wrong and not giving me a peak at 50hz
>> Thanks in advance!
>>
>> //Code:
>>
>> Fs =6500;            % Sampling frequency
>> Y=SINWAVTest;
>> T = 1/Fs;             % Sampling period
>> L = length(Y);             % Length of signal
>> t = (0:L-1)*T;        % Time vector
>> t2 = flipud(rot90(t));
>> y2 = Y; %+ 2*randn(size(t2));
>> y2 = y2;% - mean(y2);
>> y3 = fft((y2))
>> P2 = abs(y3/L);
>> P1 = P2(1:L/2+1);
>> P1(2:end-1) = 2*P1(2:end-1);
>> f = Fs*(0:(L/2))/L;
>> %%Interpolated
>> T_mean = (t(L)-t(1))/(L-1);
>> t_u = t(1):T_mean:t(L);
>> yy = interp1(t,Y,t_u,'spline');
>> y4 = fft(yy)
>> Psd_i=abs(fft(yy)).^2/(L*T_mean)
>> fr=[-ceil((L-1)/2):floor((L-1)/2)]/(L*T_mean);
>> Psd_a=abs(nedft(Y,t2,fr)).^2/(L*T_mean);
>> P1I = Psd_i(1:L/2+1);
>> P1I(2:end-1) = 2*P1I(2:end-1);
>> %Plot time-domain signal
>> subplot(4,1,1);
>> plot(t, Y);
>> ylabel('Amplitude'); xlabel('Time (secs)');
>> axis tight;
>> title('Shaker Input Signal');
>> subplot(4,1,2);
>> plot(1000*t(1:1000),y2(1:1000))
>> title('Signal Corrupted with Zero-Mean Random Noise')
>> xlabel('t (milliseconds)')
>> ylabel('X(t)')
>> subplot(4,1,3);
>> plot(f,P1)
>>
>> title('Single-Sided Amplitude Spectrum of X(t)')
>> xlabel('f (Hz)')
>> ylabel('|P1(f)|')
>> %ylim([0,2000]);
>> subplot(4,1,4);
>> plot(f,P1I,'r')
>> title('Interpolated FFT')
>> xlabel('f (Hz)')
>> ylabel('|P1(f)|')
>> %ylim([0,2000]);
>>
>> //Code
>>
>

```
```Thank you for the reply Gene,  I have ordered the Lyons book and it should be here in a couple days. Based on your direction I was able to figure out my code to work..

Thanks again!

Mike

On Thursday, March 7, 2019 at 3:59:03 AM UTC-8, Gene Filatov wrote:
> Also, I haven't seen you doing any interpolation in the code, which is
> why you might end up getting an integer multiple of a frequency bin as
> the output.
>
> In that regard, it's essential to note that interpolation is to be done
> in the frequency domain, which could be achieved by either zero-padding
> of the time-domain series, or any conventional interpolation algorithms
> in the frequency domain (such as any kind of 3-point frequency
> estimation algorithms, which have been discussed extensively in this
> group in the past).
>
> Best regards,
> Gene.
>
>
> On 07.03.2019 8:42, Gene Filatov wrote:
> > Well... I apologize if I say something wrong, but I hope I do not.
> >
> > So... first, to put the terms right, what you are doing is DFT (discrete
> > fourier transform), and FFT (fast fourier transform) is how you are
> > doing it.
> >
> > Second, when you do a DFT of a peak that doesn't exactly coincide with
> > one of your DFT bins, you don't only get a single peak in that bin, but
> > also a number of smaller peaks in other bins. Which is the source of
> > your error. To reduce the number of bins containing any of the peaks,
> > you need to multiply your signal by the window function prior to the
> > DFT. That should massively reduce the error, and let you obtain much
> > more accurate results.
> >
> > Third, there's a bunch of window functions to choose from. I suggest you
> > to start with something as simple as hamming window:
> > https://www.mathworks.com/help/signal/ref/hamming.html
> > After that you might try one of the more complicated windows such as
> > Chebushev or Kaiser which allow you to control the magnitude of
> > sidelobes, and see if it works better for you.
> >
> > Fourth, at this point you might wonder, why does the lack of a window
> > function affect your results at all? Without a window function (or, to
> > put it in more precise terms, with a rectangular window function), you
> > get noticeable sidelobes across all your DFT bins, but that shouldn't,
> > in principle, affect the main peak, so you still should be able to get
> > the correct result. Well, the problem here is that your signal contains
> > not one complex sinusoid but two -- one at 50 Hz and the other at -50
> > Hz. With a rectangular window function the sidelobes from either peak
> > contaminate the other peak which results in a measurable error while
> > determining its position.
> >
> > Fifth, I hope my input was helpful, but you would be much better off if
> > you read the first three chapters of "Understanding Digital Signal
> > Processing" by Richard Lyons, that is the major source of my insight on
> > the problem.
> >
> > Hope that helps!
> >
> > Gene.
> >
> >
> > On 07.03.2019 2:57, Michael R wrote:
> >> Hi,
> >> I am trying to use interpolation to detect an FFT peak between bins
> >> however my interpolation results in the same peak as the FFT.  I am
> >> inputting a 50Hz sine wave.. Sampling freq is 6500hz and I have 2048
> >> sample points.  There fore my bin freq is 3.17hz which multipled out
> >> gives me a 50.8hz nearest bin frequency which is what my code is
> >> giving me.  I am trying to see where my interpolation code is going
> >> wrong and not giving me a peak at 50hz
> >> Thanks in advance!
> >>
> >> //Code:
> >>
> >> Fs =6500;            % Sampling frequency
> >> Y=SINWAVTest;
> >> T = 1/Fs;             % Sampling period
> >> L = length(Y);             % Length of signal
> >> t = (0:L-1)*T;        % Time vector
> >> t2 = flipud(rot90(t));
> >> y2 = Y; %+ 2*randn(size(t2));
> >> y2 = y2;% - mean(y2);
> >> y3 = fft((y2))
> >> P2 = abs(y3/L);
> >> P1 = P2(1:L/2+1);
> >> P1(2:end-1) = 2*P1(2:end-1);
> >> f = Fs*(0:(L/2))/L;
> >> %%Interpolated
> >> T_mean = (t(L)-t(1))/(L-1);
> >> t_u = t(1):T_mean:t(L);
> >> yy = interp1(t,Y,t_u,'spline');
> >> y4 = fft(yy)
> >> Psd_i=abs(fft(yy)).^2/(L*T_mean)
> >> fr=[-ceil((L-1)/2):floor((L-1)/2)]/(L*T_mean);
> >> Psd_a=abs(nedft(Y,t2,fr)).^2/(L*T_mean);
> >> P1I = Psd_i(1:L/2+1);
> >> P1I(2:end-1) = 2*P1I(2:end-1);
> >> %Plot time-domain signal
> >> subplot(4,1,1);
> >> plot(t, Y);
> >> ylabel('Amplitude'); xlabel('Time (secs)');
> >> axis tight;
> >> title('Shaker Input Signal');
> >> subplot(4,1,2);
> >> plot(1000*t(1:1000),y2(1:1000))
> >> title('Signal Corrupted with Zero-Mean Random Noise')
> >> xlabel('t (milliseconds)')
> >> ylabel('X(t)')
> >> subplot(4,1,3);
> >> plot(f,P1)
> >>
> >> title('Single-Sided Amplitude Spectrum of X(t)')
> >> xlabel('f (Hz)')
> >> ylabel('|P1(f)|')
> >> %ylim([0,2000]);
> >> subplot(4,1,4);
> >> plot(f,P1I,'r')
> >> title('Interpolated FFT')
> >> xlabel('f (Hz)')
> >> ylabel('|P1(f)|')
> >> %ylim([0,2000]);
> >>
> >> //Code
> >>
> >

```
```Mike, you are welcome!

Gene.

On 07.03.2019 22:57, Michael R wrote:
> Thank you for the reply Gene,  I have ordered the Lyons book and it should be here in a couple days. Based on your direction I was able to figure out my code to work..
>
> Thanks again!
>
> Mike
>
> On Thursday, March 7, 2019 at 3:59:03 AM UTC-8, Gene Filatov wrote:
>> Also, I haven't seen you doing any interpolation in the code, which is
>> why you might end up getting an integer multiple of a frequency bin as
>> the output.
>>
>> In that regard, it's essential to note that interpolation is to be done
>> in the frequency domain, which could be achieved by either zero-padding
>> of the time-domain series, or any conventional interpolation algorithms
>> in the frequency domain (such as any kind of 3-point frequency
>> estimation algorithms, which have been discussed extensively in this
>> group in the past).
>>
>> Best regards,
>> Gene.
>>
>>
>> On 07.03.2019 8:42, Gene Filatov wrote:
>>> Well... I apologize if I say something wrong, but I hope I do not.
>>>
>>> So... first, to put the terms right, what you are doing is DFT (discrete
>>> fourier transform), and FFT (fast fourier transform) is how you are
>>> doing it.
>>>
>>> Second, when you do a DFT of a peak that doesn't exactly coincide with
>>> one of your DFT bins, you don't only get a single peak in that bin, but
>>> also a number of smaller peaks in other bins. Which is the source of
>>> your error. To reduce the number of bins containing any of the peaks,
>>> you need to multiply your signal by the window function prior to the
>>> DFT. That should massively reduce the error, and let you obtain much
>>> more accurate results.
>>>
>>> Third, there's a bunch of window functions to choose from. I suggest you
>>> to start with something as simple as hamming window:
>>> https://www.mathworks.com/help/signal/ref/hamming.html
>>> After that you might try one of the more complicated windows such as
>>> Chebushev or Kaiser which allow you to control the magnitude of
>>> sidelobes, and see if it works better for you.
>>>
>>> Fourth, at this point you might wonder, why does the lack of a window
>>> function affect your results at all? Without a window function (or, to
>>> put it in more precise terms, with a rectangular window function), you
>>> get noticeable sidelobes across all your DFT bins, but that shouldn't,
>>> in principle, affect the main peak, so you still should be able to get
>>> the correct result. Well, the problem here is that your signal contains
>>> not one complex sinusoid but two -- one at 50 Hz and the other at -50
>>> Hz. With a rectangular window function the sidelobes from either peak
>>> contaminate the other peak which results in a measurable error while
>>> determining its position.
>>>
>>> Fifth, I hope my input was helpful, but you would be much better off if
>>> you read the first three chapters of "Understanding Digital Signal
>>> Processing" by Richard Lyons, that is the major source of my insight on
>>> the problem.
>>>
>>> Hope that helps!
>>>
>>> Gene.
>>>
>>>
>>> On 07.03.2019 2:57, Michael R wrote:
>>>> Hi,
>>>> I am trying to use interpolation to detect an FFT peak between bins
>>>> however my interpolation results in the same peak as the FFT.  I am
>>>> inputting a 50Hz sine wave.. Sampling freq is 6500hz and I have 2048
>>>> sample points.  There fore my bin freq is 3.17hz which multipled out
>>>> gives me a 50.8hz nearest bin frequency which is what my code is
>>>> giving me.  I am trying to see where my interpolation code is going
>>>> wrong and not giving me a peak at 50hz
>>>> Thanks in advance!
>>>>
>>>> //Code:
>>>>
>>>> Fs =6500;            % Sampling frequency
>>>> Y=SINWAVTest;
>>>> T = 1/Fs;             % Sampling period
>>>> L = length(Y);             % Length of signal
>>>> t = (0:L-1)*T;        % Time vector
>>>> t2 = flipud(rot90(t));
>>>> y2 = Y; %+ 2*randn(size(t2));
>>>> y2 = y2;% - mean(y2);
>>>> y3 = fft((y2))
>>>> P2 = abs(y3/L);
>>>> P1 = P2(1:L/2+1);
>>>> P1(2:end-1) = 2*P1(2:end-1);
>>>> f = Fs*(0:(L/2))/L;
>>>> %%Interpolated
>>>> T_mean = (t(L)-t(1))/(L-1);
>>>> t_u = t(1):T_mean:t(L);
>>>> yy = interp1(t,Y,t_u,'spline');
>>>> y4 = fft(yy)
>>>> Psd_i=abs(fft(yy)).^2/(L*T_mean)
>>>> fr=[-ceil((L-1)/2):floor((L-1)/2)]/(L*T_mean);
>>>> Psd_a=abs(nedft(Y,t2,fr)).^2/(L*T_mean);
>>>> P1I = Psd_i(1:L/2+1);
>>>> P1I(2:end-1) = 2*P1I(2:end-1);
>>>> %Plot time-domain signal
>>>> subplot(4,1,1);
>>>> plot(t, Y);
>>>> ylabel('Amplitude'); xlabel('Time (secs)');
>>>> axis tight;
>>>> title('Shaker Input Signal');
>>>> subplot(4,1,2);
>>>> plot(1000*t(1:1000),y2(1:1000))
>>>> title('Signal Corrupted with Zero-Mean Random Noise')
>>>> xlabel('t (milliseconds)')
>>>> ylabel('X(t)')
>>>> subplot(4,1,3);
>>>> plot(f,P1)
>>>>
>>>> title('Single-Sided Amplitude Spectrum of X(t)')
>>>> xlabel('f (Hz)')
>>>> ylabel('|P1(f)|')
>>>> %ylim([0,2000]);
>>>> subplot(4,1,4);
>>>> plot(f,P1I,'r')
>>>> title('Interpolated FFT')
>>>> xlabel('f (Hz)')
>>>> ylabel('|P1(f)|')
>>>> %ylim([0,2000]);
>>>>
>>>> //Code
>>>>
>>>
>

```