TETERI
How TETERI is built
The Soundtrack Is a Sequencer, Not a File
A four-bar progression with drums, bass, arpeggio and a lead, whose tempo and arrangement climb with your level.
The music is generated by a step sequencer running in the browser. There is no audio file and no loop point, because there is no recording.
The structure
Four bars, sixteen steps each, cycling through a chord progression in A minor: A minor, F, C, G. Each step, the sequencer decides what to play on four parts.
Drums. A synthesised kick on four steps of each bar, a snare on two, and hi-hats every other step, all built from oscillators and filtered noise.
Bass. A filtered sawtooth on the root of the current chord, on six steps per bar, jumping an octave on two of them.
Arpeggio. A square wave walking up and down the chord tones, one note per step.
Lead. A detuned sawtooth melody, written out as a short list of step, note and length per bar, fed through a delay.
Scheduling
Web Audio has a precise clock, and JavaScript timers do not. So the sequencer uses a lookahead: a timer fires every 25 milliseconds, and schedules any notes falling within the next 120 milliseconds at exact audio-clock times.
The timer can be late without the music being late, because the notes were already booked.
Scaling with the level
Three things change as you climb:
Tempo rises from 124 to about 186 beats per minute.
Filter brightness opens up, so the whole mix gets more aggressive.
The lead comes in once you are a few levels up, so the arrangement thickens rather than merely speeding up.
Ducking
Every line clear briefly lowers the music bus, so the clear sound cuts through. It ramps back over about half a second. This is a standard mixing trick and it is the difference between a soundtrack and a mess.
The bug worth mentioning
Resuming an audio context is asynchronous, so for a few milliseconds after a run starts the clock is frozen while the sequencer is still queueing notes. Those notes then all fire at once on resume. The fix is to idle the scheduler until the context is genuinely running.
Read next
- One Layout Engine, Four ShapesSolo widescreen, solo portrait, split screen and a focus view, all produced by the same function.
- Telling a Flick From a DragTwo gestures that differ only in speed, and why measuring velocity at release is the only reliable answer.
- Making It Work Offline ProperlyCache the shell, revalidate in the background, and never serve a mix of old and new modules.
- Keeping Inside a Sixteen-Millisecond BudgetSixty frames a second means 16.7ms for everything. Here is where it goes and how it was measured.
- Plan in Sequences, Not PlacementsA piece that is awkward alone is often fine as the middle of a three-piece plan.
- Combo Pressure: Why Small Attacks Can Beat Big OnesContinuous garbage denies your opponent the quiet piece they need to survive.