Warning: This is some pretty advanced stuff and requires a bit of lua knowledge.
With some clever abuse of the formula device you can generate some pretty cool musical sequences in real time:
An example: generative-acid.xrns (71.9 KB)
To start with we create an instrument and set its pitch modulation range to the maximum value of 96. Then we create a macro control for the pitch slider.
Next we create a formula device and route a rising sawtooth LFO to one its inputs.
If we do something like the following:
seq = {0, 3, 1, 6, 3, 5, 7, 8}
function playSeq()
idx = floor(A * #seq) + 1
pitch = seq[idx]
return (96 + pitch) / 192 -- this bit normalizes the pitch values from semitones to macro values
end
and have our output be
y = playSeq()
We can modulate our pitch macro control with the formula output and play back arbitrary sequences. This can get particularly interesting if we generate new sequences on the fly using some sort of generative/procedural algorithm. In the attached XRNS file I’m using this code to generate the pitch data:
SCALE = {0, 1, 5, 7, 8, 12}
pitches = {}
glides = {}
shouldReset = true
glideChance = 0.25
currentPitch = 0
currentGlide = false
numOctaves = 3
numPitchSteps = 16
numGlideSteps = 32
function generatePitch()
local idx = floor(random(1, 6))
local octave = floor(random(0, numOctaves)) * 12
return SCALE[idx] + octave
end
function generatePitches()
for i = 1, numPitchSteps do
pitches[i] = generatePitch()
end
end
function generateGlide()
return random() < glideChance
end
function generateGlides()
for i = 1, numGlideSteps do
glides[i] = generateGlide()
end
end
function resetData()
generatePitches()
generateGlides()
end
function makePitch(steps)
return (steps + 96) / 192
end
function tick()
if LINE == 0 or #pitches == 0 then
if shouldReset then
resetData()
shouldReset = false
end
else
shouldReset = true
end
local idx = floor(A * 32)
local pitchIdx = mod(idx, numPitchSteps) + 1
local glideIdx = mod(idx, numGlideSteps) + 1
currentPitch = pitches[pitchIdx]
currentGlide = glides[glideIdx]
local glideRate = 1
if currentGlide then
glideRate = 0.2
end
local pitch = makePitch(currentPitch)
return (glideRate * pitch) + ((1 - glideRate) * OUTPUT)
end
With the output being:
y = tick()
Check out the attached file to see this in action.