Discrete-Time Fourier Transform (DTFT) examples

Mathematica definitions

Load needed packages for this notebook

<< Graphics`Colors`;
<< Calculus`FourierTransform`;

Set up defaults

Turn off annoying warning messages

Off[General::spell];
Off[General::spell1];

Set default options for specific functions

SetOptions[Plot, Frame -> True];
SetOptions[ListPlot, Frame -> True,  PlotJoined -> True,  
        Axes -> {True, False}];
SetOptions[Fourier, 
        FourierParameters -> {1, -1}];
SetOptions[InverseFourier, 
        FourierParameters -> {1, -1}];
SetOptions[FourierTransform,  
        FourierParameters -> {0, -2 π}];
SetOptions[FourierTransform,  
        FourierParameters -> {0, -2 π}];
SetOptions[InverseFourierTransform,  
        FourierParameters -> {0, -2 π}];

Visualization functions

Fix time variable for sampled signals

FixTime[signal_, 
          sampleRate_] := 
Module[{time, 
            data}, 
time = 
            Table[i/sampleRate, {i, 1, 
                Length[signal]}]; 
data  =  {time, 
                signal} // Transpose
];

Generate periodic waveform from one period

PeriodicSignal[f, {dmin, dmax}, {t, min, max}] generates a periodic waveform for the interval [min, max]. It is assumed that one period of the function f(t) is defined over the interval [dmin, dmax].

PeriodicSignal[
          f_, {dmin_, dmax_}, {t_, min_, 
            max_}] := 
Module[{T, imin, 
            imax}, 
T  =  
            dmax  -  dmin; 
imin = 
            Floor[(min - dmin)/T]; 
imax = 
            Ceiling[(max - dmax)/T];  
Sum[
            f[t - i T] (UnitStep[t - dmin - i T]  -  
                  UnitStep[t - dmax - i T]), {i, imin, 
              imax}]
];

Plot periodic waveforms

PeriodicPlot[f, {dmin, dmax}, {t, min, max}, opts] plots a a periodic waveform for the interval [min, max]. It is assumed that one period of the function f(t) is defined over the interval [dmin, dmax]. The 'opts' argument passed plotting options to the Mathematica function Plot[ ].

PeriodicPlot[f_, {dmin_, dmax_}, {t_, min_, max_}, 
          opts___] := 
Module[{fnc}, 
fnc = PeriodicSignal[f, {dmin, dmax}, {t, min, max}]; 
Plot[
            fnc, {t, min, max}, opts]
];

Plot discrete-time signal as sequence of amplitude lines

DiscreteListPlot[signal_, color_:  Black, 
          opts___] := 
Module[{data, g1, 
            g2}, 
If[
            Length[signal[[1]]]  ==  2, 
data = 
              signal, 
data = 
              FixTime[signal, 
                1]
]; 
g1 = Line[{{#[[1]], 0}, {#[[1]], #[[2]]}}] &  /@  
              data; 
g2 = {PointSize[ .015], 
                  Point[#]} &  /@  data; 
Show[
            Graphics[{color, g1, g2}], 
            opts]
];

Plot discrete-time signal as sequence of amplitude lines

DiscreteListPlot2[signal_, color_:  Black, 
          opts___] := 
Module[{data, g1, 
            g2}, 
If[
            Length[signal[[1]]]  ==  2, 
data = 
              signal, 
data = 
              FixTime[signal, 
                1]
]; 
g1 = Line[{{#[[1]], 0}, {#[[1]], #[[2]]}}] &  /@  
              data; 
g2 = {PointSize[ .005], 
                  Point[#]} &  /@  data; 
Show[
            Graphics[{color, g1, g2}], 
            opts]
];

Fourier rearrange

FourierRearrange[fft] rearranges the result of an FFT (Mathematica function Fourier[ ]), to a easier to visualize the spectrum represented by 'fft'. The length of the list 'fft' is assumed to be even; if it is not, the last term in 'fft' is dropped.

FourierRearrange[fft_,  
          samplingRate_] := 
Module[{fft2, n, 
            n2}, 
If[EvenQ[Length[fft]],  
            fft2  =  fft,  
            fft2  =  Drop[fft, -1]];  
n = 
            Length[fft]; 
          n2 = n/2; 
{Table[ 
                samplingRate i/n, {i, -n2 + 1, n2}], 
              Take[fft2, {n2 + 2, n2*2}]~Join~Take[fft2, {1, n2 + 1}]} // 
            Transpose
];

Short-cut functions

Dirac delta function

δ[t_] := DiracDelta[t];

Unit step function

u[t_] := UnitStep[t];

Pulse of width w

p[t_, w_] := u[t + w/2] - u[t - w/2];

Hack to plot δ(t)

PlotConvert[X_, 
        w_] := 
X  /.  {δ[a_] -> 
            p[a, w]}

Sampler (CT to DT converter)

sampler[xc_, fs_, 
          range_: {0, 5}] := 
Table[{n, xc[n/fs]}, {n, 
            range[[1]]*fs, range[[2]]*fs}];

Sampled frequency spectrum

SampledSpectrum[X_, f_, fs_, n_:  5] := 
Sum[
          X[f - k fs], {k, -n, n}];

Definition of DTFT

DTFT[
          xd_, θ_] := 
Module[{n, xn, n1, 
            n2}, 
{n, xn}  =  
            xd  //  Transpose; 
n1  =  First[n];  
          n2  =  Last[n]; 
Sum[
            xn[[k - n1 + 1]] Exp[-I k θ], {k, n1, 
              n2}]
];

Discrete-time Fourier transform (DTFT) analytic example

Discrete-time pulse of width 2M

pulse[n_,  M_] := 
        If[n  <  -M  ||  n  >  M,  0,  1];

Symmetric discrete-time pulse of width 2M

dtft1  =  (∑_(n = -M)^M) (E^(-I n θ));
dtft1  //  TraditionalForm

dtft2  =  dtft1  //  FullSimplify  //  
          TrigReduce;
dtft2  //  TraditionalForm

Plot results for some sample M

M = 0

m = 0;
g10  =  
        DiscreteListPlot[Table[{n,  pulse[n,  m]}, {n, -20, 20}], Blue, 
          Frame -> True,  Axes -> {True, False},  
          PlotRange -> {- .05, 2.05},  
          DisplayFunction -> Identity];
g20  =  
        Plot[Evaluate[
            dtft2  /.  M -> m], {θ,  -π,  π}, 
          PlotStyle -> Red,  PlotRange -> All,  
          Axes -> False,  
          DisplayFunction -> Identity];
g30  =  
        Plot[Evaluate[dtft2  /.  M -> m], {θ,  -2 π,  
            2  π}, PlotStyle -> Red,  PlotRange -> All,  
          Axes -> False,  
          DisplayFunction -> Identity];
g40  =  
        Plot[Evaluate[dtft2  /.  M -> m], {θ,  -4 π,  
            4  π}, PlotStyle -> Red,  PlotRange -> All,  
          Axes -> False,  
          DisplayFunction -> Identity];
Show[GraphicsArray[{{g10, g20}, {g30, g40}}],  
        ImageSize -> 504];

M = 1

m = 1;
g1a  =  
        DiscreteListPlot[Table[{n,  pulse[n,  m]}, {n, -20, 20}], Blue, 
          Frame -> True,  Axes -> {True, False},  
          PlotRange -> {- .05, 2.05},  
          DisplayFunction -> Identity];
g2a  =  
        Plot[Evaluate[
            dtft2  /.  M -> m], {θ,  -π,  π}, 
          PlotStyle -> Red,  PlotRange -> All,  
          Axes -> False,  
          DisplayFunction -> Identity];
g3a  =  
        Plot[Evaluate[dtft2  /.  M -> m], {θ,  -2 π,  
            2  π}, PlotStyle -> Red,  PlotRange -> All,  
          Axes -> False,  
          DisplayFunction -> Identity];
g4a  =  
        Plot[Evaluate[dtft2  /.  M -> m], {θ,  -4 π,  
            4  π}, PlotStyle -> Red,  PlotRange -> All,  
          Axes -> False,  
          DisplayFunction -> Identity];
Show[GraphicsArray[{{g1a, g2a}, {g3a, g4a}}],  
        ImageSize -> 504];

M = 2

m = 2;
g1b  =  
        DiscreteListPlot[Table[{n,  pulse[n,  m]}, {n, -20, 20}], Blue, 
          Frame -> True,  Axes -> {True, False},  
          PlotRange -> {- .05, 2.05},  
          DisplayFunction -> Identity];
g2b  =  
        Plot[Evaluate[
            dtft2  /.  M -> m], {θ,  -π,  π}, 
          PlotStyle -> Red,  PlotRange -> All,  
          Axes -> False,  
          DisplayFunction -> Identity];
g3b  =  
        Plot[Evaluate[dtft2  /.  M -> m], {θ,  -2 π,  
            2  π}, PlotStyle -> Red,  PlotRange -> All,  
          Axes -> False,  
          DisplayFunction -> Identity];
g4b  =  
        Plot[Evaluate[dtft2  /.  M -> m], {θ,  -4 π,  
            4  π}, PlotStyle -> Red,  PlotRange -> All,  
          Axes -> False,  
          DisplayFunction -> Identity];
Show[GraphicsArray[{{g1b, g2b}, {g3b, g4b}}],  
        ImageSize -> 504];

M = 4

m = 4;
g1c  =  
        DiscreteListPlot[Table[{n,  pulse[n,  m]}, {n, -20, 20}], Blue, 
          Frame -> True,  Axes -> {True, False},  
          PlotRange -> {- .05, 2.05},  
          DisplayFunction -> Identity];
g2c  =  
        Plot[Evaluate[
            dtft2  /.  M -> m], {θ,  -π,  π}, 
          PlotStyle -> Red,  PlotRange -> All,  
          Axes -> False,  
          DisplayFunction -> Identity];
g3c  =  
        Plot[Evaluate[dtft2  /.  M -> m], {θ,  -2 π,  
            2  π}, PlotStyle -> Red,  PlotRange -> All,  
          Axes -> False,  
          DisplayFunction -> Identity];
g4c  =  
        Plot[Evaluate[dtft2  /.  M -> m], {θ,  -4 π,  
            4  π}, PlotStyle -> Red,  PlotRange -> All,  
          Axes -> False,  
          DisplayFunction -> Identity];
Show[GraphicsArray[{{g1c, g2c}, {g3c, g4c}}],  
        ImageSize -> 504];

M = 8

m = 8;
g1d  =  
        DiscreteListPlot[Table[{n,  pulse[n,  m]}, {n, -20, 20}], Blue, 
          Frame -> True,  Axes -> {True, False},  
          PlotRange -> {- .05, 2.05},  
          DisplayFunction -> Identity];
g2d  =  
        Plot[Evaluate[
            dtft2  /.  M -> m], {θ,  -π,  π}, 
          PlotStyle -> Red,  PlotRange -> All,  
          Axes -> False,  
          DisplayFunction -> Identity];
g3d  =  
        Plot[Evaluate[dtft2  /.  M -> m], {θ,  -2 π,  
            2  π}, PlotStyle -> Red,  PlotRange -> All,  
          Axes -> False,  
          DisplayFunction -> Identity];
g4d  =  
        Plot[Evaluate[dtft2  /.  M -> m], {θ,  -4 π,  
            4  π}, PlotStyle -> Red,  PlotRange -> All, 
          PlotPoints -> 200,  Axes -> False,  
          DisplayFunction -> Identity];
Show[GraphicsArray[{{g1d, g2d}, {g3d, g4d}}],  
        ImageSize -> 504];

Summary of results

Show[
        GraphicsArray[{{g10, g20}, {g1a, g2a}, {g1b, g2b}, {g1c, g2c}, {g1d, 
              g2d}}], ImageSize -> 504];

Comparison to continuous-time Fourier transform (CTFT)

Discrete-time Fourier transform (DTFT): additional illustrations

Example #1a: 1Hz cosine (finite length, discrete-time)

x[t_] := Cos[2  π t];
xd =  sampler[x, fs = 10];  
    If[OddQ[Length[xd]],  xd  =  Drop[xd, -1]];
DiscreteListPlot2[xd,  Blue,  Frame -> True, 
        Axes -> {True, False},  AspectRatio -> 1/3, 
        ImageSize -> 504];

DTFT

Xθ  = DTFT[xd, θ];
Xθ  //  TraditionalForm

Xθ  =  
        Xθ  //  Simplify;
Xθ  //  TraditionalForm

Plots of DTFT

g1 = 
        Plot[Abs[Xθ], {θ, -π, π},  
          PlotStyle -> {Red},  PlotRange -> All, 
          PlotPoints -> 200,  
          DisplayFunction -> Identity];
g2 = 
        Plot[Arg[Xθ], {θ, -π, π},  
          PlotStyle -> {Red},  PlotRange -> All, 
          PlotPoints -> 200,  
          DisplayFunction -> Identity];
Show[GraphicsArray[{{g1, g2}}], ImageSize -> 504];

Plot DTFT as a function of frequency

g1 = 
        Plot[Abs[
            Xθ  /.  θ ->  2  π f/fs], {f, -fs/
              2, fs/2},  PlotStyle -> {Red},  PlotRange -> All, 
          PlotPoints -> 200,  
          DisplayFunction -> Identity];
g2 = 
        Plot[Arg[
            Xθ /.  θ ->  2  π f/fs], {f, -fs/2, 
            fs/2},  PlotStyle -> {Red},  PlotRange -> All, 
          PlotPoints -> 200,  
          DisplayFunction -> Identity];
Show[GraphicsArray[{{g1, g2}}], ImageSize -> 504];

Plot more than one period of the DTFT as a function of frequency

Plot[
        Abs[Xθ  /.  θ ->  2  π f/fs], {f, -2.5 
            fs, 2.5  fs},  PlotStyle -> {Red},  PlotRange -> All, 
        AspectRatio -> 1/3, PlotPoints -> 400,  
        ImageSize -> 504];

Example #1b: 1Hz cosine (finite length, continuous-time)

Length =  5 seconds

x[t_] := Cos[2  π t] (u[t]  -  u[t - 5]);
Plot[x[t],  {t,  -1, 6},  PlotStyle -> Blue,  
        ImageSize -> 504,  AspectRatio -> 1/3,  
        Axes -> False];

xf  =  
        Integrate[
            Cos[2  π t] Exp[-I 2  π f t], {t, 0,  
              5}]  //  FullSimplify;
xf  //  TraditionalForm

g1 = 
        Plot[Abs[xf], {f, -5, 5},  PlotStyle -> {Red},  
          PlotRange -> All, PlotPoints -> 200,  
          DisplayFunction -> Identity];
g2 = 
        Plot[Arg[xf], {f, -5, 5},  PlotStyle -> {Red},  
          PlotRange -> All, PlotPoints -> 200,  
          DisplayFunction -> Identity];
Show[GraphicsArray[{{g1, g2}}], ImageSize -> 504];

Length =  10 seconds

x[t_] := Cos[2  π t] (u[t]  -  u[t - 10]);
Plot[x[t],  {t,  -5, 15},  
        PlotStyle -> Blue];

xf  =  
        FourierTransform[x[t],  t,  f]  //  
          Simplify;
xf  //  TraditionalForm

g1 = 
        Plot[Abs[xf], {f, -5, 5},  PlotStyle -> {Red},  
          PlotRange -> All, PlotPoints -> 200,  
          DisplayFunction -> Identity];
g2 = 
        Plot[Arg[xf], {f, -5, 5},  PlotStyle -> {Red},  
          PlotRange -> All, PlotPoints -> 200,  
          DisplayFunction -> Identity];
Show[GraphicsArray[{{g1, g2}}], ImageSize -> 504];

Example #1c: 1Hz cosine (longer sampling length, discrete-time)

Sampled sequence

x[t_] := Cos[2  π t];
xd =  sampler[x, fs = 10,  {0, 20}];  
    If[OddQ[Length[xd]],  xd  =  Drop[xd, -1]];
DiscreteListPlot2[xd,  Blue,  Frame -> True, 
        Axes -> {True, False},  AspectRatio -> 1/3, 
        ImageSize -> 504];

DTFT

Xθ  = DTFT[xd, θ];
Xθ  //  TraditionalForm

Xθ  =  
        Xθ  //  Simplify;
Xθ  //  TraditionalForm

Plots of DTFT

g1 = 
        Plot[Abs[Xθ], {θ, -π, π},  
          PlotStyle -> {Red},  PlotRange -> All, 
          PlotPoints -> 200,  
          DisplayFunction -> Identity];
g2 = 
        Plot[Arg[Xθ], {θ, -π, π},  
          PlotStyle -> {Red},  PlotRange -> All, 
          PlotPoints -> 200,  
          DisplayFunction -> Identity];
Show[GraphicsArray[{{g1, g2}}], ImageSize -> 504];

Plot DTFT as a function of frequency

g1 = 
        Plot[Abs[
            Xθ  /.  θ ->  2  π f/fs], {f, -fs/
              2, fs/2},  PlotStyle -> {Red},  PlotRange -> All, 
          PlotPoints -> 200,  
          DisplayFunction -> Identity];
g2 = 
        Plot[Arg[
            Xθ /.  θ ->  2  π f/fs], {f, -fs/2, 
            fs/2},  PlotStyle -> {Red},  PlotRange -> All, 
          PlotPoints -> 200,  
          DisplayFunction -> Identity];
Show[GraphicsArray[{{g1, g2}}], ImageSize -> 504];

Example #2a: sum of cosines (homework #2, problem 7 example)

Continuous-time signal

x[t_] := 1 + 2  Cos[2  π t] + 4  Cos[4  π t];
Plot[x[t], {t, 0, 5},  PlotStyle -> {Blue},  
        Frame -> True, Axes -> {True, False},  
        AspectRatio -> 1/3, ImageSize -> 504];

Sampled sequence (fs = 10Hz)

x[t_] := 1 + 2  Cos[2  π t] + 4  Cos[4  π t];
xd =  sampler[x, fs = 10];  
    If[OddQ[Length[xd]],  xd  =  Drop[xd, -1]];
DiscreteListPlot2[xd,  Blue,  Frame -> True, 
        Axes -> {True, False},  AspectRatio -> 1/3, 
        ImageSize -> 504];

DTFT

Xθ  = DTFT[xd, θ];
Xθ  //  TraditionalForm

Xθ  =  
        Xθ  //  Simplify;
Xθ  //  TraditionalForm

Plots of DTFT

g1 = 
        Plot[Abs[Xθ], {θ, -π, π},  
          PlotStyle -> {Red},  PlotRange -> All, 
          PlotPoints -> 200,  
          DisplayFunction -> Identity];
g2 = 
        Plot[Arg[Xθ], {θ, -π, π},  
          PlotStyle -> {Red},  PlotRange -> All, 
          PlotPoints -> 200,  
          DisplayFunction -> Identity];
ga = 
        Show[GraphicsArray[{{g1, g2}}], ImageSize -> 504];

Plot DTFT as a function of frequency

g1 = 
        Plot[Abs[
            Xθ  /.  θ ->  2  π f/fs], {f, -fs/
              2, fs/2},  PlotStyle -> {Red},  PlotRange -> All, 
          PlotPoints -> 200,  
          DisplayFunction -> Identity];
g2 = 
        Plot[Arg[
            Xθ /.  θ ->  2  π f/fs], {f, -fs/2, 
            fs/2},  PlotStyle -> {Red},  PlotRange -> All, 
          PlotPoints -> 200,  
          DisplayFunction -> Identity];
ga2 = 
        Show[GraphicsArray[{{g1, g2}}], ImageSize -> 504];

Plot more than one period of the DTFT as a function of frequency

Plot[
        Abs[Xθ  /.  θ ->  2  π f/fs], {f, -2.5 
            fs, 2.5  fs},  PlotStyle -> {Red},  PlotRange -> All, 
        AspectRatio -> 1/3, PlotPoints -> 400,  
        ImageSize -> 504];

Example #2b: infinite-length spectrum of sample waveform ((Subscript[f, s]) = 10  Hz  >  2  (Subscript[f, max]))

Sampling frequency

fs = 10   ;

Original waveform

x[t_] := 1 + 2  Cos[2  π t] + 4  Cos[4  π t];
Plot[x[t], {t, 0, 5},  PlotStyle -> {Blue},  
        Frame -> True, Axes -> {True, False},  
        AspectRatio -> 1/3, ImageSize -> 504];

Continuous-time frequency spectrum (CTFT)

X[f_] = 
      FourierTransform[x[t], t, 
          f]  /. {δ[b_ a_ + f_ a_] -> δ[b + f]/
              a, δ[ a_ + f_ a_] -> δ[1 + f]/
              a}

gX = 
        Plot[Evaluate[PlotConvert[X[f],  .04]], {f, -5, 5}, 
          PlotStyle -> {Blue, Thickness[ .005]},  
          PlotPoints -> 1000,  
          PlotRange -> {- .02, 4.02}];

Frequency spectrum of sampled signal

Xs[f_, fs_, n_:  5] := SampledSpectrum[X, f, fs, n];

gXs = 
        Plot[Evaluate[PlotConvert[Xs[f, fs, 10],  .05]], {f, -25, 25}, 
          PlotStyle -> {Red},  PlotPoints -> 1000,  
          PlotRange -> {- .02, 2.12},  ImageSize -> 504,  
          AspectRatio -> 1/3];

Undersampling and the DTFT: Example #1

Sampling frequency

fs = 3   ;

Continuous-time signal

x[t_] := 
        1  +  2 Cos[2  π t]  +  4 Cos[4  π t];
gxt = 
        Plot[x[t], {t, 0, 5}, PlotStyle -> {Blue, Thickness[ .005]},  
          PlotPoints -> 100];

CTFT of infinite-length x(t)

X[f_] = 
        FourierTransform[x[t], t, 
            f]  /. {δ[b_ a_ + f_ a_] -> δ[b + f]/
                a, δ[ a_ + f_ a_] -> δ[1 + f]/
                a};
X[f]  //  TraditionalForm

gX = 
        Plot[Evaluate[PlotConvert[X[f],  .04]], {f, -2.5 fs, 2.5  fs}, 
          PlotStyle -> {Blue, Thickness[ .005]},  
          PlotPoints -> 1000,  
          PlotRange -> {- .02, 3.12}];

CTFT of finite-length x(t)

xf  =  
        Integrate[x[t] Exp[-I 2  π f t], {t, 0,  5}]  //  
          FullSimplify;
xf  //  TraditionalForm

gX2 = 
        Plot[Abs[xf], {f, -5, 5},  PlotStyle -> {Blue},  
          PlotRange -> All, PlotPoints -> 200];

Sampled waveform (finite-length)

xd =  sampler[x, fs];  
    If[OddQ[Length[xd]],  xd  =  Drop[xd, -1]];
gxn  =  
        DiscreteListPlot[xd,  Blue,  Frame -> True, 
          Axes -> {True, False}, 
          PlotRange -> {All, 
              Evaluate[AbsoluteOptions[gxt, PlotRange][[1, 2, 
                    2]]]}];

CTFT of infinite-length sampled signal

Xs[f_, fs_, n_:  5] := SampledSpectrum[X, f, fs, n];

gXs = 
        Plot[Evaluate[PlotConvert[Xs[f, fs, 10],  .05]], {f, -2.5 fs, 
            2.5  fs}, PlotStyle -> {Red, Thickness[ .01]},  
          PlotPoints -> 500,  
          PlotRange -> {- .02, 3.12}];

gXXs = Show[gXs, gX];

DTFT of finite-length sampled signal

Xθ  = DTFT[xd, θ]  //  Simplify;

gXθ = 
        Plot[Abs[
            Xθ  /.  θ ->  2  π f/fs], {f, -2.5 
              fs, 2.5  fs},  PlotStyle -> {Red},  
          PlotRange -> All, PlotPoints -> 200,  
          AspectRatio -> 1/3,  ImageSize -> 504];

Show all

ga  =  
        Show[GraphicsArray[{{gxt, gxn}, {gX,  gXXs}}], 
          ImageSize -> 504];

Undersampling and the DTFT: Example #2

Sampling frequency

fs = 3.5   ;

Continuous-time signal

x[t_] := 
        1  +  2 Cos[2  π t]  +  4 Cos[4  π t];
gxt = 
        Plot[x[t], {t, 0, 5}, PlotStyle -> {Blue, Thickness[ .005]},  
          PlotPoints -> 100];

CTFT of infinite-length x(t)

X[f_] = 
        FourierTransform[x[t], t, 
            f]  /. {δ[b_ a_ + f_ a_] -> δ[b + f]/
                a, δ[ a_ + f_ a_] -> δ[1 + f]/
                a};
X[f]  //  TraditionalForm

gX = 
        Plot[Evaluate[PlotConvert[X[f],  .04]], {f, -2.5 fs, 2.5  fs}, 
          PlotStyle -> {Blue, Thickness[ .005]},  
          PlotPoints -> 1000,  
          PlotRange -> {- .02, 3.12}];

CTFT of finite-length x(t)

xf  =  
        Integrate[x[t] Exp[-I 2  π f t], {t, 0,  5}]  //  
          FullSimplify;
xf  //  TraditionalForm

gX2 = 
        Plot[Abs[xf], {f, -5, 5},  PlotStyle -> {Blue},  
          PlotRange -> All, PlotPoints -> 200];

Sampled waveform (finite-length)

xd =  sampler[x, fs];  
    If[OddQ[Length[xd]],  xd  =  Drop[xd, -1]];
gxn  =  
        DiscreteListPlot[xd,  Blue,  Frame -> True, 
          Axes -> {True, False}, 
          PlotRange -> {All, 
              Evaluate[AbsoluteOptions[gxt, PlotRange][[1, 2, 
                    2]]]}];

CTFT of infinite-length sampled signal

Xs[f_, fs_, n_:  5] := SampledSpectrum[X, f, fs, n];

gXs = 
        Plot[Evaluate[PlotConvert[Xs[f, fs, 10],  .05]], {f, -2.5 fs, 
            2.5  fs}, PlotStyle -> {Red, Thickness[ .01]},  
          PlotPoints -> 500,  
          PlotRange -> {- .02, 3.12}];

gXXs = Show[gXs, gX];

DTFT of finite-length sampled signal

Xθ  = DTFT[xd, θ]  //  Simplify;

gXθ = 
        Plot[Abs[
            Xθ  /.  θ ->  2  π f/fs], {f, -2.5 
              fs, 2.5  fs},  PlotStyle -> {Red},  
          PlotRange -> All, PlotPoints -> 200,  
          AspectRatio -> 1/3,  ImageSize -> 504];

Show all

ga  =  
        Show[GraphicsArray[{{gxt, gxn}, {gX,  gXXs}}], 
          ImageSize -> 504];

Comparison to oversampled case

Sampling frequency

fs = 10   ;

Continuous-time signal

x[t_] := 
        1  +  2 Cos[2  π t]  +  4 Cos[4  π t];
gxt = 
        Plot[x[t], {t, 0, 5}, PlotStyle -> {Blue, Thickness[ .005]},  
          PlotPoints -> 100];

CTFT of infinite-length x(t)

X[f_] = 
        FourierTransform[x[t], t, 
            f]  /. {δ[b_ a_ + f_ a_] -> δ[b + f]/
                a, δ[ a_ + f_ a_] -> δ[1 + f]/
                a};
X[f]  //  TraditionalForm

gX = 
        Plot[Evaluate[PlotConvert[X[f],  .04]], {f, -2 fs, 2  fs}, 
          PlotStyle -> {Blue, Thickness[ .005]},  
          PlotPoints -> 2000,  
          PlotRange -> {- .02, 3.12}];

CTFT of finite-length x(t)

xf  =  
        Integrate[x[t] Exp[-I 2  π f t], {t, 0,  5}]  //  
          FullSimplify;
xf  //  TraditionalForm

gX2 = 
        Plot[Abs[xf], {f, -2 fs, 2  fs},  PlotStyle -> {Blue},  
          PlotRange -> All, PlotPoints -> 200];

Sampled waveform (finite-length)

xd =  sampler[x, fs];  
    If[OddQ[Length[xd]],  xd  =  Drop[xd, -1]];
gxn  =  
        DiscreteListPlot[xd,  Blue,  Frame -> True, 
          Axes -> {True, False}, 
          PlotRange -> {All, 
              Evaluate[AbsoluteOptions[gxt, PlotRange][[1, 2, 
                    2]]]}];

CTFT of infinite-length sampled signal

Xs[f_, fs_, n_:  5] := SampledSpectrum[X, f, fs, n];

gXs = 
        Plot[Evaluate[PlotConvert[Xs[f, fs, 10],  .05]], {f, -2 fs, 
            2  fs}, PlotStyle -> {Red, Thickness[ .01]},  
          PlotPoints -> 1000,  
          PlotRange -> {- .02, 3.12}];

gXXs = Show[gXs, gX];

DTFT of finite-length sampled signal

Xθ  = DTFT[xd, θ]  //  Simplify;

gXθ = 
        Plot[Abs[
            Xθ  /.  θ ->  2  π f/fs], {f, -2 
              fs, 2  fs},  PlotStyle -> {Red},  PlotRange -> All, 
          PlotPoints -> 200,  AspectRatio -> 1/3,  
          ImageSize -> 504];

Show all

ga  =  
        Show[GraphicsArray[{{gxt, gxn}, {gX,  gXXs}}], 
          ImageSize -> 504];