MATLAB Code
%% Advanced Filter Visualization: The "Signal Cleaner"
clc; clear; close all;
% --- 1. SETUP PARAMETERS ---
fs = 1000; % Sampling frequency (1kHz)
T = 1.5; % Duration in seconds
t = (0:1/fs:T-1/fs)'; % Time vector
% --- 2. CREATE A "MESSY" INPUT SIGNAL ---
% Desired Signal: 20 Hz (Clean sine wave)
s1 = 1.0 * sin(2*pi*20*t);
% Interference 1: 50 Hz (Strong Power-line Hum) - TARGET FOR NOTCH
n1 = 0.8 * sin(2*pi*50*t);
% Interference 2: 150 Hz (High-frequency Noise) - TARGET FOR LOW-PASS
n2 = 0.6 * sin(2*pi*150*t);
% The combined "Dirty" signal
x = s1 + n1 + n2;
% --- 3. DESIGN ANALOG FILTERS (using coefficients) ---
% A. Notch Filter @ 50 Hz (Deep cut at exactly 50Hz)
f0 = 50; w0 = 2*pi*f0;
Q = 10; % Quality factor (higher = narrower notch)
b_notch = [1 0 w0^2];
a_notch = [1 w0/Q w0^2];
% B. Low-Pass Filter @ 80 Hz (Blocks 150Hz)
fc = 80; wc = 2*pi*fc;
[b_lp, a_lp] = butter(2, wc, 's'); % 2nd order Butterworth
% C. Resonator @ 20 Hz (Boosts the desired 20Hz signal)
wr = 2*pi*20;
zeta = 0.05;
b_res = [2*zeta*wr 0];
a_res = [1 2*zeta*wr wr^2];
% Combine all: Total = Notch * LowPass * Resonator
b_total = conv(conv(b_notch, b_lp), b_res);
a_total = conv(conv(a_notch, a_lp), a_res);
% --- 4. APPLY FILTERING ---
% Convert to digital for simulation
[bz, az] = bilinear(b_total, a_total, fs);
y = filter(bz, az, x);
% --- 5. FREQUENCY DOMAIN ANALYSIS (FFT) ---
L = length(x);
f_axis = (0:L-1)*(fs/L);
X_fft = abs(fft(x)/L); % Spectrum of Dirty Signal
Y_fft = abs(fft(y)/L); % Spectrum of Cleaned Signal
% --- 6. VISUALIZATION ---
figure('Color', 'w', 'Position', [100, 100, 1000, 700]);
% TOP: TIME DOMAIN COMPARISON
subplot(2,1,1);
plot(t, x, 'Color', [0.7 0.7 0.7], 'LineWidth', 1); hold on;
plot(t, y, 'r', 'LineWidth', 2);
title('TIME DOMAIN: Dirty Input vs. Cleaned Output');
xlabel('Time (s)'); ylabel('Amplitude');
legend('Input (20Hz + 50Hz + 150Hz)', 'Filtered (Only 20Hz left)');
grid on; xlim([0.5 0.8]); % Zoom into a stable portion
% BOTTOM: FREQUENCY DOMAIN (The "Proof")
subplot(2,1,2);
semilogy(f_axis, X_fft, 'Color', [0.7 0.7 0.7], 'LineWidth', 1.5); hold on;
semilogy(f_axis, Y_fft, 'r', 'LineWidth', 2);
title('FREQUENCY DOMAIN: Magnitude Spectrum (Log Scale)');
xlabel('Frequency (Hz)'); ylabel('Magnitude');
grid on; xlim([0 250]); % Focus on area of interest
legend('Original Spectrum (3 Peaks)', 'Filtered Spectrum (1 Peak)');
% Annotations for clarity
text(20, X_fft(round(20*T))+0.1, '← 20Hz Signal (Kept/Boosted)', 'FontWeight', 'bold');
text(50, X_fft(round(50*T))+0.1, '← 50Hz Hum (ERASED BY NOTCH)', 'Color', 'blue');
text(150, X_fft(round(150*T))+0.1, '← 150Hz Noise (BLOCKED BY LOW-PASS)', 'Color', [0 .5 0]);
Output
Another MATLAB Code
%% Advanced Filter Visualization: "Signal Cleaner" (Pole-Zero Edition)
clc; clear; close all;
%% 1. SETUP PARAMETERS
fs = 1000; % Sampling frequency (Hz)
T = 1.5; % Duration (s)
t = (0:1/fs:T-1/fs)'; % Time vector
%% 2. CREATE "MESSY" INPUT SIGNAL
s1 = 1.0 * sin(2*pi*20*t); % 20 Hz Desired Signal
n1 = 0.8 * sin(2*pi*50*t); % 50 Hz Hum (Notch target)
n2 = 0.6 * sin(2*pi*150*t); % 150 Hz Noise (LP target)
x = s1 + n1 + n2; % Combined "dirty" signal
%% 3. DESIGN ANALOG FILTERS (Poles & Zeros)
% --- A. Notch Filter at 50 Hz ---
f0 = 50; w0 = 2*pi*f0; Q = 10;
z_notch = [1j*w0; -1j*w0]; % Zeros cancel 50Hz
zeta_notch = 1/(2*Q);
p_notch = [-zeta_notch*w0 + 1j*w0*sqrt(1-zeta_notch^2);
-zeta_notch*w0 - 1j*w0*sqrt(1-zeta_notch^2)]; % Poles near zeros
k_notch = 1;
% --- B. Low-Pass Filter at 80 Hz ---
fc = 80; wc = 2*pi*fc;
[b_lp, a_lp] = butter(2, wc, 's'); % Analog Butterworth
[z_lp, p_lp, k_lp] = tf2zp(b_lp, a_lp); % Convert to ZPK
% --- C. Resonator at 20 Hz ---
wr = 2*pi*20; zeta_r = 0.05; % Small damping
p_res = [-zeta_r*wr + 1j*wr*sqrt(1-zeta_r^2);
-zeta_r*wr - 1j*wr*sqrt(1-zeta_r^2)];
z_res = []; % No zeros for pure resonator
k_res = 1;
% --- COMBINE ALL FILTERS ---
z_total = [z_notch; z_lp; z_res];
p_total = [p_notch; p_lp; p_res];
k_total = k_notch * k_lp * k_res;
% Convert ZPK → TF (Analog)
[b_total, a_total] = zp2tf(z_total, p_total, k_total);
% Digital conversion via Bilinear Transform
[bz, az] = bilinear(b_total, a_total, fs);
%% 4. APPLY FILTERING
y = filter(bz, az, x);
%% 5. FREQUENCY DOMAIN ANALYSIS
L = length(x);
f_axis = (0:L-1)*(fs/L);
X_fft = abs(fft(x)/L);
Y_fft = abs(fft(y)/L);
% Correct FFT indices for annotations
idx_20 = round(20 / (fs/L)) + 1;
idx_50 = round(50 / (fs/L)) + 1;
idx_150 = round(150 / (fs/L)) + 1;
%% 6. VISUALIZATION
figure('Color', 'w', 'Position', [100, 100, 1000, 700]);
% --- Time Domain ---
subplot(2,1,1);
plot(t, x, 'Color', [0.7 0.7 0.7]); hold on;
plot(t, y, 'r', 'LineWidth', 2);
title('TIME DOMAIN: Input vs. Cleaned Output');
xlabel('Time (s)'); ylabel('Amplitude');
legend('Dirty Input', 'Filtered (20 Hz)');
grid on; xlim([0.5 0.8]);
% --- Frequency Domain ---
subplot(2,1,2);
semilogy(f_axis, X_fft, 'Color', [0.7 0.7 0.7], 'LineWidth', 1.5); hold on;
semilogy(f_axis, Y_fft, 'r', 'LineWidth', 2);
title('FREQUENCY DOMAIN: Magnitude Spectrum (Log Scale)');
xlabel('Frequency (Hz)'); ylabel('Magnitude');
grid on; xlim([0 250]);
legend('Original Spectrum', 'Filtered Spectrum');
% --- Annotations ---
text(20, X_fft(idx_20)+0.02, '← 20Hz Signal (Boosted)', 'Color', 'red', 'FontWeight','bold');
text(50, X_fft(idx_50)+0.02, '← 50Hz Hum (Notch Cut)', 'Color', 'blue', 'FontWeight','bold');
text(150, X_fft(idx_150)+0.02, '← 150Hz Noise (LP Blocked)', 'Color', [0 0.5 0], 'FontWeight','bold');
Further Reading