
Command Line Customize Your Interactive Experience
Here's an overview of the different parts of the command line window. At the top, if you're lucky, you can see funny quotes from famous people. In the center is the text box to type your formula. At the bottom, there's the contextual help for the selected item in the text box. And finally, there is the sync button which is enabled when multiple sources are selected. The sync button lets you reset the time of the selected sources. The index button gives you access to the list of available items you can use in your formula.
The next sections will show you all available functions, variables and operators you can use in your formulas.
Notes: parameters inside brackets [] are optional.

Shapes Time Based Functions
These functions are the building blocks to create your effects. They all work with the master and grid sub-master speeds in a nice way.

result: All functions return a value between 0% and 100%. This is the standard range in Lightjams.
time: The length of one cycle in seconds. For example, 0.5 means half a second. You can play with the master and grid sub-master speeds to gracefully slow down or speed-up the shape generation.
duration: For the pulse function, this is the length of the pulse in seconds. The default special value of 1 frame means that the pulse will last exactly 1 simulation frame which is about 1/80th second. The 1 frame duration is handy to make sure an event is triggered exactly one time per cycle and no more.
probability: From 0% to 100%. For the randsquare, this is the chance of a state change from active to inactive or the reverse. For randpulse, this is the chance of a pulse to happen.
Note: The cos function is mostly used with the sin function to generate circular shapes. For example, you use the sin function to compute the tilt value and the cos function to compute the pan value.
Conditional Expressions Introduce Intelligent Behaviors
Conditional expressions let you encode your very unique interactive experience logics. For example, you can react to events in an intelligent way and generate different shapes based on the current state of the experience.
if(condition, resultIfTrue, resultIfFalse)
condition: Boolean expression (true or false). True is any values other than 0. False is 0. You can use any logical operators to express complex conditions:
& and
| or
== equal
!= not equal
> greater than
< less than
>= greater or equal
<= less or equal
! not
resultIfTrue: This part is evaluated only if the condition is true (other than 0). This can be a number or another complex formula.
resultIfFalse: This part is evaluated only if the condition is false (0). This can be a number or another complex formula.
The switch function is a special case of condition of the form: if(myvalue == 1, resultIf1, if(myvalue == 2, resultIf2,...)). It tests each case for equality and returns the corresponding value.
switch(valueToMatch, case1, value1, case2, value2, ..., [defaultValue])
valueToMatch: The value to be compared for equality.
caseX: The case for which to return the corresponding valueX.
valueX: The value to be returned when the valueToMatch is equal to caseX
[defaultValue]: Optional result if no match is found. If no default value is provided, then the last result is returned.
The selectCondition function is a special case of condition of the form: if(myvalue < 10, result1, if(myvalue < 20, result2, if(myvalue > 50, result3...)). You can specify multiple conditions and the corresponding return values.
selectCondition(condition1, value1, condition2, value2, ..., [defaultValue])
conditionX: Boolean expression (true or false). Like the condition in the if function.
valueX: The value to be returned when the corresponding condition is true.
[defaultValue]: Optional result if no match is found. If no default value is provided, then the last result is returned.
Examples
music.1.avg < 30
Gives 100% when the music average is below 30%. Otherwise the result is 0%.
if(music.1.avg > 70 & midi.control(1,1) == 0, sin(2), 0)
If the music is loud enough and the midi control value is off then generate a sine wave otherwise shut up.
switch(dmxinraw(0, 1), 0,sin(1), 1,rand(), 5,sawtooth(1))
Generates a different shapes based on the dmx input. When the dmx channel is 0, generates a sinus wave. When it's 1, generates noise. When it's 5, generates a sawtooth wave.
selectCondition(dmxin(0, 1) < 10,sin(1), dmxin(0, 1) < 20,rand(), dmxin(0, 1) < 30,sawtooth(1), 0)
Generates a different shapes based on the dmx input, but this time using ranges. When the dmx channel is less then 10, generates a sinus wave. When it's less than 20, generates noise. When it's less 30, generates a sawtooth wave. Otherwise, return 0% (this is the last optional parameter).
Mix and Mash
Mix multiple simple functions together to create more complex and deep moods.
loop(totalDuration, crossFadeDuration, fct1, fct2, fct3, ...)
randloop(totalDuration, crossFadeDuration, fct1, fct2, fct3, ...)
Loop through a list of functions and do a nice crossfade when switching function. The randloop version plays the functions in "shuffle" mode instead of one after another.
totalDuration: The total duration of the loop in seconds. For example, if the total duration is 15 seconds and you have 3 functions, each function will be played 5 seconds.
crossFadeDuration: The crossfade time in seconds.
fct1, fct2, fct3... : Specify any number of functions.
sequence(totalDuration, crossFadeDuration, resetFct, fct1, fct2, fct3, ...)
resetFct: Reset the sequence when the value is > 0.
Play each function one after another. When reaching the end of the sequence, the last function is evaluated continuously.
select(indexPercent, fct1, fct2, fct3, ...)
indexPercent: Will select the corresponding function based on this percent value. For example, 0% is the first function and 100% is the last one.
Return the function (or value) corresponding to the specified percent index.
Examples
loop(9, 1, sin(1), pulse(0.2), triangle(3))
Play 3 functions, one after another, for 3 seconds each (total 9 seconds). At the end, start over playing the first function. Do a 1 second crossfade between each function.
sequence(9, 1, onbeat(midi.note(1,20)), sin(1), pulse(0.2), 0)
Play the sin and pulse functions for 3 seconds each and then fade to 0%. At any time if the midi note is pressed, the sequence resets.
select(midi.control(1,10), sin(1), rand(), 0)
Select one of the three functions with the MIDI control value. From 0% to 33%, a sinus wave will be generated. From 34% to 66%, noise will be generated and after 66%, it's a blackout.
Trigger React to Events
When something happens, may that be a user pressing a button or a value passing a threshold, the trigger function lets you react intelligently.
trigger(activationFct, duration, thresholdDown, thresholdUp, delay)
activationFct: The value being monitored to fire the trigger.
duration: Once activated, this gives the time in seconds that the trigger will stay active.
thresholdDown: To be re-activated, the activation value must goes below or equal to this threshold. You can disable this feature by specifying 100%.
thresholdUp: The activation value must goes over or equal to this thresold to fire the trigger.
delay: The minimum delay in seconds between two re-triggering. If less than the activation duration, allows firing while active and then resets the activation timer.
The trigger function returns 0% when not activated and 100% when activated.
The onBeat function is a simpler form of the trigger function. It fires when it detects a higher than average value.
onBeat(activationFct, [multiple], [offset])
activationFct: The value being monitored to fire the trigger.
[multiple]: Optionally specifies to not fire on every beats. For example, a multiple of 4 means we fire once and then skip 3 beats.
[offset]: Optionally fires on the 2nd, 3rd, 4th, etc. beats when using the multiple parameter. For example, if you want to fire on the first beat out of four, the multiple is 4 and the offset is 0.
The toggle function goes from 0% to 100% and then from 100% to 0% each time there's a beat.
toggle(activationFct)
activationFct: The value being monitored to fire the trigger.
The timeout function fires when there's no activity for a while. This is handy when you want to trigger something only when some other thing isn't active.
timeout(time, activationFct)
time: Time to wait before saying "timeout"!
activationFct: The value being monitored to fire the trigger.
The timeoutOrActive function, like the timeout function, fires when there's no activity for a while but also when some activity just happened. In the later case, the timer is resetted. This is handy when you want to be sure there's a minimum of action even without user input.
timeoutOrActive(time, activationFct)
time: Time to wait before saying "timeout"!
activationFct: The value being monitored to fire the trigger.
The onChange function pulses when the value changes. You can optionally specify the threshold.
onChange(value, [threshold])
value: The value to watch.
[threshold]: Optionnaly specify how much the value needs to change before we pulse.
Examples
trigger(midi.note(1,40), 1, 0, 50, 1.3)
Fire for 1 second when a midi note goes over 50%. There is a 0.3 second delay between activations (1.3 second delay - 1 second activation). The note must be released and goes to 0% before firing again.
onbeat(midi.note(1,40))
Pulse when a midi note is pressed.
onbeat(midi.note(1,40), 4)
Pulse when a midi note is pressed, but only fire 1 time out of 4.
toggle(midi.note(1,40))
Each time the midi note is pressed, toggle between 0% and 100%.
timeoutOrActive(4, midi.note(1,40))
Pulse when a midi note is pressed or if nothing happens after 4 seconds.
onChange(midi.note.latest(1))
Pulse each time a different midi note is pressed on channel 1.
Operators Bread and Butter
Operators can be used anywhere in your formulas.
+, - Addition and substraction.
*, / Multiplication and division.
^ Exponent. Example: 2^3 is 8.
% Modulo. Return the remaning of a division. Example: 10%3 is 1.
Examples
(video.hue + 50) % 100
This gives you the complementary color by adding 50% to the hue (which is the color at the opposite position on the color wheel) and then using the modulo operator (%) to wrap the result inside 0%-100%.
Grid & Source Variables Contextual Information
When you're using multiple sources to create an effect and the formulas are really similars, you can use the source and grid variables to parametrize your formula in order to use the same for all sources, thus reducing complexity.
Source:
x, y Absolute source horizontal (x) and vertical (y) cell positions. The origin point (0,0) is bottom, left.
px, py Percent source horizontal (x) and vertical (y) cell positions. For example, the leftmost x is 0% and the rightmost is 100%.
last Last (or previous) result of this formula.
inactive Special value usable for the power meaning no power at all (not even 0%).
Grid:
grid.lastx, grid.lasty The position of the last horizontal and vertical cell.
grid.activation The current grid activation level in percent.
grid.speed The current grid sub-master speed in percent.
grid.powerAt(x, y) Get the resulting power at the specified position. This is handy to reuse values accross sources and is an alternative to using the mem and recall functions.
Examples
x*10
When using this formula for a source range, the more at the right the source is, the higher its range will be.
distance(x, y, grid.lastx/2, grid.lasty/2)*10
The farther to the grid center a source is, the higher the result is. The *10 at the end is to boost the result to achieve a good range difference between the center and the border.
if(grid.speed<50, sin(2), rand())
If the grid sub-master speed is less than half, use a smooth sine wave and when the speed is very high, generate chaotic random values.
grid.powerat(0, 0)
Get the power of the bottom left cell.
grid.powerat(x-1, y)
Get the power of the cell at the left. This shows you can use relative position in your formula.
Memory Functions Share Values Between Sources and Grids
When you have a really complex formula used by many sources and want to be able to change it quickly without changing all sources, use memory functions! They work like your old time calculator.
Local Grid Memories (private to a grid):
mem(id, value) Put a value into the memory identified by the id.
recall(id) Get the memory value identified by the id.
Global or Shared Grid Memories (accessible by all grids):
gmem(id, value) Put a value into the global memory identified by the id.
grecall(id) Get the global memory value identified by the id.
Examples
mem(0, sin(3) + 2 * midi.note(1, 40))
Set the result of your big formula in the memory 0.
recall(0)
Get the value stored by using mem(0, ...).
gmem(0, sin(3) + 2 * midi.note(1, 40))
Set the result of your big formula in the GLOBAL memory 0. This value can be reused in any formula across your entire project.
General Purpose Functions Jack of All Trade
abs(value) Absolute value.
avg(value1, value2, value3, ...) Compute the average of a set of values. Can have any number of values.
bpmCounter(beatInput): Count the number of beats per minute in real-time. The result is in BPM, not percent.
bpmCounter.speed(beatInput): Convert the beats per minute to a percent value usable for speed parameters.
counter(from, to, incrementNow, [decrementNow], [resetFct]) Increment a counter between the from and to values only when the incrementNow value is true (other than 0). If the resetFct value is > 0, the counter resets.
noLoopCounter(from, to, incrementNow, [decrementNow], [resetFct]) Like the counter function but don't wrap around when reaching the to value.
pingCounter(from, to, incrementNow, [resetFct]) Increment a counter between the from and to values only when the incrementNow value is true (other than 0). When reaching the to value, start counting backward. If the resetFct value is > 0, the counter resets.
delay(time, value) Delay the value of the given time in seconds.
delta(value) Return the difference between the last iteration value and the current value. That's the instantaneous rate of change.
distance(x1, y1, x2, y2) The euclidean distance between two points.
latch(updateNow, value) Store a value that is updated when the updateNow parameter is positive.
latchDelta(updateNow, value, [min=0], [max=100]) Update the stored value by adding the delta value (difference between the current and first values when starting the update). The update starts when updateNow is > 0.
max(value1, value2, value3, ...) Compute the largest value of a set. Can have any number of values.
min(value1, value2, value3, ...) Compute the smallest value of a set. Can have any number of values.
record(isRecording, value) Record the values and replay in a loop the recorded values when not recording. The isRecording trigger the start of a new recording when it is true (other than 0).
restrain(value, min, max) Make sure the value is between the specified minimum and maximum values.
round(value) Round the fractional part of a number.
scale(value, toMin, toMax) Scale a percent value to fit the specified toMin and toMax range.
scale(value, min, max, toMin, toMax) Scale a value ranging from min and max to fit the specified toMin and toMax range.
smooth(time, value) Average values over the specified time. This is handy when handling jittering signals like Wiimote accelerometers.
sqrt(value) Square root.
sum(value1, value2, value3, ...) Sum all values. Can have any number of values.
tapTempo.bpm(beatInput): Return the number of beats per minute of the detected tempo.
tapTempo.pulse(beatInput): Generate pulses based on the detected tempo.
tapTempo.sawtooth(beatInput): Generate a sawtooth wave in sync with the beat.
tapTempo.speed(beatInput): Convert the beats per minute of the tempo to a percent value usable for speed parameters.
Examples
counter(0, 10, onbeat(midi.note(1, 40)))
Count from 0 to 10. Increment the counter each time the midi note is pressed.
counter(0, 10, onbeat(midi.note(1, 40)), onbeat(midi.note(1, 41)))
Count from 0 to 10. Increment the counter each time the midi note 40 is pressed and decrement each time the midi note 41 is pressed.
latch(onbeat(midi.note(1, 40)), rand())
Take a new random value each time the midi note is pressed.
tapTempo.pulse(onbeat(midi.note(1, 40)))
Generate pulses based on the tempo made by pressing a midi note.
map.triangle(taptempo.sawtooth(midi.note(1,40)))
Generate a triangle wave in sync with the detected tempo.
tapTempo.speed(onbeat(midi.note(1, 40)))
Return a value suitable to control the speed of a grid or group based on the tempo made by pressing a midi note. If you generate a tempo of 60 BPM, the speed value will be 1x. 120 BPM will be 2x...
Fades Smooth Transitions
To apply nice fades to Wii, MIDI or any other interactive inputs, the fade functions are your best friends. You can also use the grid fade in and out properties if you want to apply the same fade to all sources on the grid.
Both Ways: Fade In and Out:
fade(time, value): Fade in and out using the exponential form.
fade.linear(time, value): Fade in and out using the linear form.
fade.exp(time, value): Fade in and out using the exponential form.
fade.log(time, value): Fade in and out using the logarithmic form.
fade.sig(time, value): Fade in and out using the sigmoid form.
Fade In Only
fadein(time, value): Fade in using the exponential form.
fadein.XYZ(time, value): Fade in using the linear, exponential, logarithmic or sigmoid form.
Fade Out Only
fadeout(time, value): Fade out using the exponential form.
fadeout.XYZ(time, value): Fade out using the linear, exponential, logarithmic or sigmoid form.
Different Fade In and Fade Out Times
fadein.XYZ(time, fadeout.XYZ(time, value)):You can imbricate a fade in and fade out funtions to specify different fade times.
Examples
fade.linear(1, pulse(2,1))
Use fade in and out of 1 second for a pulse function. This gives a triangle shape.
fadein.linear(0.2, fadeout.exp(1, pulse(2,1)))
A quick linear fade in and a longer exponential fade out. It is often desirable having short fade in time and longer fade out in order to be really responsive and give quick feedback.
DMX In ArtNET and sACN Inputs
You can access the whole 16 ArtNET and sACN input universes using the following formulas:
dmxin(universe, address)
This gives you the dmx value in percent.
universe: The universe from 0 to 15.
address: The DMX address from 1 to 512.
dmxinraw(universe, address)
This gives you the raw dmx value from 0 to 255.
universe: The universe from 0 to 15.
address: The DMX address from 1 to 512.
Examples
midi.control(1, dmxinraw(0, 1))
Select the proper midi control based on the raw DMX input value at universe 0 and channel 1. You can use this formula to let another lighting controller sends DMX to Lightjams and switches the midi control.

