(*sinc interpolation to reconstruct a signal from its samples
by Nasser M. Abbasi
version Feb 18 2010*)

Manipulate[process[ Fs, fun],
 Item[
  Grid[{
    {Control[{{Fs, 1, 
        Row[{Style["sampling frequency", 12], 
          Style[ " (Hz)", Italic]}]}, 1, 10, .1, ImageSize -> Small, 
       Appearance -> "Labeled"}],
     
     Control[{  {fun, 1, Style["signal to sample", 12]},
       {1 -> Style["Cos[2 Pi t]", 10],
        2 -> Style["Sin[2 Pi t]", 10],
        3 -> Style["t", 10],
        4 -> Style["\!\(\*SuperscriptBox[\(t\), \(2\)]\)", 10],
        5 -> Style["\!\(\*SuperscriptBox[\(t\), \(3\)]\)", 10],
        6 -> Style["SquareWave[t]", 10],
        6.1 -> Style["TriangleWave[t]", 10],
        6.2 -> Style["SawtoothWave[t]", 10],
        7 -> Style["[Sin[2 Pi t]+Cos[3 Pi t]", 10],
        8 -> Style["Cos[2 Pi t]+t", 10]
        },
       ControlType -> PopupMenu, ImageSize -> Small}
      ]
     }
    }]
  ],
 FrameMargins -> 0,
 ImageMargins -> 0,
 ContinuousAction -> False,
 SynchronousUpdating -> False,
 AutorunSequencing -> {{1, 60}},
 Initialization :> 
  {
   
   (* This is the sinc interpolation formula *)
   sincInterpolate[t_, T_, samples_] := Module[{k},
     Sum[samples[[ k ]]*Sinc[Pi/T (t - (k - 1) T)], {k, 1, 
       Length[samples]}]
     ];
   
   (* Main function called from Manipulate *)
   process[Fs_, fun_] := 
    Module[{f, maxt, T, originalSignalPlot, p2, t, k, xa, samples, 
      lines, absError, label, perror, sincDeltaTime, disks, 
      sincNumberOfPoints = 20, ymin = 1.3, ymax = 1.3, 
      numberOfSamples, functionName, averageAbsError},
     
     T = 1/Fs;
     
     (* Check which function we are sampling and set appropriate plot \
limits*)
     Which[
      fun == 1, {f[t_] := Cos[2 Pi  t]; maxt = 4; 
       functionName = "y(t) = Cos[2 Pi t]"},
      fun == 2, {f[t_] := Sin[2 Pi  t]; maxt = 4; 
       functionName = "y(t) = Sin[2 Pi t]"},
      fun == 3, {f[t_] := t; maxt = 3; ymin = .5; ymax = 4; 
       functionName = "y(t) = t"},
      
      fun == 4, {f[t_] := t^2; maxt = 4; ymin = .5; ymax = 20; 
       functionName = "y(t) = \!\(\*SuperscriptBox[\(t\), \(2\)]\)"},
      
      fun == 5, {f[t_] := t^3; maxt = 4; ymin = .5; ymax = 70; 
       functionName = "y(t) = \!\(\*SuperscriptBox[\(t\), \(3\)]\)"},
      
      fun == 6, {f[t_] := SquareWave[t]; maxt = 6; 
       functionName = "y(t) = SquareWave[t]"},
      
      fun == 6.1, {f[t_] := TriangleWave[t]; maxt = 6; 
       functionName = "y(t) = TriangleWave[t]"},
      
      fun == 6.2, {f[t_] := SawtoothWave[t]; maxt = 6; 
       functionName = "y(t) = SawtoothWave[t]"},
      
      fun == 7, {f[t_] := Sin[2 Pi t] + Cos[3 Pi t]; maxt = 4; 
       ymin = 2.5; ymax = 2.5; 
       functionName = "y(t) = Sin[2 Pi t]+Cos[3 Pi t]]"},
      
      fun == 8, {f[t_] := Cos[2 Pi t] + t; maxt = 6; ymin = 1; 
       ymax = 8; functionName = "y(t) = Cos[2 Pi t]+t"}
      
      ];
     
     numberOfSamples = Floor[maxt/T] + 1;
     samples = Table[f[k  T], {k, 0, numberOfSamples - 1}];
     maxt = (numberOfSamples - 1)*T;
     
     (* find the sinc function sampling period *)
     sincDeltaTime = T/(sincNumberOfPoints - 1);
     
     (* This draws the samples lines, 
     but not being used in this version *)
     lines = Table[Line[{{t, 0}, {t, f[t]}}], {t, 0, maxt, T}];
     
     (* This puts little dots the sample location *)
     disks = 
      Table[{PointSize[.014], Red, Opacity[1], Point[{t, f[t]}]}, {t, 
        0, maxt, T}];
     
     
     (* format the plot label *)
     label = Grid[
       {
        {Style[
          "Sinc interpolation of the sampled signal " <> functionName,
           Bold, 14] 
         },
        {
         Grid[{
           {
            
            Row[{Style["number of samples = ", 12], 
              Style[Length[samples], 12]}], ,
            
            Row[{Style["sampling period = ", 12], 
              Style[NumberForm[N[T], {7, 5}], 12], Style[" sec", 12]}]
            , SpanFromLeft
            }
           }, Alignment -> Left
          ]
         }
        }, Alignment -> Center
       ];
     
     
     (* draw the original signal *)
     originalSignalPlot =
      Plot[f[t], {t, 0, maxt + 0.1*maxt},
       PlotRange -> {Automatic, {-ymin, ymax}},
       Frame -> True,
       ImagePadding -> {{30, 1}, {45, 60}},
       ImageMargins -> 0,
       ImageSize -> 540,
       AspectRatio -> .3,
       FrameTicksStyle -> Directive[10],
       AxesOrigin -> {0, 0},
       FrameLabel -> {{Null, Null}, { 
          Row[{Style["time", 12], Style[ "(sec)", 12, Italic]}], 
          label}},
       (*Epilog->{Dashed,Red,lines,disks}*)
       Epilog -> {Dashed, Red, disks}
       ];
     
     (* Do the sinc interpolation sum *)
     xa = Table[{t,
        sincInterpolate[t, T, samples]}, {t, 0, maxt, sincDeltaTime}
       ];
     
     (* plot the result of the sinc interpolation *)
     p2 = 
      ListPlot[xa, Joined -> False, PlotRange -> All, 
       PlotStyle -> {Dotted, Magenta}, ImageMargins -> 5,
       ImageSize -> 400];
     
     (* determine absolute error and plots it *)
     absError = Table[{xa[[i, 1]],
        Abs[ f[ xa[[i, 1]] ] - xa[[i, 2]] ]}, {i, 1, Length[xa]}];
     averageAbsError = Mean [absError[[All, 2]]] ;
     
     label = Grid[{
        {Style["absolute error in sinc interpolation", Bold, 14] , 
         SpanFromLeft},
        {Row[{Style["average absolute error = ", 12], 
           Style[NumberForm[N[averageAbsError], {8, 5}], 12]}], 
         SpanFromLeft}},
       Alignment -> Center
       ];
     
     perror =
      ListPlot[absError,
       Joined -> False,
       Filling -> Axis,
       PlotStyle -> Black,
       PlotRange -> All,
       Frame -> True,
       ImagePadding -> {{30, 1}, {35, 45}},
       ImageMargins -> 0,
       ImageSize -> 540,
       AspectRatio -> .23,
       FrameTicksStyle -> Directive[10],
       AxesOrigin -> {0, 0},
       FrameLabel -> {{Null, Null}, { 
          Row[{Style["time", 12], Style[ "(sec)", 12, Italic]}], 
          label}}
       ];
     
     (*all done, puts all the plots in a grid *)
     Grid[
      {
       {Item[Show[{originalSignalPlot, p2}], ItemSize -> Full], 
        SpanFromLeft},
       {Item[perror, ItemSize -> Full], SpanFromLeft}
       },
      Alignment -> Center,
      Spacings -> {1, 1},
      Frame -> None
      ]
     ]
   }
 ]