Discrete Signal Processing (DSP):
Linear Time-Invariant (LTI) Systems
Table of Contents
A discrete-time system ${H}$ is a transformation (a rule or formula) that maps a discrete-time input signal $x$ into a discrete-time output signal $y$
System examples
$$ \begin{align*} &\text{Identity} \quad &y[n] &= x[n] \quad &\forall n\\ &\text{Scaling} \quad &y[n] &= 2\,x[n] \quad &\forall n\\ &\text{Offset} \quad &y[n] &= x[n]\, + \,2 \quad &\forall n\\ &\text{Square signal} \quad &y[n] &= (x[n])^2 \quad &\forall n\\ &\text{Shift} \quad &y[n] &= x[n + 2] \quad &\forall n\\ &\text{Decimate} \quad &y[n] &= x[2n] \quad &\forall n\\ &\text{Square time} \quad &y[n] &= x[n^2] \quad &\forall n \end{align*} $$A system ${H}$ is linear if it satisfies the following two properties:
1) Scaling
$${H} \{\alpha x \} = \alpha {H}\{x\} \quad \forall \, \alpha \in \mathbb{C}$$
2) Additivity
$$ \text{If}\,\, y_1 = {H} \{x_1\} \,\, \text{and}\,\, y_2 = {H} \{ x_2 \} \, \, \text{then } {H} \{x_1 + x_2\} = y_1 + y_2$$
$\quad\;$ where $h_{n,m} = [H]_{n,m}$ represents the row-$n$, column-$m$ entry of the matrix $H$
For infinite-length signals
For finite-length signals
A system $H$ is linear time-invariant (LTI) if it is both linear and time-invariant
We will only consider Linear Time-Invariant (LTI) systems.
%plot -s 560,200
N = 8;
nh = [0:2*N-1];
nx = [-N:N-1];
x = zeros(size(nx))';
x(N+1) = 1;
h = zeros(size(nh))';
h(1) = 2;
subplot(2,1,1), stem(nx,x,'filled'), ylabel('x[n]'), axis tight, ylim([0,2])
subplot(2,1,2), stem(nh,h,'filled'), ylabel('h[n]'), axis tight, ylim([0,2])
%plot -s 560,420
hc = h;
hr = [h(1),zeros(1,length(x)-1)];
H = toeplitz(hc,hr);
imagesc(H); colormap('jet'); axis('square'); axis off
%plot -s 560,200
N = 8;
nh = [0:2*N-1];
nx = [-N:N-1];
x = zeros(size(nx))';
x(N+1) = 1;
h = zeros(size(nh))';
h(4) = 1;
subplot(2,1,1), stem(nx,x,'filled'), ylabel('x[n]'), axis tight, ylim([0,1])
subplot(2,1,2), stem(nh,h,'filled'), ylabel('h[n]'), axis tight, ylim([0,1])
%plot -s 560,420
hc = h;
hr = [h(1),zeros(1,length(x)-1)];
H = toeplitz(hc,hr);
imagesc(H); colormap('jet'); axis('square'); axis off
%plot -s 560,200
N = 8;
nh = [0:2*N-1];
nx = [-N:N-1];
x = zeros(size(nx))';
x(N+1) = 1;
h = zeros(size(nh))';
h(1) = 1/3;
h(2) = 1/3;
h(3) = 1/3;
subplot(2,1,1), stem(nx,x,'filled'), ylabel('x[n]'), axis tight, ylim([0,1])
subplot(2,1,2), stem(nh,h,'filled'), ylabel('h[n]'), axis tight, ylim([0,1])
%plot -s 560,420
hc = h;
hr = [h(1),zeros(1,length(x)-1)];
H = toeplitz(hc,hr);
imagesc(H); colormap('jet'); axis('square'); axis off
%plot -s 560,200
N = 8;
nh = [0:2*N-1];
nx = [-N:N-1];
x = zeros(size(nx))';
x(N+1) = 1;
h = 0.8.^nh;
h = h';
subplot(2,1,1), stem(nx,x,'filled'), ylabel('x[n]'), axis tight, ylim([0,1])
subplot(2,1,2), stem(nh,h,'filled'), ylabel('h[n]'), axis tight, ylim([0,1])
%plot -s 560,420
hc = h;
hr = [h(1),zeros(1,length(x)-1)];
H = toeplitz(hc,hr);
imagesc(H); colormap('jet'); axis('square'); axis off
$$h_{n,m} = h_{(n+q)_N (m+q)_N} \qquad \forall q \in \mathbb{Z}$$
%plot -s 560,200
N = 8;
nh = [0:N-1];
nx = [0:N-1];
x = zeros(size(nx))';
x(1) = 1;
h = zeros(size(nh))';
h(3) = 1;
subplot(2,1,1), stem(nx,x,'filled'), ylabel('x[n]'), axis tight, ylim([0,1])
subplot(2,1,2), stem(nh,h,'filled'), ylabel('h[n]'), axis tight, ylim([0,1])
%plot -s 560,420
H = zeros(N,N);
for k = 0:N-1
H(:,k+1) = circshift(h,k);
end
imagesc(H); colormap('jet'); axis('square'); axis off
%plot -s 560,200
N = 8;
nh = [0:N-1];
nx = [0:N-1];
x = zeros(size(nx))';
x(1) = 1;
h = zeros(size(nh))';
h(1) = 1/3;
h(2) = 1/3;
h(3) = 1/3;
subplot(2,1,1), stem(nx,x,'filled'), ylabel('x[n]'), axis tight, ylim([0,1])
subplot(2,1,2), stem(nh,h,'filled'), ylabel('h[n]'), axis tight, ylim([0,1])
%plot -s 560,420
H = zeros(N,N);
for k = 0:N-1
H(:,k+1) = circshift(h,k);
end
imagesc(H); colormap('jet'); axis('square'); axis off
%plot -s 560,200
N = 8;
nh = [0:N-1];
nx = [0:N-1];
x = zeros(size(nx))';
x(1) = 1;
h = zeros(size(nh))';
h = 0.8.^nh;
subplot(2,1,1), stem(nx,x,'filled'), ylabel('x[n]'), axis tight, ylim([0,1])
subplot(2,1,2), stem(nh,h,'filled'), ylabel('h[n]'), axis tight, ylim([0,1])
%plot -s 560,420
H = zeros(N,N);
for k = 0:N-1
H(:,k+1) = circshift(h,k);
end
imagesc(H); colormap('jet'); axis('square'); axis off
Convolution is defined as the integral of the product of the two functions after one is reversed and shifted
$$y[n] = \sum \limits_{m=-\infty}^{\infty} h[n - m]\,x[m] = x[n]*h[n]$$
Output $y[n]$ came out by convolution of input $x[n]$ and system $h[n]$
$$
\begin{align*}
y[n] &= \sum \limits_{m=-\infty}^{\infty} h[n - m]\,x[m] =x[n]*h[n]\\ \\
&= \sum \limits_{k=-\infty}^{\infty} h[k]\,x[n - k] = \sum \limits_{k=-\infty}^{\infty} x[n - k]\,h[k]=h[n]*x[n]\\ \\
&\quad \;(k = n -m \, \implies \, m = n - k)
\end{align*}
$$
%plot -s 560,200
%% matlab command 'conv'
x = [3,11,7,0,-1,4,2];
h = [2,3,0,-5,2,1];
y = conv(x,h);
stem(y,'filled'), ylim([-60 60])
% this is not correct
conv_m
function file in the path.function [y,ny] = conv_m(x,nx,h,nh)
% Modified convolution routine for signal processing
% [y,ny] = conv_m(x,nx,h,nh)
% y = convolution result
% ny = support of y
% x = first signal on support nx
% nx = support of x
% h = second signal on support nh
% nh = support of h
nyb = nx(1) + nh(1);
nye = nx(length(x)) + nh(length(h));
ny = [nyb:nye];
y = conv(x,h);
%plot -s 560,200
x = [3,11,7,0,-1,4,2]; nx = [-3:3];
h = [2,3,0,-5,2,1]; nh = [-1:4];
[y,ny] = conv_m(x,nx,h,nh);
stem(ny,y,'filled'), axis tight, ylim([-60 60])
% this is what we want
%plot -s 560,600
subplot(3,1,1), stem(nx,x,'filled'); xlim([ny(1),ny(end)]); ylabel('x')
subplot(3,1,2), stem(nh,h,'filled'); xlim([ny(1),ny(end)]); ylabel('h')
subplot(3,1,3), stem(ny,y,'filled'); xlim([ny(1),ny(end)]); ylabel('y')
(= Toeplitz Matrices)
$$\begin{align*}y[n] &= x[n]*h[n] = \sum \limits_{m=-\infty}^{\infty} h[n - m]\,x[m]\\\\ &= \cdots + \,h[n+2]\,x[-2] + h[n+1]\,x[-1] + h[n]\,x[0] + h[n-1]\,x[1] + h[n-2]\,x[2]\, + \cdots \end{align*}$$
It is an inner product of $h$ vectors and $x$
Convolution is product of matrix $H$ and $x$
x = [3, 11, 7, 0, -1, 4, 2]';
h = [2, 3, 0, -5, 2, 1]';
hc = [h,zeros([length(x)-1,1])];
hr = [h(1),zeros([1,length(x)-1])];
H = toeplitz(hc,hr)
y = H*x
Circular Convolution
$$y[n] = x[n] \otimes h[n] = \sum_{m = 0}^{N-1} h \left[(n-m)_N \right]\,x[m]$$
%plot -s 560,200
N = 8;
n = 0:N-1;
h = [0 1 2 3 4 5 6 7]';
stem(n,h,'filled');
%% Create a circulent matrix H based on h
H = zeros(N,N);
for k = 0:N-1
H(:,k+1) = circshift(h,k);
end
H
%plot -s 800,300
subplot(1,2,1), imagesc(H); colormap('jet'); axis('square'); axis off
subplot(1,2,2), imagesc(h); colormap('jet'); axis equal; axis off
x = [1,1,0,0,0,0,0,0]';
y1 = H*x
x = [1,1,0,0,0,0,0,0];
h = [0,1,2,3,4,5,6,7];
y3 = cconv(x,h,8)
x1 = [1,2,2];
x2 = [1,2,3,4];
y = cconv(x1,x2,4)
% 5-point circular convolution
y = cconv(x1,x2,5)
% 6-point circular convolution
y = cconv(x1,x2,6)
%plot -s 560,500
N = 8;
xn = 0:N-1;
x = [1 0 -1 0 1 0 -1 0];
h = [0 1 2 3 4 0 0 0];
y = cconv(x,h,N);
subplot(3,1,1), stem(xn,x,'filled'), ylim([-2 4]), ylabel('x')
subplot(3,1,2), stem(xn,h,'filled'), ylim([-2 4]), ylabel('h')
subplot(3,1,3), stem(xn,y,'filled'), ylim([-2 4]), ylabel('y')
%plot -s 560,600
N = 8;
theta2 = (0:1/N:1)*2*pi;
theta = theta2(1:end-1);
re = cos(theta);
im = sin(theta);
subplot(3,1,1), stem3(re,im,x,'filled'); hold on;
plot(re,im,'k')
quiver(0,0,1,0,'k','maxheadsize',0.5)
quiver(0,0,0,1,'k','maxheadsize',0.5), hold off
xlabel('Real','fontsize',8), ylabel('Imaginary','fontsize',8), zlabel('x[n]')
zlim([-2,4])
subplot(3,1,2), stem3(re,im,h,'filled'); hold on;
plot(re,im,'k')
quiver(0,0,1,0,'k','maxheadsize',0.5)
quiver(0,0,0,1,'k','maxheadsize',0.5), hold off
xlabel('Real','fontsize',8), ylabel('Imaginary','fontsize',8), zlabel('h[n]')
zlim([-2,4])
subplot(3,1,3), stem3(re,im,y,'filled'); hold on;
plot(re,im,'k')
quiver(0,0,1,0,'k','maxheadsize',0.5)
quiver(0,0,0,1,'k','maxheadsize',0.5), hold off
xlabel('Real','fontsize',8), ylabel('Imaginary','fontsize',8), zlabel('y[n]')
zlim([-2,4])
%plot -s 560,800
N = 50;
n = 0:N-1;
s = sin(pi/N*n) .* [ones(1,N/2), -ones(1,N/2)];
subplot(4,1,1)
stem(s,'b','Marker','none','LineWidth',2);
axis([1 N -1.5 1.5])
title('piecewise smooth signal','fontsize',8)
% add noise to the signal
x = s + 0.1*randn(1,N);
subplot(4,1,2)
stem(x,'b','Marker','none','LineWidth',2);
axis([1 N -1.5 1.5])
title('piecewise smooth signal + noise','fontsize',8)
% construct moving average filter impulse response of length M
M = 5;
h = ones(1,M)/M;
subplot(4,1,3)
stem(h,'b','Marker','none','LineWidth',2);
axis([1 N 0 1])
title('impulse response','fontsize',8)
% convolve noisy signal with impulse response
y = cconv(x,h,N);
subplot(4,1,4)
stem(y,'b','Marker','none','LineWidth',2);
axis([1 N -1.5 1.5])
title('output','fontsize',8)
%plot -s 560,500
N = 50;
n = 0:N-1;
s = sin(pi/N*n) .* [ones(1,N/2), -ones(1,N/2)];
% add noise to the signal
x = s + 0.1*randn(1,N);
subplot(311)
stem(x,'b','Marker','none','LineWidth',2);
axis([1 N -1.5 1.5])
title('piecewise smooth signal + noise','fontsize',8)
% haar wavelet edge detector
h = (1/4)*[-ones(1,2), ones(1,2)];
subplot(312)
stem(h,'b','Marker','none','LineWidth',2);
axis([1 N -0.5 0.5])
title('Haar wavelet edge detector','fontsize',8)
% % convolve noisy signal with impulse response
y = cconv(x,h,N);
subplot(313)
stem(y,'b','Marker','none','LineWidth',2);
axis([1 N -1.5 1.5])
title('output','fontsize',8)
Download wave file 1
Download wave file 2
[x, Fs] = audioread([pwd,'\data_files\violin_origional.wav']);
x = x/max(x); % normalize
sound(x, Fs); % play a wave file with sampling rate Fs
%plot -s 560,200
% plot wave file
xn = (1:length(x))/Fs;
plot(xn,x), xlabel('time in sec')
% impulse response in a closed room (by gunshot)
[h, Fs] = audioread([pwd,'\data_files\gunshot.wav']);
h = h(:,1); % stereo to mono
sound(h, Fs);
plot((1:length(h))/Fs, h), xlabel('sec')
% image how the music played in a closed room sounds like
y = cconv(x,h);
y = y/max(y);
sound(y, Fs);
%%javascript
$.getScript('https://kmahelona.github.io/ipython_notebook_goodies/ipython_notebook_toc.js')