Question 1:
I often use short decay pitch or filter envelope drops to add some bite to a synth sound’s attack. To spare the internal zone envelopes for other uses, I made a simple modulation parameter to do the job. There is a problem though.
When playing lower notes, there are noticeable variations in the attack character of successive notes, especially sounds with a longer release. It sounds like the oscillator phase and rapid envelope decay are out of sync (with fixed phase osc). The modulation param also doesn’t take “Key On Del” into account. I’m guessing this has something to do with the execution order of the program tree.
The same thing happens with the standard Env Midi Module.
I’ve tried various ways of delaying the mod param to sync with onNote, but nothing worked. Any ideas?
defineModulation("Quick Decay", false)
modVal = 1
durationMS = 15
function calcModulation()
if retrigger then
modVal = 1
retrigger = false
end
rate = getSamplingRate() / 32
rateVal = 1 / (rate * (durationMS / 1000))
if modVal <= 0 then
modVal = 0
else
modVal = modVal - rateVal
end
return modVal
end
function onNote(event)
retrigger = true
postEvent(event)
end
function onRelease(event)
postEvent(event)
end
Question 2:
I have a boolean parameter tied to a UI switch with no callback function. It’s only there to retrieve the state of the switch.
As soon as you use the boolean parameter in the onNote function, it changes the values to 0 and 1 instead of false and true. This messes with the shorthand “if boolParam then” syntax, as both become true. Even when the “if statement” is inside an external function and called from onNote, this still happens.
I know this runs in different threads in the Halion engine, but as parameters are variables, this is kind of strange.
Any help with these 2 questions would be much appreciated.
Hi AposMus.
Regarding your second question, can you use an integer parameter instead?
Or maybe an indexed string array with two entries, on and off.
I had similar problems problem with boolean parameters and if statements. In the end I went with the integer option.
Edit: Actually I think it works if you assign the value of the Boolean parameter to a local variable first.
Something like:
defineParameter("Play",nil,true)
function onNote(event)
local p=this:getParameter("Play")
if p then postEvent(event) end
end
When playing lower notes, there are noticeable variations in the attack character of successive notes, especially sounds with a longer release. It sounds like the oscillator phase and rapid envelope decay are out of sync (with fixed phase osc). The modulation param also doesn’t take “Key On Del” into account. I’m guessing this has something to do with the execution order of the program tree.
The same thing happens with the standard Env Midi Module.
I’ve tried various ways of delaying the mod param to sync with onNote, but nothing worked. Any ideas?
Having a go at your first question I came up with this. Each note on event should trigger the modulation and also take the Key on delay into account as long as it’s set to ms. Don’t know if that helps.
defineModulation("Quick Decay", false)
modVal = 1
durationMS = 15
zone=this.parent:getZone()
function calcModulation()
rate=getSamplingRate()/32
rateVal=1/(rate*(durationMS/1000))
modVal=modVal-rateVal
if modVal<0 then
modVal=0
end
return modVal
end
function onNote(event)
postEvent(event)
wait(zone:getParameter("VoiceControl.KeyOnDelay"))
modVal=1
end
Thanks misohoza
With Q1 I did end up using and integer switch, I’m just curious though how a boolean can change to an integer mid script. Also I like a certain conformity in the script, so having to change it for one parameter kind of bugs me.
As for Q2, that is something I already tried, but it doesn’t really work. Delaying the note doesn’t get rid of the attack phase issues, but I’m working on another idea, so might post it when I’m done.
Hi ApoMus,
regarding the “QuickDecay” and calcModulation, I think, you must use note expression, instead.
In general, the modulations from MIDI modules are monophonic. That is, the same modulation value goes to all voices that are still being processed.
If you use changeNoteExpression, you should be able to send the “QuickDecay” with every note and do this polyphonically.
Cheers,
Matthias
Hi AposMus,
regarding the boolean parameter, unfortunately, this is a bug. I created a bug report, so it gets fixed.
Here, is a workaround.
defineParameter("Play",nil,true)
function onNote(event)
if Play and Play ~= 0 then
postEvent(event)
end
end
The workaround from misohoza is fine, too. Thanks @misohoza for posting this.
After the fix Play will keep its boolean values. The workarounds above should still work after we have fixed this problem.
You should not use this statement:
if Play == 1 then
postEvent(event)
end
This will not work anymore after our fix.
Sorry, for the inconvenience this might cause.
Best,
Matthias
Hi Matthias, good to hear from you.
Thanks for the boolean workaround. I’m glad it’s a bug, because I was beginning to doubt my understanding of the scripting language and thought I missed something major in the reference manual.
I eventually defined my switch parameter with integers instead of a boolean, but I’m going change that.
The “QuickDecay” using the changeNoteExpression function is working like a charm. I wouldn’t have thought of that. One just has to keep controller smoothing in mind.
Thanks for the feedback.