DSPRelated.com
Code

Continuous-time equivalent of a discrete-time impulse response

Markus Nentwig August 12, 2011 Coded in Matlab

Constructs a continuous-time waveform that corresponds to a discrete-time impulse response (i.e. FIR filter coefficients).

Description:
A sampled (time-discrete) signal often represents a continuous-time waveform, for example a voltage waveform from a microphone that can be reconstucted from the samples by a lowpass filter. Accordingly, also the discrete-time impulse response from a digital filter has an analog equivalent, which is provided by the program below. Reconstruction is effectively based on an ideal lowpass filter, implemented via frequency domain methods. 

Example:
Fig. 1 shows a time-discrete impulse response (black circles) and the resulting continuous-time equivalent (blue). Fig. 1: Original discrete-time impulse response (black) and resulting cont. time equivalent

Fig. 1: Original discrete-time impulse response (black) and reconstructed continuous-time equivalent (blue)

Applications:

  • Can be used to illustrate the "meaning" behind unintuitive FIR coefficients, for example fractional delay banks in a polyphase filter.
  • Shows the difficulty of "interpolating" by geometric means, i.e. polynomial, splines, etc, since the continuous-time waveform clearly depends on many (strictly speaking: all) supporting points.
  • May provide a continuous-time impulse response for a (Farrow) resampler design, based on a discrete-time prototype.

Note:
The continuous-time equivalent impulse response of a discrete-time "finite impulse response" (FIR) filter is zero at all sampling instants beyond the duration of the discrete-time impulse response. However, it does not show the same finite duration as a whole.
The difference is subtle, but clearly visible for example on equiripple designs that exhibit a "discontinuous" last sample.

As is well-known, a linear-phase filter (without group delay dispersion) exhibits a symmetric impulse response. What is interesting here is that the continuous-time equivalent can be symmetric, even if the discrete-time impulse response appears asymmetrical (example: FIR with fractional-sample group delay).
Code tested on Octaveforge and Matlab

% ************************************************************
% * Construct a continuous-time impulse response based on a discrete-time filter
% ************************************************************
close all; clear all;

% ************************************************************
% * example filter
% * f = [0 0.7 0.8 1]; a = [1 1 0 0];
% * b = remez(45, f, a);
% * h = b .';
% Illustrates rather clearly the difficulty of "interpolating" (in a geometric sense, 
% via polynomials, splines etc) between impulse response samples
% ************************************************************    
h = [2.64186706e-003 2.50796828e-003 -4.25450455e-003 4.82982358e-003 -2.51252769e-003 -2.52706568e-003 7.73569146e-003 -9.30398382e-003 4.65100223e-003 5.17152459e-003 -1.49409856e-002 1.76001904e-002 -8.65545521e-003 -9.78478603e-003 2.82103205e-002 -3.36173643e-002 1.68597129e-002 2.01914744e-002 -6.17486493e-002 8.13362871e-002 -4.80981494e-002 -8.05143565e-002 5.87677665e-001 5.87677665e-001 -8.05143565e-002 -4.80981494e-002 8.13362871e-002 -6.17486493e-002 2.01914744e-002 1.68597129e-002 -3.36173643e-002 2.82103205e-002 -9.78478603e-003 -8.65545521e-003 1.76001904e-002 -1.49409856e-002 5.17152459e-003 4.65100223e-003 -9.30398382e-003 7.73569146e-003 -2.52706568e-003 -2.51252769e-003 4.82982358e-003 -4.25450455e-003 2.50796828e-003 2.64186706e-003];

% ************************************************************
% zero-pad the impulse response of the FIR filter to 5x its original length
% (time domain)
% The filter remains functionally identical, since appending zero taps changes nothing
% ************************************************************
timePaddingFactor = 5;
n1 = timePaddingFactor * size(h, 2);
nh = size(h, 2);
nPad = n1 - nh;
nPad1 = floor(nPad / 2);
nPad2 = nPad - nPad1;
h = [zeros(1, nPad1), h, zeros(1, nPad2)];
hOrig = h;

% ************************************************************
% Determine equivalent Fourier series coefficients (frequency domain)
% assume that the impulse response is bandlimited (time-discrete signal by definition) 
% and periodic (period length see above, can be extended arbitrarily)
% ************************************************************
h = fft(h); % Fourier transform time domain to frequency domain

% ************************************************************
% Evaluate the Fourier series on an arbitrarily dense grid 
% this allows to resample the impulse response on an arbitrarily dense grid
% ************************************************************
% zero-pad Fourier transform
% ideal band-limited oversampling of the impulse response to n2 samples
n2 = 10 * n1;

h = [h(1:ceil(n1/2)), zeros(1, n2-n1), h(ceil(n1/2)+1:end)];
h = ifft(h); % back to time domain
% Note: One may write out the definition of ifft() and evaluate the exp(...) term at an 
% arbitrary time to acquire a true continuous-time equation.

% numerical inaccuracy in (i)fft causes some imaginary part ~1e-15
assert(max(abs(imag(h))) / max(abs(real(h))) < 1e-14);
h = real(h);

% scale to maintain amplitude level
h = h * n2 / n1;

% construct x-axis [0, 1[
xOrig = linspace(-timePaddingFactor/2, timePaddingFactor/2, size(hOrig, 2) + 1); xOrig = xOrig(1:end-1);
x = linspace(-timePaddingFactor/2, timePaddingFactor/2, size(h, 2) + 1); x = x(1:end-1);

% ************************************************************
% Plot 
% ************************************************************
% ... on a linear scale

% find points where original impulse response is defined (for illustration)
ixOrig = find(abs(hOrig) > 0);

figure(); grid on; hold on;
stem(xOrig(ixOrig), hOrig(ixOrig), 'k');
plot(x, h, 'b'); 
legend('discrete-time FIR filter', 'continuous-time equivalent');
title('equivalent discrete- and continuous-time filters');
xlabel('time (relative to discrete time IR duration)'); ylabel('h(t)');

% ... and again on a logarithmic scale
myEps = 1e-15;
figure(); grid on; hold on;
u = plot(xOrig(ixOrig), 20*log10(abs(hOrig(ixOrig)) + myEps), 'k+'); set(u, 'lineWidth', 3);
plot(x, 20*log10(abs(h) + myEps), 'b');
legend('discrete-time FIR filter', 'continuous-time equivalent');
title('equivalent discrete- and continuous-time filters');
xlabel('time (relative to discrete time IR duration)'); ylabel('|h(t)| / dB');