3.4  Linear Time-Invariant Systems

This section is dedicated to the study of linear and time-invariant (LTI) systems.

PIC

Figure 3.5: Diagram of systems, emphasizing the linear and time-invariant (LTI) systems and the systems described by linear, constant-coefficient differential (or difference) equations (LCCDE).

Figure 3.5 depicts the position of LTI systems and also includes the important subset of systems described by linear, constant-coefficient differential (or difference, in discrete-time) equations (LCCDE). In this text, it is assumed that the LCCDE systems have zero initial conditions or, equivalently, that the system is at rest.

3.4.1  Impulse response and convolution for LTI systems

A LTI system is completely characterized by its impulse response.1 This fact is illustrated in the sequel using a simple example. Assume that a system H is LTI and its impulse response h[n] = 2δ[n] + 5δ[n 1] is obtained by imposing an input x[n] = δ[n]. For example, assuming x[n] = 4δ[n] 3δ[n 1], one has

y[n] = H{x[n]} = H{4δ[n] 3δ[n 1]} = 4H{δ[n]} 3H{δ[n 1]} (using linearity) = 4h[n] 3h[n 1] (using time-invariance) = 4(2δ[n] + 5δ[n 1]) 3(2δ[n 1] + 5δ[n 2]) = 8δ[n] + 14δ[n 1]) 15δ[n 2].

This example illustrates that, knowing h[n] and using linearity and time-invariance, one can calculate the output.

In general, the input/output relation of a LTI depends on two facts:

These two key facts lead to the convolution operation:

y[n] = H{x[n]} = H{ k=x[k]δ[n k]} = k=x[k]H{δ[n k]} (using linearity) = k=x[k]h[n k]        (using time-invariance) (3.1)

Note how linearity and time-invariance were both invoked in this proof. The continuous-time convolution is similar:

y(t) =x(τ)h(t τ).
(3.2)

The convolution is so important that it is represented by the operator . For example, y[n] = x[n]h[n] denotes the convolution of x[n] and h[n]. Because is the same symbol used for multiplication in programming languages, the context has to distinguish them.

PIC

Figure 3.6: Example of convolution between x[n] = 2δ[n] 3δ[n 1] and h[n] = δ[n] 2δ[n 1] + δ[n 2]. The top-left and top-right plots are x[n] and y[n], respectively, while the other plots are the parcels of x[n] (left) and the corresponding parcels of y[n] (right).

Figure 3.6 illustrates the convolution between two sequences. The interpretation is that y[n] is composed by the sum of several scaled and shifted impulse responses. The plots at the right in Figure 3.6 indicate that y[n] is the sum of the two parcels 2h[n] and 3h[n 1]. The Listing 3.1 provides an example of implementing convolution of discrete-time sequences,2 which gives the same result as the (faster) conv function in Matlab/Octave.

Listing 3.1: MatlabOctaveFunctions/ak_convolution.m
1function y=ak_convolution(x,h) 
2% function y=ak_convolution(x,h) 
3%convolution between sequences x and h 
4N1=length(x); %get the number of samples in x 
5N2=length(h); 
6N=N1+N2-1; %this is the number of samples in the output y 
7y=zeros(1,N); %pre-allocate space for y[n] 
8for i=1:N1 %calculate y[n]= sum_k x[k] h[n-k] 
9    y(i:i+N2-1)=y(i:i+N2-1)+x(i)*h; %scaling h by x(i) 
10end
  

Note that if the samples of x[n] and h[n] are organized as elements of vectors of polynomial coefficients, convolving them is equivalent to multiplying the two polynomials. For the example in Figure 3.6 one can obtain the convolution result by multiplying the equivalent polynomials 2x 3 and x2 2x + 1, which leads to 2x3 7x2 + 8x 3, i. e., the coefficients are the samples of y[n].

If the impulse response completely characterizes a LTI system, all its properties can be inferred from the corresponding impulse response. This is discussed in Appendix A.27.7.

3.4.2  Advanced: Convolution properties

The convolution is:

Some other facts about the convolution:

An example of this last fact is appropriate: if x1[n] = δ[n] + 2δ[n 1] + 3δ[n 2] and x2[n] = 5δ[n] + 6δ[n 1] + 7δ[n 2] + 8δ[n 3], the output y[n] = x1[n]x2[n] is given by

y[0] = x1[0] x2[0] = 5
y[1] = x1[0] x2[1] + x1[1] x2[0] = 16
y[2] = x1[0] x2[2] + x1[1] x2[1] + x1[2] x2[0] = 34
y[3] = x1[0] x2[3] + x1[1] x2[2] + x1[2] x2[1] = 40
y[4] = x1[1] x2[3] + x1[2] x2[2] = 37
y[5] = x1[2] x2[3] = 24

where one can note that the indexes of the input sequences sum up to the index of the output. Hence, one can alternatively implement convolution as in Listing 3.2.

Listing 3.2: MatlabOctaveFunctions/ak_convolution2.m
1function [y,n]=ak_convolution2(x1,x2,n1,n2) 
2% function [y,n]=ak_convolution2(x1,x2,n1,n2) 
3%calculate the convolution between the sequences x1 and x2 
4%that start at index n1 and n2, respectively 
5%Example: [y,n]=ak_convolution2(1:3,5:8,-3,2); stem(n,y) 
6N1=length(x1); %get the number of samples in x1 
7N2=length(x2); %get the number of samples in x2 
8N=N1+N2-1; %this is the number of samples in the output y 
9y=zeros(1,N); %pre-allocate space for y[n] 
10for i=0:N1-1 %calculate y[n] = sum_k x1[k] x2[n-k] 
11    for j=0:N2-1 
12        y(i+j+1) = y(i+j+1) + x1(i+1)*x2(j+1); %update 
13    end 
14end 
15n=n1+n2:n1+n2+N-1; %generate the "time" indices
  

Note that Listing 3.2 allows to explicitly deal with sequences that do not start at n = 0. When using Matlab/Octave, it is often necessary to explicitly deal with and generate the time indexes.

It can be observed from Listing 3.2 that the first non-zero sample of the convolution between two sequences x1[n] and x2[n] is located at n = n1 + n2, which are assumed to be the indexes of the first non-zero samples of the two sequences. Similarly, the last non-zero sample of the convolution is the sum of the indexes of the last non-zero samples of x1[n] and x2[n]. This can be seen by running Listing 3.3.

Listing 3.3: MatlabOctaveCodeSnippets/snip_systems_ak_convolution.m. [ Python version]
1x1=1:3; %define sequence x1 
2x2=5:8; %define sequence x2 
3nx1=-3:-1; %define abscissa for x1 
4nx2=2:5; %define abscissa for x2 
5subplot(311); stem(nx1,x1) 
6subplot(312); stem(nx2,x2) 
7[y,n]=ak_convolution2(x1,x2,-3,2); %calculate convolution 
8subplot(313); stem(n,y) %show result with proper time axis
  

3.4.3  Advanced: Convolution via correlation and vice-versa

Given that convolution and cross-correlation are tightly related, Listing 3.4 illustrates how the Matlab/Octave functions xcorr and conv can be used to calculate the other operation.

Listing 3.4: MatlabOctaveCodeSnippets/snip_systems_convolution_correlation.m. [ Python version]
1x=(1:4)+j*(4:-1:1); %define some complex signals as row vectors, such 
2y=rand(1,15)+j*rand(1,15); %that fliplr inverts the ordering 
3%% Correlation via convolution 
4Rref=xcorr(x,y); %reference of a cross-correlation 
5xcorrViaConv=conv(x,conj(fliplr(y))); %use the second argument 
6%% Convolution via correlation 
7Cref=conv(x,y); %reference of a convolution 
8convViaXcorr=xcorr(x,conj(fliplr(y))); %using the second argument 
9%convViaXcorr=conj(fliplr(xcorr(conj(fliplr(x)),y))); %alternative 
10%% Make sure they have the same length and compare the results 
11if length(x) ~= length(y) %this case requires post-processing because 
12    %xcorr assumes the sequences have the same length and uses 
13    %zero-padding if they do not. We treat the effect of these zeros: 
14    convolutionLength=length(x)+length(y)-1; 
15    correlationLength=2*max(length(x),length(y))-1; 
16    if length(x) < length(y) %zeros at the end 
17        convViaXcorr = convViaXcorr(1:convolutionLength); 
18        xcorrViaConv = [xcorrViaConv zeros(1,correlationLength- ... 
19            length(xcorrViaConv))]; 
20    elseif length(x) > length(y) %zeros at the beginning 
21        convViaXcorr = convViaXcorr(end-convolutionLength+1:end); 
22        xcorrViaConv = [zeros(1,correlationLength- ... 
23            length(xcorrViaConv)) xcorrViaConv]; 
24    end 
25end 
26ErroXcorr= max(abs(Rref - xcorrViaConv)) %calculate maximum errors 
27ErroConv = max(abs(Cref - convViaXcorr)) %should be small numbers
  

As indicated in Listing 3.4, the key step to mimic a convolution via correlation or vice-versa is to flip the signal using x(t), use its complex conjugate and eventually shift by t0 as indicated in

x^(t) = x(t + t 0).
(3.3)

3.4.4  Advanced: Discrete-time convolution in matrix notation

Convolution can be denoted in matrix notation. This is especially convenient when dealing with finite-duration discrete-time signals. When these signals are represented by column vectors x1 and x2, a convolution matrix H1 allows to obtain the convolution result y = x1x2 as

y = H1x2,
(3.4)

where H1 is composed by the elements of x1. It is also possible to create H2 from the elements of x2 and use y = H2x1.

This can be better understood with examples. Considering the goal is to obtain the convolution of two column vectors x1=[1; 2; 3] and x2=[5; 6; 7; 8] (previous example), instead of using y=conv(x1,x2), one can create a matrix

hmatrix = [
     1     0     0     0
     2     1     0     0
     3     2     1     0
     0     3     2     1
     0     0     3     2
     0     0     0     3]

with the command hmatrix = convmtx(x1,length(x2)), and then calculate the convolution with y=hmatrix * x2. Note that when using row vectors, the commands could be hm = convmtx(x1,length(x2)); x2*hm (in this case, hm would be the transpose of hmatrix). Application 3.8 discusses the issue of repeatedly processing blocks of samples using the convolution in matrix notation. The matrices created by convmtx are Toeplitz matrices and the command toeplitz.m can also be useful to compose convolution matrices.

3.4.5  Approximating continuous-time via discrete-time convolution

Some situations require approximating the continuous-time convolution denoted by Eq. (3.2) via the discrete-time convolution in Eq. (3.1). In such cases, the sampling interval Ts should be used as a normalization factor, as indicated in Eq. (A.31). This factor is adopted in the next example.

Example 3.2. Convolution of a pulse with itself leads to a triangular waveform. Assume a pulse p(t) = 4rect(5t 0.1) (see rect() in Section 1.3.6) with amplitude A = 4 V and support T0 = 0.2 s. The convolution p(t)p(t) corresponds to a triangular waveform: it is 0 for t < 0 and assumes its maximum value at A2T0 = 42 × 0.2 = 3.2 at 0.2 s, which corresponds to the time that the two pulses overlap completely and A2T0 is the area of p2(t). Figure 3.7 depicts both the pulse and continuous-time convolution p(t)p(t).

PIC

Figure 3.7: Convolution of a pulse p(t) = 4rect(5t 0.1) with itself, obtained with Listing 3.5.

But Figure 3.7 was in fact obtained by representing p(t) via its discrete-time version p[n], and approximating the convolution p(t)p(t) with the scaled discrete-time convolution Ts(p[n]p[n]), i. e., Eq. (A.31). Listing 3.5 shows the first lines of the script that generated Figure 3.7. After running Listing 3.5, the vectors pulse and triangle are shown in Figure 3.7 with the proper time axes.

Listing 3.5: MatlabOctaveCodeSnippets/snip_systems_continuous_discrete_conv
1T0=0.2; %pulse "duty cycle" (interval with non-zero amplitude): 0.2 s 
2Ts=2e-3; %sampling interval: 2 ms 
3N=T0/Ts; %number of samples to represent the pulse "duty cycle" 
4A=4; %pulse amplitude: 4 Volts 
5pulse=A*[zeros(1,N) ones(1,N) zeros(1,4*N)]; %pulse 
6triangle=Ts*conv(pulse,pulse); %(approximated) continuous convolution 
7disp(['Convolution peak at ' num2str(T0) ' is ' num2str(A^2*T0)])
  

Note in line 6 the scaling factor Ts, which leads to the correct values, as indicated by the datatip in Figure 3.7.    

3.4.6  Frequency response: Fourier transform of the impulse response

As indicated in Table 3.1, the frequency response of an LTI system is the Fourier transform of its impulse response. In continuous-time it will be denoted by H(f) (f in Hz) or H(ω) (ω in rad/s), while in discrete-time the notation is H(ejΩ) (Ω in rad). The frequency response is particularly useful because complex exponentials are eigenfunctions of LTI systems as explained in the sequel.

Eigenfunctions

Eigenfunctions are closely related to eigenvectors. if A is a matrix (a linear transformation), a non-null vector x is an eigenvector of A if there is a scalar λ such that

Ax = λx.

The scalar λ is an eigenvalue of A corresponding to the eigenvector x. In general, the matrix A generates a completely new vector y = Ax, i. e., y and x have different directions and magnitudes. However, if x is an eigenvector of A, then y = λx, which means that the operation changed only the magnitude of x, leaving its direction unchanged (or possibly reversing it in case λ < 0).

Similarly, for any LTI system H (continuous-time is assumed here), a complex exponential is an eigenfunction because the output is y(t) = λejω0t when the input is x(t) = ejω0t. The frequency response is useful because the eigenvalue λ = H(ω0) is the value of the frequency response H(ω) at the specific frequency ω = ω0. This implies that an LTI never creates new frequencies, because it can simply change the magnitude and phase of frequencies that were presented at its input. This fact can be represented as

ejω0t H H(ω 0)ejω0t.

It is then possible to analyze an LTI in the frequency domain by following the steps:

f 1.
Decompose the input as a sum (if the signal is periodic) or integral of complex exponentials. For that, one can use the Fourier series or transform X(ω) = F{x(t)}
f 2.
Obtain the frequency response, which provides the eigenvalues for all frequencies: H(ω) = F{h(t)}
f 3.
Conceptually, multiply each complex exponential ejω0t by its eigenvalue H(ω0) and add the partial results to obtain the system output y(t). In practice, this step is performed by Y (ω) = H(ω)X(ω) and then using the inverse transform to obtain y(t) = F1{Y (ω)}.

PIC

Figure 3.8: Frequency response of H(ω) = 1 +2 represented in polar form: magnitude (top) and phase (bottom). The data tips indicate the values for ω = ±4 rad/s.

Example 3.3. LTI filtering of continuous-time complex exponential. For example, consider that x(t) = 6ej4t + 6ej4t = 12cos (4t) is the input of an LTI with h(t) = e2tu(t). The eigenvalues corresponding to each the complex exponential eigenfunctions with frequencies ω = ±4 rad/s can be obtained from the frequency response H(ω) = F{h(t)} = 1 +2. The Matlab/Octave commands Omega=4; H=1/(j*Omega+2) calculate H(ω)|ω=4 = 0.1 0.2j for the positive frequency. Because h(t) is real-valued, the frequency response presents Hermitian symmetry and H(ω)|ω=4 = H(ω)|ω=4, i. e., H(ω)|ω=4 = 0.1 + 0.2j. The commands abs(H), angle(H) can transform from Cartesian to polar: H(ω)|ω=4 0.2236ej1.107 and H(ω)|ω=4 0.2236ej1.107. Therefore, the output is y(t) = (0.2236ej1.107)6ej4t+(0.2236ej1.107)6ej4t = 1.32ej(4t1.11)+1.32ej(4t+1.11) = 2.64cos (4t1.11).

The effect of the LTI system was to impose a gain of |H(4)| = 0.2236 and a phase of ∠H(4) = 1.107 rad. Figure 3.8 depicts the frequency response for a range ω = 2π[3,3] rad/s. Because of the Hermitian symmetry (when h(t) is real), it is common to plot only the positive frequencies. For example, investigate the command freqs(1,[1 2]), which shows the frequency response of H(ω) = 1 +2 in a different format.   

The previous discussion was restricted to exponentials of the form ejω0t, but a general complex exponential est (with σ0) is also an eigenfunction of any LTI and the eigenvalue is given by the Laplace transform H(s), as represented by

es0t H H(s 0)es0t.

The frequency response H(ejΩ) of discrete-time LTI systems is also very useful. When the time axis t is discretized by sampling, i. e., t = nTs, the complex exponential est becomes esnTs, which is more conveniently represented by zn, where

z = esTs

with z,s .

The discrete-time complex exponential zn is an eigenfunction of discrete-time LTI systems. To prove that, consider x[n] = (z0)n,z0 , then

y[n] = k=(z 0)kh[n k] = k=h[k](z 0)nk = (z 0)n k=h[k](z 0)k = (z0)nH(z)| z=z0.

The eigenvalue H(z)|z=z0 can be obtained from the transfer function

H(z) = n=h[n]zn,

which is the Z-transform of the system’s impulse response. As a special case, when |z| = 1, the eigenfunction ejΩn has its amplitude and phase eventually modified by a LTI as depicted by:

ejΩ0n H H(ejΩ0 )ejΩ0n.

Example 3.4. LTI filtering of discrete-time complex exponentials. This example describes how an LTI system filters a complex exponential. Consider that x[n] = 4ej0.5πn + 4ej0.5πn = 8cos (0.5πn) is the input of an LTI with h[n] = 0.7nu[n]. The eigenvalues can be obtained from H(ejΩ) = F{h[n]} = 1 10.7ejΩ when Ω = 0.5π rad. The Matlab/Octave commands omega=pi/2; H=1/(1-0.7*exp(-j*omega)) calculate H(ejΩ)|Ω=0.5π = 0.6711 0.4698j. Because h[n] is real-valued, the frequency response presents Hermitian symmetry. The commands abs(H), angle(H) can transform from Cartesian to polar: H(ejΩ)|Ω=0.5π 0.8192ej0.6107. Therefore, the output is y[n] = (0.8192ej0.6107)4ej0.5πn+(0.8192ej0.6107)4ej0.5πn = 3.2769ej(0.5πn0.6107)+3.2769ej(0.5πn+0.6107) = 6.5539cos (0.5πn0.6107). The effect of the LTI system was to impose a gain of 0.8192 and a phase of 0.6107 rad.

PIC

Figure 3.9: Frequency response of H(ejΩ) = 1 10.7ejΩ represented in polar form: magnitude (top) and phase (bottom). The data tips indicate the values for Ω = π2 rad.

PIC

Figure 3.10: Version of Figure 3.9 obtained with the command freqz(1,[1 -0.7]).

Figure 3.9 depicts the frequency response for a range Ω = [15,15] rad. As expected, H(ejΩ) is periodic because H(ejΩ) = H(ej(Ω+2π)). Given this periodicity and the Hermitian symmetry (when h[n] is real), it is common to plot only the positive frequencies in the range Ω = [0,π]. For example, Figure 3.10 shows the plots obtained with the command freqz(1,[1 -0.7]), which shows the frequency response of H(ejΩ) with the magnitude in dB, the phase in degrees (instead of rad) and the abscissa in a “normalized frequency” Ωπ that maps [0,π] into [0,1].    

3.4.7  Fourier convolution property

The convolution property of Fourier transforms states that the convolution between two signals has a Fourier transform given by the multiplication of their Fourier transforms. In other words, the convolution between these signals by can be obtained as the inverse Fourier transform of the multiplication of their Fourier transforms. For example, assuming continuous-time, the convolution y(t) = x1(t)x2(t) can be obtained with

y(t) = F1{X 1(f)X2(f)},
(3.5)

where X1(f) and X2(f) are the corresponding Fourier transforms. Similarly, in discrete-time, the convolution result y[n] can be written as

y[n] = x1[n]x2[n] = DTFT1{X 1(ejΩ)X 2(ejΩ)},
(3.6)

where X1(ejΩ) and X2(ejΩ) are the corresponding DTFTs and, in this case, F1 denotes the inverse DTFT.

Example 3.5. Convolution using DTFTs and inverse DTFT. For example, if x1[n] = α1nu[n] and x2[n] = α2nu[n] are two discrete-time complex exponentials with |α1| < 1 and |α2| < 1, their DTFTs are Xi(ejΩ) = 1 αiejΩ,i = 1,2, respectively. The convolution result is

y[n] = x1[n]x2[n] = 1 α1 α2 (α1n+1u[n] α 2n+1u[n])
(3.7)

and can be obtained via the inverse DTFT of Y (ejΩ), which is given by

Y (ejΩ) = X 1(ejΩ)X 2(ejΩ) = 1 (1 α1ejΩ)(1 α2ejΩ).
(3.8)

Eq. (3.7) can be obtained by using partial fraction expansion of Eq. (3.8).    

Due to the duality of Fourier transforms, the multiplication in time-domain corresponds to convolution in frequency-domain between the respective spectra. This is called the multiplication property and corresponds to

x1(t)x2(t) X1(f)X2(f) =X 1(p)X2(f p)dp.
(3.9)

in continuous-time.

In discrete-time, one needs to take in account that the spectra are periodic and the conventional convolution is not adequate when both signals are periodic. In fact, the multiplication property for discrete-time signals is

x1[n]x2[n] 1 2π<2π>X(ejΩ)X 2(ej(Ω𝜃))d𝜃.
(3.10)

The integral in Eq. (3.10) differs from a conventional convolution because it is calculated over only one period (2π rad in this case) and the result is normalized by this period. This modified convolution is denoted as and is called periodic, cyclic or circular convolution. As in a Fourier series expansion to obtain coefficients ck, the associated period must be known in order to properly use . The normalization by the period can be incorporated in its definition, which leads to the following expression for the periodic convolution:

x1(t)x2(t) = 1 T<T>x1(τ)x2(t τ)dτ,
(3.11)

where both signals are periodic in T.

The definition of Eq. (3.11) allows to write Eq. (3.10) as

x1[n]x2[n] X(ejΩ)X 2(ejΩ),
(3.12)

where the period 2π is implicit.

The periodic convolution corresponds to performing the conventional convolution (called “linear” convolution, in contrast to “circular”) between x1(t) and x 2(t), where x 2(t) is a single period of x2(t) that is normalized by the period T. The interval to define x 2(t) can be conveniently chosen as x2(t) = x2(t)T,0 t < T, or 0 otherwise, or x2(t) = x2(t)T,T2 t < T2, or 0 otherwise.

As discussed in the sequel, the periodic convolution is typically associated to FFT-based processing.

3.4.8  Circular and fast convolutions using FFT

Recalling that the FFT corresponds to sampling the DTFT, Eq. (3.6) suggests that FFTs can be used to efficiently compute a convolution. However, even if x[n] were not periodic, when its DTFT X(ejΩ) is sampled (in frequency domain) by the FFT, the FFT values X[k] are representing the spectrum of a periodic version of x[n]. Consequently, when FFTs substitute DTFTs in Eq. (3.6), the result is not the linear but the circular convolution represented as

y[n] = x1[n]x2[n] = FFT1{X 1[k]X2[k]},
(3.13)

where both FFTs must have the same length N, which plays the whole of the period of a circular convolution.

Listing 3.6 provides an example of using Eq. (3.13). Note how zero-padding is used to assure the element-wise multiplication fft(x,N).*fft(h,N) uses arrays with the same length. The result of Listing 3.6 confirms that, in general, linear and circular convolution differ.

Listing 3.6: MatlabOctaveCodeSnippets/snip_systems_circularConvolution.m. [ Python version]
1x=[1 2 3 4]; h=[.9 .8]; %signals to be convolved 
2shouldMakeEquivalent=0 %in general, linear and circular conv. differ 
3if shouldMakeEquivalent==1 
4    N=length(x)+length(h)-1; %to force linear and circular coincide 
5else 
6    N=max(length(x),length(h)); %required for FFT zero-padding 
7end 
8linearConv=conv(x,h) %linear convolution 
9circularConv=ifft(fft(x,N).*fft(h,N)) %circular convolution, N=4 
10%circularConv=cconv(x,h,N) %note that Matlab has the cconv function
  

If the value of shouldMakeEquivalent is made equal to 1, Listing 3.6 returns the same results for both linear and circular convolutions. In fact, when the FFT length is at least the number of non-zero samples of the convolution output, the circular and linear convolution results coincide. This suggests that Eq. (3.13) can be used to calculate a linear convolution, provided that the FFT length is made long enough.

Obtaining a linear convolution via FFTs is trickier when one of the signals to be convolved has infinite duration. In this case, it is obviously not possible to find a large enough FFT length to use Eq. (3.13). However, if the other signal has finite duration, it is feasible and often used in practice to segment the long signal into blocks and calculate the linear convolution by sequentially calculating one FFT per block and properly combining the results. There are basically two alternatives to combine the intermediate results that are called overlap-add and overlap-save methods, and are roughly equivalent. Listing 3.7 illustrates the former.

Listing 3.7: MatlabOctaveCodeSnippets/snip_systems_overlapAdd.m. [ Python version]
1x=1:1000; %infinite duration (or "long") input signal 
2h=ones(1,3); %non-zero samples of finite-length impulse response 
3Nh=length(h); %number of impulse response non-zero samples 
4Nb=5; %block (segment) length 
5Nfft=2^nextpow2(Nh+Nb-1); %choose a power of 2 FFT size 
6Nx = length(x); %number of input samples 
7H = fft(h,Nfft); %pre-compute impulse response DFT, with zero-padding 
8beginIndex = 1; %initialize index for first sample of current block 
9y = zeros(1,Nh+Nx-1); %pre-allocate space for convolution output 
10while beginIndex <= Nx %loop over all blocks 
11    endSample = min(beginIndex+Nb-1,Nx);%last sample of current block 
12    Xblock = fft(x(beginIndex:endSample),Nfft); %DFT of block 
13    yblock = ifft(Xblock.*H,Nfft); %get circular convolution result 
14    outputIndex  = min(beginIndex+Nfft-1,Nh+Nx-1); %auxiliary variab. 
15    y(beginIndex:outputIndex) = y(beginIndex:outputIndex) + ... 
16        yblock(1:outputIndex-beginIndex+1); %add parcial result 
17    beginIndex = beginIndex+Nb; %shift begin of block 
18end 
19stem(y-conv(x,h)) %compare the error with result from conv
  

A typical application of the overlap-add and overlap-save methods is to compute the output of a LTI system represented by a finite-duration impulse response (i. e., a FIR filter, as will be discussed in Section 3.14). Listing 3.7 provides an example where the impulse response has only three non-zero samples, and the long input signal is segmented in blocks of Nb=5 samples.