3
$\begingroup$

This is my MATLAB code

Amp = 0.3;
freqHz = 1000;
fsHz = 160000;
dt = 1/fsHz;
t = 0:dt:2000*dt;
sine = Amp * sin(2*pi*freqHz*t);
t = 0:2000
subplot(2,2,1)
plot(t,sine)

y1 = sine;
Fs = 160000;                   % samples per second
N = length(y1);            % samples
dF = Fs/N;                 % hertz per sample
f = -Fs/2:dF:Fs/2-dF + (dF/2)*mod(N,2);      % hertz
Y1_fft = fftshift(fft(y1))/N;
subplot(2,2,2)
plot(f , (abs(Y1_fft)) - min((abs(Y1_fft))));
legend(num2str(i))
shg;

and this is the result: enter image description here

The amplitude of my sin is 0.3 so I expect to get the FFT signal with the amplitude of 0.15 at 1Khz while I get 0.096 as the amplitude. My goal is to extract the amplitude of a tone among different frequencies.

$\endgroup$
2
  • $\begingroup$ You need to a have an integer number of periods. You don't, so you have spectral leakage. $\endgroup$
    – Ben
    May 11, 2021 at 14:07
  • $\begingroup$ @Ben thank a lot. It worked. please post your answer. $\endgroup$
    – SeAlGhz
    May 11, 2021 at 14:11

4 Answers 4

1
$\begingroup$

Your signal frequency is 1000 Hz while your sampling frequency is 160 kHz. Since there are 160 samples per period, the number of points for the FFT should be a multiple of 160. In this case, I used 1600 points.

Amp = 0.3;
NbPoints  = 1600;
freqHz = 1000;
fsHz = 160000;
dt = 1/fsHz;
t = 0:dt:(NbPoints-1)*dt;
sine = Amp * sin(2*pi*freqHz*t);
n = 1 : NbPoints;
subplot(2,2,1)
plot(t,sine)

y1 = sine;
Fs = 160000;                   % samples per second
N = length(y1);            % samples
dF = Fs/N;                 % hertz per sample
f = -Fs/2:dF:Fs/2-dF + (dF/2)*mod(N,2);      % hertz
Y1_fft = fftshift(fft(y1))/N;
subplot(2,2,2)
plot(f , (abs(Y1_fft)) - min((abs(Y1_fft))));
legend(num2str(1))
shg;
$\endgroup$
12
  • $\begingroup$ Could you please help what should I do if my tone frequency would be 7000? because my sampling frequency is 16000, 16000/7000 is never an integer. What should I do ? $\endgroup$
    – SeAlGhz
    May 11, 2021 at 14:30
  • $\begingroup$ You can use windowing $\endgroup$
    – Ben
    May 11, 2021 at 14:38
  • $\begingroup$ How does it work? $\endgroup$
    – SeAlGhz
    May 11, 2021 at 14:41
  • 1
    $\begingroup$ download.ni.com/evaluation/pxi/… $\endgroup$
    – Ben
    May 11, 2021 at 14:45
  • 1
    $\begingroup$ You can select the number of samples to be really close to an integer number of samples. Other solution, you can use least-squares fitting to estimate the amplitude. $\endgroup$
    – Ben
    May 11, 2021 at 15:46
2
$\begingroup$

The amplitude peak is hidden between FFT result bins for frequencies that are not exactly integer periodic in the FFT's length. But you can interpolate to find the results for those frequencies. Try windowed Sinc interpolation of the real and imaginary components, then compute the magnitude of the complex result. If you don't know the exact frequency, you can use successive approximation to find an interpolated magnitude peak between FFT result bins.

$\endgroup$
1
  • $\begingroup$ I know the exact frequency but could you please explain a little bit more? $\endgroup$
    – SeAlGhz
    May 11, 2021 at 16:53
2
$\begingroup$

Note that if you do know the exact frequency (which can be at a fractional bin Position) and are only interested in the amplitude and phase, the FFT is rather inefficient on top of its inaccuracy.

Better ways to it are goertzel demodulation or quadrature demodulation.

$\endgroup$
2
  • $\begingroup$ Thank for your advise. Do you have any useful link or pdf to read about your advice? $\endgroup$
    – SeAlGhz
    May 13, 2021 at 12:47
  • $\begingroup$ I added a link for the fractional goertzel algorithm. The quadrature demodulation is just multiplying the signal with a sin and cos signal of the known frequency. The total of the two multiplications is the re+im demodulation value. $\endgroup$
    – tobalt
    May 13, 2021 at 13:05
2
$\begingroup$

If you are trying to use the FFT to estimate the frequency and/or amplitude of a sinusoid you run into a problem when the frequency of your signal doesn't fall exactly on a FFT bin. In this case, the result of the FFT causes the energy to leak into nearby FFT bins - often called scalloping loss. The common approach to reduce scalloping loss is to use windows, e.g. Hamming, Blackman etc. While using windows reduces the scalloping effect there are additional unwanted sideeffects, two of which are: Coherent energy loss (loss of amplitude as you have seen), and the increase of the effect FFT bin size (FFT frequency resolution - nominally sampling frequency/FFT size).

There are a couple of possible solutions to your problem: First, use what is called a Flattop window. This is a special window that tries to maintain the amplitude i.e. it tries to avoid to coherent energy loss. See here for an article by Richard Lyons describing this. Note there are several slightly different versions of Flattop windows out there.

An alternative method, is two use the FFT bin with the peak amplitude and the amplitude of the adjacent FFT bins. To interpolate both the frequency and the amplitude estimates. Typically, before you can estimate the amplitude you'll need to know the frequency. The interpolation mechanism can vary from: linear, quadratic, spline and others.

A couple references are here:

Ref 1 - by Matt Donadio

Ref 2 - Eric Jacobsen

Note - a couple of problems also arise when:

  • Noise is present
  • There are nearby sinusoids / signals that leak energy into the FFT bins you are using for your frequency estimation.
$\endgroup$
1
  • $\begingroup$ I actually have some noise because I am recording a pure tone from microphone. anyway, thanks for your through answer. $\endgroup$
    – SeAlGhz
    May 14, 2021 at 15:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.