hello, I am using the layer selector script (made by misohoza) this mutes all the layers except the selected one, the problem is that when you have a lot, about 150 in my case, even if they are muted they continue loading the cpu and as a result there is a very high load.
I have been told that to reduce the load instead of mutating, just load the selected layer.
Someone has some example of this or can give me some clue.
Hi miclo,
There are some examples in the online script documentation. You can use loadPreset or loadPresetAsync to load a layer preset then remove the old layer and append or insert new layer.
You can also use the Sample Selector template that’s used by Hot Brass, Studio Strings or Skylab instruments. Check one of those instruments to see how it’s done. The advantage of using the sample selector is that you don’t need to write the path of each layer preset into your script, it works like a preset browser.
thank you very much, I have already lost count of all the beers that I owe you , I will investigate
hello I’ve been seeing how to do it with Sample Selector template (as Hot Brass)
I first created a working directory with Export Program as VST3 Preset with Files …
I have saved it in c: / documents / my library
and a vstpreset and a folder called Mother Source have been generated with the samples and macropages, I have added a folder called Layer Presets and added a few preset of my layers.
and I have loaded the vstpreset again to create the relative paths that I think are needed and I have configured the Sample Selector template as you see in the photo, but it doesn’t find anything …
something escapes me?
I tried to find the Hot Brass folder to see what the structure is like but it has been impossible for me to find it.
any advice?
It seems that you have to have this route: documents / steinberg / and already the instrument folder.
Inside the instrument folder you have to create a folder called “sub Presets” and inside one called “Layer Presets”
in this way he recognizes my instrument and the vstpresets of the layers appear to me …
the first load of a layer always works fine but when I want to change to another layer halion I get the error “A serius problem has occurred …”
or gives a script error that says:
Parameter change callback selectedPath = data: cannot resume non-suspended coroutine
Any ideas anyone?
- I am using the Hot Brass script
I think I know what the problem is …
The rest of the script’s functions conflict with my macro page, if I remove my macro page and leave only the sampler selector template, everything seems fine.
I need to leave the script only with the functions necessary for the “selectedPatch” and “selectedPreset” parameters to work and remove everything else.
could someone tell me how it should be the script?
I’m trying but it always throws errors
I paste the complete script
-- copy relevant zone parameters
defineSlotLocal("copiedParameters")
copiedParameters =
{
{"Filter.Type", nil}, -- second value will be set to the parameter of the previous zones
{"Filter.VelocityToCutoff", nil},
{"DCFAttOffset", nil},
{"DCFSusOffset", nil},
{"DCAAttOffset", nil},
{"DCASusOffset", nil},
{"Amp Env.VelocityToLevel", nil},
{"UserAttOffset", nil},
{"Pitch.Coarse", nil},
{"Pitch.Fine", nil},
{"Pitch.Random", nil},
{"VoiceControl.UseStartRange", nil},
{"Amp.Pan", nil},
{"Filter.Cutoff", nil},
{"Filter.Resonance", nil},
{"Filter.Distortion", nil},
{"Filter.EnvAmount", nil},
{"Filter.Keytrack", nil},
{"Filter.Bypass", nil},
{"Filter.ShapeA", nil},
{"DCFRelOffset", nil},
{"DCFDecOffset", nil},
{"DCARelOffset", nil},
{"DCADecOffset", nil},
{"Amp.Level", nil},
{"User Env.VelocityToLevel", nil},
{"UserDecOffset", nil},
{"UserSusOffset", nil},
{"UserRelOffset", nil},
{"VoiceControl.GlideOn", nil},
{"VoiceControl.Fingered", nil},
{"VoiceControl.Glide", nil},
{"Pitch.PitchBendUp", nil},
{"Pitch.PitchBendDn", nil},
{"UserL0Offset", nil},
{"UserL1Offset", nil},
{"UserLROffset", nil},
}
defineSlotLocal("copiedModulationMatrixParameters")
copiedModulationMatrixParameters = {}
for i = 1, 19, 1 do
copiedModulationMatrixParameters[i] =
{
{"Source1.Polarity", nil},
{"Source2.Polarity", nil},
{"Source1.Smoothing", nil},
{"Source2.Smoothing", nil},
{"Destination.Depth", nil},
{"Destination.Bypass", nil}
}
end
-- keep track of last applied parameter values
last = {}
-- load handling
-- selectedPath and selectedPreset should not appear in the undo history,
-- so we make them non-persistent, but save and restore them explicitly with
-- onSave and onLoad
defineParameter{name = "selectedPath", default = "", onChanged = function() onSelectPath() end, persistent = false, automatable = false}
defineParameter{name = "selectedPreset", default = "", persistent = false, automatable = false}
function onSave()
return { selectedPath = selectedPath, selectedPreset = selectedPreset }
end
function onLoad(data)
if type(data) == "table" then
-- beware of old tables still filled with other entries
if data.selectedPath then
selectedPath = data.selectedPath
end
if data.selectedPreset then
selectedPreset = data.selectedPreset
end
end
end
function onUndo()
-- print("onUndo: updatePreset = ", undoInfo.updatePreset)
if undoInfo.updatePreset then
local layer = this.parent:getLayer()
if layer then
selectedPreset = layer.name
end
end
end
-- pseudo parameter to add a callback into the undo group for replacing the sample layer
defineParameter{name = "undoInfo", default = {}, onChanged = onUndo, automatable = false}
-- all parameters but the modulation sources can be restored
-- before insertion into the parent layer
function restoreZoneParameters(layer)
local zones = layer:findZones()
for i, zone in pairs(zones) do
for j, parameter in pairs(copiedParameters) do
zone:setParameter(parameter[1], parameter[2])
end
for j = 1, 16, 1 do
local modDestination = modDestinations[_G["ModDestination"..j]]
zone:getModulationMatrixRow(j):setParameter("Destination.Destination", modDestination.index)
end
for j = 1, 3, 1 do
local modDestination = modDestinations[_G["CtrlLane"..j.."Dest"]]
zone:getModulationMatrixRow(j + 16):setParameter("Destination.Destination", modDestination.index)
end
for j, parametersOfRow in pairs(copiedModulationMatrixParameters) do
local row = zone:getModulationMatrixRow(j)
for k, parameter in pairs(parametersOfRow) do
row:setParameter(parameter[1], parameter[2])
end
end
end
end
-- modulation sources must be restored after insertion into the parent layer
-- because QC and MidiModule references do not exist before
function restoreMatrixSources(layer)
local zones = layer:findZones()
for i, zone in pairs(zones) do
for j = 1, 16, 1 do
local row = zone:getModulationMatrixRow(j)
local polarity1 = row:getParameter("Source1.Polarity")
local polarity2 = row:getParameter("Source2.Polarity")
local modSource = modSources[_G["ModSource"..j]]
modSource.assignFunc(row, 1, modSource.bipolar, modSource.smoothing, modSource.index)
local modModifier = modSources[_G["ModModifier"..j]]
modModifier.assignFunc(row, 2, modModifier.bipolar, modModifier.smoothing, modModifier.index)
row:setParameter("Source1.Polarity", polarity1)
row:setParameter("Source2.Polarity", polarity2)
end
end
end
function saveZoneParameters(layer)
local sourceZone = layer:getZone()
if not sourceZone then
return false
end
for i, parameter in pairs(copiedParameters) do
parameter[2] = sourceZone:getParameter(parameter[1])
end
for i, parametersOfRow in pairs(copiedModulationMatrixParameters) do
local row = sourceZone:getModulationMatrixRow(i)
for j, parameter in pairs(parametersOfRow) do
parameter[2] = row:getParameter(parameter[1])
end
end
return true
end
function forwardSphere(layer)
local sphereH = layer:getParameterDefinition("QuickControl.QC9").id
local sphereV = layer:getParameterDefinition("QuickControl.QC10").id
this.parent:addQCAssignment(9, layer, sphereH, layer)
this.parent:addQCAssignment(10, layer, sphereV, layer)
end
function loadFinished(currentProgressInfo)
if currentProgressInfo.root then
startUndoBlock("Load Layer " .. currentProgressInfo.root.name)
undoInfo = { updatePreset = true }
this:setParameter("undoInfo", { updatePreset = false }, true)
local saved = false
local layer = this.parent:getLayer()
if layer then
saved = saveZoneParameters(layer)
if saved then
restoreZoneParameters(currentProgressInfo.root)
end
end
this.parent:appendLayer(currentProgressInfo.root)
if layer then
this.parent:removeLayer(layer)
if saved then
restoreMatrixSources(currentProgressInfo.root)
end
end
forwardSphere(currentProgressInfo.root)
undoInfo = { updatePreset = false }
this:setParameter("undoInfo", { updatePreset = true }, true)
endUndoBlock()
end
end
function onSelectPath()
loadPresetAsync(selectedPath, loadFinished)
end
-- set parameter of all zones
function setParameterOfZones(parameterName, value)
local zones = this.parent:getLayer():findZones()
for i, zone in pairs(zones) do
zone:setParameter(parameterName, value)
end
end
-- parameter change callback for pitch random
function onPitchRandomChanged()
last.PitchRandom = PitchRandom
setParameterOfZones("Pitch.Random", PitchRandom)
end
defineParameter("PitchRandom", "Pitch Random", 0, 0, 1, onPitchRandomChanged)
-- define the filter types
defineSlotLocal("filterTypes")
filterTypes = {
{ name = "Tube", index = 2 },
{ name = "Hard Clip", index = 3 },
{ name = "Bit Reduction", index = 4 },
{ name = "Rate Reduction", index = 5 },
{ name = "Rate Reduction Key Follow", index = 6 },
}
-- create table with the names of the filter types
function getFilterTypeNames()
filterTypeNames = {}
for i=1, #filterTypes do
filterTypeNames[i] = filterTypes[i].name
end
end
getFilterTypeNames()
-- parameter change callbacks for the filter parameters
function onFilterTypeChanged()
setParameterOfZones("Filter.Type", filterTypes[FilterType].index)
end
function onFilterVelChanged()
last.FilterVelocity = FilterVelocity
setParameterOfZones("Filter.VelocityToCutoff", FilterVelocity)
end
-- define parameters for the filter section
defineParameter("FilterType", "Filter Type", 1, filterTypeNames, onFilterTypeChanged)
defineParameter("FilterVelocity", "Filter Velocity", 0, 0, 200, onFilterVelChanged)
-- parameter change callbacks for filter envelope offsets
function onFilterEnvAttackChanged()
last.FilterEnvAttack = FilterEnvAttack
setParameterOfZones("DCFAttOffset", FilterEnvAttack)
end
function onFilterEnvSustainChanged()
last.FilterEnvSustain = FilterEnvSustain
setParameterOfZones("DCFSusOffset", FilterEnvSustain)
end
-- define parameters for filter envelope offsets
defineParameter("FilterEnvAttack", "Filter Envelope Attack", 0, 0, 100, 0.1, onFilterEnvAttackChanged)
defineParameter("FilterEnvSustain", "Filter Envelope Sustain", 0, 0, 100, 0.1, onFilterEnvSustainChanged)
-- parameter change callbacks for the amplifier parameters
function onAmpVelChanged()
last.AmpVelocity = AmpVelocity
setParameterOfZones("Amp Env.VelocityToLevel", AmpVelocity)
end
-- define parameters for the amplifier section
defineParameter("AmpVelocity", "Amp Velocity", 100, 0, 100, onAmpVelChanged)
-- parameter change callbacks for amplifier envelope offsets
function onAmpEnvAttackChanged()
last.AmpEnvAttack = AmpEnvAttack
setParameterOfZones("DCAAttOffset", AmpEnvAttack)
end
function onAmpEnvSustainChanged()
last.AmpEnvSustain = AmpEnvSustain
setParameterOfZones("DCASusOffset", AmpEnvSustain)
end
-- define parameters for amplifier envelope offsets
defineParameter("AmpEnvAttack", "Amp Envelope Attack", 0, 0, 100, 0.1, onAmpEnvAttackChanged)
defineParameter("AmpEnvSustain", "Amp Envelope Sustain", 100, 0, 100, 0.1, onAmpEnvSustainChanged)
-- parameter change callbacks for the user envelope parameters
function onUserEnvVelChanged()
last.UserEnvVelocity = UserEnvVelocity
setParameterOfZones("User Env.VelocityToLevel", UserEnvVelocity)
end
function onUserEnvAttackChanged()
last.UserEnvAttack = UserEnvAttack
setParameterOfZones("UserAttOffset", UserEnvAttack)
end
function onUserEnvLevel0Changed()
last.UserEnvLevel0 = UserEnvLevel0
setParameterOfZones("UserL0Offset", UserEnvLevel0 * 0.5)
end
function onUserEnvLevel1Changed()
last.UserEnvLevel1 = UserEnvLevel1
setParameterOfZones("UserL1Offset", UserEnvLevel1 * 0.5)
end
function onUserEnvSustainChanged()
last.UserEnvSustain = UserEnvSustain
setParameterOfZones("UserSusOffset", UserEnvSustain * 0.5)
end
function onUserEnvLevelRChanged()
last.UserEnvLevelR = UserEnvLevelR
setParameterOfZones("UserLROffset", UserEnvLevelR * 0.5)
end
-- define parameters for the user envelope
defineParameter("UserEnvVelocity", "User Envelope Velocity", 0, 0, 100, 0.1, onUserEnvVelChanged)
defineParameter("UserEnvAttack", "User Envelope Attack", 0, 0, 100, 0.1, onUserEnvAttackChanged)
defineParameter("UserEnvLevel0", "User Envelope Start Level", 0, -100, 100, 0.1, onUserEnvLevel0Changed)
defineParameter("UserEnvLevel1", "User Envelope Attack Level", 0, -100, 100, 0.1, onUserEnvLevel1Changed)
defineParameter("UserEnvSustain", "User Envelope Sustain Level", 0, -100, 100, 0.1, onUserEnvSustainChanged)
defineParameter("UserEnvLevelR", "User Envelope Release Level", 0, -100, 100, 0.1, onUserEnvLevelRChanged)
-- function for setting the LFO sync mode
function setLfoSyncMode(lfo, LfoSync, LfoSyncMode)
if LfoSync then
if LfoSyncMode == 1 then
lfo:setParameter("Trigger", 0)
lfo:setParameter("Sync", 2)
elseif LfoSyncMode == 2 then
lfo:setParameter("Trigger", 1)
lfo:setParameter("Sync", 1)
else
lfo:setParameter("Trigger", 2)
lfo:setParameter("Sync", 1)
end
else
lfo:setParameter("Trigger", 0)
lfo:setParameter("Sync", 0)
end
end
-- parameter change callbacks for LFO A and B
function onLfoASyncModeChanged()
local lfo = this.parent:getChild("LFO A")
if lfo then
setLfoSyncMode(lfo, LfoASync, LfoASyncMode)
end
end
function onLfoBSyncModeChanged()
local lfo = this.parent:getChild("LFO B")
if lfo then
setLfoSyncMode(lfo, LfoBSync, LfoBSyncMode)
end
end
-- names of the LFO sync modes
defineSlotLocal("syncModeNames")
syncModeNames = { "Beat", "First", "Each" }
-- define parameters for the LFO section
defineParameter("LfoASync", "LFO A Sync", false, onLfoASyncModeChanged)
defineParameter("LfoASyncMode", "LFO A Sync Mode", 1, syncModeNames, onLfoASyncModeChanged)
defineParameter("LfoBSync", "LFO B Sync", false, onLfoBSyncModeChanged)
defineParameter("LfoBSyncMode", "LFO B Sync Mode", 1, syncModeNames, onLfoBSyncModeChanged)
-- functions for assigning the modulation sources
function setSource(row, source, polarity, smoothing, sourceIndex, sourceExtra1, sourceExtra2)
if source == 1 then
row:setSource1(sourceIndex, sourceExtra1, sourceExtra2)
row:setParameter("Source1.Polarity", polarity)
row:setParameter("Source1.Smoothing", smoothing)
else
row:setSource2(sourceIndex, sourceExtra1, sourceExtra2)
row:setParameter("Source2.Polarity", polarity)
row:setParameter("Source2.Smoothing", smoothing)
end
end
function assignStandardSource(row, source, polarity, smoothing, sourceIndex)
setSource(row, source, polarity, smoothing, sourceIndex)
end
function assignLfoA(row, source, polarity, smoothing)
local lfoA = this.parent:getMidiModule("LFO A")
if lfoA then
setSource(row, source, polarity, smoothing, ModulationSource.modulationModule, lfoA)
else
setSource(row, source, polarity, smoothing, ModulationSource.unassigned)
end
end
function assignLfoB(row, source, polarity, smoothing)
local lfoB = this.parent:getMidiModule("LFO B")
if lfoB then
setSource(row, source, polarity, smoothing, ModulationSource.modulationModule, lfoB)
else
setSource(row, source, polarity, smoothing, ModulationSource.unassigned)
end
end
function assignQC(row, source, polarity, smoothing, qcIndex)
setSource(row, source, polarity, smoothing, ModulationSource.quickControl, this.parent, qcIndex)
end
function assignMidiCtrl(row, source, polarity, smoothing, sourceIndex)
setSource(row, source, polarity, smoothing, ModulationSource.midiControl, sourceIndex)
end
-- define modulation sources
defineSlotLocal("modSources")
modSources = {
{ name = "-", assignFunc = assignStandardSource, index = ModulationSource.unassigned, bipolar = 0, smoothing = -1 },
{ name = "LFO A", assignFunc = assignLfoA, bipolar = 1, smoothing = -1 },
{ name = "LFO B", assignFunc = assignLfoB, bipolar = 1, smoothing = -1 },
{ name = "Amp Envelope", assignFunc = assignStandardSource, index = ModulationSource.ampEnv, bipolar = 0, smoothing = -1 },
{ name = "Filter Envelope", assignFunc = assignStandardSource, index = ModulationSource.filterEnv, bipolar = 0, smoothing = -1 },
{ name = "Env3", assignFunc = assignStandardSource, index = ModulationSource.userEnv, bipolar = 1, smoothing = -1 },
{ name = "Key Follow", assignFunc = assignStandardSource, index = ModulationSource.keyFollow, bipolar = 1, smoothing = -1 },
{ name = "Note-on Velocity", assignFunc = assignStandardSource, index = ModulationSource.noteOnVelocity, bipolar = 0, smoothing = -1 },
{ name = "Note-on Vel Squared", assignFunc = assignStandardSource, index = ModulationSource.noteOnVelocitySquared, bipolar = 0, smoothing = -1 },
{ name = "Pitch Bend", assignFunc = assignStandardSource, index = ModulationSource.pitchBend, bipolar = 1, smoothing = -1 },
{ name = "Modulation Wheel", assignFunc = assignStandardSource, index = ModulationSource.modWheel, bipolar = 0, smoothing = -1 },
{ name = "Aftertouch", assignFunc = assignStandardSource, index = ModulationSource.aftertouch, bipolar = 0, smoothing = -1 },
{ name = "Arp Controller 1", assignFunc = assignMidiCtrl, index = 110, bipolar = 0, smoothing = 0 },
{ name = "Arp Controller 2", assignFunc = assignMidiCtrl, index = 111, bipolar = 0, smoothing = 0 },
{ name = "Arp Controller 3", assignFunc = assignMidiCtrl, index = 112, bipolar = 0, smoothing = 0 },
{ name = "Bus 1", assignFunc = assignStandardSource, index = ModulationSource.bus1, bipolar = 1, smoothing = -1 },
{ name = "Bus 2", assignFunc = assignStandardSource, index = ModulationSource.bus2, bipolar = 1, smoothing = -1 },
{ name = "Bus 3", assignFunc = assignStandardSource, index = ModulationSource.bus3, bipolar = 1, smoothing = -1 },
{ name = "Bus 4", assignFunc = assignStandardSource, index = ModulationSource.bus4, bipolar = 1, smoothing = -1 },
{ name = "Bus 5", assignFunc = assignStandardSource, index = ModulationSource.bus5, bipolar = 1, smoothing = -1 },
{ name = "Bus 6", assignFunc = assignStandardSource, index = ModulationSource.bus6, bipolar = 1, smoothing = -1 },
{ name = "Bus 7", assignFunc = assignStandardSource, index = ModulationSource.bus7, bipolar = 1, smoothing = -1 },
{ name = "Bus 8", assignFunc = assignStandardSource, index = ModulationSource.bus8, bipolar = 1, smoothing = -1 },
{ name = "Quick Control 1", assignFunc = assignQC, index = 1, bipolar = 1, smoothing = -1 },
{ name = "Quick Control 2", assignFunc = assignQC, index = 2, bipolar = 1, smoothing = -1 },
{ name = "Quick Control 3", assignFunc = assignQC, index = 3, bipolar = 1, smoothing = -1 },
{ name = "Quick Control 4", assignFunc = assignQC, index = 4, bipolar = 1, smoothing = -1 },
{ name = "Quick Control 5", assignFunc = assignQC, index = 5, bipolar = 1, smoothing = -1 },
{ name = "Quick Control 6", assignFunc = assignQC, index = 6, bipolar = 1, smoothing = -1 },
{ name = "Quick Control 7", assignFunc = assignQC, index = 7, bipolar = 1, smoothing = -1 },
{ name = "Quick Control 8", assignFunc = assignQC, index = 8, bipolar = 1, smoothing = -1 }
}
-- create table with mod source names
function getModSrcNames()
modSrcNames = {}
for i=1, #modSources do
modSrcNames[i] = modSources[i].name
end
end
getModSrcNames()
-- parameter change callback to set the modulation source
function onModSourceChanged(row, source, modSourceParam)
local modSource = modSources[modSourceParam]
local zones = this.parent:getLayer():findZones()
for i, zone in pairs(zones) do
modSource.assignFunc(zone:getModulationMatrixRow(row), source, modSource.bipolar, modSource.smoothing, modSource.index)
end
end
defineSlotLocal("mmParameterInfo")
mmParameterInfo =
{
default = 1,
automatable = false,
strings = modSrcNames
}
-- define parameters for modulation matrix rows
for i = 1, 16 do
mmParameterInfo.name = "ModSource"..i
mmParameterInfo.longName = "Modulation Source "..i
mmParameterInfo.onChanged = function() onModSourceChanged(i, 1, _G["ModSource"..i]) end
defineParameter(mmParameterInfo)
mmParameterInfo.name = "ModModifier"..i
mmParameterInfo.longName = "Modulation Modifier "..i
mmParameterInfo.onChanged = function() onModSourceChanged(i, 2, _G["ModModifier"..i]) end
defineParameter(mmParameterInfo)
end
-- define modulation destinations
defineSlotLocal("modDestinations")
modDestinations = {
{ name = "-", index = ModulationDestination.unassigned },
{ name = "Pitch", index = ModulationDestination.pitch },
{ name = "Cutoff", index = ModulationDestination.cutoff },
{ name = "Resonance", index = ModulationDestination.resonance },
{ name = "Distortion", index = ModulationDestination.distortion },
{ name = "Level", index = ModulationDestination.level },
{ name = "Volume", index = ModulationDestination.volume1 },
{ name = "Pan", index = ModulationDestination.pan },
{ name = "Amp Env Attack", index = ModulationDestination.ampEnvAttack },
{ name = "Amp Env Decay", index = ModulationDestination.ampEnvDecay },
{ name = "Amp Env Sustain", index = ModulationDestination.ampEnvSustain },
{ name = "Amp Env Release", index = ModulationDestination.ampEnvRelease },
{ name = "Filter Env Attack", index = ModulationDestination.filterEnvAttack },
{ name = "Filter Env Decay", index = ModulationDestination.filterEnvDecay },
{ name = "Filter Env Sustain", index = ModulationDestination.filterEnvSustain },
{ name = "Filter Env Release", index = ModulationDestination.filterEnvRelease },
{ name = "Env3 Start Level", index = ModulationDestination.userEnvStartLev },
{ name = "Env3 Attack", index = ModulationDestination.userEnvAttack },
{ name = "Env3 Attack Level", index = ModulationDestination.userEnvAttLev },
{ name = "Env3 Decay", index = ModulationDestination.userEnvDecay },
{ name = "Env3 Sustain", index = ModulationDestination.userEnvSustain },
{ name = "Env3 Release", index = ModulationDestination.userEnvRelease },
{ name = "Env3 Release Level", index = ModulationDestination.userEnvRelLev },
{ name = "Bus 1", index = ModulationDestination.bus1 },
{ name = "Bus 2", index = ModulationDestination.bus2 },
{ name = "Bus 3", index = ModulationDestination.bus3 },
{ name = "Bus 4", index = ModulationDestination.bus4 },
{ name = "Bus 5", index = ModulationDestination.bus5 },
{ name = "Bus 6", index = ModulationDestination.bus6 },
{ name = "Bus 7", index = ModulationDestination.bus7 },
{ name = "Bus 8", index = ModulationDestination.bus8 }
}
-- create table with the names of the modulation destinations
function getModDestNames()
modDestNames = {}
for i=1, #modDestinations do
modDestNames[i] = modDestinations[i].name
end
end
getModDestNames()
-- parameter change callback to set the modulation destination
function onModDestChanged(row, modDestinationParam)
local modDestination = modDestinations[modDestinationParam]
local zones = this.parent:getLayer():findZones()
for i, zone in pairs(zones) do
zone:getModulationMatrixRow(row):setParameter("Destination.Destination", modDestination.index)
end
end
mmParameterInfo.strings = modDestNames
-- define parameters for modulation matrix rows
for i = 1, 16 do
mmParameterInfo.name = "ModDestination"..i
mmParameterInfo.longName = "Modulation Destination "..i
mmParameterInfo.onChanged = function() onModDestChanged(i, _G["ModDestination"..i]) end
defineParameter(mmParameterInfo)
end
-- define parameters for arpeggiator controller lane destinations
for i = 1, 3 do
mmParameterInfo.name = "CtrlLane"..i.."Dest"
mmParameterInfo.longName = "Ctrl Lane "..i.." Destination"
mmParameterInfo.onChanged = function() onModDestChanged(16 + i, _G["CtrlLane"..i.."Dest"]) end
defineParameter(mmParameterInfo)
end
--[[
verify some parameters for being updated by automation/QC
(QC relative changes don't produce a change notification because the document isn't changed)
Relying on the document update has idle timing for absolute changes, so might not be fast enough
--]]
function verifyParam(name, callback)
if last[name] ~= _G[name] then
callback()
end
end
function onNote(ev)
verifyParam("PitchRandom", onPitchRandomChanged)
verifyParam("FilterVelocity", onFilterVelChanged)
verifyParam("FilterEnvAttack", onFilterEnvAttackChanged)
verifyParam("FilterEnvSustain", onFilterEnvSustainChanged)
verifyParam("AmpVelocity", onAmpVelChanged)
verifyParam("AmpEnvAttack", onAmpEnvAttackChanged)
verifyParam("AmpEnvSustain", onAmpEnvSustainChanged)
verifyParam("UserEnvVelocity", onUserEnvVelChanged)
verifyParam("UserEnvAttack", onUserEnvAttackChanged)
verifyParam("UserEnvLevel0", onUserEnvLevel0Changed)
verifyParam("UserEnvLevel1", onUserEnvLevel1Changed)
verifyParam("UserEnvSustain", onUserEnvSustainChanged)
verifyParam("UserEnvLevelR", onUserEnvLevelRChanged)
postEvent(ev)
end
This should do the loading of layer presets. It doesn’t copy the state of the parameters though.
-- load handling
-- selectedPath and selectedPreset should not appear in the undo history,
-- so we make them non-persistent, but save and restore them explicitly with
-- onSave and onLoad
defineParameter{name = "selectedPath", default = "", onChanged = function() onSelectPath() end, persistent = false, automatable = false}
defineParameter{name = "selectedPreset", default = "", persistent = false, automatable = false}
function onSave()
return { selectedPath = selectedPath, selectedPreset = selectedPreset }
end
function onLoad(data)
if type(data) == "table" then
-- beware of old tables still filled with other entries
if data.selectedPath then
selectedPath = data.selectedPath
end
if data.selectedPreset then
selectedPreset = data.selectedPreset
end
end
end
function onUndo()
-- print("onUndo: updatePreset = ", undoInfo.updatePreset)
if undoInfo.updatePreset then
local layer = this.parent:getLayer()
if layer then
selectedPreset = layer.name
end
end
end
-- pseudo parameter to add a callback into the undo group for replacing the sample layer
defineParameter{name = "undoInfo", default = {}, onChanged = onUndo, automatable = false}
function loadFinished(currentProgressInfo)
if currentProgressInfo.root then
startUndoBlock("Load Layer " .. currentProgressInfo.root.name)
undoInfo = { updatePreset = true }
this:setParameter("undoInfo", { updatePreset = false }, true)
local layer = this.parent:getLayer()
this.parent:appendLayer(currentProgressInfo.root)
if layer then
this.parent:removeLayer(layer)
end
undoInfo = { updatePreset = false }
this:setParameter("undoInfo", { updatePreset = true }, true)
endUndoBlock()
end
end
function onSelectPath()
loadPresetAsync(selectedPath, loadFinished)
end
Sample Selector.zip (13.8 KB)
The same thing happens
it works correctly without the macro page like the other one, at the moment I add the macro page I get the same error of
Parameter change callback selectedPath = data: cannot resume non-suspended coroutine
Now I don’t understand anything
The layer presets you want to load, do they have any parameters connected to macro page?
I haven’t tested this thoroughly so I’m not sure if this is the case but when you load new preset the controls on macro page might still refer to the layer preset that has been removed. This could cause problems. If you look at the Hot Brass instrument all macro page controls are connected to script parameters which in turn handle the parameters of the loaded layer.
Edit
It looks like it’s working if the layer preset doesn’t have its own macro page.
(Which is what you found out already. )
If it does then it crashes. Sometimes I was able to load 2 or 3 presets but then it eventually crashed with “serious error…” message.
Hello, I hook up to the interesting topic.
loadPresetAsync script on this page loadPresetAsync - HALion Script - Steinberg Developer Help or similar script, could be good a good choice and easy to apply.
But I don’t know if it is only a my problem, when I reload a saved preset with a “replace layer” function, Halion crash. It is very frustrating…
I use Mac OSX.
thanks
If you look at the Hot Brass instrument all macro page controls are connected to script parameters which in turn handle the parameters of the loaded lay
If it seems that everything has to go in the script, if it doesn’t break, I’m going to have to discard this
thanks for everything as always
But I don’t know if it is only a my problem, when I reload a saved preset with a “replace layer” function, Halion crash. It is very frustrating…
If layers are a part of an instrument and are connected to a macro page it is not possible to exchange, delete or move them. Those issues cannot be solved by HALion. You have to remove all connections first before you exchange any layer
A question for misohoza
your layer selection script that does exactly.
Do you mutate the layers minus the selected one or are you doing the same thing as the MIDI layer mute parameter?
The parameter I am referring to is that of Photo 1.
it seems that this 2 option would cut the midi shot and the voice would not be reproduced and the performance would improve.
layers = this.parent:findLayers()
function getLayerNames()
layerNames = {}
for i, layer in ipairs(layers) do
layerNames[i] = layer.name
end
end
getLayerNames()
defineParameter("LayerSelect", nil, 1, layerNames)
function onNote(event)
playNote(event.note, event.velocity, -1, layers[LayerSelect])
end
No, I’m not using the Layer Midi Mute parameter. Although this is also an option.
Play note function has optional arguments. You can choose which layer or zone should receive the midi message.
Now that Halion 6.4 is out you could try it again to see if it still crashes when loading layers.
Now that Halion 6.4 is out you could try it again to see if it still crashes when loading layers.
I have to discard the option to load layers, because there is a layer that always has to be available (it is the one of the script that you made of importing sampler).
Play note function has optional arguments. You can choose which layer or zone should receive the midi message.
if I can understand this a bit because as I said my knowledge of programming are bad, bad
Does this function send midi to the selected layer?
function onNote (event)
playNote (event.note, event.velocity, -1, layers [LayerSelect])
end
Now I have to do another function that sets the layer midi mute parameter to “on” in all layers except the selected one, right? or I just have no idea
Well, yes if you want to do it with LayerMidiMute parameter.
layers = this.parent:findLayers()
function getLayerNames()
layerNames = {}
for i, layer in ipairs(layers) do
layerNames[i] = layer.name
end
end
getLayerNames()
function layerSelectChanged()
for i = 1, #layers do
local layer = layers[i]
if i == LayerSelect then
layer:setParameter("LayerMidiMute", false)
else
layer:setParameter("LayerMidiMute", true)
end
end
end
defineParameter("LayerSelect", nil, 1, layerNames, layerSelectChanged)
layerSelectChanged()
thank you very much misohoza, you are the boss
ohhhh … there is a problem with the script, when you save a preset and reload it, the macro shows the saved layer, but the one that sounds is always the first layer, not the saved layer
Put the last line inside the onLoad callback.
function onLoad()
layerSelectChanged()
end
Or delete the last line altogether.
The purpose of that line is to make sure that only the selected layer is unmuted. But it looks like it’s executed before the correct parameter value is loaded.
Perfect