-
Notifications
You must be signed in to change notification settings - Fork 4
Tutorial: Tempo and Sound
LX offers a number of ways to create time-synced effects based upon a musical information. This can be done either via custom code, by using LX's parameter and trigger modulation systems, or by responding to incoming audio data.
Tempo can be thought of as the rate of regular divisions underlying a piece of music. A tempo is analogous to a metronome because the beats it represents will be steady even if a live musician (or live audio feed) deviates from it temporarily.
Within LX, the global tempo is represented by the Tempo object. This is accessible to pattern and effect code via lx.engine.tempo
. Its clock can be controlled internally, synced to an external Midi clock, or synced via OSC messages. The internal clock source can be set either by direct numeric value, or manually tapped and adjusted.
The Tempo clock source can be set via the global Tempo control in the top bar.
From left to right the controls are:
-
tempo.clockSource
- how clock is generated-
Int
- internal clock, generated based upon fixed BPM value -
Midi
- clock will be derived from incoming Midi data for any device withSync
activated (using the metronome icon in the MIDI INPUT section) -
Osc
- clock will be derived from incoming OSC messages-
/lx/tempo/beat
- OSC message that triggers a beat, with an optional integer argument for the human-indexed beat-count -
/lx/tempo/setBPM
- OSC message that takes a floating point argument with a BPM
-
-
-
TAP
-tempo.tap
- learns the tempo by timing the gaps between successive taps, the tempo will be updated after 4 or more taps in a row, and thebeatCount
is reset to 0 on each tap. The counter resets after 2 seconds of no taps -
120.00
-tempo.bpm
- raw data input field to specify BPM manually -
<
/>
-tempo.nudgeDown
/tempo.nudgeUp
- hold down these buttons to temporarily shift the BPM down or up in order to adjust alignment without changing the BPM itself -
tempo.enabled
- clicking turns on or off tempo trigger messages, which are fired by theBooleanParameter
tempo.trigger
on every beat, may be used as a trigger modulation source
The lx.engine.tempo
object holds:
-
tempo.bpm
andtempo.period
The frequency (in Beats Per Minute, AKA “BPM”) and a corresponding period, typically measured in milliseconds per beat.
-
tempo.basis()
The fraction (percentage) we are into the current beat as a double in [0→1]. This is called the
basis
. If we're halfway between beats,basis()
returns 0.5. Think of it like a progress bar. The resulting 0→1 ramp is a useful field to consume as the primary way to sync patterns to beats. Use it as you would a SawLFO modulator with outputs from zero to one every beat. For instance, if you want a dot to move from left to right once per beat, set its fractional position directly to this value.You can also retrieve a sawtooth ramp for longer periods, such as a four beat measure. Since four beats is called a whole note, this is retrieved with:
lx.engine.tempo.getBasis(Tempo.Division.WHOLE)
-getBasis()
may be called with anyTempo.Division
argument. -
tempo.beatCount()
Returns an integer with the number of beats that have elapsed since the metronome was last triggered. This is useful for patterns that want to perform some evolving action, based upon elapsed musical time. Note the 0-indexing of the current beat number since it was reset. In music we typically count "1-2-3-4, 1-2-3-4"; but
beatCount()
counts incrementally "0-1-2-3-4-5-6-7-etc." from0
without looping.The
beatCount()
is zeroed on external clock trigger events, as well as when you tap manually in LX Studio to set the internal tempo's BPM. This is why tapping out 5 beats is suggested (count "1-2-3-4-1" in your mind). It aligns your patterns to the beat and measure. If the rate seems off, wait at least 2 seconds and try tapping again. If it's only slightly off, you can nudge it into phase similar to how a DJ sometimes physically nudges rotating records. DJs learn that sensing a frequent need for a nudge forward is a hint that the rotation speed (tempo) is too slow. -
tempo.getCompositeBasis()
This useful quantity combines the
beatCount()
andbasis()
. For example, assuming a typical 4 beat measure, whengetCompositeBasis()
is7.5
, we are halfway through the last quarter note of the second measure. -
Methods to signal that the current frame we’re composing (in a Pattern's
run()
) is the one that is immediately following a beat or measure (so effectively, it's on-beat).-
tempo.beat()
Returns a boolean that will be true if the metronome just clicked on a new beat in this iteration of the run-loop. This is a useful way for patterns to trigger some action on the start of every beat.
-
tempo.measure()
Similar to the
beat()
method, but returns the boolean value of true only once every measure has completed, based upon the number of beats per measure stored in thetempo.beatsPerMeasure
parameter.
Alternatively, you can register tempo listeners that implement onBeat(tempo, beatInMeasure) or onMeasure(tempo).
This is useful for triggering something that animates at a speed independent of tempo. If you're new to writing animations, first try using the
basis()
, fractional values between zero and one. -
Pattern code may query any of the above methods in combination to perform custom time-based calculations.
Many of the core LX Modulators extend from the LXPeriodicModulator
which offers tempo synchronization options. Rather than passing a fixed period
, these modulators may be configured to automatically follow tempo divisions. Among others, this applies to SawLFO
, SinLFO
, TriangleLFO
, SquareLFO
, and Click
.
All LXPeriodicModulator
instances offer the following parameters:
-
tempoSync
- Whether this modulator syncs to a tempo -
tempoDivision
- Enum value of typeTempo.Division
, which specifies the musical time-value -
tempoLock
- Whether the modulator is locked in phase alignment with the absolute tempo clock, or allowed to start/stop freely -
period
- A manually specified period, only used whentempoSync
is off
An LXPeriodicModulator
behaves as follows under their various tempo-aware settings:
-
If
tempoSync
is off, loop through the modulator at once everyperiod
ms, likely out of sync with the global tempo.tempoDivision
andtempoLock
are ignored. -
If
tempoSync
is on, ignoreperiod
, (instead it comes from lx.engine.tempo) and:- If
tempoLock
is off, loop through the modulator at the global Tempo’s rate scaled by thetempoDivision
. For example, if the division isTempo.Division.WHOLE
, the modulator will loop every four beats. SincetempoLock
is off, this loop is possibly out of phase with the globallx.engine.tempo
's beat and measure. - If
tempoLock
is on, do the above in sync with the global tempo’s frequency AND phase by aligning the start of the modulator to the start of the beat. If using a longer division such asTempo.Division.WHOLE
, it will also be synchronized to the start of the measure via the Tempo'sbeatCount()
.
- If
While using tempo information is an excellent technique for visualizing musical information, raw audio reactivity is another useful technique for material which may or may not conform to any tempo grid.
Audio can be easily used as a modulation source in LX via the modulation system. Audio input can be enabled via the Audio section in the Global controls section on the left-pane.
When the Audio Input is enabled, the control shows real-time audio level metering (lx.audio.meter
), as well as individual frequency-band meters (lx.audio.meter.bands
) along with smoothing controls.
The response of the meters may be customized using the following controls:
-
audio.meter.gain
- how much gain is applied to the input signal -
audio.meter.range
- the total range of the meter in dB -
audio.meter.attack
- determines how quickly the meter responds to new signal -
audio.meter.release
- determines how quickly the meter falls off after signal goes away -
audio.meter.slope
- determines how much the response curve slopes as octaves increase. For most modern music, the meter will show an "even" amount of energy across the spectrum with a slope of something like 3-6dB per octave
To map audio as a modulation source, click the modulation mapping button in the right-pane Modulation section, then choose either the global level meter or one of the individual frequency bands. Both the global meter and the bands will be highlighted in green, indicating that they are valid mapping sources.
Custom audio patterns and effects may also access these meter levels directly in code, using the fields lx.engine.audio.meter
and lx.engine.audio.meter.bands
.
For more precise response to musical information, the Beat Detect modulation device may be used. This may be added in the global modulation section in the right-pane, or to an individual device's modulation section.
This modulation device is similar to the graphic meter, with additional controls to focus on a limited range of frequency bands. The controls from the audio section are replicated here, as well as the following additional controls:
-
Min
-beat.minFreq
- Minimum frequency the device responds to -
Max
-beat.maxFreq
- Maximum frequency the device responds to -
Threshold
-beat.threshold
- Sets the threshold level at which a beat is detected. When the average signal level in the monitored range surpasses this level, a beat event is triggered. -
Floor
-beat.floor
- Sets a floor value which the audio must drop beneath for a second beat event to fire. This value represents a fraction of the threshold value. For example, if threshold is set to0.8
and floor is set to0.5
, a beat event will fire when the signal surpasses0.8
. The device will then wait for the signal level to drop below0.4
(which isthreshold * floor
) before it will fire another event. -
Decay
-beat.decay
- When a beat event is detected, the modulator's output value jumps up to1
and will then drop back down to0
over the amount of time specified by the decay parameter.
The device has two outputs which may be used as modulation sources. The main output (meter furthest on the right) outputs the detected beat events. This may also be used as a trigger modulation source.
Alternately, the audio meter on the left displays the ongoing average level of the frequency bands being inspected.
© 2020 LX Studio — Heron Arts LLC