Matlab Design Digital Filter
MathWorksOfficialCreated by MathWorks
- Skill
- Tool integration
- Science and research
- BSD-2-Clause
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a structured workflow for designing and validating digital filters within MATLAB. It guides users through signal analysis, architecture selection, and verification, ensuring that filter designs meet specific frequency and magnitude requirements. The skill emphasizes the use of standard MATLAB functions like designfilt and filterAnalyzer, while enforcing best practices for numerical stability and frequency-aware design.
What it does
- Designs FIR and IIR filters including lowpass, highpass, bandpass, bandstop, and notch types.
- Provides a systematic workflow for signal analysis and architecture selection.
- Facilitates visual comparison of filter designs using Filter Analyzer.
- Enforces best practices for numerical stability, such as using SOS forms for IIR filters.
- Includes validation steps to verify filter performance against specifications.
- Supports both streaming and offline filtering implementation strategies.
When to use it
- When you need to clean up noisy signals or remove specific interference.
- When designing digital filters with specific frequency and ripple requirements.
- When comparing different filter architectures like FIR versus IIR.
- When working on streaming or batch signal processing pipelines.
Advantages
- Ensures consistent design methodology through a preflight and verification checklist.
- Promotes numerical stability by recommending specific filter forms.
- Integrates directly with MATLAB's signal processing and DSP toolboxes.
- Provides clear guidance on handling narrow transition bands.
Usage examples
- “Design a lowpass filter for a 1000 Hz signal with a 200 Hz cutoff.”
- The agent will ask for the sample rate (Fs), filter mode (streaming vs offline), and phase requirements before generating the design code.
- “How do I compare two different filter designs in MATLAB?”
- The agent will guide you to use the filterAnalyzer function and provide the necessary steps to visualize and compare their magnitude and group delay responses.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/matlab/matlab-design-digital-filter/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip matlab-design-digital-filter.zip -d .agents/skills
Documentation by MathWorks
Design Digital Filters in MATLAB
Design, implement, and validate digital filters using Signal Processing Toolbox and DSP System Toolbox. Choose the right architecture (single-stage vs efficient alternatives), generate correct code, and verify the result with plots and numbers.
When to Use
Designing lowpass, highpass, bandpass, bandstop, or notch filters
Cleaning up noisy signals or removing interference
Choosing between FIR and IIR filter architectures
Comparing filter designs in Filter Analyzer
Building streaming (real-time) or offline (batch) filtering pipelines
Handling narrow transition bands with multirate or IFIR approaches
When NOT to Use
Adaptive filtering (LMS, RLS) -- use Signal Processing Toolbox docs directly
Audio-specific processing (equalization, room correction) -- use Audio Toolbox
Image filtering (2D convolution, morphological ops) -- use Image Processing Toolbox
General spectral analysis without filtering intent -- FFT/periodogram docs suffice
Key Rules
Read references/INDEX.md before writing any filter design code.
Always write to .m files. Never put multi-line MATLAB code directly in
evaluate_matlab_code. Write to a.mfile, run withrun_matlab_file, edit on error.Preflight before ANY MATLAB call. Before calling any function listed in INDEX.md, read the required quick-ref first. State
Preflight: [files]at the top of the response.Do not guess key requirements. If Mode (streaming vs offline) or Phase requirement is not stated, ask.
No Hz designs without Fs. If
Fsis unknown, stop and ask (unless the user explicitly wants normalized frequency).Always pin the sample rate. Use
designfilt(..., SampleRate=Fs)andfreqz(d, [], Fs).IIR stability: Prefer SOS/CTF forms (avoid high-order
[b,a]polynomials).
Preflight Procedure
List MATLAB functions to call
Check
references/INDEX.mdfor each (function-level + task-level tables)Read required quick-ref files
State at response top:
Preflight: quick-ref/filter-analyzer.md, quick-ref/designfilt.md(orPreflight: none required)
Workflow
Phase 1: Signal Analysis
Analyze input data via MCP (spectrum, signal length, interference location)
Compute
trans_pctand identify interference characteristics
Phase 2: Clarify Intent
After signal analysis, ask Mode + Phase if not stated:
Mode: streaming (causal) | offline (batch)
Phase: zero-phase | linear-phase | don't-care
Wait for answer before showing any approach comparison or overview.
Phase 3: Architecture Selection
Open
references/efficient-filtering.mdiftrans_pct < 2%Show only viable candidates given Mode + Phase constraints
Explicitly state excluded families with one-line reason
Use Filter Analyzer for visual comparison
Design Intake Checklist
Required signal + frequency spec (cannot proceed without)
Fs(Hz)Response type: lowpass / highpass / bandpass / bandstop / notch
Edge frequencies in Hz
If any item is missing, ask.
Required intent for architecture choice (ask if unknown)
Mode: streaming (causal) | offline (batch)
Phase: zero-phase | linear-phase | don't-care
Magnitude constraints:
Rp_dBpassband ripple (default 1 dB),Rs_dBstopband attenuation (default 60 dB)
If Mode or Phase is unknown, ask 1-2 clarifying questions and stop.
Architecture Checkpoint
Compute and state before finalizing an approach:
trans_bw = Fstop - Fpasstrans_pct = 100 * trans_bw / FsM_max = floor(Fs/(2*Fstop))(only meaningful for lowpass-based multirate)
Decision rule:
trans_pct > 5%-- single-stage FIR or IIR is usually fine2% <= trans_pct <= 5%-- single-stage possible; mention efficient alternatives if cost/latency matterstrans_pct < 2%-- stop and do a narrow-transition comparison (seereferences/quick-ref/efficient-filtering.md)
Design + Verify
Feasibility check -- Let
designfiltchoose minimum order, then queryfiltord(d). Optionally usekaiserord/firpmordfor FIR length estimates.Design candidates -- Prefer
designfilt()with explicitRp/RsandSampleRate=Fs. Streaming IIR: useSystemObject=true. Offline zero-phase:filtfilt()is allowed but state that it squares the magnitude response.Compare visually -- Use
filterAnalyzer()for comparing 2+ designs. Readreferences/quick-ref/filter-analyzer.mdfirst. Minimum displays: magnitude + group delay.Verify with numbers -- Worst-case passband ripple and stopband attenuation vs spec. For
filtfilt(), verify the effective response (magnitude squared).Deliver the output -- Specs recap, derived metrics, chosen architecture + why, MATLAB code, verification snippet + results, implementation form.
Key Functions
| Function | Purpose |
|---|---|
designfilt() | Primary filter design (FIR and IIR, all response types) |
filterAnalyzer() | Visual comparison of 2+ filter designs |
freqz(), grpdelay() | Frequency response and group delay analysis |
filtfilt() | Zero-phase offline filtering |
dsp.SOSFilter | Streaming IIR via SystemObject=true |
designMultirateFIR() | Multirate decimator/interpolator design |
ifir() | Interpolated FIR for narrow transitions at constant rate |
cost() | MPIS (MultiplicationsPerInputSample) on DSP System objects |
kaiserord(), firpmord() | FIR order estimation |
Conventions
Always specify
SampleRate=Fsindesignfilt()and plot in Hz withfreqz(d, [], Fs)Use
filterAnalyzer()for multi-filter comparison, not customfreqz/grpdelayplotsUse SOS form for IIR (avoid
[b,a]for order > 8)Use
tiledlayout/nexttilefor multi-panel figures (notsubplot)
Copyright 2026 The MathWorks, Inc.
Files
- ATTRIBUTION.mdAdded by AutoGineer1.0 KiB
- LICENSELicence file added by AutoGineer1.4 KiB
- SKILL.md6.1 KiB
- manifest.yaml473 B
- references/INDEX.md2.9 KiB
- references/best-practices.md7.8 KiB
- references/efficient-filtering.md14.4 KiB
- references/filter-analyzer.md18.1 KiB
- references/multirate.md13.2 KiB
- references/multistage-ifir.md8.5 KiB
- references/patterns.md16.2 KiB
- references/quick-ref/designfilt.md6.0 KiB
- references/quick-ref/efficient-filtering.md6.1 KiB
- references/quick-ref/filter-analyzer.md3.0 KiB
- references/quick-ref/general-iir-fir.md3.0 KiB
- references/quick-ref/multirate-offline.md2.3 KiB
- references/quick-ref/multirate-streaming.md3.6 KiB
- references/quick-ref/multistage-ifir.md2.8 KiB
references/multirate.md
Multirate Filtering Guide
Complete guide for multirate filtering in MATLAB. Covers when to use each function, streaming vs offline workflows, and cost analysis.
Table of Contents
Critical Decision: Which Function to Use?
When Not to Use designMultistageDecimator/Interpolator
Concept: Multirate Pipeline
Workflow 1: Streaming Multirate
Workflow 2: Offline Zero-Phase
Workflow 3: Wideband Rate Conversion
Workflow 4: Complex Specifications
Cost Analysis
Key Functions Reference
Gotchas
API References
Visualization
Critical Decision: Which Function to Use?
The choice of multirate function depends on your use case. Using the wrong function can result in 5× worse performance.
Quick Decision Table
| Use Case | Recommended Approach | Why |
|---|---|---|
| Narrow transition + streaming | designMultirateFIR + separate sharp filter | Relaxed anti-alias + efficient sharp filter at low rate |
| Narrow transition + offline | resample() + sharp filter + filtfilt() | Simplest, built-in anti-alias, zero-phase |
| Wideband rate change (M≥8) | designMultistageDecimator/Interpolator | Automatic cascade optimization |
| Complex frequency specs | fdesign.decimator + design() | Flexible specification object |
| CIC or halfband filters | fdesign.decimator with CIC response | Specialized filter types |
IMPORTANT: When NOT to Use designMultistageDecimator/Interpolator
These functions are NOT optimal for narrow-transition filtering!
When you pass tight specs (narrow TW, high Astop), these functions try to achieve the sharp transition within the decimation/interpolation, requiring very long filters.
Real Example (Fs=44.1kHz, Fpass=2.8kHz, Fstop=3.1kHz, 60dB)
| Approach | MPIS | Result |
|---|---|---|
designMultirateFIR + sharp filter | 115.75 | BEST |
| Single-stage FIR | 407.00 | Baseline |
designMultistageDecimator + Interpolator with tight specs | 531.25 | WORSE! |
Lesson: For narrow transitions, use designMultirateFIR (relaxed anti-alias) + separate sharp filter at reduced rate.
When designMultistage* IS Optimal
For wideband rate conversion (just anti-alias, no specific filtering), designMultistageDecimator/Interpolator with default specs is very efficient:
| M | designMultirateFIR (MPIS) | designMultistage* (MPIS) | Winner |
|---|---|---|---|
| 4 | 90.2 | 60.8 | Multistage |
| 8 | 189.1 | 81.9 | Multistage (2.3×) |
| 16 | 382.6 | 128.4 | Multistage (3.0×) |
| 32 | 767.3 | 190.7 | Multistage (4.0×) |
Concept: Multirate Pipeline
Input (Fs) → Decimate (÷M) → Filter (Fs/M) → Interpolate (×M) → Output (Fs)Why it works: A 400-tap filter at 44.1 kHz becomes a ~100-tap filter at 11 kHz (after 4× decimation), and processes 1/4 as many samples.
Output rate = Input rate: Decimation and interpolation cancel out.
Workflow 1: Streaming Multirate (Narrow Transition)
Use designMultirateFIR for anti-alias + separate sharp filter.
%% Streaming multirate with narrow transition band
Fs = 44100;
Fpass = 2800; Fstop = 3100;
Rp = 0.1; Rs = 60;
M = 4; % Decimation/interpolation factor
Fs_dec = Fs / M;
%% Design filters
% Step 1: Decimator with RELAXED anti-alias (just prevent aliasing)
dec = designMultirateFIR(DecimationFactor=M, ...
StopbandAttenuation=Rs, SystemObject=true);
% Step 2: Sharp lowpass at reduced rate
d_sharp = designfilt("lowpassfir", ...
PassbandFrequency=Fpass, StopbandFrequency=Fstop, ...
PassbandRipple=Rp, StopbandAttenuation=Rs, ...
SampleRate=Fs_dec, DesignMethod="equiripple");
% Step 3: Interpolator with anti-image
interp = designMultirateFIR(InterpolationFactor=M, ...
StopbandAttenuation=Rs, SystemObject=true);
%% Process frames (streaming)
frameSize = 1024; % Must be multiple of M
y = zeros(size(x));
for i = 1:frameSize:length(x)-frameSize+1
frame = x(i:i+frameSize-1);
% Pipeline: decimate → sharp filter → interpolate
frame_dec = dec(frame);
frame_filt = filter(d_sharp, frame_dec); % Causal
frame_out = interp(frame_filt);
y(i:i+frameSize-1) = frame_out;
endNote: Streaming is causal only — no filtfilt(). There will be group delay.
Workflow 2: Offline Zero-Phase (Narrow Transition)
Use resample() for simplicity — it has built-in anti-alias/anti-image filters.
%% Offline multirate with zero-phase sharp filter
Fs = 44100;
Fpass = 2800; Fstop = 3100;
Rp = 0.1; Rs = 60;
M = 4;
Fs_dec = Fs / M;
% Load signal
[x, ~] = audioread("noisy_signal.wav");
%% Stage 1: Decimate (resample handles anti-aliasing)
x_dec = resample(x, 1, M);
%% Stage 2: Sharp lowpass at reduced rate (zero-phase)
d_sharp = designfilt("lowpassfir", ...
PassbandFrequency=Fpass, StopbandFrequency=Fstop, ...
PassbandRipple=Rp, StopbandAttenuation=Rs, ...
SampleRate=Fs_dec, DesignMethod="equiripple");
x_filt = filtfilt(d_sharp, x_dec); % Zero-phase at low rate
%% Stage 3: Interpolate back (resample handles anti-imaging)
y = resample(x_filt, M, 1);
% Output y is at original Fs, zero-phase filteredAdvantages:
Simple 3-line pipeline
resample()handles anti-alias/anti-image automaticallyfiltfilt()gives zero-phase at reduced computational cost
Workflow 3: Wideband Rate Conversion (Large M)
Use designMultistageDecimator/Interpolator with DEFAULT specs for pure rate change.
%% Wideband rate conversion (M=16, no specific filtering)
M = 16;
Fs = 48000;
% Default specs - optimized for wideband anti-alias
dec = designMultistageDecimator(M);
interp = designMultistageInterpolator(M);
% View cascade structure
info(dec)
info(interp)
% Cost comparison
cost_dec = cost(dec);
cost_interp = cost(interp);
fprintf('Decimator: %.2f MPIS\n', cost_dec.MultiplicationsPerInputSample);
fprintf('Interpolator: %.2f MPIS\n', cost_interp.MultiplicationsPerInputSample);
% Apply (streaming)
y_dec = dec(x);
y_out = interp(y_dec);When to use: Decimation factor M > 8, or when you want MATLAB to optimize the cascade automatically.
Workflow 4: Complex Specifications (fdesign)
Use fdesign.decimator when you need specific passband/stopband control.
%% fdesign.decimator with lowpass specification
M = 4;
Fs = 44100;
Fpass_norm = 2800 / Fs; % Normalized to Fs
Fstop_norm = 3100 / Fs;
Rp = 0.1; Rs = 60;
% Create specification object
d = fdesign.decimator(M, 'lowpass', 'Fp,Fst,Ap,Ast', ...
Fpass_norm, Fstop_norm, Rp, Rs);
% Available design methods
designmethods(d)
% Design with kaiserwin (handles tight specs)
hd = design(d, 'kaiserwin', SystemObject=true);
cost(hd)
% Design with multistage (deprecated - use designMultistageDecimator)
% hd_multi = design(d, 'multistage', SystemObject=true);Key points:
Frequencies are normalized to Fs (0 to 1)
Use
'kaiserwin'for tight specs where'equiripple'failsThe
'multistage'method is deprecated — usedesignMultistageDecimatorinstead
Cost Analysis: How to Compare Approaches
Using the cost() Function
%% Measure MPIS for each component
M = 4;
Rs = 60;
% Decimator
dec = designMultirateFIR(DecimationFactor=M, ...
StopbandAttenuation=Rs, SystemObject=true);
cost_dec = cost(dec);
fprintf('Decimator: %d taps, %.2f MPIS\n', ...
length(dec.Numerator), cost_dec.MultiplicationsPerInputSample);
% Sharp filter at reduced rate
d_sharp = designfilt("lowpassfir", ...
PassbandFrequency=2800, StopbandFrequency=3100, ...
StopbandAttenuation=Rs, SampleRate=44100/M, ...
DesignMethod="equiripple");
sharp_sys = dsp.FIRFilter(Numerator=d_sharp.Numerator);
cost_sharp = cost(sharp_sys);
fprintf('Sharp filter: %d taps, %.2f MPIS (at 1/%d rate = %.2f effective)\n', ...
length(d_sharp.Numerator), cost_sharp.MultiplicationsPerInputSample, ...
M, cost_sharp.MultiplicationsPerInputSample/M);
% Interpolator
interp = designMultirateFIR(InterpolationFactor=M, ...
StopbandAttenuation=Rs, SystemObject=true);
cost_interp = cost(interp);
fprintf('Interpolator: %d taps, %.2f MPIS\n', ...
length(interp.Numerator), cost_interp.MultiplicationsPerInputSample);
% Total pipeline cost
total_mpis = cost_dec.MultiplicationsPerInputSample + ...
cost_sharp.MultiplicationsPerInputSample/M + ...
cost_interp.MultiplicationsPerInputSample;
fprintf('TOTAL: %.2f MPIS\n', total_mpis);Comparing with resample() Pipeline
resample() has internal filters not exposed to cost(). Use timeit():
x = randn(44100*2, 1); % 2 seconds at 44.1 kHz
f_pipeline = @() resample(filtfilt(d_sharp, resample(x, 1, M)), M, 1);
t_pipeline = timeit(f_pipeline);
fprintf('Offline pipeline: %.2f ms\n', t_pipeline * 1000);Key Functions Reference
| Function | Use Case | Returns |
|---|---|---|
designMultirateFIR() | Single-stage decimator/interpolator | Coefficients or System object |
designMultistageDecimator() | Optimal cascaded decimator (large M, wideband) | dsp.FilterCascade |
designMultistageInterpolator() | Optimal cascaded interpolator (large M, wideband) | dsp.FilterCascade |
resample(x, P, Q) | Offline rate conversion with anti-alias | Resampled signal |
fdesign.decimator() | Flexible decimator specification | Specification object |
fdesign.interpolator() | Flexible interpolator specification | Specification object |
dsp.FIRDecimator | Streaming decimation System object | System object |
dsp.FIRInterpolator | Streaming interpolation System object | System object |
Gotchas
1. Don't Use designMultistage* with Tight Specs for Narrow Transitions
% Template
% WRONG: Trying to do sharp filtering within decimation
dec = designMultistageDecimator(M, Fs, TW, Rs); % TW = narrow
% RIGHT: Relaxed decimator + separate sharp filter
dec = designMultirateFIR(DecimationFactor=M, ...);
d_sharp = designfilt("lowpassfir", ..., SampleRate=Fs/M);2. Don't Use System Objects with filtfilt()
% Anti-pattern
% WRONG: System objects have internal state
dec_sys = designMultirateFIR(DecimationFactor=M, SystemObject=true);
y = filtfilt(dec_sys, x); % ERROR!
% RIGHT: Use resample() for offline zero-phase
x_dec = resample(x, 1, M);3. Frame Size Must Be Multiple of M
% For streaming decimation
frameSize = 1024; % OK for M=4 (1024/4 = 256)
frameSize = 1000; % ERROR for M=4 (not divisible)4. resample() Has Hidden Filter Cost
Don't claim "100 taps at 11 kHz" — resample() adds its own anti-alias/anti-image filtering. Measure total pipeline cost with timeit().
5. Fs Meaning Differs Between Functions
designMultistageDecimator(M, Fs, ...): Fs = input ratedesignMultistageInterpolator(L, Fs, ...): Fs = output rate (R2024b+)
API References
| Doc File | Content |
|---|
Visualization
All multirate filters work with Filter Analyzer for response visualization and comparison.
Visualizing Individual Multirate Filters
% Compare decimator designs in Filter Analyzer
dec4 = designMultirateFIR(DecimationFactor=4, SystemObject=true);
decMulti = designMultistageDecimator(8);
filterAnalyzer(dec4, decMulti, SampleRates=Fs, ...
FilterNames=["SingleStage", "Multistage"]);Visualizing Complete Multirate Pipelines
IMPORTANT: For comparing dec→filter→interp pipelines against single-stage filters, wrap the complete pipeline in dsp.FilterCascade:
%% Create cascade from multirate pipeline for Filter Analyzer
Fs = 44100; M = 4;
% Build pipeline components
dec_sys = designMultirateFIR(DecimationFactor=M, StopbandAttenuation=60, SystemObject=true);
d_core = designfilt("lowpassfir", ...
PassbandFrequency=2800, StopbandFrequency=3000, ...
StopbandAttenuation=60, SampleRate=Fs/M, DesignMethod="equiripple");
core_sys = dsp.FIRFilter('Numerator', d_core.Numerator); % Wrap digitalFilter!
interp_sys = designMultirateFIR(InterpolationFactor=M, StopbandAttenuation=60, SystemObject=true);
% Create cascade for visualization
multirate_cascade = dsp.FilterCascade(dec_sys, core_sys, interp_sys);
% Add to Filter Analyzer alongside other filter types
filterAnalyzer(multirate_cascade, SampleRates=Fs, FilterNames="Multirate_Pipeline");Key points:
Wrap
digitalFilterindsp.FIRFilterbefore adding to cascadedsp.FilterCascadeshows the overall response of the pipelineUse same
SampleRates=Fsas the input rate
See filter-analyzer.md → "Visualizing Multirate Pipelines" for complete comparison examples.
See Also
efficient-filtering.md— Decision guide for choosing approachmultistage-ifir.md— IFIR (constant-rate alternative)patterns.md— Code templatesfilter-analyzer.md— Multirate filter visualization
Copyright 2026 The MathWorks, Inc.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- MathWorks
- Publisher
- MathWorks (Official)
- Source
- matlab/matlab-agentic-toolkit · skills-catalog/signal-processing/matlab-design-digital-filter · commit 2a7f215
- Licence
- BSD 2-Clause License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE.md)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by MathWorks.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download matlab-design-digital-filter.zip