I would like to use the clone () function to clone a user envelope and then be able to restore to original via macro button, after making edits . I tried following the example of cloning a program shown at the developer site, however there is no mention of how to restore a cloned object.
If anyone has some code that can clone and restore an envelope could you please post it?
Thank you ![:slight_smile: :slight_smile:](https://emoji.discourse-cdn.com/apple/slight_smile.png?v=12)
You cannot clone just the user envelope - you would need to clone the whole zone. But it should be possible by creating a couple of variables and store the relevant envelope parameters. I guess you would need the EnvelopePoints, SustainIndex and probably Mode. You can use getParameter to store those values into variables. Then to restore those value simply use setParameter.
1 Like
I just need to be able to restore the env points table. I suppose I could try various deep copy/clone table functions out there on the net. You wouldānt happen to know of one that would work well, do you?
Iāve created a script and macro that Iām using to manipulate the points table in whole or even just sections of the table and it would be nice to be able to restore the original without having to always fummble with the preset menu.
In my other post about the script reset buttonā¦, that is
related to this same script project. Any time I want to reset the env points table or load a different one I have to also click the script reset button so that my function can gather the table data.
I was hoping to be able to assign it to a macro button so I could control it via midi, this way I wouldnāt have to reach for the mouse as much. ![:slight_smile: :slight_smile:](https://emoji.discourse-cdn.com/apple/slight_smile.png?v=12)
You can try something like this to copy and restore an envelope.
defineParameter("CopyEnv", nil, false, function() copyEnvelope("Amp Env") end)
defineParameter("RestoreEnv", nil, false, function() restoreEnvelope("Amp Env") end)
defineParameter{name = "DataCopied", default = false, persistent = false, automatable = false, readOnly = true}
zone = this.parent:getLayer():getZone()
function copyEnvelope(envType)
if CopyEnv then
envelopePoints = zone:getParameter(envType..".EnvelopePoints")
sustainIndex = zone:getParameter(envType..".SustainIndex")
mode = zone:getParameter(envType..".Mode")
DataCopied = true
wait(50)
CopyEnv = false
end
end
function restoreEnvelope(envType)
if RestoreEnv and DataCopied then
zone:setParameter(envType..".EnvelopePoints", envelopePoints)
zone:setParameter(envType..".SustainIndex", sustainIndex)
zone:setParameter(envType..".Mode", mode)
wait(50)
RestoreEnv = false
end
end
Restore Envelope.vstpreset (12.8 KB)
1 Like
ooh cool! Iāll try it out and let you know how it goes.
Thank You ![:smiley: :smiley:](https://emoji.discourse-cdn.com/apple/smiley.png?v=12)
Tried it out and it works greatā¦, thank you so much.
There is one other thing I was wondering if you might have a solution to? So, say Iām iterating over the level values of an envelope, using just the standard for loop, there is the step parameter which allows for things like every nāth, but what Iām looking to do is to manipulate groups of points. So things like
xxoxxo or xxooxxoo, āxā being the points I want to control. I donāt know if it would require a nested for loop or some sort of custom function? Any ideas?
Not sure I understand correctly.
If it is a repeating pattern you could try modulus operatorā¦
-- xx0
for i = 1, 12 do
if i % 3 == 1 or i % 3 == 2 then
print(i)
end
end
for i = 1, 12 do
if i % 3 ~= 0 then
print(i)
end
end
--xx00
for i = 1, 12 do
if i % 4 == 1 or i % 4 == 2 then
print(i)
end
end
Yes, repeated patterns, I believe you understood correctly and just glancing at the code it looks like that will be a good solution. Unfortunately itās bedtime so Iāll have a go at it in the morning and let you know how it went. Appreciate all your help! ![:smiley: :smiley:](https://emoji.discourse-cdn.com/apple/smiley.png?v=12)
Well it works, however Iām not sure if modulus is the way to go, certain ratios donāt work out quite right.
So basically what Iām looking to do is control a group of points which will be a repeated pattern but the ratio of points being controlled vs stationary points could be anythingā¦, 1/3, 3/1, 2/2, 5/2ā¦, whatever. Also the function should take into account that there could be a āstart and end offsetā or rather a range.
Here is a pic of the what I originally came up with, on the right you can see part of the macro I created.
What Iām thinking now, which would be even more versatile is two sliders, each of which would control itās own group of points and then maybe just a couple of knobs to set the ratio.
I guess you need to sort out the range first before checking against the pattern. How do you set the ratio? Do you have parameters for it?
Here is what I tried for my loop which works except when startL = 2, 5, 8ā¦ etc. Also I was messing around with the modulus and couldānt figure out how I could produce a pattern such as xxxooo.
function myLevel()
for i = startL, endL do
if i % 3 == 2 or i % 3 == 1 then
uE[i].level = myLevel
zone:setParameter("User Env.EnvelopePoints", uE)
end
end
end
The more I think about, Iād like to go with a 2 slider approach, so as to be able to control both point groups,
xās and oās, but I donāt know how to go about doing it that way.
You need to sort out the range so that whatever point you start with is considered point 1 of the pattern. I would use setParameter at the very end after you finish the loop.
startL = 15
endL = 30
function myLevel()
for i = startL, endL do
if (i - startL + 1) % 6 > 0 and (i - startL + 1) % 6 < 4 then
print(i, "X")
else
print(i, "O")
end
end
end
myLevel()
Hopefully that should give you the xxxooo pattern starting from startL.
*** Another idea for checking the patterns:
patterns = {
{[0] = true, true, false, false},
{[0] = true, false, false, false},
{[0] = true, true, true, false, false, false},
}
startL = 15
endL = 30
selectedPattern = 3
function myLevel()
for i = startL, endL do
local point = i - startL
local mod = #patterns[selectedPattern] + 1
if patterns[selectedPattern][point % mod] then
print(i, "X")
else
print(i, "O")
end
end
end
myLevel()
Awesome!
Both solutions work really well.
I think I may go with the table of patterns one because it seems to be the most flexable, plus super quick to add other patterns. So much exciting territory to transverse, I canāt thank you enough!
Good to hear it works. Maybe we could do a slight variation of the table version and get rid of the [0] index:
patterns = {
{true, true, false, false},
{true, false, false, false},
{true, true, true, false, false, false},
}
startL = 15
endL = 30
selectedPattern = 3
function myLevel()
for i = startL, endL do
local point = i - startL
local mod = #patterns[selectedPattern]
if patterns[selectedPattern][point % mod + 1] then
print(i, "X", point % mod + 1)
else
print(i, "O", point % mod + 1)
end
end
end
myLevel()
I was going to ask you about that, what was the purpose of that? I was defining a parameter to select which pattern to use and thought I might have a problem with those indexes, but surprisingly it worked fine.
So here is a crazy idea I just had. Given the clone script discussed earlier I wonder if you created a clone of the envelope then you could make a point selection using HALionās selection tool, (even non-contiguous by holding shift key), then move the points just enough to make it different from the clone, you could then run a comparison function that would return the edited points, then those could be saved into a pattern table.
How cool would that be? ā¦, anyway just an idea.
Oh, by the way how hard would it be to mod that āclone/resetā script into a sort of āa/bā toggle?
Try if this worksā¦
defineParameter("AB", nil, 1, {"A", "B"}, function() abChanged("Amp Env") end)
envelope = {{}, {}}
zone = this.parent:getLayer():getZone()
function copyEnvelope(envType, index)
envelope[index].envelopePoints = zone:getParameter(envType..".EnvelopePoints")
envelope[index].sustainIndex = zone:getParameter(envType..".SustainIndex")
envelope[index].mode = zone:getParameter(envType..".Mode")
end
function restoreEnvelope(envType, index)
zone:setParameter(envType..".EnvelopePoints", envelope[index].envelopePoints)
zone:setParameter(envType..".SustainIndex", envelope[index].sustainIndex)
zone:setParameter(envType..".Mode", envelope[index].mode)
end
function abChanged(envType)
local newIndex = AB
local oldIndex = math.abs(AB - 2) + 1
copyEnvelope(envType, oldIndex)
if envelope[newIndex].envelopePoints then
restoreEnvelope(envType, newIndex)
end
end
Envelope AB.vstpreset (12.8 KB)
1 Like
Wow, that was quick, and yes it sure does work. ![:grin: :grin:](https://emoji.discourse-cdn.com/apple/grin.png?v=12)
Thanks.
@misohoza,
One more thing which Iād like to add to the āpatternsā code which Iām struggling to figure out isā¦, Iād like to be able to have a 3rd defined parameter that can move both groups together while keeping their relative difference intact, is this possible?
I would probably create an on/off parameter that would link the two sliders. When the link is turned on you need to check the values of both sliders and assign the difference to a variable.
The callbacks for the sliders need to be adjusted to take into account the link parameter. If the link is on you should also change the other slider and apply the difference to it.
Cool, thanks for the info. I like the idea of the link switch. I wonder if there are any 3-way switches in the macro templates? I could maybe set it up to where I only need one slider. Position 1 & 2 would allow control of point groups 1 & 2 independently, and sw pos.3 would allow control of both groups together.