We saw above that any discrete sequence can be expressed exactly as an infinite sum of complex exponentials. The same kind of result exist for continuous time signals. Any x(t) can be expressed as the Fourier integral x(t)=∫+∞−∞X(f) ej2πft df, where X(f)=∫+∞−∞x(t) e−j2πft dt.
The Fourier transform exists if the three sufficient conditions of Dirichlet are verified:
Let us look at this sinc function (you may play with several values of the width):
%matplotlib inline
def sinc(x):
if isinstance(x,(int,float)): x=[x]
x=np.array(x)
out=np.ones(np.shape(x))
I=np.where(x!=0)
out[I]=np.sin(x[I])/x[I]
return out
def dsinc(x,L): # This is the "discrete time" cardinal sinus
if isinstance(x,(int,float)): x=[x]
x=np.array(x)
out=np.ones(np.shape(x))
I=np.where(x!=0)
out[I]=np.sin(x[I])/(L*np.sin(x[I]/L))
return out
N=1000
f=np.linspace(-0.5,0.5,400)
plt.plot(f,sinc(pi*6*f))
plt.grid(b=True)
Playing with values using a slider.
N=1000
f=np.linspace(-0.5,0.5,400)
out = widgets.Output()
#----- Callbacks des widgets -------------
@out.capture(clear_output=True, wait=True)
def pltsinc(value):
#clear_output(wait=True)
T = s.value
plt.plot(f,sinc(pi*T*f))
plt.grid(b=True)
plt.show()
s=widgets.FloatSlider(min=0, max=20, step=0.1, value=8)
pltsinc('Width')
s.observe(pltsinc,'value')
display(widgets.VBox([s, out]))
#alternatively
#interact(pltsinc,value=fixed(1), T=[0.1,10,0.1])
The integral of sinc(πfT) -- Using the fact the Dirichlet integral is ∫+∞0sinc(x)dx=π2, the symmetry of sinc(), and a change of variable, we obtain that ∫+∞−∞Tsinc(πfT)df=1.
It is now useful to look at the limit cases.
%matplotlib tk
from matplotlib.widgets import Slider
fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.2, left=0.1)
slider_ax = plt.axes([0.1, 0.1, 0.8, 0.02])
slider = Slider(slider_ax, "L/T", 0, 100, valinit=8, color='#AAAAAA')
L=10
f=np.linspace(-0.5,0.5,400)
line, = ax.plot(f,dsinc(pi*L*f,L), lw=2,label="Discrete time sinc")
line2, = ax.plot(f,sinc(pi*L*f), lw=2,label="Standard sinc")
#line2 is in order to compare with the "true" sinc
ax.grid(b='on')
ax.legend()
def on_change(L):
line.set_ydata(dsinc(pi*L*f,L))
line2.set_ydata(sinc(pi*L*f))
slider.on_changed(on_change)
(table adapted from cv.nrao.edu)
Recall that the Dirac impulse δ(t) satisfies δ(t)={0 if t≠0,+∞ for t=0, and is such that ∫+∞−∞δ(t)dt=1.
The Dirac impulse plays the role of an indicator function. In particular, we have x(t)δ(t−t0)=x(t0)δ(t−t0). Consequently, ∫+∞−∞x(t)δ(t−t0)dt=x(t0)∫+∞−∞δ(t−t0)dt=x(t0). Therefore, we always have
{x(t)=∫+∞−∞x(τ)δ(t−τ)dτwith x(τ)=∫+∞−∞x(t)δ(t−τ)dt.This is nothing but the continuous-time version of the representation formula.
The set of distributions {δτ(t):δ(t−τ)}, forms an orthonormal basis and x(τ) can be viewed as a coordinate of x(t) on this basis. Indeed, the scalar product between x(t) and δτ(t) is nothing but x(τ)=<x(t),δτ(t)>=∫+∞−∞x(t)δ(t−τ)dt, and x(t) is then given as the sum of the basis functions, weighted by the associated coordinates: x(t)=∫+∞−∞x(τ)δ(t−τ)dτ.
Following the same approach as in the discrete case, we define the impulse response h(t) as the output of a linear invariant system to a Dirac impulse. By linearity, the output of the system to any input x(t), expressed using the representation formula, is y(t)=∫+∞−∞x(τ)h(t−τ)dτ=[x∗h](t). This is the time-continuous convolution between x and h, denoted [x∗h](t). It enables to express the output of the filter using only the input and the impulse response. This shows the importance of the impulse response as a description of the system. The other notions we studied in the discrete case, namely transfer function, Plancherel and Parseval theorems, etc, extends straightforwardly to the continuous case.