Claude Code Plugins

Community-maintained marketplace

Feedback
0
0

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.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

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:

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:

# 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:

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:

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):

# 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

# 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

# 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

# 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

# 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):

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:

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)