Using random numbers can be useful to create scripts that have variations in execution, this can create a more dynamic feel than a "static" composition that plays exactly the same each time.
In this simple example we will make a script that plays a drum beat and chooses drum fills at random.
First we create a drum machine sampler and connect it to the system outputs:
local sampler = Lv2.Plugin("http://www.openavproductions.com/fabla", "fabla808")
sampler.setControl("volume", 0.5)
local mainOutput = Audio.StereoOutput("main", "system:playback_1", "system:playback_2")
mainOutput.connect(sampler)
Now we are going to create several patterns from drum tabs, so we create a DrumTabReader that can be reused:
local drumtabReader = Midi.DrumTabReader()
Now a simple drum beat:
local drumBeat = drumtabReader.read(@" 40|--o---o-| 36|o---oo--| ")
and a few fills:
local fill1 = drumtabReader.read(@" 40|--o-oooo| 36|o-------| ") local fill2 = drumtabReader.read(@" 40|--------| 36|o---oooo| ") local fill3 = drumtabReader.read(@" 40|oooo----| 36|----oooo| ")
First we create our random number generator:
local random = Math.Random()
Now we create the arrangement, as usual, by looping over measures, if a measure is not a multiple of 4, we'll just play the beat:
for(local measure = 1; measure <= 16; measure++) {
if(measure % 4 != 0) { // measure is not a multiple of 4
sampler.schedule(drumBeat, measure)
}
else {
If the measure is a multiple of 4, we will make a decision whether or not to do a fill. We will use the Random.integer(2) method to randomly return a value of 0 or 1, like a coin toss: if the value is 1 we continue to play the beat, otherwise play a fill:
// measure *is* a multiple of 4
if(random.integer(2) == 1) { // keep the beat
sampler.schedule(drumBeat, measure)
}
else {
If we are going to play a fill we need to decide which fill to use, once again we make the decision with a random number. Since there are three fills however we will call Random.integer(3) which returns 1, 2, or 3, then we schedule the corresponding fill:
// play a fill
local fillChoice = random.integer(3)
if(fillChoice == 1) {
sampler.schedule(fill1, measure)
}
else if(fillChoice == 2) {
sampler.schedule(fill2, measure)
}
else {
sampler.schedule(fill3, measure)
}
}
}
}
Add a transport master object with a tempo of 120 BPM:
Transport.Master(120)
Now when we play the script, we don't know in advance when it will choose to do a fill, or which fill it will use, because these decisions are made at random.
local sampler = Lv2.Plugin("http://www.openavproductions.com/fabla", "fabla808")
sampler.setControl("volume", 0.5)
local mainOutput = Audio.StereoOutput("main", "system:playback_1", "system:playback_2")
mainOutput.connect(sampler)
local drumtabReader = Midi.DrumTabReader()
local drumBeat = drumtabReader.read(@"
40|--o---o-|
36|o---oo--|
")
local fill1 = drumtabReader.read(@"
40|--o-oooo|
36|o-------|
")
local fill2 = drumtabReader.read(@"
40|--------|
36|o---oooo|
")
local fill3 = drumtabReader.read(@"
40|oooo----|
36|----oooo|
")
local random = Math.Random()
for(local measure = 1; measure <= 16; measure++) {
if(measure % 4 != 0) { // measure is not a multiple of 4
sampler.schedule(drumBeat, measure)
}
else {
// measure *is* a multiple of 4
if(random.integer(2) == 1) { // keep the beat
sampler.schedule(drumBeat, measure)
}
else {
// play a fill
local fillChoice = random.integer(3)
if(fillChoice == 1) {
sampler.schedule(fill1, measure)
}
else if(fillChoice == 2) {
sampler.schedule(fill2, measure)
}
else {
sampler.schedule(fill3, measure)
}
}
}
}
Transport.Master(120)
This work is licensed under a
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.