Skip to content

Impulse Response and Convolution

We use the notation of the overview: an input signal \(x(t)\), an output signal \(y(t)\), and a filter \(h\). We model a filter as a linear, time-invariant operator carrying an input signal to an output signal. Such an operator is determined by a single function, and it acts by convolution.

Definition: impulse response and convolution

The impulse response \(h\) of a filter is its output in response to the unit impulse \(\delta\). The filter acts on an input \(x\) by convolution, $$ y(t) = (h * x)(t) = \int_{-\infty}^{\infty} h(\tau)\, x(t - \tau)\, d\tau. $$ The filter has finite impulse response of duration \(T\) if \(h\) is supported on \([0, T]\), in which case the integral runs over \(\tau \in [0, T]\) and each value \(y(t)\) is a weighted average of the input over the preceding interval \([t - T,\, t]\), with weights \(h\).

The name records a simple fact: taking \(x = \delta\) reproduces \(y = h\), so the impulse response is literally the filter's response to an impulse. Every other output is assembled from shifted, scaled copies of that response, one for each instant of the input.

Example: two boxes make a triangle

Let both the impulse response and the input be the unit box \(\mathbf{1}_{[0, T]}\), equal to \(1\) on \([0, T]\) and \(0\) elsewhere. The convolution is the triangle $$ y(t) = \bigl(T - \lvert t - T \rvert\bigr)_{+}, \qquad 0 \le t \le 2T, $$ where \((\cdot)_{+}\) denotes the positive part. It rises linearly to its peak of height \(T\) at \(t = T\), the instant of full overlap between the box and its reflected copy, and falls back to zero at \(t = 2T\).

Convolution of two unit boxes, giving a triangle of height T peaked at t = T

Valid outputs

The convolution at time \(t\) draws on the input over the interval \([t - T,\, t]\). For a signal known only from time \(0\) onward, an output at \(t < T\) would require input from before the record began. We call an output value valid when the interval it depends on lies entirely within the available record, that is, when \(t \ge T\).

In discrete time

Sampling at rate \(f_s\) replaces the impulse response by its taps \(h[n] = h(n / f_s)\) for \(n = 0, \ldots, N - 1\), with \(N = \lfloor T f_s \rfloor + 1\), and replaces the convolution integral by the sum $$ y[n] = \sum_{k=0}^{N-1} h[k]\, x[n - k]. $$ An output \(y[n]\) computed without assuming zeros before the record requires the \(N - 1\) samples preceding index \(n\), so the first \(N - 1\) outputs are not valid. A record of \(M\) samples yields \(M - N + 1\) valid outputs.

Sampling the two boxes of the example and convolving recovers the triangle, with its peak one duration \(T\) after the onset:

import numpy as np

fs = 100                          # samples per unit time
box = np.ones(fs)                 # unit box of duration T = 1
y = np.convolve(box, box) / fs    # the 1/fs factor turns the sum into the integral
t = np.arange(y.size) / fs
assert np.isclose(t[np.argmax(y)], 1.0, atol=1 / fs)   # peak at t = T
assert np.isclose(y.max(), 1.0, atol=1e-2)             # peak height T

Correlation

Convolution reflects the impulse response before sliding it across the input. The unreflected operation is cross-correlation.

Definition: cross-correlation

The cross-correlation of \(h\) with \(x\) is $$ (h \star x)(t) = \int_{-\infty}^{\infty} h(\tau)\, x(t + \tau)\, d\tau . $$ It slides \(h\) across the input without reflecting it.

Correlation against \(h\) therefore coincides with convolution against the reflected impulse response \(\tilde h(\tau) = h(-\tau)\); for a filter supported on \([0, T]\) the reflection about its support is \(h(T - \tau)\). The two operations agree precisely when \(h\) is symmetric about the midpoint of its support. The distinction is immaterial for a symmetric filter but essential for an asymmetric one, where reflection reverses the filter in time.

In discrete time

Reflection becomes reversal of the tap order, \(\tilde h[k] = h[N - 1 - k]\), so correlation against the taps equals convolution against the reversed taps.

For the asymmetric taps \((1, 2, 3)\), correlation reproduces convolution against the reversed taps \((3, 2, 1)\):

import numpy as np
from scipy.signal import correlate

x = np.arange(1.0, 7.0)
h = np.array([1.0, 2.0, 3.0])          # asymmetric taps
assert np.allclose(correlate(x, h, "valid"), np.convolve(x, h[::-1], "valid"))

References