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://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/efficient-filtering.md
Efficient Filtering for Narrow Transitions
When transition bands are narrow (trans_pct < 2%; see quick-ref/efficient-filtering.md), single-stage FIR filters require hundreds of taps. This guide helps you choose an efficient alternative.
Table of Contents
When You Need This
Four Approaches Compared
Quantify Single-Stage FIR Cost
Multirate Design
IFIR Quick Syntax
Decision Flowchart
MPIS Cost Comparison
Why MPIS is the Right Metric
Visualizing All Approaches in Filter Analyzer
Quick Selection Guide
Cross-References
When You Need This
Calculate your transition percentage:
Compute constraining transition width Δf (Hz):
- lowpass: Δf = Fstop - Fpass
- highpass: Δf = Fpass - Fstop
- bandpass: Δf = min(Fpass1 - Fstop1, Fstop2 - Fpass2)
- bandstop: Δf = min(Fstop1 - Fpass1, Fpass2 - Fstop2)
Then:
trans_pct = 100 * (Δf / Fs)| trans_pct | Recommendation |
|---|---|
| > 5% | Single-stage filter is fine |
| 2-5% | Consider efficient alternatives |
| < 2% | Efficient approach strongly recommended (see quick-ref/efficient-filtering.md) |
Four Approaches Compared
| Approach | Sample Rate | Structure | Best When |
|---|---|---|---|
| Single-stage IIR | Constant | SOS (biquads) | Offline zero-phase OK, minimum coefficients |
| Multirate | Changes internally | Decimate→filter→interpolate | Large M possible, prefer linear phase |
| IFIR | Constant | Sparse + image suppressor | Rate change problematic, constant rate required |
| Single-stage FIR | Constant | One filter | trans_pct > 5%, or simplicity matters |
Key insight: For offline processing, IIR + filtfilt() is often the most efficient because filtfilt() cancels phase distortion, allowing minimum-order IIR designs.
Note: Because filtfilt() applies the filter forward and backward, the effective magnitude response is the squared magnitude of the original filter (amplitude specs should be checked on the combined response).
Quantify Single-Stage FIR Cost
Before you jump to multirate/IFIR, quantify how bad a single-stage FIR really is using MATLAB-native estimators.
% Convert dB specs to linear deviations
dev_p = (10^(Rp_dB/20)-1) / (10^(Rp_dB/20)+1);
dev_s = 10^(-Rs_dB/20);
% LOWPASS example (Hz). Adapt f/a for other responses:
f = [Fpass Fstop];
a = [1 0];
dev = [dev_p dev_s];
% Order estimates
[N_kaiser, Wn, beta, ftype] = kaiserord(f, a, dev, Fs);
[N_pm, fo, ao, w] = firpmord(f, a, dev, Fs);
fprintf("Estimated FIR order: Kaiser=%d, Equiripple=%d\n", N_kaiser, N_pm);Interpretation:
If the estimate is already in the hundreds of taps, a single-stage linear-phase FIR is likely expensive in streaming.
If the estimate is modest, you may not need multirate/IFIR at all — keep it simple and verify.
Multirate Design: Function Selection
For multirate approaches, select functions based on your goal:
| Goal | Recommended Approach |
|---|---|
| Pure rate conversion (wideband anti-alias) | designMultistageDecimator/Interpolator with default TW |
| Narrow-transition filtering at reduced rate | designMultirateFIR (anti-alias) + separate sharp filter |
| Offline FIR-based rate conversion (delay-compensated) | resample() |
When Multistage Excels
designMultistageDecimator/Interpolator automatically factor the overall rate-change (when the factor is composite) into stages and select a stage sequence that minimizes MPIS.
Example (from MathWorks docs): For M=48 decimation, multistage reduces MPIS from ~15.7 to ~7.3 — roughly 2× savings.
Note: Actual savings depend heavily on TW, Astop, and factorization. Use cost() to compare specific designs.
These functions are optimized for wideband anti-aliasing. Default transition width depends on the function and MATLAB release:
designMultistageDecimator: default TW = 0.2×Fs/MdesignMultistageInterpolator: default TW = 0.2×Fs (R2024b+; was 0.2×Fs/L previously)
Narrow-Transition Strategy
For narrow transition bands, the sharp filtering is more efficient at reduced sample rate:
Decimate with relaxed anti-alias (
designMultirateFIR)Sharp filter at reduced rate (
designfiltwith tight specs)Interpolate with anti-image (
designMultirateFIR)
This separates the anti-aliasing (wideband) from the sharp filtering (narrowband), allowing each to be optimized independently.
### Multirate Candidate Selection Recipe (repeatable)
For lowpass-style “keep baseband” problems, start with:
```matlab
% Max decimation factor that keeps stopband below new Nyquist (lowpass heuristic)
M_max = floor(Fs / (2*Fstop));
M_try = [2 3 4 5 6 8];
M_try = M_try(M_try <= M_max);
```
Then evaluate each `M` by **total MPIS** (multiplications per input sample):
```matlab
best = struct(M=1, mpis=Inf);
for M = M_try
Fs_dec = Fs / M;
% Anti-alias / anti-image (relaxed) at full rate
dec = designMultirateFIR(DecimationFactor=M, StopbandAttenuation=Rs_dB, SystemObject=true);
interp = designMultirateFIR(InterpolationFactor=M, StopbandAttenuation=Rs_dB, SystemObject=true);
% Sharp filter at reduced rate (digitalFilter -> wrap for cost())
d_sharp = designfilt("lowpassfir", ...
PassbandFrequency=Fpass, StopbandFrequency=Fstop, ...
PassbandRipple=Rp_dB, StopbandAttenuation=Rs_dB, ...
SampleRate=Fs_dec, DesignMethod="equiripple");
sharp = dsp.FIRFilter(Numerator=d_sharp.Numerator);
mpis_total = cost(dec).MultiplicationsPerInputSample + ...
cost(sharp).MultiplicationsPerInputSample / M + ...
cost(interp).MultiplicationsPerInputSample;
if mpis_total < best.mpis
best.M = M; best.mpis = mpis_total;
end
end
fprintf("Best multirate candidate: M=%d (%.2f MPIS)\n", best.M, best.mpis);
```
**Why this is “standard”**: it turns “multirate might help” into a repeatable cost-based selection, instead of a vibe-based guess.
**Caveat**: `M_max` above is a *lowpass heuristic*. For highpass/bandpass/bandstop, safe rate-change needs spectrum-aware reasoning.→ See multirate.md for complete workflows and cost analysis examples.
IFIR Quick Syntax
Method 1: Direct ifir() with linear deviations
% WARNING: ifir() uses LINEAR deviations and NORMALIZED frequencies (0-1)!
delta_p = 10^(Rp_dB/20) - 1; % passband deviation
delta_s = 10^(-Rs_dB/20); % stopband deviation
[h, g] = ifir(L, 'low', [Fpass Fstop]/(Fs/2), [delta_p delta_s]);
y = filter(g, 1, filter(h, 1, x)); % cascade application
% For Filter Analyzer: wrap in System objects
H = dsp.FIRFilter(Numerator=h);
G = dsp.FIRFilter(Numerator=g);
filterAnalyzer(cascade(H,G), FilterNames="IFIR_Cascade");Method 2: fdesign + ifir (Recommended for Filter Analyzer)
% Returns dsp.FilterCascade directly - works with filterAnalyzer
Hf = fdesign.lowpass(Fpass/(Fs/2), Fstop/(Fs/2));
Hd = ifir(Hf, SystemObject=true);
filterAnalyzer(Hd, FilterNames="IFIR_Lowpass");Decision Flowchart
Narrow transition band (trans_pct < 2%)?
│
├── No → Single-stage filter is fine
│ - FIR for linear phase (streaming)
│ - IIR for efficiency
│
└── Yes → Is this offline or streaming?
│
├── OFFLINE → Do you need linear phase (constant group delay)?
│ │
│ ├── No → **IIR + filtfilt()** (BEST: 23 MPIS)
│ │ Zero-phase, far fewer coefficients
│ │
│ └── Yes → Choose efficient FIR approach:
│ ├── Can you tolerate internal rate change?
│ │ ├── Yes → **Multirate** (decimate→filter→interpolate)
│ │ └── No → **IFIR** (constant rate)
│ └── Or just accept ~400 taps if simplicity matters
│
└── STREAMING → Do you need linear phase?
│
├── No → **IIR** (minimum order, sharp cutoff)
│
└── Yes → Choose efficient FIR approach:
├── Can you tolerate internal rate change?
│ ├── Yes → **Multirate** (System objects)
│ └── No → **IFIR** (constant rate)
└── Or accept latency of ~400-tap FIRMPIS Cost Comparison (Real Example)
Specifications: Fs=44.1kHz, Fpass=2.8kHz, Fstop=3.1kHz, 60dB stopband (trans_pct = 0.68%)
%% Measure MPIS with cost() function
Fs = 44100; Fpass = 2800; Fstop = 3100; Rs = 60;
% FIR Equiripple
d_fir = designfilt("lowpassfir", ...
PassbandFrequency=Fpass, StopbandFrequency=Fstop, ...
StopbandAttenuation=Rs, SampleRate=Fs, DesignMethod="equiripple");
fir_sys = dsp.FIRFilter('Numerator', d_fir.Numerator);
cost_fir = cost(fir_sys);
% IIR Elliptic
d_iir = designfilt("lowpassiir", ...
PassbandFrequency=Fpass, StopbandFrequency=Fstop, ...
StopbandAttenuation=Rs, SampleRate=Fs, DesignMethod="ellip");
iir_sys = dsp.SOSFilter('Numerator', d_iir.Numerator, 'Denominator', d_iir.Denominator);
cost_iir = cost(iir_sys);
fprintf('FIR Equiripple: %d taps, %.0f MPIS\n', length(d_fir.Numerator), cost_fir.MultiplicationsPerInputSample);
fprintf('IIR Elliptic: %d sections, %.0f MPIS\n', size(d_iir.Numerator,1), cost_iir.MultiplicationsPerInputSample);Results:
| Filter | Taps/Sections | MPIS | Relative Cost |
|---|---|---|---|
| FIR Equiripple | 407 taps | 407 | 1.00× (baseline) |
| IIR Elliptic | 5 sections | 23 | 0.06× (17× more efficient) |
| FIR Decimator (M=4) | 96 taps | 18.25 | (per input sample) |
| FIR Interpolator (L=4) | 96 taps | 72 | (per output sample) |
Why MPIS is the Right Metric
| Metric | Problem |
|---|---|
| Tap count | Ignores polyphase efficiency, IIR structure, rate changes |
timeit() | Hardware-dependent, JIT-variable, not reproducible |
MPIS via cost() | Deterministic, structure-aware, MathWorks standard |
Use the cost() function on DSP System objects to get accurate MPIS values.
Visualizing All Approaches in Filter Analyzer
All filter types can be visualized together in Filter Analyzer, including:
Single-stage FIR/IIR (
digitalFilter,dsp.FIRFilter,dsp.SOSFilter)IFIR cascades (
dsp.FilterCascadefromifir())Multirate pipelines (
dsp.FilterCascadewrapping dec→filter→interp)Individual multirate filters (
dsp.FIRDecimator,dsp.FIRInterpolator)
Complete Comparison Example (FIR vs IFIR vs Multirate Pipeline)
IMPORTANT: For multirate pipelines, wrap the complete dec→filter→interp chain in dsp.FilterCascade so it appears as a single filter for comparison.
%% Complete comparison: FIR vs IFIR vs Multirate Pipeline
Fs = 44100; M = 4;
Fpass = 2800; Fstop = 3000; Rp = 0.1; Rs = 60;
% Approach 1: Single-stage FIR (baseline)
d_fir = designfilt("lowpassfir", ...
PassbandFrequency=Fpass, StopbandFrequency=Fstop, ...
PassbandRipple=Rp, StopbandAttenuation=Rs, ...
SampleRate=Fs, DesignMethod="equiripple");
fir_sys = dsp.FIRFilter('Numerator', d_fir.Numerator);
% Approach 2: IFIR cascade
Hf = fdesign.lowpass(Fpass/(Fs/2), Fstop/(Fs/2), Rp, Rs);
ifir_sys = ifir(Hf, 'SystemObject', true);
% Approach 3: Multirate pipeline (dec → filter → interp)
dec_sys = designMultirateFIR(DecimationFactor=M, StopbandAttenuation=Rs, SystemObject=true);
d_core = designfilt("lowpassfir", ...
PassbandFrequency=Fpass, StopbandFrequency=Fstop, ...
PassbandRipple=Rp, StopbandAttenuation=Rs, ...
SampleRate=Fs/M, DesignMethod="equiripple");
core_sys = dsp.FIRFilter('Numerator', d_core.Numerator); % Wrap for cascade!
interp_sys = designMultirateFIR(InterpolationFactor=M, StopbandAttenuation=Rs, SystemObject=true);
multirate_cascade = dsp.FilterCascade(dec_sys, core_sys, interp_sys);
% Open Filter Analyzer with ALL THREE
fa = filterAnalyzer(fir_sys, ifir_sys, multirate_cascade, ...
FilterNames=["FIR_SingleStage", "IFIR_Cascade", "Multirate_Pipeline"], ...
SampleRates=Fs, Analysis="magnitude");
% Add group delay and impulse response
addDisplays(fa, Analysis="groupdelay");
addDisplays(fa, Analysis="impulse");
showFilters(fa, true);
% Compare MPIS
fprintf('MPIS: FIR=%.0f, IFIR=%.0f, Multirate=%.0f\n', ...
cost(fir_sys).MultiplicationsPerInputSample, ...
cost(ifir_sys).MultiplicationsPerInputSample, ...
cost(multirate_cascade).MultiplicationsPerInputSample);Key points:
Wrap
digitalFilterindsp.FIRFilterbefore adding todsp.FilterCascadeUse
dsp.FilterCascade(dec, filter, interp)to create a single object for comparisonFilter Analyzer shows the overall frequency response of the cascade
Use same
SampleRates=Fsfor all (multirate rates are handled internally)IFIR cascades automatically expand to show individual stages
→ See filter-analyzer.md § "Visualizing Multirate Pipelines" for more details.
Quick Selection Guide
| Your Situation | Recommended Approach | Details |
|---|---|---|
| Offline, zero-phase OK | IIR + filtfilt() | Simplest, most efficient |
| Offline, linear phase needed, rate change OK | Multirate | resample() + sharp filter |
| Offline, linear phase needed, constant rate | IFIR | ifir() function |
| Streaming, no phase requirement | IIR | dsp.SOSFilter |
| Streaming, linear phase, rate change OK | Multirate | System objects pipeline |
| Streaming, linear phase, constant rate | IFIR | ifir(..., SystemObject=true) |
Cross-References
Detailed Guides:
Multirate workflows →
multirate.mdIFIR/Multistage workflows →
multistage-ifir.md
API Documentation:
Other Knowledge:
filter-analyzer.md— Visualizing and comparing filterspatterns.md— Code templates for all approaches
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 or MathWorks.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download matlab-design-digital-filter.zip