D.10  Applications

This section will briefly discuss some applications of transforms.

Application D.1. Time-localization property of Haar coefficients.

PIC
Figure D.33: Signal x[n] = δ[n − 11] analyzed by 32-point DCT and Haar transforms. The right column shows the transform coefficients (abscissa is k). The left column shows time-domain plots. Below the signal itself, one can visualize the “best” (the one corresponding to the coefficient with largest absolute value) basis functions for each transform.

A very simple experiment will help illustrating the time-localization property of Haar functions. Consider the signal to be analyzed in the transform domain is a single impulse x[n] = δ[n − n0],n0 = 0,…,31, which will be represented by a vector x will zeroed elements but the one corresponding to the n0 position. The script MatlabOctaveBookExamples/ex_transforms_dcthaar_example.m can be used to observe the behavior of the transforms. Figure D.33 shows the output of the script when the signal is x[n] = δ[n − 11]. In this case, many Haar coefficients are zero and the one with largest magnitude (k = 21) has a corresponding basis function (bottom of the left column) that helps to localize the occurrence of the impulse in x[n]. In contrast, most DCT coefficients have relatively large values and the basis functions do not help in time-localization. The mentioned script allows to investigate this aspect more deeply. Compare the results of DCT and Haar transforms when the signal is a cosine summed to an impulse.   

Application D.2. Inverse Laplace transforms with Matlab’s Symbolic Math Toolbox. Keeping in mind that Matlab adopts the unilateral Laplace transform, its Symbolic Math Toolbox can be used to calculate Laplace transforms and their inverses. For example, the unilateral Laplace transform X(s) = 1∕s of u(t) can be obtained with the commands syms t; laplace(t / t). Similarly, the commands syms w0,t; laplace(sin(w0*t)) indicate that X(s) = ω0∕(s2 + ω02) for x(t) = sin(ω0t)u(t). The following commands illustrate the inverse transform of X(s) given by Eq. (D.54):

Listing D.4: MatlabOnly/snip_transforms_ilaplace.m. [ Python version]
1syms s %defines s as a symbolic variable 
2a=1; b=-2; c=-1+j*2; %choose poles and zeros 
3X=(s-a)/((s-b)*(s-c)*(s-conj(c))); %define X(s) 
4ilaplace(X) %Matlab's inverse unilateral Laplace transform

The command pretty (e. g., pretty(ilaplace(X))) can be used to beautify the output, which in this case is - 3/5 exp(-2 t) + 1/5 exp(-t) (3 cos(2 t) + sin(2 t)). Find the inverse Laplace transform for other signals, such as x(t) = cos(ω0t)u(t).    

Application D.3. ECG transform coding. Because a block transform is completely specified by an invertible matrix A, going from one domain to another (x to X or vice-versa) is loss-less, which means there is no loss of information. In many applications, such as image coding, where the goal is to minimize the number of bits to represent an image, it is useful to compress the signal using a lossy algorithm. Transform coding can be a lossy algorithm when it discards or quantizes coefficients in the transform domain. This is effective in many applications because, while all samples in x have the same “importance”, in the transform domain X the coefficients can be organized according to some hierarchy or rank. In transform coding the most “important” coefficients are quantized more carefully than the unimportant ones.

Figure D.34 depicts a segment (first 1,500 samples) of an ECG signal. The ECG data used here is from the MIT-BIH Arrhythmia Database.18, and Figure D.34 corresponds to the first channel of file 12531_04.dat. The function ak_rddata.m indicates that the DC offset of the ADC chip was calibrated to be zero. It also indicates that the ECG signals were digitized with a sampling frequency Fs = 250 Hz, 12 bits per sample, and a quantizer with step ΔAD = 1∕400 mV. The (empirical) signal power is 3.07 mW and, following the conventional quantization model, Eq. (C.20) suggests the quantization noise power was 5.2 × 10−10 mW. Hence, the SNR corresponding to the quantization stage alone is approximately 97.7 dB.

PIC
Figure D.34: A segment of one channel of the original ECG data.

A very simple example of a transform coding system is provided as Matlab/Octave code in the companion software (in directory Applications/ECGTransformCoding). The idea is to simply discard the higher-order coefficients in the transform domain. For example, assume that N is the dimension of x and X, which are related by a N × N transform matrix A. In the encoding stage, a discrete-time input signal x[n] is segmented into blocks of dimension N, composing a set of M input vectors {x1,…,xM}, where N × M is the available number of samples of x[n]. The coding scheme converts each xi into Xi = AHxi and keeps in a new vector X^i only the first K ≤ N elements of Xi (the remaining N − K are discarded). The M vectors X^i can be concatenated to create an encoded output signal X^[n] with M × K samples.

In the decoding stage, in order to reconstruct a signal x ′[n] from X^[n] (if there were no losses, x ′[n] = x[n]), an inverse procedure is adopted. The signal X^[n] is blocked into vectors of dimension K and N − K zero elements are inserted to create vectors X i of dimension N (this operation is called zero-padding). Each of these N-dimensional vectors is converted to time-domain vectors x i = AX i, which are then concatenated to form x ′[n].

Figure D.35 was obtained using a DCT matrix A of N = 32 points and discarding 26 (high-frequency) coefficients. It can be seen that keeping only K = 6 out of 32 coefficients is enough to provide a rough representation of x[n] but the error is significant in high-frequency regions. Note that the DCT operation is performed in blocks of N = 32 samples and Figure D.35 is the result of processing many of these blocks.

PIC
Figure D.35: Original and reconstructed ECG signals with DCT of N = 32 points and discarding 26 (high-frequency) coefficients. Therefore, the error is predominant in high-frequency regions as indicated in the plot.

In practice, a quantization scheme should be adopted to represent X^[n] with a small number of bits per sample. The compression ratio is the number of bits to represent x[n],n = 0,…,M × N divided by the number of bits to represent X^[n],n = 0,…,M × K. For simplicity, the proposed example does not involve quantization and the compression ratio is evaluated by N∕K. This corresponds to assuming that each sample of both x[n] and X^[n] is represented with the same number of bits.

Figure D.36 shows the percentage of kept coefficients K∕N in the abscissa and 10log10MSE in the ordinate, where

MSE = 1 M × Nn=0M×N−1(x[n] − x ′[n])2

is the mean-squared error, which is equivalent to the power of the error signal. If K = N (100% in the abscissa) the system is lossless and MSE = 0 ( −∞ in log scale), so the graphs do not show these points. The larger N, the better the coding performance but the higher the computational cost.

Assuming N = 128 and K = 10 as indicated in Figure D.36, the abscissa is K∕N = 10∕128 ≈ 7.81% and the corresponding error is MSE = 1.4824 × 10−8 W ( − 78.29 dBW) or, equivalently, − 48.29 dBm. Given that the signal power was estimated as 3.07 mW (4.87 dBm), the SNRdB ≈ 4.87 + 48.3 = 53.16 dB when considering only the distortion incurred by this specific encoding procedure.

PIC
Figure D.36: Performance of five DCT-based ECG coding schemes. The number of points is varied N ∈{4,8,32,64,128} and K = 1,2,…,M − 1. The larger N, the better the coding performance but the higher the computational cost.

It should be noted that the dataset used is formed by abnormal ECG signals and, eventually, better results could be obtained when using another dataset.

Write an encoder that uses DCT coding to generate files of a relatively small size and a decoder to “decompress” such files and recover an ECG signal (an approximation to the original one). To do that, it is necessary to quantize the DCT coefficients and pack them in a way that the resulting file has a small size. Consider using scalar or vector quantization. The advantage of vector quantization is that you need to store only the index to the codebook entry (codeword) with a vector that will represent the DCT. In case you use a codebook with 28 = 256 codewords, each entry can be conveniently written as an unsigned char of 8 bits. To design the codebook, besides the Mathwork’s code in the DSP System Toolbox, there are many algorithms such as the K-means with implementations available on the Web.

Another interesting exercise is to apply KLT and other transforms to this problem, trying to get better results than with the DCT.    

Application D.4. DCT coding of image.

The usefulness of DCT in coding is illustrated by the JPEG image coding standard.19 Before describing an example, two dimensional transforms are briefly discussed.

Linearly-separable two dimensional (2-D) transforms of a block x (e. g., a matrix with pixel values) is obtained by first using the transform along the rows (or columns) and then transforming this result along the columns (or rows). Alternatively, one can use matrix notation: X = AHxA. Because, A is real for a DCT, one has

X = AT xA.

This is equivalent to first calculating T = AHx: the 1-D DCT transform of each column of x is placed in its corresponding column in a temporary matrix T. Then, each row of T is transformed by another 1-D DCT, which could be accomplished by AHTT . This result should be transposed to generate X. These operations are equivalent to:

X = (AH(AHx)T )T = AHxA.
PIC
Figure D.37: A zoom of the eye region of the Lenna image.

Listing D.5 illustrates the adoption of a 2-D DCT for coding an image block (represented by a matrix).

Listing D.5: MatlabBookFigures/figs_transforms_dctimagecoding
1%load black & white 256 x 256 pixels of Lenna: 
2fullPath='lenna_bw.gif' %file location 
3  [lenaImage,map]=imread(fullPath); %read file 
4colormap(map); %use the proper color map 
5x1=128; x2=135; y1=160; y2=167; %to take a 8x8 block close to her eye 
6x=lenaImage(x1:x2,y1:y2); %get the region 
7x=double(x); %cast x to be double instead of integer 
8%draw a rectangle to indicate the block: 
9lenaImage(x1,y1:y2)=1; lenaImage(x2,y1:y2)=1; 
10lenaImage(x1:x2,y1)=1; lenaImage(x1:x2,y2)=1; 
11imagesc(lenaImage) %show the image 
12axis equal %correct the aspect ratio 
13%Some calculations to practice: 
14X=octave_dct2(x); %calculate forward DCT 
15x2=octave_idct2(X); %calculate inverse DCT to check 
16numericError = max(x(:)-x2(:)) %any numeric error? 
17Ah=octave_dctmtx(8); %now calculate in an alternative way 
18X2 = Ah*x*transpose(Ah); 
19%X2 = transpose(Ah)*x*Ah; %Note: this would be wrong! 
20numericError2 = max(X(:)-X2(:)) %any numeric error?

Similar to the 1-D ECG coding example in Application D.3, few DCT coefficients can be enough to represent an image. Study the code MatlabOctaveFunctions/ak_dctdemo.m using DCT to represent different images,20 including ones with text. Even better results can be obtained with the wavelet transform, which is used in the JPEG 2000 image coding standard. Write an encoder and decoder that use a transform to compress and decompress an image file.    

Application D.5. Orthogonality of continuous-time sinusoids over a given interval. In applications such as frequency modulation, it is important to know the conditions in which two cosines with frequencies f1 and f2 and phase 𝜃, are orthogonal over a given interval Tsym of interest. Mathematically, this requirement can be expressed as

<Tsym> cos(2πf1t + 𝜃)cos(2πf2t + 𝜃) = 0

and, because the phase 𝜃 is the same for both cosines, this requirement is called “coherent orthogonality”. It can be shown21 that this condition is satisfied with integers m and n such that

f1 = 2n − m 4Tsym ,f2 = 2n + m 4Tsym  and f2f1 = m 2Tsym.

For example, assume that Tsym = 0.01 seconds, m = 4 and n = 35. In this case, f1 and f2 are 1650 and 1850 Hz, respectively. Note that the minimum value of f2f1 is 1∕(2Tsym) = 50 Hz in this case, which corresponds to choosing m = 1.

As a side note, for “noncoherent orthogonality”, the minimum frequency separation22 is 1∕Tsym.    

Application D.6. Orthogonality of finite duration discrete-time sinusoids. It is also important to evaluate in what conditions a pair of discrete-time sinusoids are orthogonal considering a finite duration interval.

Two discrete-time exponentials ejΩ0n and ejΩ1n, Ω0Ω1, are always orthogonal when summed over a range −∞ to (see Example D.1), but this is not the case when the summation interval is finite. One way of inspecting what happens when the duration is finite is to reason as following: 1) keep in mind that the sum of the samples of a single sinusoid over a multiple of its fundamental period is zero. 2) Interpreting Example D.3 in discrete-time allows to decompose the inner product for testing orthogonality into a sum of two sinusoids. 3) the inner product is mapped to summations of sinusoids with frequencies equal to Ω0 + Ω1 and Ω0Ω1 and the goal is to find an integer N that is a multiple of both fundamental periods.

One application of this orthogonality principle is the design of a binary transmission, where the two signals are distinguished by their frequencies f0 and f1. This scheme is called frequency shift keying (FSK). We are interested on determining the minimum symbol period that guarantees orthogonality between the two sinusoids. In the context of telecommunications, this minimum period will correspond to the highest symbol rate. The script MatlabOctaveBookExamples/ex_transforms_check_orthogonality.m can be used for studying this question and is repeated below. The sampling frequency is Fs and one should check different pairs of f0 and f1.

Listing D.6: MatlabOctaveBookExamples/ex_transforms_check_orthogonality.m
1if 1 %choose between two options 
2    f0 = 980;   %frequency of first sinusoid (in telecom, of bit 0) 
3    f1 = 1180;   %frequency of 2nd sinusoid (in telecom, of bit 1) 
4else %another example 
5    f0 = 1650; %1st sinusoid 
6    f1 = 1850; %2nd sinusoid 
7end 
8Fs=9600; %assumed sampling frequency 
9sumSinusoidFrequency = f0+f1; 
10subractSinusoidFrequency = f1-f0; 
11%reduce numbers to rational forms 
12[m,n]=rat(sumSinusoidFrequency/Fs) 
13[p,q]=rat(subractSinusoidFrequency/Fs) 
14Nmin = lcm(n,q) %find the least commom multiple 
15disp(['Minimum common period: ' num2str(Nmin)]) 
16T_duration = Nmin / Fs; %minimum number of samples in seconds 
17%disp(['Maximum symbol rate: ' num2str(1/T_symbolDuration) ' bauds']) 
18%% Check if the product of the two sinusoids is really orthogonal 
19Tsum = 1 / sumSinusoidFrequency; 
20Tsub = 1 / subractSinusoidFrequency; 
21disp('Numbers below should be integers:') 
22T_duration/Tsum 
23T_duration/Tsub 
24Ts=1/Fs; %sampling interval 
25t = 0:Ts:T_duration-Ts; %generate (discrete) time 
26%use sin or cos with arbitrary phase 
27b0 = sin(2*pi*f0*t+4)';  %column vector 
28b1 = sin(2*pi*f1*t)';  %column vector 
29normalizedInnerProduct = sum(b0.*b1) / length(b0) %inner product 
30if (normalizedInnerProduct > 1e-13) 
31    error('not orthogonal! should not happen!'); 
32end

Modify Listing D.6 to use discrete-time sinusoids in radians, not Hz. Assume N = 8 and find a set of M sinusoids that are mutually orthogonal over an interval of eight consecutive samples. What was the maximum value of M that you could find? Now, consider the set of basis functions for a N-point DFT and evaluate their orthogonality. Going back to the question about M, can it be larger than N? Why?   

Application D.7. Better visualizing the FFT spectrum: Using fftshift to reorganize the spectrum and masking numerical errors. Two improvements of the procedure adopted to obtain Figure D.14 are typically used. The first one is with respect to the range k = ⟨N⟩. Figure D.14 reminds that the definition of an N-point DFT assumes k = 0,…,N − 1. Sometimes it is more convenient to work with ranges that use “negative” frequencies. Typical ranges are k = −N∕2,−N∕2 + 1,…,0,1,N∕2 − 1 when N is even and − (N − 1)∕2,−(N − 1)∕2 + 1,…,0,1,(N − 1)∕2 when N is odd. In these cases, to represent negative frequencies (or angles in discrete-time processing) the command fftshift can be used. For example, fftshift([0 1 2 3]) returns [2 3 0 1], while fftshift([0 1 2 3 4]) returns [3 4 0 1 2].

PIC
Figure D.38: Alternative representation of the DTFS / DFT of x[n] = 10cos(π 6 n + π∕3) using fftshift. Compare with Figure D.14 and note that the current plots clearly indicates that when x[n] is real, the magnitude and phase are even and odd functions, respectively.

The second one aims at eliminating spurious values. Note that, due to numerical errors, the elements of X that should be zero, have small values such as -1.4e-15 - j 3.3e-16, which leads to random angles for k≠1,11 in Figure D.14. It is a good practice to eliminate these random angles based on a threshold for the magnitude. This post-processing step can be done with a command such as X(abs(X) < 1e-12)=0, and is adopted in the Matlab/Octave fft routine.

Figure D.38 benefits from these two improvements and was obtained using Listing D.7.

Listing D.7: MatlabOctaveCodeSnippets/snip_transforms_fftshift.m
1k=-N/2:N/2-1; %range with negative k (assume N is even) 
2X(abs(X)<1e-12)=0;%discard small values (numerical errors) 
3X=fftshift(X); %rearrange to represent negative freqs. 
4subplot(211);stem(k,abs(X));subplot(212);stem(k,angle(X));

Note that fftshift does not calculate the FFT but simply reorders the elements in a vector.    

Application D.8. DTFS analysis of single cosines. Figure D.39 depicts five cosines xi[n] = 10cos(Ωin) with angular frequencies Ωi = i2π∕32 rad, where i = 0,1,2,16,31, and their respective DTFS spectrum calculated with a DFT of N = 32 points and normalized by N.

PIC
Figure D.39: Five cosine signals xi[n] = 10cos(Ωin) with frequencies Ωi = 0, 2π∕32, 4π∕32, π, 31π∕16 for i = 0,1,2,16,32, and the real part of their DTFS using N = 32 points.

The first x0[n] = 10 is a DC signal (Ω0 = 0), the second is x1[n] = 10cos(2π∕32n), where Ω1 = 32 is the fundamental frequency in this DTFS analysis (given that N = 32) and the other three signals are cosines with the following harmonic frequencies: Ω2 = 2Ω1, Ω16 = 16Ω1 and Ω31 = 31Ω1 rad. Because the cosines are even functions, the imaginary part of their DTFS is zero.

Note in Figure D.39 that the frequency increases up to the N∕2-th harmonic Ω16 = 16Ω0 = π. When N is even, the coefficient of k = N∕2 corresponds to Ω = N k|k=N∕2 = π. It is important to note that the highest “frequency” of a discrete-time signal is always Ω = π rad.

Another aspect of Figure D.39 is that for x0[n] and x16[n], corresponding to the angles Ω = 0 and Ω = π, the spectra have only one non-zero coefficient X[k], while the other three signals are represented by two coefficients. Figure D.7, for N = 4 and N = 6 can be invoked to help interpreting why the coefficients for angles different than Ω = 0 and Ω = π occur in pairs with Hermitian symmetry (i. e., X[k] = X[−k] when x[n] is real). The basis functions for Ω = 0 and Ω = π are real signals while the other angles lead to complex-valued signals. In the analysis of a real signal x[n], using the k-th complex basis requires also using the − k-th basis, such that their imaginary parts can cancel in the synthesis of a real x[n].    

Application D.9. DTFS analysis of a sum of sines and cosines. This example aims at illustrating how the cosines and sines are mapped in the DTFS, especially when two of them have the same frequency. Figure D.40 shows the spectrum of a more complex example obtained with Listing D.8.

Listing D.8: MatlabOctaveCodeSnippets/snip_transforms_DTFS_sinusoid.m. [ Python version]
1N=32; %number of DFT-points 
2n=0:N-1; %abscissa to generate signal below 
3x=2+3*cos(2*pi*6/32*n)+8*sin(2*pi*12/32*n)-... 
4    + 4*cos(2*pi*7/32*n)+ 6*sin(2*pi*7/32*n); 
5X=fft(x)/N; %calculate DTFS spectrum via DFT 
6X(abs(X)<1e-12)=0; %mask numerical errors
PIC
Figure D.40: Analysis with DFT of 32 points of x[n] composed by three sinusoids and a DC level. From top to bottom: x[n], real, imaginary, magnitude and phase of X[k].

Note in Figure D.40 that the coefficient X[0] = 2 is due to the DC level, X[6] = X[−6] = 1.5 are due to the cosine 3cos(6(2π∕32)n), X[12] = −4j and X[−12] = 4j are due to 8sin(12(2π∕32)n), X[7] = −2 − 3j and X[−7] = −2 + 3j are due to the two parcels of frequency 7(2π∕32) with the − 4cos(7(2π∕32)n) being represented by the real part ( − 2) and 6sin(7(2π∕32)n) represented by the imaginary part (3j).   

Application D.10. Spurious frequency components: When the number N of DFT points is not a multiple of the signal period. Figure D.41 illustrates the DTFS spectrum of a signal x[n] = 4cos((2π∕6)n) with period of 6 samples obtained via a 16-point DFT. Note that because 16 is not a multiple of 6, the spectrum has many non-zero spurious components. The coefficients X[3] = 0.99 − 1.48j and X[−3] = 0.99 + 1.48j, both with magnitude 1.78, are the closest to representing the angle π∕3 ≈ 1.05 rad. In fact, when using N = 16 points to divide (see Figure D.7), the angle increment is

ΔΩ = N ,
(D.64)

which in this case is ΔΩ = π∕8 ≈ 0.39, and the DFT / DTFS can deal only with the angles [0,0.39,0.78,1.18,1.57,…,5.89] rad. This explains why X[3] and X[−3] are concentrating most of the power P = 42∕2. The other coefficients absorb the remaining power that “leaks” due to the imperfect match of the cosine frequency π∕3 with the discrete grid of 16 points imposed by the DFT / DFTS.

PIC
Figure D.41: Spectrum of a signal x[n] = 4cos((2π∕6)n) with period of 6 samples obtained with a 16-point DFT, which created spurious components.

The creation of spurious components is associated to leakage and the picket-fence effect, which are discussed in Section F.3. This phenomenon is very common when using the FFT to analyze signals that are non-periodic, have infinite duration, etc. In the current case, the spurious components could be avoided by choosing an appropriate number of points for the DFT / DTFS (a multiple of 6). In practice, spurious components due to FFT usage occur most of the times. Even when the original signal is periodic, say x(t) with period T, it is typically not guaranteed that NTs is a multiple of T, where N is the number of DFT points and Ts the sampling period.

PIC
Figure D.42: Explicitly repeating the block of N cosine samples from Figure D.41 to indicate that spurious components are a manifest of the lack of a perfect cosine in time-domain.

Figure D.42 shows part of the signal obtained by repeating the segment of 16 samples depicted in Figure D.41. This represents the signal “assumed” by the DFT / DTFS. Spurious components appear because, in spite of x[n] having a period of N = 6, an abrupt transition (from − 4 to 4) occurs in the boundary of the segments of 16 samples. In general, the periodic extension (that is assumed by the FFT when approximating a DTFS) of a signal x[n] not commensurate23 with its period, leads to discontinuities at the boundaries of the replicas of x[n].    

Application D.11. DTFS for periodic discrete-time pulses. Assume a periodic train of pulses x[n] with period N and one period described as x[n] = 1 from n = 0 to N1 − 1 and x[n] = 0 from N1 to N − 1. Its DTFS coefficients are given by

X[k] = 1 Nn=0N−1x[n]e−j N nk = 1 Nn=0N1−1e−j N nk = 1 Nn=0N1−1 (e−j N k) n,

which is the sum of N1 terms of a geometric series with ratio r = e−j N k. Applying Eq. (A.16) leads to

X[k] = 1 N (1 − e−j N N1k 1 − e−j N k ) .

This expression can be simplified by applying Eq. (A.14) to both numerator and denominator:

X[k] = 1 N sin(kN1π∕N) sin(kπ∕N) e−j N (N1−1),
(D.65)

for k = 0,…,N − 1 and then periodically repeated in k. For k = 0 the expression is undetermined (because of the 0∕0 fraction) and L’Hospital’s rule leads to X[0] = N1∕N.

Listing D.9 obtains the DTFS of the periodic pulses in two distinct ways.

Listing D.9: MatlabOctaveCodeSnippets/snip_transforms_DTFS_pulses.m. [ Python version]
1N=10; N1=5; k=0:N-1; %define durations and k 
2Xk=(1/N)*(sin(k*N1*pi/N)./sin(k*pi/N)) .* ... 
3    exp(-j*k*pi/N*(N1-1)); %obtain DTFS directly 
4Xk(1)=N1/N; %eliminate the NaN (not a number) in Xk(1) 
5%second alternative, via DFT. Generate x[n]: 
6xn=[ones(1,N1) zeros(1,N-N1)] %single period of x[n] 
7Xk2=fft(xn)/N %DTFS via DFT, Xk2 is equal to Xk
PIC
Figure D.43: Three periods of each signal: pulse train x[n] with N = 10 and N1 = 5 and amplitude assumed to be in volts (a), the magnitude (b) and phase (c) of its DTFS.

Figure D.43 illustrates the result using N = 20 and N1 = 10. Note that |X[k]| has the behavior of a sinc function, as expected. The DTFS phase in Figure D.43 c) is the combined effect of the linear phase e−j N (N1−1) and the sign of sin(kN1π∕N)∕sin(kπ∕N) in Eq. (D.65). This sign is responsible for Figure D.43 c) not being a linear function of frequency.

PIC
(a) N1 = 4
PIC
(b) N1 = 3

PIC
(c) N1 = 2
PIC
(d) N1 = 1
Figure D.44: Behavior when N1 of Figure D.43 is decreased from N1 = 4 to 1.

Figure D.44 shows the behavior of the DTFS of x[n] when N1 of Figure D.43 is decreased from N1 = 4 to 1 Note the duality between time and frequency: as the pulse duty cycle gets smaller (smaller N1), the spectrum gets wider and with smaller maximum values. When N1 = 1, then |X[k]| = N1∕N = 0.05. Also, in this case, N1 dictates the number of nulls in the spectrum, while N controls how the unit circle ejΩ is sampled by the DFT.   

Application D.12. Calculating the DTFT of a pulse via the DFT. Following steps similar to the ones that led to Eq. (D.65), the DTFT pair of a pulse is given by

x[n] = { 1,0 ≤ n ≤ N1 − 1 0,otherwise sin(ΩN1∕2) sin(Ω∕2) e−jΩ(N1−1)∕2
(D.66)

Listing D.10 illustrates how to obtain samples of the DTFT for a pulse with N1 = 5 non-zero samples using a DFT of N = 20 points.

Listing D.10: MatlabOctaveCodeSnippets/snip_transforms_DTFT_pulse.m. [ Python version]
1N=20; %DFT size 
2N1=5; %num. non-zero samples in the (aperiodic) pulse 
3x=[ones(1,N1) zeros(1,N-N1)]; %signal x[n] 
4N2=512; %num. samples of the DTFT theoretical expression 
5k=0:N2-1; %indices of freq. components 
6wk = k*2*pi/N2; %angular frequencies 
7Xk_fft = fft(x); %use N-point DFT to sample DTFT 
8Xk_theory=(sin(wk*N1/2)./sin(wk/2)).*exp(-j*wk*(N1-1)/2); 
9Xk_theory(1) = N1; %take care of 0/0 (NaN) at k=0 
10subplot(211); stem(2*pi*(0:N-1)/N,abs(Xk_fft)); 
11hold on, plot(wk,abs(Xk_theory),'r'); 
12subplot(212); stem(2*pi*(0:N-1)/N,angle(Xk_fft)); 
13hold on, plot(wk,angle(Xk_theory),'r');

The code plots the DTFT superimposed to the DFT result, as illustrated in Figure D.45.

PIC
Figure D.45: DTFT of an aperiodic pulse with N1 = 5 non-zero samples and DTFT estimates obtained via a DFT of N = 20 points.

As stated by Eq. (D.35), Figure D.45 pictorially illustrates that the DFT values at the discrete frequencies Ωk = k(2π∕N) coincide with the DTFT of the aperiodic pulse x[n] calculated at these frequencies using Eq. (D.66).

PIC
Figure D.46: A version of Figure D.45 using a DFT of N = 256 points.

The DTFT can be calculated in a grid of frequencies with arbitrary resolution by increasing the number N of DFT points. For example, using N = 256 leads to the spectrum in Figure D.46. Note that if x has less than N samples, the command fft(x,N) conveniently extends its duration with zero-padding.    

Application D.13. Calculating the DTFT using Matlab/Octave’s freqz. When N is relatively large, it is more convenient to use plot instead of stem (as in Figure C.19), in spite of X[k] being discrete. This is also convenient when X[k] is used to represent values of X(ejΩ) as in this example. Matlab/Octave has the command freqz that uses the DFT to calculate the DTFT at a grid of discrete frequencies. Assuming the same vector x of the previous code snippet, the command freqz(x) generates Figure D.47.

PIC
Figure D.47: A version of Figure D.45 using freqz with 512 points representing only the positive part of the spectrum.

Note that Figure D.46 and Figure D.47 provide the same information in spite of looking quite different. For instance, Figure D.47 is not explicitly showing that the DTFT is being calculated only at a grid of discrete frequencies.

PIC
Figure D.48: Reproducing the graphs generated by freqz in Figure D.47.

To better understand how freqz works, Listing D.11 mimics freqz and was used to obtain Figure D.48.

Listing D.11: MatlabOctaveCodeSnippets/snip_transforms_freqz.m. [ Python version]
1N1=5; %num. non-zero samples in the (aperiodic) pulse 
2x=[ones(1,N1) zeros(1,2)]; %signal x[n] 
3halfN=512; N=2*halfN; %half of the DFT dimension and N 
4k=0:N-1; %indices of freq. components 
5wk = k*2*pi/N; %angular frequencies 
6Xk_fft=fft(x,N);%use 2N-DFT to get N positive freqs. 
7Xk_fft=Xk_fft(1:halfN);%discard negative freqs. 
8wk=(0:halfN-1)*(2*pi/N); %positive freq. grid 
9subplot(211); plot(wk,20*log10(abs(Xk_fft))); %in dB 
10subplot(212); plot(wk,angle(Xk_fft)*180/pi); %in degrees

It can be seen that Figure D.48 is very similar to Figure D.47. The only distinction is that, by default, Matlab/Octave represents the abscissa normalizing Ω by π, such that the maximum frequency is not π but 1. It is interesting to note that Matlab/Octave and GNU Radio, for example, indicate Ω in rad/sample, while this and other texts assume Ω is given in radians (n is dimensionless).