This example show how to add and remove events from a timing loop.
Scripts can create timing loops by using a VariableClock and scheduling a reposition, here we reposition from measure 2.0 directly to measure 1.0 thereby creating a 1 bar loop:
Time.def = Time.VariableClock(120) Time.def.reposition(1.0, 2.0) // reposition to time 1.0 at time 2.0 Time.def.start()
Instantiate a plugin and connect to a system stereo output:
synth <- Lv2.Plugin("http://gareus.org/oss/lv2/avldrums#BlackPearl") synth => Audio.StereoOutput("out", true)
Events such as midi notes can be scheduled using this clock as the default:
Events scheduled within the loop will repeat on each run of the loop
Events scheduled outside of the current loop range will never occur while looping is in effect
The schedule method validates the measure and then schedules the message, storing the resulting event in a map:
eventmap <- {} function schedule(measure) { local note = Midi.Note(40, 64, 0.125) eventmap[measure] <- synth.schedule(note, measure) }
Once an event is added to a loop it will play on each repeat of the loop forever unless we remove it.
The event object returned from the schedule method can be used to later remove the event from the timeline:
function remove(measure) { local event = eventmap[measure] synth.remove(event) }
This example has no GUI, we will use OSC messages to control the application. We can receive OSC messages by creating an Osc.Input object:
Osc.Input(3033).onReceive(function(message) { switch(message.path) { case "/schedule": schedule(message.arg(0)) break; case "/remove": remove(message.arg(0)) break;
Other OSC commands can be use to start and stop the loop:
case "/start": Time.def.start() break; case "/stop": Time.def.stop() break;
Scripts that play directly from start to finish will exit by default when the last scheduled event has occurred. Scripts that loop have no such obvious exit, the reposition itself is an event so the script will not exit even if all other scheduled events are removed.
We can explicity end the script with another OSC command:
case "/exit": Script.exit(0) break; } })
The oscsend command is a useful command line tool to send OSC commands to our app:
// $ oscsend localhost 3033 /start // $ oscsend localhost 3033 /schedule f 1.0 // $ oscsend localhost 3033 /schedule f 1.25 // $ oscsend localhost 3033 /schedule f 1.5 // $ oscsend localhost 3033 /remove f 1.0 // $ oscsend localhost 3033 /stop // $ oscsend localhost 3033 /exit
Time.def = Time.VariableClock(120) Time.def.reposition(1.0, 2.0) // reposition to time 1.0 at time 2.0 Time.def.start() synth <- Lv2.Plugin("http://gareus.org/oss/lv2/avldrums#BlackPearl") synth => Audio.StereoOutput("out", true) eventmap <- {} function schedule(measure) { local note = Midi.Note(40, 64, 0.125) eventmap[measure] <- synth.schedule(note, measure) } function remove(measure) { local event = eventmap[measure] synth.remove(event) } Osc.Input(3033).onReceive(function(message) { switch(message.path) { case "/schedule": schedule(message.arg(0)) break; case "/remove": remove(message.arg(0)) break; case "/start": Time.def.start() break; case "/stop": Time.def.stop() break; case "/exit": Script.exit(0) break; } }) // $ oscsend localhost 3033 /start // $ oscsend localhost 3033 /schedule f 1.0 // $ oscsend localhost 3033 /schedule f 1.25 // $ oscsend localhost 3033 /schedule f 1.5 // $ oscsend localhost 3033 /remove f 1.0 // $ oscsend localhost 3033 /stop // $ oscsend localhost 3033 /exit