User Script Examples - Virtual instruments - Steinberg Forums
It looks like it’s not possible to post in the original thread anymore. Also some attachments didn’t make it to new forum. As I had some users asking for those I decided to post them here.
Here are some midi module presets from the linked topic. Also some new additions. Mostly inspired and adapted from Falcon scripts.
MIDI Modules.zip (36.8 KB)
Some of the new lua script modules:
Chorder
for i=1,6 do
defineParameter("Shift"..i, nil, 0, -36, 36, 1)
end
for i=1,6 do
defineParameter("Velocity"..i, nil, 1, 0.01, 2)
end
local ids = {}
defineParameter("Mono", nil, false)
function onNote(e)
local done = {} -- store already played notes in order to avoid redundancy
if Mono then
-- release previous chord
while ids[1] do
local id = table.remove(ids)
releaseVoice(id)
end
end
for i = 1, 6 do
local shift = _G["Shift"..i]
local velocity = _G["Velocity"..i]
if not done[shift] then
local id = playNote(e.note + shift, math.min(127, e.velocity * velocity))
done[shift] = true
if Mono then
table.insert(ids, id)
end
end
end
end
function onRelease()
-- eat event
end
Polyphonic Sequencer
local resolutions = {16., 8., 4., 2., 1.5, 4./3., 1., 0.75, 2./3., 0.5, 0.375, 1./3., 0.25, 0.1875, 0.5/3., 0.125}
local resolutionNames = {"4", "2", "1", "1/2", "1/4d", "1/2t", "1/4", "1/8d", "1/4t", "1/8", "1/16d", "1/8t", "1/16", "1/32d", "1/16t", "1/32"}
defineParameter("timeGlobal", nil, 13, resolutionNames)
defineParameter("repeats", nil, 16, 1, 32, 1)
defineParameter("lengthGlobal", nil, 100, 0, 150)
defineParameter("oneShot", nil, false)
defineParameter("randomStart", nil, false)
-------------------------------------------- Scales --------------------------------------------
local KEY = {"C", "Db", "D", "Eb", "E", "F", "F#", "G", "Ab", "A", "Bb", "B"}
defineParameter("rootKey", nil, 1, KEY)
scales = {
{"--", {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}},
{"Major (Ionian)", {0, 0, 2, 2, 4, 5, 5, 7, 7, 9, 9, 11}},
{"Minor (Aeolian)", {0, 0, 2, 3, 3, 5, 5, 7, 8, 8, 10, 10}},
{"Harmonic Minor", {0, 0, 2, 3, 3, 5, 5, 7, 8, 8, 11, 11}},
{"Melodic Minor", {0, 0, 2, 3, 3, 5, 5, 7, 7, 9, 9, 11}},
{"Major Pentatonic", {0, 0, 2, 2, 4, 4, 7, 7, 7, 9, 9, 12}},
{"Minor Pentatonic", {0, 0, 3, 3, 3, 5, 5, 7, 7, 10, 10, 10}},
{"Dorian (D)", {0, 0, 2, 3, 3, 5, 5, 7, 7, 9, 10, 10}},
{"Phrygian (E)", {0, 1, 1, 3, 3, 5, 5, 7, 8, 8, 10, 10}},
{"Lydian (F)", {0, 0, 2, 2, 4, 4, 6, 7, 7, 9, 9, 11}},
{"Mixolydian (G)", {0, 0, 2, 2, 4, 5, 5, 7, 7, 9, 10, 10}},
{"Locrian (B)", {0, 1, 1, 3, 3, 5, 6, 6, 8, 8, 10, 10}},
{"Whole Tone", {0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10}},
{"1/2 Tone 1 Tone", {0, 1, 1, 3, 4, 4, 6, 7, 7, 9, 10, 10}},
{"1 Tone 1/2 Tone", {0, 0, 2, 3, 3, 5, 6, 6, 8, 9, 9, 11}},
{"Altered", {0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10}},
{"Hungarian", {0, 0, 2, 3, 3, 6, 6, 7, 8, 8, 10, 10}},
{"Phrygish", {0, 1, 1, 4, 4, 5, 5, 7, 8, 8, 10, 10}},
{"Arabic", {0, 1, 1, 4, 4, 5, 5, 7, 8, 8, 11, 11}},
{"Persian", {0, 1, 1, 4, 4, 5, 5, 7, 7, 10, 10, 11}},
{"Acoustic (Lydian b7)", {0, 0, 2, 2, 4, 4, 6, 7, 7, 9, 10, 10}},
{"Harmonic Major", {0, 0, 2, 2, 4, 5, 5, 7, 8, 8, 11, 11}}
}
scaleNames = {}
for i = 1, #scales do
scaleNames[i] = scales[i][1]
end
defineParameter("scaleMenu", nil, 1, scaleNames)
function getScaledNote(note)
local degree = (note - (rootKey - 1) + 12) % 12
return note + scales[scaleMenu][2][degree + 1] - degree
end
defineParameter("paramSelected", nil, 1, {"Tune", "Velocity", "Pan", "Repeat", "Length"})
for i = 1, 32 do
defineParameter("Tune"..i, nil, 0, -24, 24, 1)
defineParameter("Velocity"..i, nil, 1, 0, 2)
defineParameter("Pan"..i, nil, 0, -1, 1)
defineParameter("Repeat"..i, nil, 1, 1, 8, 1)
defineParameter("Length"..i, nil, 1, 0, 1)
end
-------------------------------------------- Playing events
local pedalDown = false
function onNote(e)
local pos = 0
local count = 0
if randomStart == true then
pos = math.random(0, repeats - 1)
end
while (oneShot == false and (isNoteHeld() or pedalDown)) or (oneShot and count < repeats) do
local time = resolutions[timeGlobal]
local pos1 = pos + 1
local vel = _G["Velocity"..pos1]
local length = lengthGlobal / 100 * _G["Length"..pos1]
if vel > 0 and length > 0 then
local pan = _G["Pan"..pos1]
local note = getScaledNote(e.note + _G["Tune"..pos1])
local rep = _G["Repeat"..pos1]
local repLength = time / rep
for i = 1, rep do
playNote(note, math.min(e.velocity * vel, 127), beat2ms(repLength * length), nil, 1, 0 + pan, e.tune)
waitBeat(repLength)
end
else
waitBeat(time)
end
pos = (pos + 1) % repeats
count = count + 1
end
end
function onRelease(e)
end
function onController(e)
if e.controller == 64 then
if pedalDown and e.value < 64 then
pedalDown = false
elseif not pedalDown and e.value >=64 then
pedalDown = true
end
else
postEvent(e)
end
end
Scale
local KEY = {"C", "Db", "D", "Eb", "E", "F", "F#", "G", "Ab", "A", "Bb", "B"}
local keyButtonText = {}
for i = 1, 12 do
defineParameter{name = "KeyButton"..i, default = false, readOnly = true, persistent = false}
end
defineParameter("KeyButtonText", nil, 1, KEY)
rootKeyChanged = function()
for i = 1, 12 do
keyButtonText[i] = KEY[(i + rootKey - 2) % 12 + 1]
end
defineParameter("KeyButtonText", nil, 1, keyButtonText)
end
defineParameter("rootKey", nil, 1, KEY, rootKeyChanged)
rootKeyChanged()
scales = {
{"--", {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}},
{"Major (Ionian)", {0, 2, 4, 5, 7, 9, 11}},
{"Minor (Aeolian)", {0, 2, 3, 5, 7, 8, 10}},
{"Harmonic Minor", {0, 2, 3, 5, 7, 8, 11}},
{"Melodic Minor", {0, 2, 3, 5, 7, 9, 11}},
{"Major Pentatonic", {0, 2, 4, 7, 9}},
{"Minor Pentatonic", {0, 3, 5, 7, 10}},
{"Dorian (D)", {0, 2, 3, 5, 7, 9, 10}},
{"Phrygian (E)", {0, 1, 3, 5, 7, 8, 10}},
{"Lydian (F)", {0, 2, 4, 6, 7, 9, 11}},
{"Mixolydian (G)", {0, 2, 4, 5, 7, 9, 10}},
{"Locrian (B)", {0, 1, 3, 5, 6, 8, 10}},
{"Whole Tone", {0, 2, 4, 6, 8, 10}},
{"1/2 Tone 1 Tone", {0, 1, 3, 4, 6, 7, 9, 10}},
{"1 Tone 1/2 Tone", {0, 2, 3, 5, 6, 8, 9, 11}},
{"Altered", {0, 2, 4, 6, 8, 10, 10}},
{"Hungarian", {0, 2, 3, 6, 7, 8, 10}},
{"Phrygish", {0, 1, 4, 5, 7, 8, 10}},
{"Arabic", {0, 1, 4, 5, 7, 8, 11}},
{"Persian", {0, 1, 4, 5, 7, 10, 11}},
{"Acoustic (Lydian b7)", {0, 2, 4, 6, 7, 9, 10}},
{"Harmonic Major", {0, 2, 4, 5, 7, 8, 11}},
}
scaleNames = {}
for i = 1, #scales do
scaleNames[i] = scales[i][1]
end
function loadScale(scale)
for i = 1, 12 do
_G["KeyButton"..i] = false
end
for i = 1, #scale do
_G["KeyButton"..scale[i] + 1] = true
end
end
scaleMenuChanged = function()
loadScale(scales[scaleMenu][2])
end
defineParameter{name = "scaleMenu", default = 1, strings = scaleNames, persistent = false, onChanged = scaleMenuChanged}
scaleMenuChanged()
function priotityChanged()
priorityValue = 2 * Priority - 3
end
defineParameter("Priority", nil, 1, {"Down", "Up"}, priotityChanged)
priotityChanged()
function getScaledNote(note)
degree = (note - (rootKey - 1) + 12) % 12
degreeDeviation = 0
while (true) do
if (_G["KeyButton"..(degree + degreeDeviation + 12) % 12 + 1]) then break end
degreeDeviation = - degreeDeviation
if (_G["KeyButton"..(degree + degreeDeviation + 12) % 12 + 1]) then break end
degreeDeviation = priorityValue - degreeDeviation
if (degreeDeviation == priorityValue * 7) then -- no button
degreeDeviation = 0
break
end
end
return note + degreeDeviation
end
function onNote(e)
playNote(getScaledNote(e.note), e.velocity)
end
function onRelease(e)
end
Step Line
-- numSteps
defineParameter("PhraserNumSteps", nil, 16, 1, 16, 1)
-- resolution
local PhraserResolutions = {2., 1.5, 4. / 3., 1., 0.75, 2. / 3., 0.5, 0.375, 1. / 3., 0.25, 0.1875, 0.5 / 3., 0.125}
local resolutionNames = {"1/2", "1/4d", "1/2t", "1/4", "1/8d", "1/4t", "1/8", "1/16d", "1/8t", "1/16", "1/32d", "1/16t", "1/32"}
defineParameter("PhraserResolution", nil, 10, resolutionNames)
-- gate
defineParameter("PhraserGate", nil, 1, 0.001, 1.1)
-- groove
defineParameter("PhraserGroove", nil, 0, 0, 0.5)
-- scales
local KEY = {"C", "Db", "D", "Eb", "E", "F", "F#", "G", "Ab", "A", "Bb", "B"}
defineParameter("rootKey", nil, 1, KEY)
scales = {
{"--", {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}},
{"Major (Ionian)", {0, 0, 2, 2, 4, 5, 5, 7, 7, 9, 9, 11}},
{"Minor (Aeolian)", {0, 0, 2, 3, 3, 5, 5, 7, 8, 8, 10, 10}},
{"Harmonic Minor", {0, 0, 2, 3, 3, 5, 5, 7, 8, 8, 11, 11}},
{"Melodic Minor", {0, 0, 2, 3, 3, 5, 5, 7, 7, 9, 9, 11}},
{"Major Pentatonic", {0, 0, 2, 2, 4, 4, 7, 7, 7, 9, 9, 12}},
{"Minor Pentatonic", {0, 0, 3, 3, 3, 5, 5, 7, 7, 10, 10, 10}},
{"Dorian (D)", {0, 0, 2, 3, 3, 5, 5, 7, 7, 9, 10, 10}},
{"Phrygian (E)", {0, 1, 1, 3, 3, 5, 5, 7, 8, 8, 10, 10}},
{"Lydian (F)", {0, 0, 2, 2, 4, 4, 6, 7, 7, 9, 9, 11}},
{"Mixolydian (G)", {0, 0, 2, 2, 4, 5, 5, 7, 7, 9, 10, 10}},
{"Locrian (B)", {0, 1, 1, 3, 3, 5, 6, 6, 8, 8, 10, 10}},
{"Whole Tone", {0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10}},
{"1/2 Tone 1 Tone", {0, 1, 1, 3, 4, 4, 6, 7, 7, 9, 10, 10}},
{"1 Tone 1/2 Tone", {0, 0, 2, 3, 3, 5, 6, 6, 8, 9, 9, 11}},
{"Altered", {0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10}},
{"Hungarian", {0, 0, 2, 3, 3, 6, 6, 7, 8, 8, 10, 10}},
{"Phrygish", {0, 1, 1, 4, 4, 5, 5, 7, 8, 8, 10, 10}},
{"Arabic", {0, 1, 1, 4, 4, 5, 5, 7, 8, 8, 11, 11}},
{"Persian", {0, 1, 1, 4, 4, 5, 5, 7, 7, 10, 10, 11}},
{"Acoustic (Lydian b7)", {0, 0, 2, 2, 4, 4, 6, 7, 7, 9, 10, 10}},
{"Harmonic Major", {0, 0, 2, 2, 4, 5, 5, 7, 8, 8, 11, 11}}}
scaleNames = {}
for i = 1, #scales do
scaleNames[i] = scales[i][1]
end
defineParameter("scaleMenu", nil, 1, scaleNames)
function getScaledNote(note)
local degree = (note - (rootKey - 1) + 12) % 12
return note + scales[scaleMenu][2][degree + 1] - degree
end
-- Step Panel
for i = 1, 16 do
defineParameter("Step"..i, nil, 100, 0, 127, 1)
defineParameter("Pitch"..i, nil, 0, -48, 48, 1)
defineParameter("Length"..i, nil, 1, 0.001, 1.1)
defineParameter("Enable"..i, nil, false)
defineParameter("Link"..i, nil, false)
defineParameter("CC1__"..i, nil, 0, 0, 127, 1)
defineParameter("CC2__"..i, nil, 0, 0, 127, 1)
end
local recordOrigin = nil
-- record
PhraserRecordChanged = function()
if PhraserRecord then
recordOrigin = nil
lastRecordedIndex = 1
else
for i = lastRecordedIndex, 16 do
_G["Pitch"..i] = 0
_G["Step"..i] = 0
end
for i = 1, 16 do
_G["Link"..i] = false
end
end
end
defineParameter("PhraserRecord", nil, false, PhraserRecordChanged)
-- skip
PhraserSkipChanged = function()
if PhraserRecord then
_G["Pitch"..lastRecordedIndex] = 0
_G["Step"..lastRecordedIndex] = 0
lastRecordedIndex = lastRecordedIndex + 1
if lastRecordedIndex == 17 then
PhraserRecord = false
end
end
PhraserSkip = false
end
defineParameter("PhraserSkip", nil, false, PhraserSkipChanged)
function randomizePattern()
PhraserNumSteps = math.floor(math.random(1, 16) + .5)
for i = 1, PhraserNumSteps do
_G["Pitch"..i] = math.floor(math.random(-12, 12) + .5)
_G["Step"..i] = math.floor(math.random(0, 127) + .5)
_G["Link"..i] = false
end
for i = PhraserNumSteps + 1, 16 do
_G["Pitch"..i] = 0
_G["Step"..i] = 0
_G["Link"..i] = false
end
end
-- Random
PhraserRandomChanged = function()
if PhraserRandom then
randomizePattern()
PhraserRandom = false
end
end
defineParameter("PhraserRandom", nil, false, PhraserRandomChanged)
-- seq selection button
local PhraserSeqDisplayItems = {"Vel", "Ptch", "Len", "CC1", "CC2"}
defineParameter("PhraserSeqDisplay", nil, 1, PhraserSeqDisplayItems) -- maybe non persistent
function clearPosition()
for i = 1, 16 do
_G["Enable"..i] = false
end
end
local arpId = 0
local heldNotes = {}
local pedalDown = false
function grooveDelay(beatPos, grooveAmount)
local semi = beatPos * 4 -- convert to 16th pos
local x = math.fmod(semi, 2.0)
if x < 1 then
return 0.25 * grooveAmount * x
else
return 0.25 * grooveAmount * (2 - x)
end
end
function arpeg(arpId_)
local index = 0
local theoricalPosInBeat = 0 -- non grooved beat pos
local beatTime = 0
while arpId_ == arpId do
local e = heldNotes[#heldNotes]
local p = PhraserResolutions[PhraserResolution]
local numSteps = PhraserNumSteps
local stepSize = 1
for i = 1, 16 do -- check for linked
local pos = (index + i) % numSteps
local pos1 = pos + 1
if _G["Link"..pos1] == true then
stepSize = stepSize + 1
else
break
end
end
local index1 = index + 1
local tune = _G["Pitch"..index1]
tune = getScaledNote(e.note + tune)
tune = tune - e.note
local velocity = _G["Step"..index1]
local nextTheoricalPosInBeat = theoricalPosInBeat + p
local beatDelay = grooveDelay(nextTheoricalPosInBeat, PhraserGroove)
if _G["Link"..index1] == false then
for i = 1, numCC do
controlChange(i, _G["CC"..i.."__"..index1])
end
end
if velocity ~= 0 and _G["Link"..index1] == false then
playNote(e.note, velocity, beat2ms(_G["Length"..index1] * PhraserGate * p * stepSize + beatDelay), nil, 1, 0, tune)
print(e.note, " ", e.note + tune)
end
_G["Enable"..((index - 1 + numSteps) % numSteps + 1)] = false
_G["Enable"..((index % numSteps) + 1)] = true
index = (index + 1) % numSteps
local timeToWait = nextTheoricalPosInBeat + beatDelay - beatTime
waitBeat(timeToWait)
theoricalPosInBeat = nextTheoricalPosInBeat
beatTime = beatTime + timeToWait
end
end
function onNote(e)
table.insert(heldNotes, e)
if PhraserRecord == true then
if recordOrigin == nil then
recordOrigin = e.note
end
_G["Pitch"..lastRecordedIndex] = e.note - recordOrigin
_G["Step"..lastRecordedIndex] = e.velocity
PhraserNumSteps = lastRecordedIndex
lastRecordedIndex = lastRecordedIndex + 1
if lastRecordedIndex == 17 then
PhraserRecord = false
end
playNote(e.note, e.velocity -1)
else
if #heldNotes == 1 then
arpeg(arpId)
end
end
end
function onRelease(e)
if pedalDown == true then
return
end
for i, v in ipairs(heldNotes) do
if v.note == e.note then
table.remove(heldNotes, i)
if #heldNotes == 0 then
clearPosition()
arpId = arpId + 1
end
break
end
end
end
function pedalChanged()
for i=#heldNotes,1,-1 do
if not isKeyDown(heldNotes[i].note) then
table.remove(heldNotes, i)
end
end
if #heldNotes == 0 then
clearPosition()
arpId = arpId + 1
end
end
function onController(e)
if e.controller == 64 then
if pedalDown and e.value < 64 then
pedalDown = false
pedalChanged()
elseif not pedalDown and e.value >= 64 then
pedalDown = true
end
else
postEvent(e)
end
end
All of these are included in the attachment as midi module presets for HALion 6. They have a simple macro page attached to the script module.