Tune FFT size and squelch to reduce false-positive recordings
Increase fft_size from 512 (default) to 2048 for better NFM channel isolation, and add squelch_snr_threshold = 15.0 dB per channel to reject noise-triggered recordings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-03-19
|
||||
@@ -0,0 +1,46 @@
|
||||
## Context
|
||||
|
||||
RTLSDR-Airband monitors 3 CB channels (26.985, 27.035, 27.075 MHz) via a single RTL-SDR dongle on a Pi 400. Recordings split per transmission produce many false positives — short noise-triggered files, often on multiple channels simultaneously.
|
||||
|
||||
Current config: `fft_size` commented out (defaults to 512), no `squelch_snr_threshold` set (defaults to 9.54 dB). Both contribute to over-sensitivity.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Reduce false-positive recordings caused by noise, static, and weak signals
|
||||
- Achieve this through RTLSDR-Airband config tuning only — no post-processing
|
||||
|
||||
**Non-Goals:**
|
||||
- Eliminating 100% of false positives (some noise will always slip through)
|
||||
- Automated cleanup scripts or post-processing pipelines
|
||||
- Changes to gain, bandwidth, or sample rate (these are working adequately)
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. Set `fft_size = 2048`
|
||||
|
||||
**Decision**: Uncomment and increase `fft_size` from the current default of 512 to 2048.
|
||||
|
||||
**Rationale**: With 3 NFM channels spaced 10 kHz apart using 8 kHz bandwidth, a 512-point FFT produces bins too wide for clean separation. This causes energy from one channel (or wideband noise) to bleed into adjacent channels, triggering simultaneous false recordings. The simultaneous cross-channel triggers observed in the recordings confirm this.
|
||||
|
||||
2048 provides 4x the spectral resolution. Going to 4096 would be even better but may stress the Pi 400's CPU; 2048 is a safe starting point.
|
||||
|
||||
**Alternatives considered**:
|
||||
- **4096**: Best selectivity but higher CPU cost. Can try later if 2048 isn't sufficient.
|
||||
- **1024** (the previously commented-out value): Moderate improvement but may not fully resolve cross-channel bleed.
|
||||
|
||||
### 2. Add `squelch_snr_threshold = 15.0` per channel
|
||||
|
||||
**Decision**: Set an explicit SNR threshold of 15 dB on each channel.
|
||||
|
||||
**Rationale**: The default 9.54 dB is calibrated for aviation AM monitoring where signals are cleaner. CB at 27 MHz has a higher noise floor and more atmospheric interference. 15 dB is a reasonable starting point that should reject most noise while still capturing normal-strength CB transmissions.
|
||||
|
||||
**Alternatives considered**:
|
||||
- **20-25 dB**: More aggressive, but risks missing weaker legitimate transmissions. Can increase later if 15 isn't enough.
|
||||
- **`squelch_threshold` (absolute dBFS)**: Harder to tune and doesn't adapt to changing noise floor conditions. The SNR-relative approach is more robust.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **[Weak signals missed]** → Higher squelch threshold will drop marginal transmissions. Acceptable trade-off — false positives are currently more disruptive than missed weak signals.
|
||||
- **[CPU increase from larger FFT]** → 2048 uses more CPU than 512. Pi 400 quad-core should handle this comfortably, but worth monitoring after deployment.
|
||||
- **[Iterative tuning needed]** → These values are starting points. May need adjustment after observing results over a day or two.
|
||||
@@ -0,0 +1,24 @@
|
||||
## Why
|
||||
|
||||
The recorder generates many short false-positive recordings (360 bytes to ~4KB) triggered by noise, static, or weak signals. Multiple channels often fire simultaneously, suggesting wideband interference or poor channel isolation. The current config uses the default FFT size (512) and default squelch SNR threshold (9.54 dB), both of which are too permissive for noisy CB monitoring at 27 MHz.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Increase `fft_size` to improve channel selectivity and reduce adjacent-channel false triggers
|
||||
- Add `squelch_snr_threshold` per channel to raise the signal-to-noise requirement for squelch opening
|
||||
- Uncomment and update the `fft_size` setting (currently commented out at 1024, defaulting to 512)
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `false-positive-reduction`: RTLSDR-Airband configuration tuning to minimize noise-triggered recordings via FFT size and squelch SNR threshold adjustments
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
_(none)_
|
||||
|
||||
## Impact
|
||||
|
||||
- **Configuration**: Changes to `rtl_airband.conf` only — no new services or code
|
||||
- **Pi resources**: Higher `fft_size` increases CPU usage slightly; monitor after deployment
|
||||
- **Recording behavior**: Fewer but higher-confidence recordings; very weak legitimate signals may be missed
|
||||
@@ -0,0 +1,19 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: FFT size configured for NFM channel isolation
|
||||
The system SHALL use an `fft_size` of 2048 or greater to provide sufficient spectral resolution for separating NFM channels spaced 10 kHz apart.
|
||||
|
||||
#### Scenario: FFT size set in config
|
||||
- **WHEN** the RTLSDR-Airband configuration is loaded
|
||||
- **THEN** the `fft_size` is set to 2048
|
||||
|
||||
### Requirement: Squelch SNR threshold configured per channel
|
||||
Each monitored channel SHALL have a `squelch_snr_threshold` set to reduce false triggers from noise and weak signals.
|
||||
|
||||
#### Scenario: Squelch threshold applied
|
||||
- **WHEN** a signal is detected on a monitored channel
|
||||
- **THEN** the squelch only opens if the signal exceeds the configured SNR threshold (starting value: 15.0 dB)
|
||||
|
||||
#### Scenario: Noise below threshold is rejected
|
||||
- **WHEN** noise or interference is present but below the SNR threshold
|
||||
- **THEN** no recording is triggered
|
||||
@@ -0,0 +1,10 @@
|
||||
## 1. Configuration Changes
|
||||
|
||||
- [x] 1.1 Set `fft_size = 2048` in `rtl_airband.conf` (uncomment and update from 1024)
|
||||
- [x] 1.2 Add `squelch_snr_threshold = 15.0` to each of the 3 channel blocks
|
||||
|
||||
## 2. Deploy and Verify
|
||||
|
||||
- [x] 2.1 Copy updated config to Pi and restart the `sdr-recorder` container
|
||||
- [x] 2.2 Clear existing false-positive recordings so results are easy to evaluate
|
||||
- [x] 2.3 Observe recording behavior — confirm fewer/no short noise-triggered files appearing
|
||||
17
openspec/specs/false-positive-reduction/spec.md
Normal file
17
openspec/specs/false-positive-reduction/spec.md
Normal file
@@ -0,0 +1,17 @@
|
||||
### Requirement: FFT size configured for NFM channel isolation
|
||||
The system SHALL use an `fft_size` of 2048 or greater to provide sufficient spectral resolution for separating NFM channels spaced 10 kHz apart.
|
||||
|
||||
#### Scenario: FFT size set in config
|
||||
- **WHEN** the RTLSDR-Airband configuration is loaded
|
||||
- **THEN** the `fft_size` is set to 2048
|
||||
|
||||
### Requirement: Squelch SNR threshold configured per channel
|
||||
Each monitored channel SHALL have a `squelch_snr_threshold` set to reduce false triggers from noise and weak signals.
|
||||
|
||||
#### Scenario: Squelch threshold applied
|
||||
- **WHEN** a signal is detected on a monitored channel
|
||||
- **THEN** the squelch only opens if the signal exceeds the configured SNR threshold (starting value: 15.0 dB)
|
||||
|
||||
#### Scenario: Noise below threshold is rejected
|
||||
- **WHEN** noise or interference is present but below the SNR threshold
|
||||
- **THEN** no recording is triggered
|
||||
@@ -2,7 +2,7 @@
|
||||
# Channels: 3 (26.985 MHz), 7 (27.035 MHz), 10 (27.075 MHz)
|
||||
|
||||
localtime = false;
|
||||
fft_size = 1024;
|
||||
fft_size = 2048;
|
||||
|
||||
devices:
|
||||
({
|
||||
@@ -20,6 +20,7 @@ devices:
|
||||
freq = 26.985;
|
||||
bandwidth = 8000;
|
||||
modulation = "nfm";
|
||||
squelch_snr_threshold = 15.0;
|
||||
label = "CB-CH03";
|
||||
outputs: (
|
||||
{
|
||||
@@ -35,6 +36,7 @@ devices:
|
||||
freq = 27.035;
|
||||
bandwidth = 8000;
|
||||
modulation = "nfm";
|
||||
squelch_snr_threshold = 15.0;
|
||||
label = "CB-CH07";
|
||||
outputs: (
|
||||
{
|
||||
@@ -50,6 +52,7 @@ devices:
|
||||
freq = 27.075;
|
||||
bandwidth = 8000;
|
||||
modulation = "nfm";
|
||||
squelch_snr_threshold = 15.0;
|
||||
label = "CB-CH10";
|
||||
outputs: (
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user