Designing the Sub-Octave: Why I Divide Instead of Pitch-Shift
The goal for Qingtan's sub-octave was narrow and specific: add a solid octave-down to a bass without smearing the low end or adding latency. That constraint made the design decision much easier than it first looked.
The three options
There are broadly three ways to get an octave down:
- FFT / phase-vocoder pitch shifter — polyphonic and general, but it needs a buffer, so it adds latency and can smear transients. Overkill for a monophonic bass.
- Analog-style frequency division (the OC-2 approach) — square the input, use a flip-flop to divide the frequency by 2 (and 4), then reconstruct amplitude. Elegant, zero-delay, but the classic version is a circuit, not a formula.
- DSP zero-crossing division — detect where the waveform crosses zero, toggle a polarity/state on those crossings, and use that to synthesize the lower octave sample-by-sample.
What I chose, and why
I went with zero-crossing frequency division (option 3), which is the DSP translation of the OC-2 idea.
For bass it's the right trade:
- Zero latency. No analysis buffer means the sub sits tight under the dry note — critical for a bass that has to lock with a kick.
- Bass is (mostly) monophonic. Frequency division only works cleanly on one note at a time, and that's exactly how bass is played. The weakness of the method isn't a weakness here.
- Strong fundamental to track. Bass has a dominant low fundamental, so zero-crossing detection is stable — the thing that makes this method fragile on guitar chords is a non-issue.
How it behaves (and the stability tricks)
Raw zero-crossing tracking jitters when harmonics or noise cross zero. Three cheap guards fixed most of it:
- A pre-lowpass before detection, so the divider tracks the fundamental, not the buzz on top.
- An amplitude gate, so silence and finger noise don't trigger false crossings.
- Post-filtering + a dry/oct-1/oct-2 mix, so the synthesized octave blends in with body instead of sounding like a raw square.
The result keeps the attack of the original note while the octave-down fills in underneath — punchy, not woolly.
Next up: the same "protect the low end" instinct shows up again in how I voice the filter.