% EE3220 Week 8, Day 3 - Dr. Durant - 2014-02-07
% additions by Dr. Rothe
% Oversampling demonstration - read the comments for more information.
% Try different values for oversampling factor and periods of interpolation
% filter.
function w8oversampling(osf,pif)
%% Setup
% If either or both inputs are omitted, use defaults:
if exist('osf','var')~=1, osf = 5; end % Oversampling factor, must be integer
if exist('pif','var')~=1, pif = 4; end % periods of interpolation filter (computation cost, delay, fidelity)
% So, calling w8oversampling(5,4) is same as calling without arguments and accepting defaults
close all % figure windows
fs = 10; % Hz
T = 20; % seconds
N = fs*T; % total samples
n = 0:N-1; % time indexes
t = n/fs; % time of each sample
%% Figure 1: The original signal and spectrum at base sampling rate
x = cos(2*pi*4*t); % 4 Hz wave, near Nyquist
X = fft(x) / sqrt(N) / sqrt(N); % Effectively dividing by N. Two parts represent:
% (a) Convert Energy of signal to Power (average per sample) and
% (b) Normalize power for transform length. (b) is necessary since the
% 1/N factor in the IDFT must be partitioned as 1/sqrt(N) for both the DFT
% and IDFT to preserve energy scaling across domains. Following MA383
% terminology, the DFT and IDFTs have all eigenvalues equal to sqrt(N) and
% 1/sqrt(N), respectively. This scaling makes all eigenvalues of both equal
% to 1. In both cases, the eigenvectors are the positive/negative rotating
% complex exponentials of the DFT frequencies sampled at N points.
f_res = fs / N; % resolution of the above spectrum
f_dft = (0:N-1)*f_res; % frequency samples resulting from the DFT
stemPlotAndSpectrum(t(1:20), x(1:20), 'Original signal (20 samples)', f_dft, X)
%% Figure 2: Select oversampling parameters and design interpolation filter
% Unwanted aliases will be stronger as pif decreases, but you can often get
% away with a fairly small pif in practice.
nh = -(osf*pif):(osf*pif); % widen by OSF
h = sinc(nh/osf); % Here we omit the 1/osf = Omega1/pi factor derived in class.
% This compensates for the power reduction from the 0-insertion step.
figure,stem(nh,h), title('(Non-causal) interpolation filter')
%% Figure 3: Perform 0-insertion and view the results in time and frequency domains
fsos = fs * osf; % Our new, higher sampling frequency
nos = 0:(fsos*T-1);
tos = nos/fsos;
xus = reshape([x; zeros(osf-1,N)],1,[]); % 0-insertion
XUS = fft(xus) / length(xus); % energy->power & power normalizations discussed above, make dB come out correctly
f_res = fsos / length(xus);
f_dft = (0:length(xus)-1)*f_res;
stemPlotAndSpectrum(tos(1:(osf*20)), xus(1:(osf*20)),'Upsampled signal (OSF * 20 samples)', f_dft, XUS)
% Note the peaks at 4 Hz (baseband) and fs*n +/- 4 Hz
%% Figure 4: Apply the interpolation filter and see how the time/frequency results improve
y = filter(h,1,xus); % osf*pif-sample delay since h implicitly moved to 0 for causality
% The time domain signal looks like a cosine with the proper samples/s,
% But the spectrum will highlight any subtle flaws.
Y = fft(y) / length(y); % energy->power & power normalizations discussed above, make dB come out correctly
stemPlotAndSpectrum(tos(1:(osf*20)), y(1:(osf*20)), 'Interpolated, oversampled signal (OSF * 20 samples)', f_dft, Y)
% There will be a phase shift due to shifting h in time, but the phase plot
% isn't very interesting with only 1 component.
% The spectrum isn't perfect, but it looks pretty good. If nh is wide
% relative to T, the transient will create some "spillage", mainly
% around the main peak.
end % function
%% Subfunction encapsulating repetitive graphing code
function stemPlotAndSpectrum(t,x,ttl,f,X)
figure
% Time domain:
subplot(2,2,1), stem(t,x), title(ttl)
subplot(2,2,3), plot(t,x)
% Frequency domain:
subplot(2,2,2), plot(f, abs(X) ), ylabel('Magnitude')
subplot(2,2,4), plot(f, 20*log10(abs(X))), ylabel('dB'), xlabel('Hz')
end % subfunction