VOLTAlearn

Learn Volta / Structure

Tempo: the journey

Shape tempo changes across an arrangement.

lesson 24 of 39 · about 9 minutes

Open this lesson in the workbench →

A constant tempo is the special case, not the rule. In Volta tempo is a map — a piecewise-linear function of the beat number, written in source and compiled into the IR. Everything already scheduled in beats inherits the curve for free.

tempo = tempoMap [[0, 124bpm], [32, 124bpm], [64, 140bpm]] declares breakpoints on the beat axis. Between two points the bpm interpolates linearly; before the first and after the last it holds. A hold is just a repeated value — there is no hold keyword, and equal-beat breakpoints are rejected because they would break the beat↔seconds bijection.

accel 124bpm 140bpm 16bars and ritard 174bpm 87bpm 4bars are stdlib sugar for the one-segment case. A bar here is the fixed authoring bar of 4 beats — 16bars is always 64 beats, whatever your patterns' cycle lengths are.

Module.tempo is redefined as the map's value at beat 0, so a curved song still reports one honest starting tempo and everything downstream — pattern events, note durations, shred waits, scene quantization, the arrangement walk — follows the curve without knowing about it.

|> clock (3/4) is polytempo: that track runs at three quarters of the global tempo, so a track-beat b lands at global beat b·4/3. The ratio must be a literal rational. Three notes now spread across the space four used to fill, and the parts drift in and out of phase.

One thing does not follow the map yet: c-declared LFO, delay and grain rates still bake their hertz at the compile tempo. Write ms/s when you need a modulation rate to stay absolute through a ramp.

The starting point#

The lesson opens with this song in the editor. Every edit recompiles and plays.

-- Tempo: the journey — one number, one speed, for the whole song.
tempo = 100bpm

pad = patch {
  source = saw (freq pitch) |> unison 5 18,
  ampEnv = adsr 250ms 250ms 0.7 500ms,
  cutoff = 1600Hz,
  gain   = vel * 0.3
}

bell = patch {
  source = sine (freq pitch),
  ampEnv = adsr 2ms 400ms 0 300ms,
  gain   = vel * 0.35
}

kick  = sound !"bd ~ bd ~"
chord = play pad !"c3 eb3 g3"
bells = play bell !"c5 eb5 g5 bb5"

What to watch#

Put the scope on the kick and let the ramp run: the spacing between transients closes visibly, but no note ever jumps or clicks — the clock integrates a closed-form curve rather than stepping between tempos. Under clock (3/4) the two grids beat against each other and slowly re-align.

Goals#

The workbench checks these as you work; the solution is there when you want it.

  1. Open somewhere danceable — 118 to 178 bpm
  2. Make the tempo a curve, not a number
  3. Write the map by hand: hold, then lift
  4. Stretch: run one track on its own clock

Make it yours#

Build the classic drop entrance: hold your tempo flat for sixteen bars, drag it down four bars into a breakdown with a ritard-shaped segment, then snap back up over one beat. Listen to what a one-beat segment sounds like versus a thirty-two-beat one.

Further reading#

Tempo changes and independent clocks in the reference.