Metronomes

Metronomes play a fundamental role in coordinating the timing of Afterglow’s effects, and helping them relate to musical structure. They keep track of musical time relative to some starting point, in terms of beats, bars (by default four beats to a bar), and phrases (usually eight bars to a phrase). In addition to keeping track of the current beat, bar, and phrase, metronomes can also tell you the phase of that beat, bar, or phrase, which is a measurement of progress through the beat, bar, or phrase. The phase starts out at 0.0 at the very beginning of the interval, and grows towards, but never quite reaches, 1.0, because at that point you have moved on to phase 0.0 of the following interval.

Metronomes are generally combined with Oscillators to generate wave shapes which drive the parameters sent to lights, creating color shifts, brightness pulses, or movements.

Since they are so important, there is always a metronome associated with a show in Afterglow. It gets created when the show is created, and is used for the show’s timing unless you create a separate metronome and explicitly tell an effect to use it (which you might want to do if that effect is to run at a very different speed than the music). The main show metronome can be synchronized to external timing sources, such as DJ controllers and mixers, to keep the light show tightly in time with the music being played. You can access the the main show’s metronome through the :metronome keyword in the show map, for example:

(:metronome *show*)

To create a separate metronome, you call:

(afterglow.rhythm/metronome bpm)

The bpm parameter tells the metronome what tempo to use, that is, how many beats happen per minute. You can also adjust the number of beats which make up a bar (or measure), and how many bars make up a phrase:

Parameter Default Purpose

:bpb

4

How many beats make up a bar (measure)

:bpp

8

How many bars make up a phrase

The metronome starts counting from the moment it was created, and you can ask it for all the counts as a string by calling:

(afterglow.rhythm/metro-marker (:metronome *show*))
; -> "15.1.4"
This is used by the Ableton Push controller mapping to display the metronome state and support beat jumping.

For that metronome, the current count was phrase 15, bar 1, beat 4. You can determine those values as individual numbers as well, but you might end up with confusing results because time is moving on while you are calling the individual functions to ask for information, and you might be on a different beat, bar, or phrase for a later call than an earlier one. So the way to start is by asking the Metronome for a snapshot of its state at an instant in time, and then ask the snapshot for the individual pieces of information you want. Afterglow does this when it starts generating a frame of lighting effects, to make sure that all the effects share the same notion of the point at which they are being rendered, and create a consistent look:

(afterglow.rhythm/metro-snapshot (:metronome *show*))
; -> #afterglow.rhythm.MetronomeSnapshot{:start 1431727332206, :bpm 120, :bpb 4, :bpp 8,
;    :instant 1431727683636, :beat 703, :bar 176, :phrase 22,
;    :beat-phase 0.8600000000000136, :bar-phase 0.7150000000000034,
;    :phrase-phase 0.9643750000000004}

Although this captures all of the information, it is not necessarily in the format you want it, for example the beat number and bar number are counted since the start of the metronome, and you usually want them since the start of the bar or phrase. The snapshot has ways of providing this information:

(def snap (afterglow.rhythm/metro-snapshot (:metronome *show*)))
; -> #'afterglow.examples/snap

snap
; -> #afterglow.rhythm.MetronomeSnapshot{:start 1431727332206, :bpm 120, :bpb 4, :bpp 8,
;    :instant 1431727967069, :beat 1270, :bar 318, :phrase 40, :beat-phase 0.7260000000001128,
;    :bar-phase 0.4315000000000282, :phrase-phase 0.6789375000000035}

(:beat snap)
; -> 1270

(afterglow.rhythm/snapshot-beat-within-bar snap)
; -> 2

Since the notion of a “down beat” (the first beat in a bar) is important in music and thus potentially to lighting effects, there is a snapshot function for checking that, too:

(afterglow.rhythm/snapshot-down-beat? snap)
; -> false

The second beat is not the down beat.

The metronome can be restarted at a particular beat by calling metro-start with a beat number. (Calling it with no argument returns the time at which the metronome was started.) This can be useful to resynchronize the metronome to the music if it has drifted, either because there is no BPM synchronization in place, or if MIDI clock sync is being used, and it’s been a long time, since that can drift, unlike Pro DJ Link sync:

(afterglow.rhythm/metro-start (:metronome *show*) 1)
; -> 1431727642086

The new metronome start timestamp is returned.

If the beats are landing in the right place but the notion of the down beat (bar start) or phrase start is wrong, you can reset those by calling metro-bar-start or metro-phrase-start with the desired bar or phrase number (usually 1). These adjust the metronome so the larger intervals are resynchronized without changing the individual beats themselves.

The metronome’s tempo (beats per minute) can be determined or changed by calling metro-bpm. Without an argument it returns the current BPM, and an argument is used as the new BPM value. The same can be done with the beats per bar (metro-bpb) and beats per phrase (metro-bpp).

There are a number of other functions which can be called on metronomes and snapshots. The IMetronome and ISnapshot protocols in afterglow.rhythm specify and describe them.

Watching Metronomes

To help get a feeling for exactly what your metronome is doing, there is an effect that flashes one bright color on the down beat, and another less-bright color on the rest of the beats. Running this while you change the metronome BPM, sync, beats per bar, and such can help drive a more visceral understanding. To run it for the main show metronome, you can do this:

(require 'afterglow.effects.fun)
(show/add-effect! :color
  (afterglow.effects.fun/metronome-effect *show*
    (show/all-fixtures *show*)))

If you want to watch a different metronome, the invocation looks like this:

(show/set-variable :my-metro (afterglow.rhythm/metronome 50))
(require 'afterglow.effects.fun)
(show/add-effect! :color
  (afterglow.effects.fun/metronome-effect *show*
    (show/all-fixtures) :metronome :my-metro))

The lights are pulsing sedately…​

(metro-bpm (show/get-variable :my-metro) 400)

…​and now they are almost seizure-worthy!