Table of Contents
Overview
In this chapter you will work with very simple signal operations in MATLAB. The focus is on basic filtering and basic transformations that you can try immediately on vectors that represent signals. You will not need any toolbox, everything here uses core MATLAB functionality.
You will treat a one dimensional vector as a discrete time signal, for example a recorded audio snippet or any numeric sequence that changes over time. Then you will see how to smooth it, how to emphasize changes, and how to apply a simple transform in the time and frequency domains using built in operations.
Representing a Simple Signal as a Vector
A basic discrete signal in MATLAB is just a numeric vector. For example, this can represent a noisy measurement over time.
t = 0:0.001:1; % time from 0 to 1 second with 1 ms step
x_clean = sin(2*pi*5*t); % clean 5 Hz sine wave
noise = 0.4*randn(size(t)); % random noise
x = x_clean + noise; % noisy signal
Here x is the noisy signal, t is the corresponding time vector, and x_clean is the underlying ideal signal. You can plot it to see the effect.
plot(t, x), xlabel('Time (s)'), ylabel('Amplitude'), title('Noisy signal')Every operation in this chapter will take such a vector and produce a new vector that is a filtered or transformed version of it.
Simple Moving Average Smoothing
A moving average filter replaces each sample by the average of it and its neighbors. This is one of the simplest ways to smooth out noise.
One way to express a length $N$ moving average is
$$
y[k] = \frac{1}{N}\sum_{i=0}^{N-1} x[k - i].
$$
In MATLAB you can implement this with convolution using conv. For a 5 point moving average, construct a filter kernel and convolve.
N = 5; % filter length
h = ones(1, N) / N; % moving average coefficients
y = conv(x, h, 'same'); % smoothed signal
The vector h contains the weights. The call conv(x, h, 'same') gives an output y of the same length as x, which is usually what you want when dealing with signals.
You can compare original and smoothed signals.
plot(t, x, 'Color', [0.8 0.8 0.8])
hold on
plot(t, y, 'b', 'LineWidth', 1.5)
hold off
legend('Noisy', 'Smoothed')
xlabel('Time (s)'), ylabel('Amplitude')
title('5-point moving average smoothing')The moving average reduces rapid fluctuations, but it also slightly blurs sharp changes in the signal.
Using `filter` for Simple FIR Filters
The function filter applies a one dimensional digital filter to a data vector. At the simplest level, you can think of it as performing a difference equation of the form
$$
y[n] = \sum_{k=0}^{M} b_k x[n-k] - \sum_{k=1}^{N} a_k y[n-k].
$$
For a simple finite impulse response, or FIR, filter you set $a_0 = 1$ and $a_k = 0$ for $k \ge 1$. Then the output does not depend on past outputs, only on current and past inputs.
A moving average is such an FIR filter. Using filter it becomes:
b = ones(1, N) / N; % numerator coefficients
a = 1; % denominator coefficient
y2 = filter(b, a, x); % filtered output
y2 and the previous y from conv will be very similar for sufficiently long signals. filter is often convenient when you use difference equation style filters.
You can also create a simple 3 point smoothing filter with more weight on the center sample.
b = [0.25 0.5 0.25];
a = 1;
y_weighted = filter(b, a, x);This keeps the central value more prominent while still smoothing.
Basic Difference Filtering to Emphasize Changes
Instead of smoothing, you might want to emphasize how the signal changes. A simple way to do this is to compute first differences. This is a kind of very simple high pass filter.
MATLAB has a direct function diff that computes differences between consecutive elements:
d = diff(x); % first difference
If $x$ represents samples at equally spaced times with spacing $\Delta t$, then d / dt approximates the derivative of the signal.
dt = t(2) - t(1);
dx_dt = d / dt;
If you prefer to use filter to build a difference filter, you can define coefficients for $y[n] = x[n] - x[n-1]$:
b = [1 -1]; % difference coefficients
a = 1;
d2 = filter(b, a, x);
d and d2 are slightly shifted relative to each other, but both indicate where the signal changes quickly. Large positive values indicate rising edges and large negative values indicate falling edges.
Basic Time Domain Transformations
Some transforms act directly in the time domain by modifying the order or sign of samples. A few very simple ones are time reversal, scaling, and shifting.
To reverse a signal in time, use indexing.
x_rev = x(end:-1:1); % reverse order of samplesThis flips the signal around its center in time.
To scale amplitude, multiply by a constant.
x_quiet = 0.5 * x; % reduce amplitude
x_loud = 2.0 * x; % increase amplitudeTo apply a simple shift in discrete time indexing, prepad or remove elements. For example, shifting the signal to the right by 3 samples corresponds to adding zeros at the beginning and truncating at the end.
shift = 3;
x_right = [zeros(1, shift) x(1:end-shift)];Shifting to the left by 3 samples is similar but removes initial values.
x_left = x(shift+1:end);
For continuous time quantities that depend on t, you would usually shift by adjusting the time vector, but the core idea is that a shift in time is a reindexing of the samples.
Very Simple Frequency Domain Insight with `fft`
Without going deep into frequency analysis, you can already get a sense of frequency content of a signal with the Fast Fourier Transform using fft. This converts your time domain vector into a complex frequency domain representation.
Assume x is your signal and Fs is the sampling frequency. From the time step dt you can get Fs = 1 / dt.
dt = t(2) - t(1);
Fs = 1/dt;
N = numel(x);
X = fft(x); % complex spectrum
f = (0:N-1) * (Fs/N); % frequency axis from 0 to Fs-1*Fs/N
magX = abs(X); % magnitude spectrum
If you plot magX against f you see which frequencies contribute most strongly.
plot(f, magX)
xlim([0 50]) % look at low frequencies
xlabel('Frequency (Hz)')
ylabel('|X(f)|')
title('Magnitude spectrum of x')For the example signal that includes a 5 Hz sine wave, you should see a clear peak near 5 Hz. Noise spreads energy across many frequencies.
You can try the same after smoothing with the moving average filter and notice that high frequency content is reduced.