Back to skills
SkillHub ClubDesign ProductFull StackDesignerTesting

dsp-filter-designer

Design and test DSP filters (highpass, lowpass, bandpass, notch) for WaveCap-SDR. Use when adding filters to demodulation pipeline, debugging filter response, or tuning cutoff frequencies and rolloff characteristics.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
1
Hot score
77
Updated
March 20, 2026
Overall rating
C2.8
Composite score
2.8
Best-practice grade
A92.0

Install command

npx @skill-hub/cli install tobiaswooldridge-wavecap-sdr-dsp-filter-designer

Repository

TobiasWooldridge/WaveCap-SDR

Skill path: .claude/skills/dsp-filter-designer

Design and test DSP filters (highpass, lowpass, bandpass, notch) for WaveCap-SDR. Use when adding filters to demodulation pipeline, debugging filter response, or tuning cutoff frequencies and rolloff characteristics.

Open repository

Best for

Primary workflow: Design Product.

Technical facets: Full Stack, Designer, Testing.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: TobiasWooldridge.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install dsp-filter-designer into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/TobiasWooldridge/WaveCap-SDR before adding dsp-filter-designer to shared team environments
  • Use dsp-filter-designer for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: dsp-filter-designer
description: Design and test DSP filters (highpass, lowpass, bandpass, notch) for WaveCap-SDR. Use when adding filters to demodulation pipeline, debugging filter response, or tuning cutoff frequencies and rolloff characteristics.
---

# DSP Filter Designer for WaveCap-SDR

This skill helps design, test, and visualize digital filters for the WaveCap-SDR DSP pipeline.

## When to Use This Skill

Use this skill when:
- Designing new filters for demodulation pipelines (FM, AM, SSB)
- Testing filter parameters (cutoff frequencies, order, rolloff)
- Debugging filter response issues (not cutting enough, too much ripple)
- Visualizing frequency and phase response of existing filters
- Optimizing filter performance vs computational cost
- Adding notch filters to remove interference

## How It Works

The skill provides an interactive filter design tool that:

1. **Designs filters** using scipy.signal (Butterworth, Chebyshev, Elliptic)
2. **Visualizes response** - frequency response, phase response, impulse response
3. **Tests performance** - applies filter to test signals to verify behavior
4. **Exports code** - generates Python code ready for wavecapsdr/dsp/filters.py

## Usage Instructions

### Step 1: Identify Filter Requirements

Determine what you need:
- **Filter type**: highpass, lowpass, bandpass, notch
- **Cutoff frequency**: Where filter should start attenuating
- **Sample rate**: Audio sample rate (typically 48000 Hz)
- **Filter order**: Higher = steeper rolloff but more CPU
- **Passband ripple**: Acceptable variation in passband (dB)

### Step 2: Run the Filter Designer

Use the provided script to interactively design filters:

```bash
PYTHONPATH=backend backend/.venv/bin/python .claude/skills/dsp-filter-designer/filter_designer.py \
  --type lowpass \
  --cutoff 15000 \
  --sample-rate 48000 \
  --order 5
```

Parameters:
- `--type`: Filter type (lowpass, highpass, bandpass, notch)
- `--cutoff`: Cutoff frequency in Hz (or low,high for bandpass/notch)
- `--sample-rate`: Sample rate in Hz (default: 48000)
- `--order`: Filter order 1-10 (default: 5)
- `--filter-design`: butterworth, chebyshev1, chebyshev2, elliptic (default: butterworth)
- `--ripple`: Passband ripple in dB for Chebyshev/Elliptic (default: 0.5)
- `--output`: Save plots to file instead of displaying
- `--export-code`: Generate Python code for wavecapsdr/dsp/filters.py

### Step 3: Interpret Results

The script outputs:

**Frequency Response:**
- Shows magnitude response in dB vs frequency
- Verify cutoff is where expected (-3 dB point)
- Check stopband attenuation is sufficient
- Look for passband ripple

**Phase Response:**
- Shows phase shift vs frequency
- Linear phase = no distortion (difficult to achieve with IIR)
- Non-linear phase can cause audio artifacts

**Impulse Response:**
- Shows filter's time-domain behavior
- Long impulse response = more "ringing"
- Short impulse response = faster transient response

**Filter Coefficients:**
- Prints b (numerator) and a (denominator) coefficients
- These can be used directly with scipy.signal.lfilter()

### Step 4: Test with Real Signals

Test the filter with actual audio:

```bash
# Generate test code that applies filter to a signal
PYTHONPATH=backend backend/.venv/bin/python .claude/skills/dsp-filter-designer/filter_designer.py \
  --type lowpass \
  --cutoff 15000 \
  --sample-rate 48000 \
  --order 5 \
  --export-code
```

This generates code like:

```python
from scipy.signal import butter, lfilter

def apply_lowpass_filter(signal, sample_rate=48000):
    """Apply 15000 Hz lowpass filter (5th order Butterworth)"""
    nyquist = sample_rate / 2
    cutoff_norm = 15000 / nyquist
    b, a = butter(5, cutoff_norm, btype='low', analog=False)
    return lfilter(b, a, signal)
```

### Step 5: Integrate into WaveCap-SDR

Add the filter to `backend/wavecapsdr/dsp/filters.py`:

```python
def lowpass_filter(signal: np.ndarray, cutoff_hz: float, sample_rate: int, order: int = 5) -> np.ndarray:
    """Apply Butterworth lowpass filter"""
    from scipy.signal import butter, lfilter

    nyquist = sample_rate / 2
    cutoff_norm = cutoff_hz / nyquist
    b, a = butter(order, cutoff_norm, btype='low', analog=False)
    return lfilter(b, a, signal)
```

Then use in demodulation pipeline (e.g., `wavecapsdr/dsp/fm.py`):

```python
# After demodulation, apply de-emphasis filter
audio = lowpass_filter(audio, cutoff_hz=15000, sample_rate=audio_rate)
```

## Common Filter Use Cases

### 1. FM De-emphasis Filter
```bash
# 15 kHz lowpass for FM broadcast de-emphasis
.claude/skills/dsp-filter-designer/filter_designer.py \
  --type lowpass --cutoff 15000 --order 5
```

### 2. SSB Audio Bandpass
```bash
# 300-3000 Hz bandpass for SSB voice
.claude/skills/dsp-filter-designer/filter_designer.py \
  --type bandpass --cutoff 300,3000 --order 4
```

### 3. DC Blocking Highpass
```bash
# 20 Hz highpass to remove DC offset
.claude/skills/dsp-filter-designer/filter_designer.py \
  --type highpass --cutoff 20 --order 2
```

### 4. Notch Filter for Interference
```bash
# 60 Hz notch to remove AC hum
.claude/skills/dsp-filter-designer/filter_designer.py \
  --type notch --cutoff 60 --order 4
```

## Filter Design Trade-offs

**Filter Order:**
- Higher order = steeper rolloff, better frequency selectivity
- Higher order = more CPU, potential instability, longer transients
- Typical: 4-6 for audio, 2-3 for computational efficiency

**Filter Type:**
- **Butterworth**: Maximally flat passband, gentle rolloff (most common)
- **Chebyshev Type I**: Steeper rolloff, passband ripple
- **Chebyshev Type II**: Steeper rolloff, stopband ripple
- **Elliptic**: Steepest rolloff, both passband and stopband ripple

**Analog vs Digital:**
- All filters in WaveCap-SDR are digital (discrete-time)
- Design in normalized frequency (0 to 1, where 1 = Nyquist)
- Nyquist frequency = sample_rate / 2

## Technical Details

**Filter Implementation:**
WaveCap-SDR uses scipy.signal IIR filters (Infinite Impulse Response):

```python
from scipy.signal import butter, lfilter

# Design filter (returns coefficients)
b, a = butter(N=order, Wn=cutoff_normalized, btype='low')

# Apply filter (stateless, per-chunk processing)
filtered = lfilter(b, a, signal)
```

**Stateful Filtering:**
For streaming applications, maintain filter state between chunks:

```python
from scipy.signal import lfilter_zi

# Initialize state
zi = lfilter_zi(b, a) * signal[0]

# Apply filter with state
filtered, zi = lfilter(b, a, signal, zi=zi)
```

**Frequency Normalization:**
- Cutoff frequencies are normalized to Nyquist (sample_rate / 2)
- Example: 15 kHz cutoff at 48 kHz sample rate → 15000 / 24000 = 0.625

## Files in This Skill

- `SKILL.md`: This file - instructions for using the skill
- `filter_designer.py`: Interactive filter design and visualization tool

## Notes

- Always test filters with real audio before deployment
- Check for numerical instability (very high orders can be unstable)
- Consider FIR filters for linear phase requirements (not yet implemented)
- Profile CPU usage when adding filters to real-time pipeline
- Use `matplotlib` for visualization (interactive plots)
dsp-filter-designer | SkillHub