# ZOH non ideal sampling loss formula

Hello i am trying to calculate the amplitude loss of non ideal sampling. My signals amplitude is 10 at 70 frequency. When we sample it at Fs=400 we have al 0.511 loss as shown in plot bellow. How can we get this 0.511 using the ZOH sinc formula bellow. What is f,Tpm,Ts is here so i could see the 0.511 loss? MATLAB code bellow. Thanks.

f3=70;
Fs=400; % sampling frequency is a bit above 2 times to get all the peaks.
Ts=1/Fs;
Tn=0:Ts:1;
fft_L=length(Tn);
y4_samples=10*sin(2*pi*f3*Tn);
%stem(Tn_new,y4_samples);
ff=fft(y4_samples);
ff1 = abs(ff/fft_L);% normalised FFT
fft2 = ff1(1:floor(fft_L/2)+1); %first half of the vector
fft2(2:end) = 2*fft2(2:end); %we multiply the amplitude by 2
f = Fs*(0:fft_L/2)/fft_L;%frequency vector
plot(f, fft2)

• The loss you are looking at has nothing to do with ideal sampling. You've sampled a periodic waveform ideally (y4_samples=10*...). If you plot that, you'll see its peak is 10, as expected. Then you take the fft of a non-integer number of cycles. So, you'll get "spectral leakage", which you see in your plot. To prove this to yourself, change f3 to 100 so there will be an integer number of cycles. Change Tn to Tn=Ts:Ts:1, so that you get exactly 400 samples and not 401. Run the script, you'll get a peak of 10 at a frequency of 100. – Nigel Redmon Apr 23 '20 at 19:05
• Hello Nigel, regarding the formula what is my Ts Tp and f ? Thanks. – rocko445 Apr 23 '20 at 19:37
• I'm not sure what you're asking rocko—I don't see Tp anywhere, and you don't have a problem with f. Let me rephrase my previosu comment, especially since I made it more complicated than necessary by moving to 100 to get the frequency middle of the plot. I'm having trouble fitting my explanation in a comment, I'll try via and answer... – Nigel Redmon Apr 23 '20 at 20:33

The discrepancy you're seeing is not related to non-ideal sampling. You are, in fact, sampling ideally. If you plot just the waveform, you'll see that peaks reach 10 as intended; here I've lowered the frequency to 1, to make it easier to see:

f3=1;
Fs=400; % sampling frequency is a bit above 2 times to get all the peaks.
Ts=1/Fs;
Tn=0:Ts:1;
y4_samples=10*sin(2*pi*f3*Tn);
plot(Tn, y4_samples);


Resulting in

Your intention is to take the FFT of this signal to determine the frequency and amplitude. However, there is a problem you're not accounting for. The FFT is designed to work, exactly, on a single cycle signal. While the above plot looks like a single cycle, it has one-too-many samples. If you repeat the array/vector of samples, the last sample in plot is zero, and then you'll start at the beginning—zero again, an unintended repeat, causing a glitch in the waveform. The FFT will see this as "almost" 1 cycle. The error will spill into other frequency "bins"—look up "spectral leakage".

To fix the issue, in this case you can simple lower the number of samples from 401 to 400, by changing the Tn calculation to Tn=0:Ts:1-Ts (Alternatively, Tn=Ts:Ts:1 to start a sample later), resulting in

Look carefully at the right end of the plot, and you'll see it now stops one sample before it would start the next cycle, allowing an exact cycle loop.

Going back to your original example, and changing just the calculation of Tn:

f3=70;
Fs=400; % sampling frequency is a bit above 2 times to get all the peaks.
Ts=1/Fs;
Tn=0:Ts:1-Ts;
fft_L=length(Tn);
y4_samples=10*sin(2*pi*f3*Tn);
%stem(Tn_new,y4_samples);
ff=fft(y4_samples);
ff1 = abs(ff/fft_L);% normalised FFT
fft2 = ff1(1:floor(fft_L/2)+1); %first half of the vector
fft2(2:end) = 2*fft2(2:end); %we multiply the amplitude by 2
f = Fs*(0:fft_L/2)/fft_L;%frequency vector
plot(f, fft2);


Produces the desired result,

Autoscaling has increased the vertical range, due to slight mathematical inaccuracies, but if you list fft2, you'll see the value is 10, as expected; the first value is 0 Hz, so index 71 corresponds to 70:

>> fft2(71)
ans =  10.000


Again, be aware this will work exactly only for integer number of cycles, so basically 0 to 199 (just under half the sampel rate) in this case. You will see the same spectral leakage you did before if you use 69.5, for instance. Here is the plot for 69.5:

This should make intuitive sense, if you consider that there is no value corresponding to index 70.5 (69.5 + 1) in your fft2 array. The energy from 69.5 is spread between nearby values—the spectral leakage.

• Hello Nigel There is a formula regarding Zero Order Hold sampling in the frequency domain: |H(f)|=(Tp/Ts)*(sin(pifTp)/(pifTp))) If you are femiliar with this formula what is Tp, Ts,f? Thanks – rocko445 Apr 24 '20 at 7:53
• Hi rocko...Simulating zero order hold is another issue, it's not what you're doing in your example. You ask, "When we sample it at Fs=400 we have al 0.511 loss as shown in plot bellow. How can we get this 0.511 using the ZOH sinc formula bellow." But the discrepancy has nothing ot do with ZOH, nor sinc. Try my code above, where I modified only the Tn vector, eliminating only the last value. You see the full value of 10. In your case, you haven't lost 0.511, you've spread it to the skirt surrounding the 69.83 value listed (notice it should be 70, but is wrong due to the vector being 401 long). – Nigel Redmon Apr 24 '20 at 8:06
• That is, you generate a frequency of 70 and amplitude 10. But plot shows a frequency of 69.83 and amplitude of 9.489, and there is spill forming the skirt around it (the missing energy). Clearly, things aren't lined up as intended. The reason is you've defined the sampling frequency as 400. The normalized frequency is 70/400 in your sine calculation, stepping in sample periods of Ts (1/Fs). But your fft is length 401. It should be 400 in order for each "bin" to represent an increment of 1. Please consider my answer, which solves the missing 0.511. Then you can form a new question about ZOH. – Nigel Redmon Apr 24 '20 at 8:24
• Hello Nigel, How to recognise that i am having and integer number of cycles in my fft domain.given my signal frequency of 100hz=>T_signal=0.01sec period(time of a single cycle) so when my sampling frequency is Fs=400Hz. Tn=Ts:Ts:1=>Tn=0.0025:0.0025:1 [400 members] So how our Tn represents integer number of cycles? why Tn=0.0025:0.0025:1 [400 members] is integer number of cycles but Tn=0:0.0025:1 [401 members] is not an integer nuber of cycles? – rocko445 Apr 24 '20 at 14:20
• fft2 represents the magnitude of each harmonic. The first value is DC (“0th harmonic”), fft2(1) is 1st, ff2(2) is 2nd, etc. For an FT of length 400, fft2(0) corresponds to zero-400ths of the frequency range, fft2(1) 1/400 * range, fft2(2) 2/400 * range, etc. Since you defined Fs to be 400 (let’s say units of Hz), that means fft2(1) is the magnitude of 1 Hz, fft2(2) is of 2 Hz… Now do the math with an Fourier Transform of length 401. fft2(1) represents 1/401 * 400 Hz, or ~0.9975 Hz. You generate a 70 Hz signal, but your closest FT grid line is 70/401*400 = 69.83 Hz. You see it in your chart. – Nigel Redmon Apr 24 '20 at 17:06

Define this

Tn=0:Ts:1;

to be

Tn=0:Ts:1 -Ts;

By defining it the way you have in the program you have not included an integer number of cycles in the samples. This will result in spectral leakage because your sinuoid now does not fit into one frqeuency bin and thus spill out into other bins and this reduces in magnitude.