Signal Processing Fundamentals

A signal sampled at fs samples per second can represent frequencies up to the Nyquist frequency fs/2.

Concept

A signal sampled at fs samples per second can represent frequencies up to the Nyquist frequency fs/2. Higher frequencies alias to lower ones — that's why data acquisition systems use anti-aliasing filters.

The Fast Fourier Transform X = fft(x) computes the discrete Fourier transform. For a real signal of length N:

bin k corresponds to frequency f = k·fs/N;

the single-sided amplitude spectrum is 2*abs(X(1:N/2+1))/N (bins 1 and N/2+1 not doubled);

frequency resolution is fs/N (longer records → finer resolution);

windowing (Hann, Hamming) reduces leakage when the record doesn't contain whole periods.

y = filter(b, a, x) implements the difference equation a₁y(n) = b₁x(n) + b₂x(n−1) + … − a₂y(n−1) − …

FIR (only b): e.g. a moving average b = ones(1, M)/M; always stable, linear phase, delay (M−1)/2 samples.

IIR (b and a): e.g. first-order low-pass y(n) = a·y(n−1) + (1−a)·x(n); efficient, but can be unstable and distorts phase.

filtfilt (Signal Processing Toolbox) filters forward and backward for zero phase; butter, cheby1, designfilt design filters (toolbox).

conv performs convolution; cross-correlation (xcorr, toolbox) finds delays and templates.

Why It Matters

Vibration analysis, audio, sensor noise reduction, CAN signal post-processing, power electronics ripple, and communications all start with the FFT and filtering.

Syntax

X = fft(x); f = fs * (0:N/2) / N;
y = filter(ones(1, 10) / 10, 1, x);      % moving average
y = filter(1 - a, [1 -a], x);            % first-order IIR low-pass

Example

25.1 Spectrum, FIR and IIR filtering, aliasing and template matching

fs = 1000;                                   % sampling frequency, Hz
t = (0:fs - 1) / fs;                        % 1 second
x = 1.0 * sin(2 * pi * 50 * t) + 0.5 * sin(2 * pi * 120 * t);

% FFT: single-sided amplitude spectrum
N = numel(x);
X = fft(x);
A = abs(X / N);
A = A(1:N / 2 + 1);
A(2:end - 1) = 2 * A(2:end - 1);
f = fs * (0:N / 2) / N;
[pk, loc] = sort(A, 'descend');
fprintf('strongest components: %g Hz (amplitude %.3f), %g Hz (amplitude %.3f)\n', f(loc(1)), pk(1), f(loc(2)), pk(2))

% moving-average FIR filter with filter()
rng(1);
noisy = sin(2 * pi * 2 * t) + 0.3 * randn(size(t));
b = ones(1, 25) / 25;
smooth = filter(b, 1, noisy);
fprintf('noise std before %.3f, after moving average %.3f\n', std(noisy - sin(2 * pi * 2 * t)), std(smooth(50:end) - sin(2 * pi * 2 * (t(50:end) - 12 / fs))))

% first-order IIR low-pass: y(n) = a*y(n-1) + (1-a)*x(n)
a = 0.9;
step_in = ones(1, 30);
y = filter(1 - a, [1 -a], step_in);
fprintf('IIR step response: y(1) = %.3f, y(10) = %.3f, y(30) = %.3f\n', y(1), y(10), y(30))

% aliasing: a 900 Hz tone sampled at 1000 Hz looks like 100 Hz
xa = sin(2 * pi * 900 * t);
Aa = abs(fft(xa)) / N;
[~, i] = max(Aa(1:N / 2 + 1));
fprintf('900 Hz sampled at
…

Expected Result

The FFT recovered both components with their exact amplitudes (1.0 at 50 Hz, 0.5 at 120 Hz), because the 1-second record contains whole periods.

The moving-average filter reduced the noise standard deviation substantially (the comparison accounts for its 12-sample delay).

The IIR step response approaches 1 exponentially.

A 900 Hz tone sampled at 1 kHz appeared at 100 Hz: aliasing.

(The noise uses a seeded random generator; exact noise values differ between MATLAB and Octave.)

strongest components: 50 Hz (amplitude 1.000), 120 Hz (amplitude 0.500)
noise std before 0.307, after moving average 0.061
IIR step response: y(1) = 0.100, y(10) = 0.651, y(30) = 0.958
900 Hz sampled at 1 kHz appears at 100 Hz (aliasing)
conv([1 2 3], [1 1]) = [1 3 5 3]
template found at index 3

Common Mistakes

Forgetting to scale the FFT by N and to double the single-sided amplitudes.

Reading frequencies from bin indices without f = k·fs/N (and the off-by-one of 1-based indexing).

Filtering and comparing signals without accounting for the filter delay.

Sampling too slowly for the signal content.

Best Practices

Choose fs ≥ 2.5× the highest frequency of interest and filter before sampling.

Use windows for spectra of non-periodic records.

Plot signals before and after filtering; check delay and attenuation.

Interview Relevance

High for signal-processing and automotive roles: "what is the Nyquist frequency?", "what is aliasing?", "how do you compute an amplitude spectrum?", "FIR vs IIR?", "what does a moving average do to a signal?".

Practice Questions

Add a 60 Hz hum to a 5 Hz signal and remove it with a moving-average filter of suitable length.

Show spectral leakage by analysing 50.5 Hz with a 1-second record, with and without a Hann window.

Implement a first-order high-pass filter with filter.

Find the delay between two copies of a signal with correlation via conv.

Quick Quiz

Q1. (Multiple choice) With fs = 1000 Hz, the highest frequency that can be represented without aliasing is: A) 1000 Hz B) 500 Hz C) 250 Hz D) 2000 Hz Answer: B.

Q2. (Predict the output) A 900 Hz sine sampled at 1 kHz appears at which frequency?

Answer: 100 Hz (verified).

Q3. (True/False) A moving-average filter is an FIR filter.

Answer: True. Q4. (Find the bug) A = abs(fft(x)); is plotted as the amplitude spectrum and shows a 500× too large peak.

Answer: Missing normalization by N (and doubling for the single-sided spectrum).

Coding Challenge

Generate 2 seconds of a 7 Hz sine sampled at 200 Hz plus a DC offset of 1.5, compute the single-sided spectrum, and print the DC value and the peak frequency and amplitude.

fs = 200; t = (0:2 * fs - 1) / fs;
x = 1.5 + 0.8 * sin(2 * pi * 7 * t);
N = numel(x);
A = abs(fft(x)) / N;
A = A(1:N / 2 + 1); A(2:end - 1) = 2 * A(2:end - 1);
f = fs * (0:N / 2) / N;
[pk, i] = max(A(2:end));
fprintf('DC %.3f, peak %.3f at %g Hz\n', A(1), pk, f(i + 1))