Project 3: The Freq-to-Volts (FM Broadcast Receiver)
Build a broadcast FM receiver that demodulates frequency deviations into audio, applies de-emphasis, and outputs clean stereo-ready audio (mono output required).
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Advanced |
| Time Estimate | 2-3 weeks |
| Main Programming Language | Python (Alternatives: C, Rust) |
| Alternative Programming Languages | C++, Julia |
| Coolness Level | High |
| Business Potential | Medium (audio/demod tools) |
| Prerequisites | IQ handling, filters, complex math |
| Key Topics | FM discrimination, de-emphasis, wideband filtering |
1. Learning Objectives
By completing this project, you will:
- Implement FM demodulation using phase differentiation or conjugate product.
- Design wideband channel filters for 200 kHz FM broadcast.
- Apply de-emphasis filtering to correct transmitter pre-emphasis.
- Normalize and resample audio output with minimal distortion.
- Diagnose common FM artifacts (capture effect, clipping, multipath).
2. All Theory Needed (Per-Concept Breakdown)
2.1 FM Modulation and Discriminator Demodulation
Fundamentals
Frequency Modulation (FM) encodes information by varying the instantaneous frequency of a carrier. If the carrier is c(t)=A cos(2πf_ct), then FM is s(t)=A cos(2πf_ct + 2π k_f ∫ m(τ) dτ). The information lives in the rate of phase change. To demodulate FM, you must recover the instantaneous frequency. In digital form, you can compute the phase of each complex sample and differentiate it in time, or use the conjugate product method: s[n] * conj(s[n-1]) yields a complex phasor whose angle is proportional to phase difference. That angle is proportional to frequency deviation. This is efficient and avoids expensive atan2 operations if you use an arctangent approximation or just take the angle directly.
FM is more resistant to amplitude noise because information is in phase, not amplitude. However, FM requires a wider bandwidth. Broadcast FM uses 75 kHz deviation and 200 kHz channel spacing. This means your filter must be wide enough to preserve the full modulation. In SDR, you must band-pass filter around the station before demodulating to prevent adjacent channel interference.
The “capture effect” is an FM property where the strongest signal dominates when two signals overlap. This is helpful in reception but also means a strong nearby station can suppress a weaker one. Understanding this helps you interpret why your demod output sometimes locks onto the strongest peak even if you thought you tuned elsewhere.
Deep Dive into the Concept
FM demodulation is essentially phase differentiation. If your complex baseband is s[n] = A e^{jθ[n]}, then the instantaneous frequency is proportional to the difference θ[n]-θ[n-1]. The conjugate product method computes s[n] * conj(s[n-1]) = A^2 e^{j(θ[n]-θ[n-1])}. The angle of this product is the phase increment, which is directly proportional to the modulation. This method is stable, efficient, and widely used in SDR.
But there are pitfalls. If your signal is noisy, the phase is noisy. Noise on phase becomes noise in the demodulated audio. This is why FM noise manifests as a hiss. A proper low-pass filter after demodulation reduces high-frequency noise. You also need to scale the discriminator output. The scale factor depends on sampling rate and deviation. If the scale is wrong, your audio will be too quiet or distorted.
The alternative method is to compute atan2(Q, I) for each sample and then differentiate. This is conceptually simple but computationally heavy. The conjugate method yields the same result without explicit unwrapping. However, the angle range is [-π, π], so large frequency deviations can cause phase wrapping if your sample rate is too low. For FM broadcast at 2.4 MSPS, this is usually fine. If you lower sample rate too far, the phase increment between samples may exceed π, causing distortion. That sets a minimum sampling rate for FM demod.
Filtering is critical. You should isolate about 200 kHz around the station before demodulation. If you filter too narrowly, you lose high-frequency audio and distort stereo subcarriers. If you filter too broadly, adjacent stations bleed in. A typical approach: mix to baseband, apply a 200 kHz low-pass filter, then demod.
Finally, FM broadcast uses pre-emphasis: high-frequency audio is boosted at the transmitter to improve SNR. Receivers must apply de-emphasis, a simple single-pole low-pass with time constant 75 µs (US) or 50 µs (EU). If you skip de-emphasis, audio sounds harsh and bright. This simple filter is essential for correct audio quality.
How this fits on projects
- Implement in §5.4 (Concepts) and §5.10 (Phases).
- Similar discriminator method appears in P06 (AIS) and P08 (POCSAG).
Definitions & key terms
- FM deviation: Maximum frequency swing from the carrier.
- Discriminator: Device or algorithm that converts frequency changes to voltage.
- Conjugate product: s[n] * conj(s[n-1]), yields phase increment.
- Capture effect: Strong FM signals dominate over weaker ones.
- Pre-emphasis/De-emphasis: High-frequency boost and corresponding attenuation.
Mental model diagram (ASCII)
FM IQ -> phase change -> frequency -> audio -> de-emphasis
How it works (step-by-step, with invariants and failure modes)
- Mix to baseband and low-pass at ~200 kHz.
- Compute phase difference (conjugate method).
- Scale discriminator output to audio amplitude.
- Low-pass to 15 kHz audio band.
- Apply de-emphasis and resample.
Invariants:
- Phase increment magnitude < π per sample.
- Output audio centered at 0.
Failure modes:
- Too low sample rate -> phase wrap distortion.
- Missing de-emphasis -> harsh audio.
Minimal concrete example
x = baseband
y = x[1:] * np.conj(x[:-1])
fm = np.angle(y)
Common misconceptions
- “FM is just phase.” It is the derivative of phase, not phase itself.
- “Higher deviation always better.” It demands wider bandwidth.
- “Any sampling rate works.” Too low causes phase wrap.
Check-your-understanding questions
- Why does FM require higher bandwidth than AM?
- What does the conjugate product compute?
- Why is de-emphasis necessary?
Check-your-understanding answers
- Because information is encoded in frequency deviation, requiring wider spectrum.
- The phase difference between adjacent samples.
- To reverse transmitter pre-emphasis and restore flat audio response.
Real-world applications
- Broadcast FM receivers.
- Two-way radio systems.
- Telemetry links.
Where you’ll apply it
- This project: §3.4, §5.10.
- Also used in: P06 AIS, P08 POCSAG.
References
- Lyons, “Understanding DSP” Ch. 13
- Collins, “Software-Defined Radio for Engineers” Ch. 4
Key insights
FM demodulation is phase differentiation; the conjugate product is the efficient path.
Summary
You learned how to recover frequency deviation from complex samples and why filtering and de-emphasis are essential.
Homework/Exercises to practice the concept
- Generate synthetic FM with a 1 kHz tone and demod it.
- Lower sample rate and observe phase wrap distortion.
- Compare audio with and without de-emphasis.
Solutions to the homework/exercises
- The demodulated tone should match 1 kHz.
- Distortion appears as clipped or aliased audio.
- De-emphasis removes harshness and restores tonal balance.
2.2 Wideband Filtering and De-Emphasis Audio Processing
Fundamentals
Broadcast FM occupies a 200 kHz channel and contains multiple subcomponents: mono audio (0-15 kHz), stereo subcarrier (38 kHz), pilot tone (19 kHz), and RDS subcarrier (57 kHz). Even if you output only mono, your demodulator sees all of these components. You need a low-pass filter after demodulation to isolate the 15 kHz mono audio. Before demodulation, you need a wideband filter to isolate the station. After demodulation, de-emphasis is a simple low-pass filter with a specific time constant that attenuates high frequencies to counter pre-emphasis.
Deep Dive into the Concept
The FM channel filter should be wide enough to capture the full deviation and modulation. A cutoff around 100-120 kHz is common for a 200 kHz wide channel, but a more conservative 200 kHz low-pass ensures you keep all energy. Overly narrow filters distort the audio and especially the stereo subcarrier. In this project, you can focus on mono audio and still use a 200 kHz low-pass to keep it simple.
The audio low-pass filter is different: it must remove everything above 15 kHz to avoid aliasing when you resample to 48 kHz. A 15 kHz cutoff with a transition band to 19 kHz is typical. This will remove the stereo pilot and subcarrier, which is fine for mono audio. If you later add stereo decoding, you will keep those bands and demodulate them separately.
De-emphasis is a first-order low-pass defined by a time constant τ. In the US, τ=75 µs; in Europe, τ=50 µs. The transfer function is H(s) = 1 / (1 + sτ). In discrete time, you implement it as a simple IIR filter. The cutoff frequency is approximately 1/(2π τ), which is about 2.1 kHz for 75 µs. This means higher frequencies are attenuated progressively. If you forget de-emphasis, audio will sound too bright and noisy. If you apply the wrong time constant, it will sound muffled or unnatural.
Resampling to audio rates requires a clean band-limited signal. If you already low-pass to 15 kHz and resample to 48 kHz, you are safe because the new Nyquist is 24 kHz. If you use 44.1 kHz, the Nyquist is 22.05 kHz, still fine but with less margin. A polyphase resampler ensures a clean conversion without aliasing.
How this fits on projects
- You will implement post-demod audio filtering in §5.10.
- The same approach is used in P05 (RDS subcarrier isolation) and P07 (NOAA APT audio band extraction).
Definitions & key terms
- Pre-emphasis: Transmitter boost of high frequencies.
- De-emphasis: Receiver attenuation to restore flat response.
- Pilot tone: 19 kHz tone in FM stereo broadcasting.
- Stereo subcarrier: 38 kHz DSB-SC subcarrier for L-R audio.
- RDS: 57 kHz data subcarrier.
Mental model diagram (ASCII)
FM IQ -> LPF(200k) -> FM demod -> LPF(15k) -> De-emphasis -> Audio
How it works (step-by-step, with invariants and failure modes)
- Band-limit RF channel before demod.
- Demodulate FM.
- Low-pass to mono audio band.
- Apply de-emphasis filter.
- Resample and normalize audio.
Failure modes:
- Harsh audio if de-emphasis missing.
- Stereo pilot leakage if audio LPF too wide.
Minimal concrete example
# simple de-emphasis IIR
alpha = dt / (tau + dt)
y[n] = y[n-1] + alpha * (x[n] - y[n-1])
Common misconceptions
- “De-emphasis is optional.” It is required for correct audio balance.
- “Mono audio ignores pilot tone.” You must still filter it out.
Check-your-understanding questions
- Why do FM broadcasters use pre-emphasis?
- What happens if you keep the 19 kHz pilot in audio?
- How does τ relate to cutoff frequency?
Check-your-understanding answers
- To improve SNR for high-frequency audio components.
- It creates an audible tone or hiss after resampling.
- fc ≈ 1/(2π τ).
Real-world applications
- Broadcast FM receivers and stereo decoding.
- Audio broadcast monitoring tools.
Where you’ll apply it
- This project: §3.7, §5.10.
- Also used in: P05 RDS, P07 NOAA APT.
References
- “FM Stereo and RDS” sections in broadcast engineering texts.
- Lyons, “Understanding DSP” Ch. 13
Key insights
FM audio quality depends as much on filtering and de-emphasis as on demodulation.
Summary
You learned how to isolate the FM channel, remove stereo subcarriers, and apply de-emphasis for correct audio.
Homework/Exercises to practice the concept
- Play demodulated audio with and without de-emphasis.
- Plot the spectrum after FM demod and identify pilot and RDS peaks.
- Change audio LPF cutoff and observe changes in clarity.
Solutions to the homework/exercises
- Without de-emphasis, audio is harsh; with it, audio is balanced.
- You should see peaks at 19 kHz and 57 kHz.
- Lower cutoff muffles audio; higher cutoff increases hiss.
3. Project Specification
3.1 What You Will Build
An FM receiver that tunes a station, demodulates frequency deviation into audio, applies de-emphasis, and outputs mono audio to a WAV file or speaker.
3.2 Functional Requirements
- Tune to a center frequency and mix to baseband.
- Apply wideband channel filter (~200 kHz).
- FM demodulate using conjugate product.
- Low-pass to 15 kHz audio band.
- Apply de-emphasis (75 µs default).
- Resample to 48 kHz and output WAV or audio stream.
3.3 Non-Functional Requirements
- Performance: Real-time on 2.4 MSPS IQ.
- Reliability: Deterministic output for recorded IQ.
- Usability: Clear CLI flags for bandwidth and de-emphasis.
3.4 Example Usage / Output
$ python fm_rx.py --freq 101.1e6 --fs 2.4e6 --audio-rate 48000
[INFO] FM demod: conjugate product
[INFO] De-emphasis: 75 us
[INFO] Audio rate: 48 kHz
3.5 Data Formats / Schemas / Protocols
- IQ input: u8 or s16 interleaved.
- Audio output: WAV 16-bit PCM, mono.
3.6 Edge Cases
- Incorrect PPM causes station offset and noise.
- Strong adjacent channel bleeding.
- Overly narrow channel filter causes muffled audio.
3.7 Real World Outcome
Clear FM audio with proper tonal balance and minimal distortion.
3.7.1 How to Run (Copy/Paste)
python fm_rx.py --input fm_101_1.iq --fs 2.4e6 --freq 101.1e6 --audio-rate 48000 \
--deemph 75us --lpf 200000 --output fm.wav
3.7.2 Golden Path Demo (Deterministic)
Use a synthetic FM tone at 1 kHz with 75 kHz deviation. Output should be a clean 1 kHz audio tone.
3.7.3 CLI Transcript (Exact)
$ python fm_rx.py --input test_fm_1k.iq --fs 2400000 --freq 0 --audio-rate 48000
[INFO] Channel LPF: 200 kHz
[INFO] Demod: conjugate product
[OK] Wrote test_fm_1k.wav
3.7.4 Failure Demo
$ python fm_rx.py --input fm.iq --fs 2400000 --freq 101.1e6 --lpf 50000
[ERROR] Channel LPF too narrow for broadcast FM
[EXIT] code=2
4. Solution Architecture
4.1 High-Level Design
IQ -> Tune -> LPF(200k) -> FM Demod -> LPF(15k) -> De-emph -> Resample -> Audio
4.2 Key Components
| Component | Responsibility | Key Decisions | |———–|—————-|—————| | Tuner | Complex mixing | NCO precision | | Channel Filter | Remove adjacent channels | FIR length | | Demodulator | Phase difference | Conjugate method | | Audio Chain | LPF + de-emphasis | Time constant |
4.3 Data Structures (No Full Code)
class FmState:
prev_sample: complex
deemph_state: float
4.4 Algorithm Overview
Key Algorithm: FM Discriminator
- Compute y[n] = x[n] * conj(x[n-1]).
- Extract angle of y[n].
- Scale to audio amplitude.
Complexity Analysis:
- Time: O(N)
- Space: O(1)
5. Implementation Guide
5.1 Development Environment Setup
python -m venv .venv
source .venv/bin/activate
pip install numpy scipy sounddevice
5.2 Project Structure
fm-receiver/
├── src/
│ ├── main.py
│ ├── tuner.py
│ ├── demod_fm.py
│ ├── filters.py
│ └── audio_out.py
└── tests/
5.3 The Core Question You’re Answering
“How do you translate phase rotation speed into audio voltage?”
5.4 Concepts You Must Understand First
- FM discriminator math (§2.1)
- Channel filtering and de-emphasis (§2.2)
5.5 Questions to Guide Your Design
- What channel bandwidth preserves audio fidelity?
- How do you scale discriminator output to avoid clipping?
- How will you validate de-emphasis effect?
5.6 Thinking Exercise
Draw a phasor rotating at varying speeds. How does its angular velocity map to audio amplitude?
5.7 The Interview Questions They’ll Ask
- What is the capture effect?
- Why does FM require wider bandwidth than AM?
- Why use de-emphasis?
5.8 Hints in Layers
- Use conjugate product to avoid atan2 per sample.
- Low-pass after demod to 15 kHz.
- Apply de-emphasis before resampling.
5.9 Books That Will Help
| Topic | Book | Chapter | |——-|——|———| | FM demod | Lyons | Ch. 13 | | Filters | Smith | Ch. 14 |
5.10 Implementation Phases
Phase 1: Foundation (3-4 days)
Goals: Demodulate synthetic FM. Tasks: Implement conjugate product and scaling. Checkpoint: 1 kHz tone demods correctly.
Phase 2: Core Functionality (5-7 days)
Goals: Real broadcast audio. Tasks: Channel filtering, de-emphasis, resampling. Checkpoint: Clean mono audio from real station.
Phase 3: Polish & Edge Cases (3-4 days)
Goals: Stability. Tasks: Handle PPM error, add CLI options. Checkpoint: Works across multiple stations.
5.11 Key Implementation Decisions
| Decision | Options | Recommendation | Rationale | |———-|———|—————-|———–| | Demod method | atan2 vs conjugate | Conjugate | Faster | | Channel LPF | 150k-250k | 200k | Standard FM channel | | De-emphasis | 50us vs 75us | 75us (US) | Region default |
6. Testing Strategy
6.1 Test Categories
| Category | Purpose | Examples | |———|———|———-| | Unit | Demod correctness | Phase increment test | | Integration | Full pipeline | Synthetic FM test file | | Edge | Offset and noise | PPM error handling |
6.2 Critical Test Cases
- 1 kHz FM tone at 75 kHz deviation.
- Strong adjacent station to test filtering.
- Low sample rate causing wrap (should warn).
6.3 Test Data
fs=2.4e6, deviation=75kHz, tone=1kHz
7. Common Pitfalls & Debugging
7.1 Frequent Mistakes
| Pitfall | Symptom | Solution | |———|———|———-| | No de-emphasis | Harsh audio | Apply 75us filter | | Too narrow channel | Muffled or distorted | Increase LPF width | | Wrong scaling | Clipping | Normalize and limit |
7.2 Debugging Strategies
- Plot phase difference histogram.
- Compare with rtl_fm output.
7.3 Performance Traps
- Using large FFT filters for streaming without overlap.
8. Extensions & Challenges
8.1 Beginner Extensions
- Add RSSI meter.
8.2 Intermediate Extensions
- Add stereo decoding (pilot + L-R subcarrier).
8.3 Advanced Extensions
- Add RDS decoding pipeline integration.
9. Real-World Connections
9.1 Industry Applications
- FM broadcast receivers and monitoring.
- Two-way radio audio demodulators.
9.2 Related Open Source Projects
- rtl_fm: command-line FM demod.
- GNU Radio: WBFM receiver blocks.
9.3 Interview Relevance
- Demonstrates DSP fundamentals and filter design trade-offs.
10. Resources
10.1 Essential Reading
- Lyons, “Understanding DSP” Ch. 13
- Collins, “SDR for Engineers” Ch. 4
10.2 Video Resources
- SDR FM demod tutorials (RTL-SDR blog)
10.3 Tools & Documentation
- scipy.signal: filters, resample_poly
10.4 Related Projects in This Series
11. Self-Assessment Checklist
11.1 Understanding
- I can explain the conjugate product method.
- I understand pre-emphasis/de-emphasis.
11.2 Implementation
- Audio is clear and properly balanced.
- No clipping or phase wrap artifacts.
11.3 Growth
- I can tune filters to improve audio quality.
12. Submission / Completion Criteria
Minimum Viable Completion:
- Demodulate FM to WAV file.
- Apply de-emphasis.
Full Completion:
- Real-time decode with stable audio and adjustable parameters.
Excellence (Going Above & Beyond):
- Stereo decoding and RDS integration.