Dealing with Loops

This example show how to add and remove events from a timing loop.

Creating Loops

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()


Audio Setup

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)


Scheduling Events

Events such as midi notes can be scheduled using this clock as the default:

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)
}


Removing Events

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)
}



App Control

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;

Transport Control

Other OSC commands can be use to start and stop the loop:


	case "/start":
		Time.def.start()
		break;

	case "/stop":
		Time.def.stop()
		break;



Ending the Script

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;
	}
})

Testing

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



Complete Script

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


List of All ExamplesDemo Applications


Creative Commons License This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.