Project 1: The Signal Generator (Creating Raw Reality)
Build a program that generates pure sine, square, and sawtooth waves and saves them as raw PCM data or a valid WAV file.
Project Overview
| Attribute | Value |
|---|---|
| Difficulty | Level 1: Beginner |
| Time Estimate | 1 evening |
| Main Language | C |
| Alternative Languages | C++, Rust, Python (math + binary I/O only) |
| Knowledge Area | Waveform generation and file formats |
| Tools | Hex editor, Audacity |
| Main Book | “The Scientist and Engineer’s Guide to DSP” by Steven W. Smith |
What you’ll build: A CLI tool that outputs WAV files containing clean, predictable test tones.
Why it teaches DSP: If you cannot generate signals, you cannot verify filters or transforms. This project forces you to understand sampling rate, phase, and quantization as real constraints.
Core challenges you’ll face:
- Phase increment math tied to sample rate
- Quantization into fixed-width integers
- Writing a correct WAV header
Real World Outcome
You will have a small CLI that emits test tones. When opened in Audacity or any media player, the tone is clean and stable with no clicks, and the waveform shape matches the signal type.
Example Output:
$ ./signal_gen --type sine --freq 440 --rate 44100 --duration 2.0
Generated 2.0s of 440Hz sine wave at 44.1kHz
Saved to output.wav (176,444 bytes)
Verification steps:
- Open
output.wavin Audacity - Zoom in on the waveform and confirm the expected shape
- Measure the frequency: it should read 440Hz
The Core Question You’re Answering
“How do I turn a mathematical waveform into discrete samples that a DAC can play back without distortion?”
If you cannot answer this, all later DSP work is guesswork. This project makes the signal concrete and measurable.
Concepts You Must Understand First
Stop and research these before coding:
- Sampling rate and frequency
- How many samples represent one full cycle at 44.1kHz?
- What happens if the frequency is not an integer divisor of the sample rate?
- Book Reference: “The Scientist and Engineer’s Guide to DSP” Ch. 3
- Quantization and clipping
- How do you map a -1.0 to 1.0 float into a 16-bit signed integer?
- What does clipping sound like and look like?
- Book Reference: “Understanding Digital Signal Processing” by Richard G. Lyons, Ch. 1
- WAV file structure
- Why does the header need sizes before the data exists?
- What do little-endian integers mean in practice?
- Book Reference: “The Scientist and Engineer’s Guide to DSP” Ch. 10
Questions to Guide Your Design
- Signal purity
- How will you avoid clicks at the start and end of the file?
- Will you use a short fade-in and fade-out?
- File writing
- Will you generate in memory or stream sample-by-sample?
- How will you compute and validate the header sizes?
Thinking Exercise
Discrete Samples on Paper
Before coding, write down the first 8 samples of a 1Hz sine wave at a 8Hz sample rate. Use these steps:
- Sample times: 0.0s, 0.125s, 0.25s, 0.375s, 0.5s, 0.625s, 0.75s, 0.875s
- Compute sine values at each time
- Scale into 16-bit integer range
Questions while working:
- Which samples align with 0, 1, 0, -1 values?
- How many distinct values do you get if you round to integers?
- What happens if the frequency is 3Hz instead of 1Hz?
The Interview Questions They’ll Ask
Prepare to answer these:
- “Why must the sample rate be at least twice the highest frequency?”
- “What is quantization noise and how does bit depth affect it?”
- “Why do WAV files use little-endian encoding?”
- “How do you avoid clicks at waveform boundaries?”
- “What is the difference between a square wave and a sine wave in the frequency domain?”
Hints in Layers
Hint 1: Starting Point Think of the waveform as a table of numbers; you are only responsible for calculating each number in order.
Hint 2: Next Level Compute a phase value that advances by a fixed amount each sample, and use it to read the waveform shape.
Hint 3: Technical Details Use a phase accumulator from 0 to 2*pi and wrap it. Then convert the result to the target integer range.
Hint 4: Tools/Debugging Open the output in Audacity, zoom in, and compare the waveform to the expected shape for sine or square.
Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| Sampling and quantization | “The Scientist and Engineer’s Guide to DSP” by Steven W. Smith | Ch. 3 |
| Waveform generation | “Understanding Digital Signal Processing” by Richard G. Lyons | Ch. 2 |
| WAV file structure | “The Scientist and Engineer’s Guide to DSP” by Steven W. Smith | Ch. 10 |
Implementation Hints
- Keep the generator deterministic: same inputs produce the same file.
- Use a single, consistent amplitude scale to avoid accidental clipping.
- Treat the WAV header as a fixed binary structure that must match the data length exactly.
Learning Milestones
- First milestone: You can generate a clean sine wave with the correct frequency.
- Second milestone: You can generate square and sawtooth waves and verify them visually.
- Final milestone: You can explain how sample rate and bit depth affect perceived quality.