Analyze and optimize AGC (Automatic Gain Control) parameters for WaveCap-SDR channels...
This skill helps analyze audio dynamics and optimize AGC (Automatic Gain Control) parameters for different demodulation modes.
Use this skill when:
The skill provides tools to:
WaveCap-SDR's AGC (in backend/wavecapsdr/dsp/agc.py) maintains consistent audio output level:
class AGC:
def __init__(self, attack_time: float, release_time: float, target_level: float):
self.attack_alpha = 1.0 - np.exp(-1.0 / (attack_time * sample_rate))
self.release_alpha = 1.0 - np.exp(-1.0 / (release_time * sample_rate))
self.target_level = target_level
self.current_gain = 1.0
Key Parameters:
attack_time: How quickly AGC responds to increases in signal level (seconds)release_time: How quickly AGC responds to decreases in signal level (seconds)target_level: Desired RMS output level (0.0 to 1.0, typically 0.1-0.3)Find the channel you want to optimize:
curl http://127.0.0.1:8087/api/v1/captures | jq '.[] | .channels'
Note the channel ID (e.g., "ch1") and current AGC settings.
Run the AGC analyzer to capture audio and measure dynamics:
PYTHONPATH=backend backend/.venv/bin/python .claude/skills/agc-tuner/agc_analyzer.py \
--channel ch1 \
--duration 10 \
--port 8087
Parameters:
--channel: Channel ID to analyze (default: ch1)--duration: Seconds of audio to capture (default: 10)--port: Server port (default: 8087)--host: Server host (default: 127.0.0.1)--attack: Test attack time in seconds (default: current AGC setting)--release: Test release time in seconds (default: current AGC setting)--target: Test target level 0.0-1.0 (default: current AGC setting)--plot: Generate plots of AGC behavior--output: Save plots to fileThe script outputs:
Signal Characteristics:
AGC Behavior:
Recommendations: The script suggests optimal attack/release times based on signal type.
FM Broadcast (Music/Talk):
attack_time = 0.010 # 10ms - respond quickly to peaks
release_time = 0.500 # 500ms - slow release to avoid pumping
target_level = 0.2 # 20% RMS output
AM/SSB Voice:
attack_time = 0.005 # 5ms - fast attack for speech peaks
release_time = 0.300 # 300ms - moderate release
target_level = 0.25 # 25% RMS output (voice needs more headroom)
Digital Modes (P25, DMR):
attack_time = 0.001 # 1ms - very fast attack
release_time = 0.100 # 100ms - fast release
target_level = 0.3 # 30% RMS output (digital is pre-compressed)
NOAA Weather Radio:
attack_time = 0.020 # 20ms - moderate attack
release_time = 0.800 # 800ms - very slow release (steady signal)
target_level = 0.15 # 15% RMS output (avoid distortion)
Update AGC parameters via API:
# Update AGC settings for channel
curl -X PATCH http://127.0.0.1:8087/api/v1/channels/ch1 \
-H "Content-Type: application/json" \
-d '{
"agcAttackMs": 10,
"agcReleaseMs": 500,
"agcTargetDb": -20
}'
# Note: Channel settings can be updated while running (no restart needed)
Or update in backend/config/wavecapsdr.yaml presets/recipes.
Symptoms: Output barely audible even at full volume Diagnosis: Target level too low, or source signal very weak Solution:
target_level from 0.1 to 0.3Symptoms: Volume swells up and down, "breathing" artifacts Diagnosis: Release time too fast for signal characteristics Solution:
release_time (e.g., 0.1 → 0.5 seconds)Symptoms: Audio sounds distorted, harsh, broken up Diagnosis: Target level too high, or attack time too slow Solution:
target_level (e.g., 0.3 → 0.15)attack_time to catch peaks faster (e.g., 0.02 → 0.005)Symptoms: AGC doesn't adjust quickly enough when switching between quiet/loud Diagnosis: Attack time too slow Solution:
attack_time (e.g., 0.05 → 0.01 seconds)Test multiple AGC configurations and compare:
# Test attack times from 1ms to 50ms
for attack in 0.001 0.005 0.010 0.020 0.050; do
echo "Testing attack_time=$attack"
PYTHONPATH=backend backend/.venv/bin/python .claude/skills/agc-tuner/agc_analyzer.py \
--channel ch1 \
--duration 5 \
--attack $attack \
--release 0.5 \
--target 0.2 \
--output "agc_test_attack_${attack}.png"
done
Compare the output plots to find optimal settings.
AGC Algorithm: The AGC uses exponential smoothing to track signal envelope:
# Compute signal envelope (RMS)
envelope = sqrt(mean(signal^2))
# Compute desired gain
desired_gain = target_level / envelope
# Smooth gain changes
if desired_gain < current_gain:
# Attack: signal increased, reduce gain quickly
current_gain += attack_alpha * (desired_gain - current_gain)
else:
# Release: signal decreased, increase gain slowly
current_gain += release_alpha * (desired_gain - current_gain)
# Apply gain
output = signal * current_gain
Time Constants: Attack/release times are converted to smoothing factors (alpha):
alpha = 1.0 - exp(-1.0 / (time_constant * sample_rate))
Headroom: AGC maintains headroom to avoid clipping:
SKILL.md: This file - instructions for using the skillagc_analyzer.py: Audio dynamics analyzer and AGC simulator