Lab 9.4 — Read WAV IQ and Analyze Spectrum¶
Goal¶
Read a real or private WAV IQ recording through a manifest, convert the stereo WAV channels into normalized complex samples, run basic quality checks, and generate report-ready plots and metrics JSON.
Why this lab matters¶
Most "real" SDR data you will meet is not a tidy course .ci16 file but a WAV
recording written by an SDR application (HDSDR, SDR#, SDR++ and similar), with the left
channel as I and the right channel as Q. Before analysing anything you must be sure you
read such a file correctly: channel order, sample width, sample rate and centre
frequency. A mistake here (swapped I and Q mirror the spectrum) is invisible on the plots and
silently corrupts everything after it. That is why reading goes through a manifest
rather than guesses from the file name, and why the output is a set of reproducible
metrics.
Executable files¶
| Environment | File | Output |
|---|---|---|
| Python | blocks/block_09_recording_and_analysis_tools/python/lab_9_4_read_wav_iq_and_analyze.py |
spectrum plot, time preview, metrics JSON |
| YAML / JSON | dataset manifest | file path hint, sample rate, center frequency, expected signal offset |
Run from the repository root:
python blocks/block_09_recording_and_analysis_tools/python/lab_9_4_read_wav_iq_and_analyze.py \
--manifest datasets/lab1_0_rtl_sdr_observation/manifest_narrowband_220860000.yaml
For the FM-band recording:
python blocks/block_09_recording_and_analysis_tools/python/lab_9_4_read_wav_iq_and_analyze.py \
--manifest datasets/lab1_0_rtl_sdr_observation/manifest_fm_103119454.yaml
Generated artifacts:
docs/assets/lab94_<dataset_id>_spectrum.png
docs/assets/lab94_<dataset_id>_time_preview.png
docs/assets/<dataset_id>_metrics.json
Processing chain¶
flowchart LR
MANIFEST[Dataset manifest] --> RESOLVE[Resolve local WAV IQ path]
RESOLVE --> READ[Read stereo WAV IQ]
READ --> MAP[Map left/right channels to complex I/Q]
MAP --> FFT[FFT analysis]
MAP --> QC[DC/clipping checks]
FFT --> METRICS[Peak, SNR, frequency error]
QC --> METRICS
METRICS --> REPORT[Plots + metrics JSON]
Supported WAV IQ assumptions¶
- stereo WAV container;
- channel 1 =
I, channel 2 =Qby default; - little-endian PCM sample data;
8-bit,16-bit, or32-bitinteger PCM;sample_rate_hzandcenter_frequency_hzcome from the manifest.
If the recording uses a different channel order, set i_first: false in the manifest.
Metrics¶
| Metric | Meaning |
|---|---|
sample_count_read |
number of complex samples recovered from the WAV file |
measured_peak_hz |
strongest FFT peak relative to baseband |
frequency_error_hz |
measured peak minus expected offset |
snr_db |
peak level minus median noise floor estimate |
dc_offset_magnitude |
magnitude of the average complex sample |
clipping_fraction |
fraction of samples close to full-scale |
quality_pass |
quick pass/fail based on optional manifest thresholds |
What to expect¶
The repository carries two short RTL-SDR recordings (about 50 MB each, stored with Git LFS, checksums in the manifests), so the commands above run as-is. For the narrowband capture at 220.86 MHz the script prints:
Samples read: 12741632
Sample rate: 2400000 Hz
Center frequency: 220860000 Hz
Expected offset: 0.000 Hz
Measured peak: 0.000 Hz
Frequency error: 0.000 Hz
SNR estimate: 39.58 dB
DC offset magnitude: 0.004375
Clipping fraction: 0.000000e+00
Quality pass: True
How to read it:
- 12 741 632 samples at 2.4 MS/s is about 5.3 s of recording.
- A peak at exactly 0 Hz with "SNR 39.6 dB". The manifest expects the signal at the
centre of the band (
expected_signal_offset_hz: 0). One spectrum cannot tell a true narrowband carrier from the receiver's own DC spike (see Lab 6.5); the honest test is to record again with a shifted centre frequency: a real signal moves, a DC artefact stays at zero. Also remember thatsnr_dbhere is the peak over the median noise floor, not the quality of a communication link. - DC offset 0.0044 and zero clipping mean the recording is not overloaded, so it is usable for further analysis.
Transition to real captures¶
The intended path is:
private WAV IQ file + manifest.yaml -> reader -> FFT + QC -> plots + metrics -> report
This keeps the raw file outside Git while still making the analysis reproducible.
Report checklist¶
- Attach the manifest path and SHA256.
- State sample rate and center frequency.
- Confirm WAV channel count and sample width.
- Include spectrum plot.
- Include time-domain preview.
- Report peak frequency, SNR, DC offset, and clipping fraction.
- State where the raw file is stored and why it is not in Git.
Engineering conclusion template¶
The WAV IQ recording ____ contains ____ complex samples at ____ MS/s.
The measured peak is ____ kHz relative to baseband, with estimated SNR ____ dB,
DC offset magnitude ____, and clipping fraction ____.
The file is / is not suitable for further replay or demodulation because ______.