Script to delay a specific CC?

Post topics about HALion scripting.
Post Reply
Brian Roland
Senior Member
Posts: 1037
Joined: Fri Jun 19, 2015 5:24 pm
Contact:

Script to delay a specific CC?

Post by Brian Roland »

I've not yet had a chance to study up on how Lua works so hopefully someone might be kind enough to help me make a simple script.

I would like a slot specific script that can delay a given CC event before it passes into the layer it resides for processing.

I'd also like a variation that can do the same for a specific note on/note off event (key switch).

Example: With Dorico, if I assign CC68 to the Legato technique (slurs), the legato pedal is always triggered before the slurred passage begins playing. What I want to happen is that the first note should be articulated normally, then a legato event sent a tick or two later to change to a legato sound and continue until the slur mark ends, and release the legato event a tick after the last note under the slur has played.

If I had a script I could drop into a HALion layer that needs it and delay the event a millisecond or two before it gets processed/played deeper in the HALion program then it would save me a LOT of time in getting Dorico to do nicer interpretations of slurred passages.

Typically I create legato effects either with CC68 shifting a variety of parameters, OR, just having a mega-trigger/key-switch that can toggle to a new layer. My current work-around is to host HALion inside a Bidule instance, and I have bidule filter out the event and delay it. It works for me, but I'd like to be able to share things easier with other Dorico users who don't own Bidule.
Last edited by Brian Roland on Mon Sep 23, 2019 3:44 am, edited 1 time in total.

misohoza
Member
Posts: 938
Joined: Sun Oct 05, 2014 12:18 am
Contact:

Re: Script to delay a specific CC?

Post by misohoza »

Hi Brian,

You can use the wait() function to delay midi events.

You can delay a specific cc like this:

Code: Select all

-- delay midi cc28 events by 250 ms
function onController(event)
  if event.controller == 28 then
    wait(250)
    postEvent(event)
  else
    postEvent(event)
  end
end
You can do the same for note on messages:

Code: Select all

-- delay a specific note by 100 ms (midi note 60)
function onNote(event)
  if event.note == 60 then
    wait(100)
    postEvent(event)
  else
    postEvent(event)
  end
end
If you want more control about the delay time without having to change the script each time you can create a delay parameter:

Code: Select all

defineParameter("delay", nil, 100, 0, 1000) -- delay in ms, numbers are default, min, max

-- delay each note
function onNote(event)
  wait(delay)
  postEvent(event)
end
And a few more experimental ideas:

Code: Select all

-- wait for next note on event if specified cc event has a value bigger then 64
defineSlotLocal("CCValue")
CCValue = false
cc = 28 -- change this to match the desired cc number

defineParameter("delay", nil, 100, 0, 1000) -- delay time - default 100 ms

function onController(event)
  if event.controller == cc and event.value > 64 then
    CCValue = event.value
  else
    postEvent(event)
  end
end

function onNote(event)
  postEvent(event)
  if CCValue then
    local ccvalue = CCValue
    wait(delay)
    controlChange(cc, ccvalue)
    CCValue = false
  end
end

Code: Select all

-- delay cc 28 if no note is being played
defineSlotLocal("anyNotePressed")
anyNotePressed = 0

function onNote(event)
  anyNotePressed = anyNotePressed + 1
  postEvent(event)  
end

function onRelease(event)
  anyNotePressed = math.max(anyNotePressed - 1, 0)
  postEvent(event)
end

function onController(event)
  if event.controller == 28 and anyNotePressed == 0 then
    wait(100)
    postEvent(event)
  else
    postEvent(event)
  end
end
Edit:
But I'm not sure if any of this would help you. Just tried in Dorico and it doesn't seem to work with keyswitches.
Win 10 Home, 64 bit, 8 gb ram,
Cubase Pro 10.5, Wavelab Pro 9.5, Halion 6, Dorico 3,
NI Komplete 10 Ultimate, Ozone 7,
UR 44

Brian Roland
Senior Member
Posts: 1037
Joined: Fri Jun 19, 2015 5:24 pm
Contact:

Re: Script to delay a specific CC?

Post by Brian Roland »

misohoza wrote:
Sun Sep 22, 2019 4:38 pm
Hi Brian,

You can use the wait() function to delay midi events.
<snip>
But I'm not sure if any of this would help you. Just tried in Dorico and it doesn't seem to work with keyswitches.
Thank you. These examples are very much appreciated.

I'll give them a try here and see how it goes. Perhaps trying them at different layer levels, and orders will get things working. If it won't delay before the event hits mega-triggers, I might still be able to kludge together some sort of CC controlled legato/portamento effects.

Also, I'm curious....what if key switches were done with a script instead of via mega-trigger?

Another possibility....have a double key-switch in the meta-trigger. Have the script wait some period after receiving the first key-switch-note-on from Dorico, and simply send a SECOND note-on event of a different value some milliseconds later. In theory that should work (assuming the event ever makes it through the mega-trigger for processing), as the mega-trigger would need two trues instead of one to spring into action. The second trigger should be delayed since it technically doesn't even exist until the script generates it.

misohoza
Member
Posts: 938
Joined: Sun Oct 05, 2014 12:18 am
Contact:

Re: Script to delay a specific CC?

Post by misohoza »

Also, I'm curious....what if key switches were done with a script instead of via mega-trigger?
Well, you might be onto something here.

It looks like when you use MegaTrig Halion grabs those keyswitches before you can do anything with them. But when using script you can delay the key switching. Here's a simple script that creates key switches for each layer (without using MegaTrig). Tried it in Cubase and Dorico and it looks like it works.

Code: Select all

layers = this.parent:findLayers()
keyswitches = getKeySwitches()
layerNames = {}

for i = 1, #layers do
  keyswitches[i] = { name = layers[i].name, keyMin = i - 1 }
  layerNames[i] = layers[i].name
end

defineParameter("LayerSelect", nil, 1, layerNames)
defineParameter("delay", nil, 0, 0, 1000)


function onNote(event)
  if event.note < #layers then
    wait(delay)
    LayerSelect = event.note + 1
  else
    playNote(event.note, event.velocity, -1, layers[LayerSelect])
  end
end
Another possibility....have a double key-switch in the meta-trigger. Have the script wait some period after receiving the first key-switch-note-on from Dorico, and simply send a SECOND note-on event of a different value some milliseconds later. In theory that should work (assuming the event ever makes it through the mega-trigger for processing), as the mega-trigger would need two trues instead of one to spring into action. The second trigger should be delayed since it technically doesn't even exist until the script generates it.
While you can create new events in a script those will not work as keyswitches. At least not with MegaTrig. But you might be able to use a keyswitch as a trigger to create new cc events. Almost like using Cubase logical editor to generate new events based on a specific note. Map the cc to some parameters or modulation matrix.
Win 10 Home, 64 bit, 8 gb ram,
Cubase Pro 10.5, Wavelab Pro 9.5, Halion 6, Dorico 3,
NI Komplete 10 Ultimate, Ozone 7,
UR 44

Brian Roland
Senior Member
Posts: 1037
Joined: Fri Jun 19, 2015 5:24 pm
Contact:

Re: Script to delay a specific CC?

Post by Brian Roland »

Misohoza,

These are super.

Thanks very much!

The syntax of lua looks rather interesting.

These examples, along with browsing the function list in the HALion docs is getting me pumped to study up and practice with lua.

I also believe you've given me more than enough to solve my immediate challenge.

Post Reply

Return to “Halion Scripting”

Who is online

Users browsing this forum: No registered users and 1 guest