Audio Quality Checker for WaveCap-SDR
This skill helps analyze the audio stream from WaveCap-SDR channels to determine if they are properly tuned and producing usable audio.
When to Use This Skill
Use this skill when:
- User asks to check if an SDR channel is "well tuned" or working properly
- User wants to verify audio quality or detect issues
- User asks if they're getting "real sound" vs "just noise" vs "nothing"
- Debugging why audio playback isn't working as expected
- Validating SDR configuration changes
How It Works
The skill captures a sample of the audio stream and analyzes it to detect:
- Silence - No signal, near-zero amplitude (broken/stopped channel)
- Noise - Random signal with no structure (poor tuning, no carrier)
- Proper Audio - Structured signal with meaningful content (well-tuned FM station)
- Clipping/Distortion - Signal hitting limits (gain too high, overmodulation)
Usage Instructions
Step 1: Identify the Server and Channel
First, determine:
- Server port (default: 8087, check
backend/config/wavecapsdr.yaml or environment variables)
- Channel ID to test (e.g., "ch1", "ch2", etc.)
- Server bind address (default: 127.0.0.1)
You can find active channels by checking:
curl http://127.0.0.1:8087/api/v1/captures | jq '.[] | .channels'
Step 2: Capture Audio Sample
Use the provided analyze_audio_stream.py script to capture and analyze:
PYTHONPATH=backend backend/.venv/bin/python .claude/skills/audio-quality-checker/analyze_audio_stream.py \
--port 8087 \
--channel ch1 \
--duration 3
Parameters:
--port: Server port (default: 8087)
--channel: Channel ID to test (default: ch1)
--duration: Seconds of audio to capture (default: 3)
--host: Server host (default: 127.0.0.1)
--format: Audio format, pcm16 or f32 (default: pcm16)
Step 3: Interpret Results
The script outputs a detailed analysis including:
Signal Level Metrics:
- RMS Level (dB): Overall signal strength (-inf = silence, -20 to 0 dB = good)
- Peak Level (dB): Maximum amplitude (near 0 dB may indicate clipping)
- Crest Factor: Peak-to-RMS ratio (high = dynamic, low = compressed/noise)
Spectral Analysis:
- Spectral Flatness: How "flat" the spectrum is (high = noise-like, low = tonal)
- Spectral Centroid: "Center of mass" of the spectrum in Hz
- Zero Crossing Rate: How often signal crosses zero (higher for noise/high-freq content)
Signal Classification:
The script will classify the signal as:
- SILENCE: RMS < -60 dB
- NOISE: High spectral flatness (> 0.7) and low RMS
- CLIPPED: Peak level > -0.5 dB
- GOOD AUDIO: Structured signal with moderate levels
Step 4: Recommendations
Based on the results:
If SILENCE detected:
- Check if channel is started:
curl -X POST http://127.0.0.1:8087/api/v1/channels/{chan_id}/start
- Verify capture is running
- Check SDR device connection
If NOISE detected:
- Adjust channel frequency (offset_hz) - may not be tuned to a station
- Check antenna connection
- Try different frequencies known to have active broadcasts
- Verify modulation mode matches the signal (wbfm, nbfm, am, ssb, p25, dmr supported)
If CLIPPED detected:
- Reduce SDR gain settings
- Check for overmodulation from the broadcaster
- Adjust RF gain in device configuration
If GOOD AUDIO:
- Channel is properly tuned and working correctly
- Can fine-tune squelch_db if needed to reduce noise during silent periods
Example Workflow
# 1. Check what channels exist
curl http://127.0.0.1:8087/api/v1/captures | jq
# 2. Start a channel if needed
curl -X POST http://127.0.0.1:8087/api/v1/channels/ch1/start
# 3. Analyze the audio quality
PYTHONPATH=backend backend/.venv/bin/python .claude/skills/audio-quality-checker/analyze_audio_stream.py \
--channel ch1 --duration 3
# 4. If noise detected, try adjusting frequency
# (Update channel configuration and restart)
Technical Details
Audio Stream Format:
- Endpoint:
GET /api/v1/stream/channels/{chan_id}.pcm?format=pcm16
- Sample Rate: 48000 Hz (default, configurable)
- Channels: Mono (1 channel)
- Format: 16-bit signed little-endian PCM
- Streaming: Continuous, no headers
Analysis Metrics:
RMS Level: 20 * log10(sqrt(mean(signal^2)))
- Measures average signal power
- Typical good audio: -20 to -6 dB
Spectral Flatness: Geometric mean / Arithmetic mean of power spectrum
- Near 1.0 = white noise (flat spectrum)
- Near 0.0 = tonal (structured frequencies)
Zero Crossing Rate: Count of sign changes / total samples
- High ZCR = noisy or high-frequency content
- Low ZCR = low-frequency or tonal content
Crest Factor: Peak / RMS
- High (>4) = dynamic audio (speech, music)
- Low (<3) = compressed or noise-like
Files in This Skill
SKILL.md: This file - instructions for using the skill
analyze_audio_stream.py: Python script to capture and analyze audio
requirements.txt: Python dependencies (numpy, scipy, requests)
Notes
- The skill uses the Python environment at
backend/.venv
- Ensure the WaveCap-SDR server is running before analysis
- For best results, capture at least 2-3 seconds of audio
- The analysis is statistical and works best with steady signals
- Some transient issues may not be detected in short samples
1---2name: audio-quality-checker3description: Analyze the WaveCap-SDR audio stream to assess tuning quality, detect silence, noise, proper audio, or distortion. Use when checking if SDR channels are properly configured or debugging audio issues.4---5
6# Audio Quality Checker for WaveCap-SDR
7
8This skill helps analyze the audio stream from WaveCap-SDR channels to determine if they are properly tuned and producing usable audio.
9
10## When to Use This Skill
11
12Use this skill when:
13- User asks to check if an SDR channel is "well tuned" or working properly
14- User wants to verify audio quality or detect issues
15- User asks if they're getting "real sound" vs "just noise" vs "nothing"
16- Debugging why audio playback isn't working as expected
17- Validating SDR configuration changes
18
19## How It Works
20
21The skill captures a sample of the audio stream and analyzes it to detect:
22
231. **Silence** - No signal, near-zero amplitude (broken/stopped channel)
242. **Noise** - Random signal with no structure (poor tuning, no carrier)
253. **Proper Audio** - Structured signal with meaningful content (well-tuned FM station)
264. **Clipping/Distortion** - Signal hitting limits (gain too high, overmodulation)
27
28## Usage Instructions
29
30### Step 1: Identify the Server and Channel
31
32First, determine:
33- Server port (default: 8087, check `backend/config/wavecapsdr.yaml` or environment variables)
34- Channel ID to test (e.g., "ch1", "ch2", etc.)
35- Server bind address (default: 127.0.0.1)
36
37You can find active channels by checking:
38```bash
39curl http://127.0.0.1:8087/api/v1/captures | jq '.[] | .channels'
40```
41
42### Step 2: Capture Audio Sample
43
44Use the provided `analyze_audio_stream.py` script to capture and analyze:
45
46```bash
47PYTHONPATH=backend backend/.venv/bin/python .claude/skills/audio-quality-checker/analyze_audio_stream.py \
48 --port 8087 \
49 --channel ch1 \
50 --duration 3
51```
52
53Parameters:
54- `--port`: Server port (default: 8087)
55- `--channel`: Channel ID to test (default: ch1)
56- `--duration`: Seconds of audio to capture (default: 3)
57- `--host`: Server host (default: 127.0.0.1)
58- `--format`: Audio format, pcm16 or f32 (default: pcm16)
59
60### Step 3: Interpret Results
61
62The script outputs a detailed analysis including:
63
64**Signal Level Metrics:**
65- RMS Level (dB): Overall signal strength (-inf = silence, -20 to 0 dB = good)
66- Peak Level (dB): Maximum amplitude (near 0 dB may indicate clipping)
67- Crest Factor: Peak-to-RMS ratio (high = dynamic, low = compressed/noise)
68
69**Spectral Analysis:**
70- Spectral Flatness: How "flat" the spectrum is (high = noise-like, low = tonal)
71- Spectral Centroid: "Center of mass" of the spectrum in Hz
72- Zero Crossing Rate: How often signal crosses zero (higher for noise/high-freq content)
73
74**Signal Classification:**
75The script will classify the signal as:
76- **SILENCE**: RMS < -60 dB
77- **NOISE**: High spectral flatness (> 0.7) and low RMS
78- **CLIPPED**: Peak level > -0.5 dB
79- **GOOD AUDIO**: Structured signal with moderate levels
80
81### Step 4: Recommendations
82
83Based on the results:
84
85**If SILENCE detected:**
86- Check if channel is started: `curl -X POST http://127.0.0.1:8087/api/v1/channels/{chan_id}/start`
87- Verify capture is running
88- Check SDR device connection
89
90**If NOISE detected:**
91- Adjust channel frequency (offset_hz) - may not be tuned to a station
92- Check antenna connection
93- Try different frequencies known to have active broadcasts
94- Verify modulation mode matches the signal (wbfm, nbfm, am, ssb, p25, dmr supported)
95
96**If CLIPPED detected:**
97- Reduce SDR gain settings
98- Check for overmodulation from the broadcaster
99- Adjust RF gain in device configuration
100
101**If GOOD AUDIO:**
102- Channel is properly tuned and working correctly
103- Can fine-tune squelch_db if needed to reduce noise during silent periods
104
105## Example Workflow
106
107```bash
108# 1. Check what channels exist
109curl http://127.0.0.1:8087/api/v1/captures | jq
110
111# 2. Start a channel if needed
112curl -X POST http://127.0.0.1:8087/api/v1/channels/ch1/start
113
114# 3. Analyze the audio quality
115PYTHONPATH=backend backend/.venv/bin/python .claude/skills/audio-quality-checker/analyze_audio_stream.py \
116 --channel ch1 --duration 3
117
118# 4. If noise detected, try adjusting frequency
119# (Update channel configuration and restart)
120```
121
122## Technical Details
123
124**Audio Stream Format:**
125- Endpoint: `GET /api/v1/stream/channels/{chan_id}.pcm?format=pcm16`
126- Sample Rate: 48000 Hz (default, configurable)
127- Channels: Mono (1 channel)
128- Format: 16-bit signed little-endian PCM
129- Streaming: Continuous, no headers
130
131**Analysis Metrics:**
132
1331. **RMS Level**: `20 * log10(sqrt(mean(signal^2)))`
134 - Measures average signal power
135 - Typical good audio: -20 to -6 dB
136
1372. **Spectral Flatness**: Geometric mean / Arithmetic mean of power spectrum
138 - Near 1.0 = white noise (flat spectrum)
139 - Near 0.0 = tonal (structured frequencies)
140
1413. **Zero Crossing Rate**: Count of sign changes / total samples
142 - High ZCR = noisy or high-frequency content
143 - Low ZCR = low-frequency or tonal content
144
1454. **Crest Factor**: Peak / RMS
146 - High (>4) = dynamic audio (speech, music)
147 - Low (<3) = compressed or noise-like
148
149## Files in This Skill
150
151- `SKILL.md`: This file - instructions for using the skill
152- `analyze_audio_stream.py`: Python script to capture and analyze audio
153- `requirements.txt`: Python dependencies (numpy, scipy, requests)
154
155## Notes
156
157- The skill uses the Python environment at `backend/.venv`
158- Ensure the WaveCap-SDR server is running before analysis
159- For best results, capture at least 2-3 seconds of audio
160- The analysis is statistical and works best with steady signals
161- Some transient issues may not be detected in short samples