Help to modify Mod Matrix Script

Hello,
I’m new in building instruments and don’t know anything about scripting. So I search and found some good ones that I need.
Now I’m on it to modify them as it is possible for me.

I found that script and modify the Source and Destination. Now I got a long list (Picture 1) but I like to have it more organized (Picture 2).
How can I do that?

Here is the Script:

-- 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 assignLFO3(row, source, polarity, smoothing)
  local LFO3 = this.parent:getMidiModule("LFO 3") -- needs to match midi module name
  if LFO3 then
    setSource(row, source, polarity, smoothing, ModulationSource.modulationModule, LFO1)
  else
    setSource(row, source, polarity, smoothing, ModulationSource.unassigned)
  end
end

function assignLFO4(row, source, polarity, smoothing)
  local LFO4 = this.parent:getMidiModule("LFO 4")
  if LFO4 then
    setSource(row, source, polarity, smoothing, ModulationSource.modulationModule, LFO4)
  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.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 1", 			assignFunc = assignStandardSource, index = ModulationSource.lfo1, bipolar = 0, smoothing = -1 },
  { name = "LFO 2", 			assignFunc = assignStandardSource, index = ModulationSource.lfo2, bipolar = 0, 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 = "Envelope 3", 		assignFunc = assignStandardSource, index = ModulationSource.userEnv, bipolar = 0, smoothing = -1 },
  { name = "Modulation Wheel", 	assignFunc = assignStandardSource, index = ModulationSource.modWheel, bipolar = 0, smoothing = -1 },
  { name = "Pitch Bend", 			assignFunc = assignStandardSource, index = ModulationSource.pitchBend, bipolar = 1, smoothing = -1 },
  { name = "Aftertouch",		assignFunc = assignStandardSource, index = ModulationSource.aftertouch, bipolar = 1, smoothing = -1 },
  { name = "Bus 1", 				assignFunc = assignStandardSource, index = ModulationSource.bus1, 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:findZones(true)
  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 1", 			index = ModulationDestination.volume1   },
  { name = "Volume 2", 			index = ModulationDestination.volume2   },
  { 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 = "Osc 1 Pitch", 	index = ModulationDestination.osc1Pitch   },
{ name = "Osc 1 Level", 	index = ModulationDestination.osc1Level   },
{ name = "Osc 1 Waveform", 	index = ModulationDestination.osc1Waveform   },
{ name = "Osc 1 Multi Detune", 	index = ModulationDestination.osc1MultiDetune   },
{ name = "Osc 1 Multi Pan", 	index = ModulationDestination.osc1MultiPan   },
{ name = "Osc 1 Multi Voices", 	index = ModulationDestination.osc1MultiVoices   },
{ name = "Osc 2 Pitch", 	index = ModulationDestination.osc2Pitch   },
{ name = "Osc 2 Level", 	index = ModulationDestination.osc2Level   },
{ name = "Osc 2 Waveform", 	index = ModulationDestination.osc2Waveform   },
{ name = "Osc 2 Multi Detune", 	index = ModulationDestination.osc2MultiDetune   },
{ name = "Osc 2 Multi Pan", 	index = ModulationDestination.osc2MultiPan   },
{ name = "Osc 2 Multi Voices", 	index = ModulationDestination.osc2MultiVoices   },
{ name = "Osc 3 Pitch", 	index = ModulationDestination.osc3Pitch   },
{ name = "Osc 3 Level", 	index = ModulationDestination.osc3Level   },
{ name = "Osc 3 Waveform", 	index = ModulationDestination.osc3Waveform   },
{ name = "Osc 3 Multi Detune", 	index = ModulationDestination.osc3MultiDetune   },
{ name = "Osc 3 Multi Pan", 	index = ModulationDestination.osc3MultiPan   },
{ name = "Osc 3 Multi Voices", 	index = ModulationDestination.osc3MultiVoices   },
{ name = "Noise Level", 	index = ModulationDestination.noiseLevel   },
{ name = "LFO 1 Shape", 	index = ModulationDestination.lfo1Shape   },
{ name = "LFO 2 Shape", 	index = ModulationDestination.lfo2Shape   },
}

-- 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:findZones(true)
  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

I also like to add to the destination the LFO1/2 Frequency, Sub Osc Level and Ring Mod Level. I tried to add it like the others but I got errors.
Thanks for help!


You could do it like this:

-- 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 assignLFO1(row, source, polarity, smoothing)
  local LFO1 = this.parent:getMidiModule("LFO 1") -- needs to match midi module name
  if LFO1 then
    setSource(row, source, polarity, smoothing, ModulationSource.modulationModule, LFO1)
  else
    setSource(row, source, polarity, smoothing, ModulationSource.unassigned)
  end
end

function assignLFO2(row, source, polarity, smoothing)
  local LFO2 = this.parent:getMidiModule("LFO 2")
  if LFO2 then
    setSource(row, source, polarity, smoothing, ModulationSource.modulationModule, LFO2)
  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/LFO 1", 			assignFunc = assignLFO1, index = ModulationSource.modulationModule, bipolar = 1, smoothing = -1 },
  { name = "/LFO/LFO 2", 			assignFunc = assignLFO2, index = ModulationSource.modulationModule, bipolar = 1, smoothing = -1 },
  { name = "/Modulation Wheel", 	assignFunc = assignStandardSource, index = ModulationSource.modWheel, bipolar = 0, smoothing = -1 },
  { name = "/Amp Envelope", 		assignFunc = assignStandardSource, index = ModulationSource.ampEnv, bipolar = 0, smoothing = -1 },
  { name = "/Pitch Bend", 			assignFunc = assignStandardSource, index = ModulationSource.pitchBend, bipolar = 1, smoothing = -1 },
  { name = "/Bus/Bus 1", 				assignFunc = assignStandardSource, index = ModulationSource.bus1, bipolar = 1, smoothing = -1 },
  { name = "/Bus/Bus 2", 				assignFunc = assignStandardSource, index = ModulationSource.bus2, bipolar = 1, smoothing = -1 },
  { name = "/Bus/Bus 3", 				assignFunc = assignStandardSource, index = ModulationSource.bus3, bipolar = 1, smoothing = -1 },
  { name = "/Bus/Bus 4", 				assignFunc = assignStandardSource, index = ModulationSource.bus4, bipolar = 1, smoothing = -1 },
  { name = "/Bus/Bus 5", 				assignFunc = assignStandardSource, index = ModulationSource.bus5, bipolar = 1, smoothing = -1 },
  { name = "/Bus/Bus 6", 				assignFunc = assignStandardSource, index = ModulationSource.bus6, bipolar = 1, smoothing = -1 },
  { name = "/Bus/Bus 7", 				assignFunc = assignStandardSource, index = ModulationSource.bus7, bipolar = 1, smoothing = -1 },
  { name = "/Bus/Bus 8", 				assignFunc = assignStandardSource, index = ModulationSource.bus8, bipolar = 1, smoothing = -1 },
  { name = "/Quick Control/Quick Control 1",		assignFunc = assignQC, index = 1, bipolar = 1, smoothing = -1 },
  { name = "/Quick Control/Quick Control 2",		assignFunc = assignQC, index = 2, bipolar = 1, smoothing = -1 },
  { name = "/Quick Control/Quick Control 3",		assignFunc = assignQC, index = 3, bipolar = 1, smoothing = -1 },
  { name = "/Quick Control/Quick Control 4",		assignFunc = assignQC, index = 4, bipolar = 1, smoothing = -1 },
  { name = "/Quick Control/Quick Control 5",		assignFunc = assignQC, index = 5, bipolar = 1, smoothing = -1 },
  { name = "/Quick Control/Quick Control 6",		assignFunc = assignQC, index = 6, bipolar = 1, smoothing = -1 },
  { name = "/Quick Control/Quick Control 7",		assignFunc = assignQC, index = 7, bipolar = 1, smoothing = -1 },
  { name = "/Quick Control/Quick Control 8",		assignFunc = assignQC, index = 8, bipolar = 1, smoothing = -1 },
  { name = "/Arp Controller 1", 	assignFunc = assignMidiCtrl, index = 110, bipolar = 0, smoothing = 0 },
}

-- create table with mod source names
function getModSrcNames()
  modSrcNames = {}
  modSrcNamesText = {}
  for i=1, #modSources do
    modSrcNames[i] = modSources[i].name
    modSrcNamesText[i] = string.match(modSources[i].name, "[^/]+$")
  end
end

getModSrcNames()

-- parameter change callback to set the modulation source
function onModSourceChanged(row, source, modSourceParam)
  if source == 1 then
    _G["ModSourceText"..row] = modSourceParam
  else
    _G["ModModifierText"..row] = modSourceParam
  end
  local modSource = modSources[modSourceParam]
  local zones = this.parent:findZones(true)
  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

mmParameterInfo.strings = modSrcNamesText
for i = 1, 16 do
  mmParameterInfo.name = "ModSourceText"..i
  defineParameter(mmParameterInfo)  


  mmParameterInfo.name = "ModModifierText"..i
  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 = "/Morph X",				index = ModulationDestination.morphX},
  { name = "/Morph Y",				index = ModulationDestination.morphY	},
  { name = "/Level", 				index = ModulationDestination.level    },
  { name = "/Volume 2", 			index = ModulationDestination.volume2   },
  { name = "/Pan", 				index = ModulationDestination.pan   },
  { name = "/Bus/Bus 1",  index = ModulationDestination.bus1},
  { name = "/Bus/Bus 2",  index = ModulationDestination.bus2},
  { name = "/Bus/Bus 3",  index = ModulationDestination.bus3},
  { name = "/Bus/Bus 4",  index = ModulationDestination.bus4},
  { name = "/Bus/Bus 5",  index = ModulationDestination.bus5},
  { name = "/Bus/Bus 6",  index = ModulationDestination.bus6},
  { name = "/Bus/Bus 7",  index = ModulationDestination.bus7},
  { name = "/Bus/Bus 8",  index = ModulationDestination.bus8},
}

-- create table with the names of the modulation destinations
function getModDestNames()
  modDestNames = {}
  modDestNamesText = {}
  for i=1, #modDestinations do
    modDestNames[i] = modDestinations[i].name
    modDestNamesText[i] = string.match(modDestinations[i].name, "[^/]+$")
  end
end

getModDestNames()

-- parameter change callback to set the modulation destination
function onModDestChanged(row, modDestinationParam)
  _G["ModDestinationText"..row] = modDestinationParam
  local modDestination = modDestinations[modDestinationParam]
  local zones = this.parent:findZones(true)
  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

mmParameterInfo.strings = modDestNamesText

for i = 1, 16 do
  mmParameterInfo.name = "ModDestinationText"..i
  defineParameter(mmParameterInfo)
end

You will need to adjust the macro page template as you will have different parameters for text and menu controls.

If you want to add more sources or destinations you have the list here: Modulation Source Types - HALion Script - Steinberg Developer Help
Modulation Matrix Template 2.zip (11.4 KB)

Hi Misohoza,
thank you, that is what I’m looking for. But after I copied it to my Template for testing (the Script for the Programm Tree, the Script for the Macro Page in the GUI Tree and the Variables) now there is the whole Text in the Menu after choosing (see Pic).
Is there something I have forgotten?
Example Row.jpg

You need to adjust the macro page template. You have different parameters for the menu controls and different for the text. Check the example preset.

I checked the template and trie to find out, what is missing. For better understanding I’ve made some screenshots and subscribed what I have done.

Did you edit the modulation row template?

For modulation sources and destinations it’s using a menu template. Menu template has menu and text controls. You need to export those separately.


Aha, I did not know that I have to do this, now it’s working. Thank you very much. But now I’m getting confused again, becaus now I have 2 Parameters selectet in the source (see Pic). What will be next?
Source.jpg

Yes, I have noticed that too. It should be selecting the correct values but the check marks are wrong. Maybe a little bug.

Can you use a menu that doesn’t show check marks?

I can look for another Menu, know I put all in different Groups - (Env to Env, Mod/Pitch/Aftertouch to Wheel) and it’s O.K.