This is the fourth post in the blinkdagger signal processing series.

## Introduction

In the previous tutorial, we showed you how correctly scale your x-axis so that your FFT results were meaningful. In this post, we will be discussing zero-padding, a method that can help you better visualize/interpret your fft results. Zero-padding means that you append an array of zeros to the end of your input signal before you fft it. Luckily, the fft command within Matlab makes it very easy to zero-pad.

Two reasons that you might want to zero pad is to increase the number of data points to a power of 2. Traditionally, the FFT algorithm is more efficient when it is dealing with signals that contain 2^N data points. Nowadays, this isn’t as important with the modern algorithms. Another reason for zero-padding is for a “better” resolution in the frequency spectrum. We’ll discuss why quotes are used around better in a bit. In general, zero-padding can prove quite useful and should be used when using the fft command. In practice, it is helpful to zero pad a signal to 4 times it’s original length, giving you a 4-fold increase in the frequency resolution.

## A Simple Example

Let’s use the same signal as the previous tutorial as our example signal:

 fo = 4; %frequency of the sine wave Fs = 100; %sampling rate Ts = 1/Fs; %sampling time interval t = 0:Ts:1-Ts; %sampling period n = length(t); %number of samples y = 2*sin(2*pi*fo*t); %the sine curve %plot the cosine curve in the time domain sinePlot = figure; plot(t,y) xlabel('time (seconds)') ylabel('y(t)') title('Sample Sine Wave') grid

But now, lets append some zeros to the end of this signal:

Case 1: Number of points = 128
Case 2: Number of points = 256
Case 3: Number of points = 512

This is what the signal would look like for these three cases:

## Taking the FFT of the Zero-Padded Signals

Luckily, the fft command within Matlab makes zero-padding extremely easy. The fft command has a second argument that allows you to specify how many data points the fft command will return. I modified the code I presented in the last tutorial to allow for zero padding and used it here:

 %remember to save this function as an m-file! function [X,freq]=centeredFFT(x,Fs,N) %this is a custom function that helps in plotting the two-sided spectrum %x is the signal that is to be transformed %Fs is the sampling rate %N is the number of points returned in the FFT result %this part of the code generates that frequency axis if mod(N,2)==0 k=-N/2:N/2-1; % N even else k=-(N-1)/2:(N-1)/2; % N odd end T=N/Fs; freq=k/T; %creates the frequency axis X=fft(x,N)/length(x); % normalizes the data X=fftshift(X);%shifts the fft data so that it is centered

Now, lets take the fft of these three signals.

## Why Does My Output Look Like a Sinc?

When we pad with zeros, we are effectively multiplying a rectangular box with the sinusoid in the time domain. In the frequency domain, this translates into convolving a sinc function with an impulse resulting in a sinc-like output!(You can download the script that I used in creating these plots at the end of this tutorial).

As you can see, there are more sampled points as N gets larger, and it is easier to see the general shape of the spectrum. The larger your N is, the finer the sampling will be. If I keep on increasing the number of zeros, it will make my frequency spectrum more refined. So does this mean I can just zero-pad my signal and get a better FFT spectrum every time? Well, technically speaking, you get more frequency bins when you zero pad, so yes, you do get a higher resolution in the frequency domain. But the caveat is that there is no new information added when you zero-pad.

When you increase the size of N, all you are really doing is interpolating the data to obtain more sample points. There is NO new information added when zero-padding is applied. The resolution has increased, but I repeat, THERE IS NO NEW INFORMATION ADDED! This might sound confusing and paradoxical, but it is a very important point.

If you have the option to take more data, it is ALWAYS better to get more data than to zero pad. Zero-padding is NOT a substitute for taking more data!

## Another Example on how Zero Padding can Help

1. In this example, we are going to use zero padding to help us distinguish between two peaks that would otherwise be difficult to distinguish.

The example signal has f1 = 4 Hz and f2 = 4.5 Hz (meaning it will have a peak at 4 Hz and a peak at 4.5 Hz):

$$y(t)=100sin(2\pi{f}_{1}t)+100sin(2\pi{f}_{2}t)$$

The following MATLAB code is used to generate the curve. Insert this into the MATLAB command prompt

 f1 = 4; %frequency of the first sine wave f2 = 4.5; %frequency of the second sine wave Fs = 100; %sampling rate Ts = 1/Fs; %sampling time interval t = 0:Ts:2-Ts; %sampling period y = 100*sin(2*pi*f1*t) + 100*sin(2*pi*f2*t); %sum of sine waves plot(t,y) title('Sample Signal', 'FontWeight','Bold') xlabel('Time (seconds)') ylabel('Amplitude') grid

2. Now, lets take the FFT of the signal without zero padding. Theoretically, we expect two peaks. One peak at 4 Hz, and another at 4.5 Hz.

As you can see, it is difficult to tell that there are two peaks in this plot. It looks like the peaks got smashed together.

3. Now, lets apply some zero padding up to N = 1024 points.

The following function is used to perform this:

 %remember to save this function as an m-file! function [X,freq]=positiveFFT_zero_padding(x,Fs,N) k=0:N-1; %create a vector from 0 to N-1 T=N/Fs; %get the frequency interval freq=k/T; %create the frequency range X=fft(x,N)/length(x); % normalize the data %only want the first half of the FFT, since it is redundant cutOff = ceil(N/2); %take only the first half of the spectrum X = X(1:cutOff); freq = freq(1:cutOff);

At the Matlab Command prompt, type the following to obtain the plot shown below:

 fftPlot2 = figure set(fftPlot2,'Position',[500,500,600,300]) zeroPadFactor = nextpow2(length(y)) + 3; [a,b] = positiveFFT_zero_padding(y,Fs,2^zeroPadFactor); plot(b,abs(a)) title('FFT of Sample Signal: Zero Padding up to N = 1024', 'FontWeight','Bold') xlabel('Freq (Hz)') ylabel('Magnitude') grid xlim([0 10])

4. But didn’t we just say that no new information is added? How were we able to distinguish these two peaks if no new information is added?

The information was always there, but it was “hidden” in a way. When we took the FFT of the signal without zero padding, the frequency bins were not fine enough to differentiate the two peaks. By the sampling theorem, as long as you sample a bandlimited signal under the Nyquist rate, you know everything you need to know to perfectly reconstruct the signal. Therefore, at that point, you’ve done the best you can do; you can zero-pad all you want to get more points at the output of your FFT, but you don’t get any new information, because you already have all the information there is on the continuous-time signal.

Inherently, there is nothing wrong with zero-padding in itself. You just have to be careful in its application. Whenever I use the fft command, I tend to use an N that is 4 times larger than the amount of data points within my signal. Zero padding cannot hurt your FFT result.