HISE Logo Forum
    • Categories
    • Register
    • Login

    Multiple instruments, single project or multiple projects?

    Scheduled Pinned Locked Moved General Questions
    94 Posts 3 Posters 22.9k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • d.healeyD
      d.healey
      last edited by d.healey

      I'm struggling to find an efficient way to organise my preset handling script. I can see this being more suited to smaller instruments.

      So I have my woowind .hip file and I'd like the user to be able to change between all of the different woodwind instruments. There will be at least 10 instruments and each one will have 10 or more samplers that will need to have their sample maps swapped as the preset is selected. Each will also need it's key range setting, modulator settings adjusted, and various behind-the-scenes knobs adjusted on scripts.

      To hardcode all of this seems a very large task. I could add code to each script so that its values are stored in the userPresetData globals object (although it would be better if HISE did this anyway I think). But I will still have to write all of the sample maps into code, and if I want to add new sample maps I will have to edit the code again. Is there a more generic and automated way to populate the userPresetData object?

      Libre Wave - Freedom respecting instruments and effects
      My Patreon - HISE tutorials
      YouTube Channel - Public HISE tutorials

      1 Reply Last reply Reply Quote 0
      • d.healeyD
        d.healey
        last edited by

        What I'm finding is that by using the global user_preset_array idea I'm essentially building my own preset system for the instrument that works independently of the actual HISE preset system which seems a bit backwards to me. The only purpose of the HISE preset system becomes to change a combo box value. Is there no way the preset system could just take a snapshot of all of the controls, loaded sample maps, and the bypass state of samplers/modulators/etc. and then restore it when the preset is selected? This seems far more practical in the long term than having to construct this functionality individually for each instrument.

        Libre Wave - Freedom respecting instruments and effects
        My Patreon - HISE tutorials
        YouTube Channel - Public HISE tutorials

        1 Reply Last reply Reply Quote 0
        • Christoph HartC
          Christoph Hart
          last edited by Christoph Hart

          I'll have to disagree with you here. The idea of the preset system is to store snapshots of the main interface so that it recalls the controls. If your library allows to select different instruments that swap out multiple sample maps and adjust modulators and key ranges, then this is something you have to add to a combobox anyway.

          On the other hand, adding support for changing modulators behind the scenes or swapping out sample maps for samplers directly opens up a parallel world which is disconnected from the main interface - do you get what I mean?

          You might be able to reduce the complexity by generating the sample map IDs dynamically (which requires a consistent naming, but we'll agree that this is good to have anyway). Let's say you have :

          • a trombone
          • a trumpet
          • a flute
          • a clarinet

          and each instrument uses sustain, release, staccato and portato samples.

          then you could do something like this:

          const var instrumentNames = ["Trombone", "Trumpet", "Flute", "Clarinet"];
          const var articulations = ["Sustain", "Release", "Staccato", "Portato"];
          const var hasPortato = [true, true, false, true];
          const var keyRanges = [[40, 80], [43, 80], [56, 90], [50, 93]];
          
          sustainSampler = Synth.getSampler( articulations[0]);
          releaseSampler = Synth.getSampler( articulations[1]);
          staccatoSampler = Synth.getSampler(articulations[2]);
          portatoSampler = Synth.getSampler( articulations[3]);
          
          
          inline function loadInstrument(i)
          {
              sustainSampler.loadSampleMap(instrumentNames[i] + "_" + articulations[0]);
              releaseSampler.loadSampleMap(instrumentNames[i] + "_" + articulations[1]);
              staccatoSampler.loadSampleMap(instrumentNames[i] + "_" + articulations[2]);
              portatoSampler.loadSampleMap(instrumentNames[i] + "_" + articulations[3]);
          
              portatoSampler.setBypassed(!hasPortato[i]);
              changeKeyRange(i);
          };
          
          inline function changeKeyRange(i)
          {
               // set the key colours for the given range in keyRanges[i]
          }
          
          

          In the onControl callback of the combobox you just have to call loadInstrument(value). The amount of needed strings is reduced from 16 to 8 here (and in your actual use case it would be 100 Strings vs. 20). Also, this collects all information into nicely readable arrays at the beginning of your script.

          1 Reply Last reply Reply Quote 1
          • d.healeyD
            d.healey
            last edited by

            Thanks, this makes it look a bit simpler and gives me an idea. I don't like having to hard code the sample map names, but what I'm thinking is if I gave the sample maps the same names as the containers and or samplers that they are to be used in then that would allow the .hip to be used for more instruments without having to keep editing the code. I could just read from the various module names.

            Libre Wave - Freedom respecting instruments and effects
            My Patreon - HISE tutorials
            YouTube Channel - Public HISE tutorials

            1 Reply Last reply Reply Quote 0
            • d.healeyD
              d.healey
              last edited by

              It seems like the group XF setup isn't saved with the sample map so switching between a sample map with for example 3 xfade groups and one with 1 causes issues

              Libre Wave - Freedom respecting instruments and effects
              My Patreon - HISE tutorials
              YouTube Channel - Public HISE tutorials

              1 Reply Last reply Reply Quote 0
              • Christoph HartC
                Christoph Hart
                last edited by

                Yes this might be true (I didn't check yet, but on the other hand I didn't add support for this explicitely so it's likely to not work). I'll try to add this soon.

                1 Reply Last reply Reply Quote 1
                • d.healeyD
                  d.healey
                  last edited by

                  I've built a little test script that should allow me to save and load the state of all simple envelopes with the user preset. My plan is now to add all the other envelopes and modulators so this is the only script I'll need to use to save all of my preset data in my projects. Before I embark on this though I want to know if you think this is the most efficient way to do it or if there is a better way?

                  Also is there a way to iterate over all of the controls of a script? Currently I can go through each one as an attribute but I have to know in advance how many controls the script has, it would be nice if there was a way to loop through them without knowing what number the last control is so I could neatly get every control's value into an array.

                  <?xml version="1.0" encoding="UTF-8"?>
                  
                  <Processor Type="SynthChain" ID="presetSaveTest" Bypassed="0" Gain="1" Balance="0"
                             VoiceLimit="64" KillFadeTime="20" IconColour="0" packageName=""
                             views="32.rk1bzA.....C.........LDZg4lakwVL.....vp+++O" currentView="-1">
                    <EditorStates BodyShown="0" Visible="1" Solo="0" Folded="0" InterfaceShown="0"/>
                    <ChildProcessors>
                      <Processor Type="MidiProcessorChain" ID="Midi Processor" Bypassed="0">
                        <EditorStates BodyShown="1" Visible="1" Solo="0" Folded="0"/>
                        <ChildProcessors>
                          <Processor Type="ScriptProcessor" ID="Script Processor" Bypassed="0" Script="Content.makeFrontInterface(600, 250);&#13;&#10;&#13;&#10;// Create a storage panel, hide it, and save it in the preset&#13;&#10;const var storagePanel = Content.addPanel(&quot;storagePanel&quot;, 0, 0);&#13;&#10;storagePanel.set(&quot;visible&quot;, false);&#13;&#10;storagePanel.set(&quot;saveInPreset&quot;, true);&#13;&#10;&#13;&#10;// Create a global object that will hold the values for the other scripts.&#13;&#10;global userPresetData = {};&#13;&#10;&#13;&#10;// Set the global storage as widget value for the hidden panel.&#13;&#10;// Important: this will not clone the object, but share a reference!&#13;&#10;storagePanel.setValue(userPresetData);&#13;&#10;&#13;&#10;const var presetHandler = Synth.getMidiProcessor(&quot;presetHandler&quot;);function onNoteOn()&#10;{&#10;&#9;&#10;}&#10;function onNoteOff()&#10;{&#10;&#9;&#10;}&#10;function onController()&#10;{&#10;&#9;&#10;}&#10;function onTimer()&#10;{&#10;&#9;&#10;}&#10;function onControl(number, value)&#10;{&#10;&#9;if (number == storagePanel)&#13;&#10;&#9;{&#13;&#10;&#9;&#9;userPresetData = value;&#9;&#13;&#10;&#9;&#9;presetHandler.setAttribute(0, 1); //Trigger load preset button&#10;&#9;}&#10;}&#10;">
                            <EditorStates BodyShown="1" Visible="1" Solo="0" contentShown="1" onInitOpen="1"
                                          onNoteOnOpen="0" onNoteOffOpen="0" onControllerOpen="0" onTimerOpen="0"
                                          onControlOpen="0" Folded="0"/>
                            <ChildProcessors/>
                            <Content>
                              <Control type="ScriptPanel" id="storagePanel" value="JSON{&quot;modName&quot;: [4, 27, 0]}"/>
                            </Content>
                          </Processor>
                          <Processor Type="ScriptProcessor" ID="presetHandler" Bypassed="0" Script="//INIT&#10;&#10;Content.setHeight(50);&#10;&#10;const var btnLoad = Content.addButton(&quot;Load Preset&quot;, 150, 10);&#10;const var btnSave = Content.addButton(&quot;Save Preset&quot;, 0, 10);&#10;&#10;const var modNames = Synth.getIdList(&quot;Simple Envelope&quot;);&#10;const var simpleEnvelopes = [];&#10;&#10;for (modName in modNames)&#10;{&#10;&#9;simpleEnvelopes[modName] = Synth.getModulator(modName);&#10;}&#10;&#10;//FUNCTIONS&#10;inline function savePresetData()&#10;{&#10;&#9;reg mod;&#10;&#10;&#9;for (modName in simpleEnvelopes)&#10;&#9;{&#10;&#9;&#9;userPresetData.modName = [];&#10;&#9;&#9;userPresetData.modName[0] = simpleEnvelopes[modName].getAttribute(0);&#10;&#9;&#9;userPresetData.modName[1] = simpleEnvelopes[modName].getAttribute(1);&#10;&#9;&#9;userPresetData.modName[2] = simpleEnvelopes[modName].getAttribute(2);&#10;&#9;}&#10;}&#10;&#10;inline function loadPresetData()&#10;{&#10;&#9;reg mod;&#10;&#10;&#9;for (modName in simpleEnvelopes)&#10;&#9;{&#10;&#9;&#9;simpleEnvelopes[modName].setAttribute(0, userPresetData.modName[0]);&#10;&#9;&#9;simpleEnvelopes[modName].setAttribute(1, userPresetData.modName[1]);&#10;&#9;&#9;simpleEnvelopes[modName].setAttribute(2, userPresetData.modName[2]);&#10;&#9;}&#10;}&#10;&#10;//CALLBACKS&#10;function onNoteOn()&#10;{&#10;&#9;&#10;}&#10;function onNoteOff()&#10;{&#10;&#9;&#10;}&#10;function onController()&#10;{&#10;&#9;&#10;}&#10;function onTimer()&#10;{&#10;&#9;&#10;}&#10;function onControl(number, value)&#10;{&#10;&#9;if (number == btnLoad)&#10;&#9;{&#10;&#9;&#9;loadPresetData();&#10;&#9;&#9;number.setValue(0);&#10;&#9;}&#10;&#10;&#9;if (number == btnSave)&#10;&#9;{&#10;&#9;&#9;savePresetData();&#10;&#9;&#9;number.setValue(0);&#10;&#9;}&#10;}">
                            <EditorStates BodyShown="1" Visible="1" Solo="0" contentShown="1" onInitOpen="1"
                                          onNoteOnOpen="0" onNoteOffOpen="0" onControllerOpen="0" onTimerOpen="0"
                                          onControlOpen="0"/>
                            <ChildProcessors/>
                            <Content>
                              <Control type="ScriptButton" id="Load Preset" value="0"/>
                              <Control type="ScriptButton" id="Save Preset" value="0"/>
                            </Content>
                          </Processor>
                        </ChildProcessors>
                      </Processor>
                      <Processor Type="ModulatorChain" ID="GainModulation" Bypassed="0" Intensity="1">
                        <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                        <ChildProcessors/>
                      </Processor>
                      <Processor Type="ModulatorChain" ID="PitchModulation" Bypassed="1" Intensity="0">
                        <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                        <ChildProcessors/>
                      </Processor>
                      <Processor Type="EffectChain" ID="FX" Bypassed="0">
                        <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                        <ChildProcessors/>
                      </Processor>
                      <Processor Type="StreamingSampler" ID="Sampler" Bypassed="0" Gain="1" Balance="0"
                                 VoiceLimit="128" KillFadeTime="20" IconColour="0" PreloadSize="8192"
                                 BufferSize="4096" VoiceAmount="128" SamplerRepeatMode="0" RRGroupAmount="1"
                                 PitchTracking="1" OneShot="0" CrossfadeGroups="0" Purged="0"
                                 NumChannels="1" SampleMap="">
                        <EditorStates BodyShown="0" Visible="1" Solo="0" MapPanelShown="1" BigSampleMap="1"
                                      GainModulationShown="1" CrossfadeTableShown="0"/>
                        <ChildProcessors>
                          <Processor Type="MidiProcessorChain" ID="Midi Processor" Bypassed="0">
                            <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                            <ChildProcessors/>
                          </Processor>
                          <Processor Type="ModulatorChain" ID="GainModulation" Bypassed="0" Intensity="1">
                            <EditorStates BodyShown="1" Visible="1" Solo="0"/>
                            <ChildProcessors>
                              <Processor Type="SimpleEnvelope" ID="DefaultEnvelope" Bypassed="0" Intensity="1"
                                         Attack="4" Release="27" LinearMode="0">
                                <EditorStates BodyShown="1" Visible="1" Solo="0"/>
                                <ChildProcessors>
                                  <Processor Type="ModulatorChain" ID="Attack Time Modulation" Bypassed="0"
                                             Intensity="1">
                                    <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                    <ChildProcessors/>
                                  </Processor>
                                </ChildProcessors>
                              </Processor>
                            </ChildProcessors>
                          </Processor>
                          <Processor Type="ModulatorChain" ID="PitchModulation" Bypassed="0" Intensity="0">
                            <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                            <ChildProcessors/>
                          </Processor>
                          <Processor Type="EffectChain" ID="FX" Bypassed="0">
                            <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                            <ChildProcessors/>
                          </Processor>
                          <Processor Type="ModulatorChain" ID="Sample Start" Bypassed="0" Intensity="1">
                            <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                            <ChildProcessors/>
                          </Processor>
                          <Processor Type="ModulatorChain" ID="Group Fade" Bypassed="0" Intensity="1">
                            <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                            <ChildProcessors/>
                          </Processor>
                        </ChildProcessors>
                        <RoutingMatrix NumSourceChannels="2" Channel0="0" Send0="-1" Channel1="1" Send1="-1"/>
                        <channels>
                          <channelData enabled="1" level="0" suffix=""/>
                        </channels>
                        <samplemap ID="" SaveMode="0" RRGroupAmount="1" MicPositions=";"/>
                      </Processor>
                    </ChildProcessors>
                    <RoutingMatrix NumSourceChannels="2" Channel0="0" Send0="-1" Channel1="1" Send1="-1"/>
                    <macro_controls>
                      <macro name="Macro 1" value="0" midi_cc="-1"/>
                      <macro name="Macro 2" value="0" midi_cc="-1"/>
                      <macro name="Macro 3" value="0" midi_cc="-1"/>
                      <macro name="Macro 4" value="0" midi_cc="-1"/>
                      <macro name="Macro 5" value="0" midi_cc="-1"/>
                      <macro name="Macro 6" value="0" midi_cc="-1"/>
                      <macro name="Macro 7" value="0" midi_cc="-1"/>
                      <macro name="Macro 8" value="0" midi_cc="-1"/>
                    </macro_controls>
                    <MidiAutomation/>
                  </Processor>
                  

                  Libre Wave - Freedom respecting instruments and effects
                  My Patreon - HISE tutorials
                  YouTube Channel - Public HISE tutorials

                  1 Reply Last reply Reply Quote 0
                  • Christoph HartC
                    Christoph Hart
                    last edited by

                    There is also the exportState and restoreState methods which export the complete state of a Modulator / Effect (including Table values and child processors) into a encoded String that can be used to restore data:

                    This example has an LFO that is resetted using a previously exported String every time you compile it (You can change anything, even add modulators to its chains and if you recompile it goes back to the original state).

                    HiseSnippet 1201.3oc0VstahaDEdLIVZSZSa218A.EoJkUzZg4ZhVU0.lKAHDHXBIj+rxWFiMwdFmwiMwT0mg9f0Wl9FzNFG.ytrWnp6O57iDNemyY72bNy4Lm9DrFzyCS.be0vPWHf6q4kCQTSISEKDnUM.22v2UwiBIoigpF5p34A0Abb60LBf6f8AKV+0uVUwVAoAWCA.ivVZvKsbrnqQ6edGKa6FJ5vgVNIrtv4szvHIrM1mwm83yBbUzdPYB7JkHyRwCBrfy7.bY4ymSf7fn57JBrEQw8VgJEgBBAsEDxOnFJCCOnYkY0XnUED.Z9DBDQGwbGvwy82rEGeccKJlHSUnP1dxWEqGJahmgh+zir7rTsgQBh.YFmhgafs0iN7QnsPrvhghFLga.ISKa89KCqd..298WGj2KNH+J9tV5VqvWGr+tEJRu1ijgatTaR482fxheZJuU5wkfd6GSuWxKqQrboq0Dwsu+YzO.6hUBR8mo3YYQOZ5.ER5KazqKV22VgQ6z+R5EWsDl.oq.O4XlIoWId7qeyQGdzgq2fmXdkbSDfO4hIzEgfSdWicIv.KruGymiycZIg7XsYWKRFTSRpVSnoW8gkMpVTx31xSMHs0mIORzsdaRGkIilGNylnHM2FKNkN.1t7MYaVQ99wJO11LeKGoIiaX26rdYFn10d1MsIMtnos3nYULcxYFbS+4mJT3hGyMty0ijqbih6c5J0uAm+Ri9plSumNr0bOgBB2hB0yPCt+rNcUGKNcZoRMGLt7EE52HStxPS5C9MdrSob4tqTm7JWVZ781C0GW2dd6vFxU6OnkYQ0IpxtH0AYbJ1bNZ9cEnXoogmROytSFhm1CEFeZ8Q4TjJZV4I8dA0rC6bsbV058UssHhSUKeiksVYZU8gnZ8tMnjzffpyK1UxvP85Jczad1Piw8mYEL2KS9qDUDfUJLbBw5Qm4yxVo58sJ6GJ52VNGbjcn8Eg8IFicb8l52Yb9d37S7ykQtdlJ4UK9HT532jNMK8rQ1i.8X+CFm9VlthSiF9HMpEFkFitBSg8Pm75C+sCO3ve+8zXXrMURXDkfssgjsoMpSC4i31IHeGUH4mX2ir8gKsiUzrYI2gedkbrqjTV+lDFhQsPVzdtvUxwGxkHYAqNbIgVenRht3vrEyVC8904.oXNE0+88J3YscVlhR1KJp+9yJXAqMp1i58g7rngI6++kuA0yORwyytUsfjeK+F8O9zbrAA9nODok.7EmG8VTq0Okc9eb9sJAPCLwI96s18KgSXemjHCgNtXViMsjO6I6fwTSKzjMeg6UmK4yJ.bVt6.tejOWAgMWA8X+wHSzOOSZgL3cCr684EX2RvL0mYx+GVDWWEAihv+ml+y9AdScKWb2IFuJ89+.F+R99VTMysWgkZK7E.9hy2mGP4H95FFPM5ZxtOei692NMxNPkAXeJqroqBkX8DqP+JeGY13fZPFSPHnczjZbohZmEKmMRdQEGDomc4vcOqTLRl6YkhKUBbTzH32pE2yLpn3EKPXbBsXPyCXS7xjSKBV7XPLucXyk8VMsn.wOyX918H2N6Q9c1iB6rGE2YOJsydTdm83zOhGQCAWwm0nLtr..9GTowfBB
                    
                    1 Reply Last reply Reply Quote 1
                    • d.healeyD
                      d.healey
                      last edited by

                      Oh that looks like a better way to do it. Does this work script processors?

                      Libre Wave - Freedom respecting instruments and effects
                      My Patreon - HISE tutorials
                      YouTube Channel - Public HISE tutorials

                      1 Reply Last reply Reply Quote 0
                      • Christoph HartC
                        Christoph Hart
                        last edited by

                        Yes. It does the same thing as copying a module with Ctrl+C.

                        1 Reply Last reply Reply Quote 0
                        • d.healeyD
                          d.healey
                          last edited by

                          This is excellent news, I'm glad I checked in with you before I went any further :D

                          Libre Wave - Freedom respecting instruments and effects
                          My Patreon - HISE tutorials
                          YouTube Channel - Public HISE tutorials

                          1 Reply Last reply Reply Quote 0
                          • d.healeyD
                            d.healey
                            last edited by

                            The functions only seem to be available for Modulators and Effects, I get a function not found error when attempting export state on a Midi Processor.

                            const var script = Synth.getMidiProcessor("Script Processor");
                            script.exportState();
                            

                            Libre Wave - Freedom respecting instruments and effects
                            My Patreon - HISE tutorials
                            YouTube Channel - Public HISE tutorials

                            1 Reply Last reply Reply Quote 0
                            • d.healeyD
                              d.healey
                              last edited by

                              I've put together a script using the export and restore state functions that will save all modulators and effects with the preset, the global userPresetData and the panel should be in whichever script is going to have the front interface of course but I've included them all in one script for the purpose of this demo. If we can have these export and restore functions working for scripts too then it will be really easy to use the preset system without having to hard code the saving and loading for each control of each script.

                              <?xml version="1.0" encoding="UTF-8"?>
                              
                              <Processor Type="SynthChain" ID="state test" Bypassed="0" Gain="1" Balance="0"
                                         VoiceLimit="64" KillFadeTime="20" IconColour="0" packageName=""
                                         views="32.rk1bzA.....C.........LDZg4lakwVL.....PA...." currentView="-1">
                                <EditorStates BodyShown="0" Visible="1" Solo="0" Folded="0" InterfaceShown="0"/>
                                <ChildProcessors>
                                  <Processor Type="MidiProcessorChain" ID="Midi Processor" Bypassed="0">
                                    <EditorStates BodyShown="1" Visible="1" Solo="0" Folded="0"/>
                                    <ChildProcessors>
                                      <Processor Type="ScriptProcessor" ID="Script Processor" Bypassed="0" Script="//INCLUDES&#10;&#10;//INIT&#10;Content.setHeight(50);&#10;&#10;// Create a storage panel, hide it, and save it in the preset&#10;const var storagePanel = Content.addPanel(&quot;storagePanel&quot;, 0, 0);&#10;storagePanel.set(&quot;visible&quot;, false);&#10;storagePanel.set(&quot;saveInPreset&quot;, true);&#10;&#10;// Create a global object that will hold the values for the other scripts.&#10;global userPresetData = {};&#10;&#10;// Set the global storage as widget value for the hidden panel.&#10;// Important: this will not clone the object, but share a reference!&#10;storagePanel.setValue(userPresetData);&#10;&#10;const var btnLoad = Content.addButton(&quot;Load Preset&quot;, 150, 10);&#10;const var btnSave = Content.addButton(&quot;Save Preset&quot;, 0, 10);&#10;&#10;const var modulatorIds = [];&#10;const var effectIds = [];&#10;const var modulators = {};&#10;const var effects = {};&#10;&#10;//MODULATORS&#10;//Voice Start&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Constant&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Velocity Modulator&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Notenumber Modulator&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Random Modulator&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Global Voice Start Modulator&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Array Modulator&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Script Voice Start Modulator&quot;));&#10;&#10;//Time Variant&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;LFO Modulator&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;CC Controller&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Pitch Wheel Modulator&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Macro Control Modulator&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Audio File Envelope&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Global Time Variant Modulator&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;CC Ducker&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Script Time Variant Modulator&quot;));&#10;&#10;//Envelopes&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Simple Envelope&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;AHDSR Envelope&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Table Envelope&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Midi CC Attack Envelope&quot;));&#10;mergeArrays(modulatorIds, Synth.getIdList(&quot;Script Envelope Modulator&quot;));&#10;&#10;for (id in modulatorIds)&#10;{&#10;&#9;modulators[id] = Synth.getModulator(id);&#10;}&#10;&#10;//EFFECTS&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Monophonic Filter&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Polyphonic Filter&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Harmonic Filter&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Harmonic Filter Monophonic&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Parametric EQ&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Stereo FX&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Simple Reverb&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Simple Gain&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Convolution Reverb&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Delay&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Limiter&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Chorus&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Phase FX&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Gain Collector&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Routing Matrix&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Saturator&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Plugin Wrapper&quot;));&#10;mergeArrays(effectIds, Synth.getIdList(&quot;Script FX&quot;));&#10;&#10;for (id in effectIds)&#10;{&#10;&#9;effects[id] = Synth.getEffect(id);&#10;}&#10;&#10;//FUNCTIONS&#10;inline function mergeArrays(a, b)&#10;{&#10;&#9;for (i = 0; i &lt; b.length; i++) a.push(b[i]);&#10;}&#10;&#10;inline function savePresetData()&#10;{&#10;&#9;for (id in modulators)&#10;&#9;{&#10;&#9;&#9;userPresetData[id] = modulators[id].exportState();&#10;&#9;}&#10;&#10;&#9;for (id in effects)&#10;&#9;{&#10;&#9;&#9;userPresetData[id] = effects[id].exportState();&#10;&#9;}&#10;}&#10;&#10;inline function loadPresetData()&#10;{&#10;&#9;for (id in modulators)&#10;&#9;{&#10;&#9;&#9;modulators[id].restoreState(userPresetData[id]);&#10;&#9;}&#10;&#10;&#9;for (id in effects)&#10;&#9;{&#10;&#9;&#9;effects[id].restoreState(userPresetData[id]);&#10;&#9;}&#10;}&#10;&#10;//CALLBACKS&#10;function onNoteOn()&#10;{&#10;&#9;&#10;}&#10;function onNoteOff()&#10;{&#10;&#9;&#10;}&#10;function onController()&#10;{&#10;&#9;&#10;}&#10;function onTimer()&#10;{&#10;&#9;&#10;}&#10;function onControl(number, value)&#10;{&#10;&#9;if (number == storagePanel)&#10;&#9;{&#10;&#9;&#9;// Replace the global object with the one from the user preset&#10;&#9;&#9;userPresetData = value;&#9;&#10;&#9;}&#10;&#10;&#9;if (number == btnLoad)&#10;&#9;{&#10;&#9;&#9;loadPresetData();&#10;&#9;&#9;number.setValue(0);&#10;&#9;}&#10;&#10;&#9;if (number == btnSave)&#10;&#9;{&#10;&#9;&#9;savePresetData();&#10;&#9;&#9;number.setValue(0);&#10;&#9;}&#10;}">
                                        <EditorStates BodyShown="1" Visible="1" Solo="0" contentShown="1" onInitOpen="1"
                                                      onNoteOnOpen="0" onNoteOffOpen="0" onControllerOpen="0" onTimerOpen="0"
                                                      onControlOpen="0"/>
                                        <ChildProcessors/>
                                        <Content>
                                          <Control type="ScriptPanel" id="storagePanel" value="JSON{&quot;DefaultEnvelope&quot;: &quot;231.3ocgOtjSBDDDFtZYlXXmtykbDvSf7zDRvjIND22RWjoBEcMYpFLyMfiE2AuHdDrGPFIZL1qp9O0iuurJYIppTAlqWTWhf4lzbZSIiS86PVhIyl.laSmfqra4Pa5n5RqpnCLlNy7AzqTnFLcSfiuOdXXHXWttM4fL3YjQqhsQ6eevbxi1pmDGd4nlql5nfTkGrATASmQhqNuPdyGqSuGdgT5UFO8IWXoopO.iKH1kc1HEhrk8seIm8KdtsrMt+wEVxezu6ROgauEzFr2WMPh++07mrl72r1+BVeTXWyVaZ42bCeBet01m&quot;, &quot;Simple Envelope&quot;: &quot;&quot;, &quot;AHDSR Envelope&quot;: &quot;307.3oc0SFqSCCCDF9LIVHPkR2XsOBkQFPMsIE0JQkhZpX2DaoXgItJ1onr0Wi91vHi7HvVW4Qfj3DR.DRcCpmN+6y286Oc1OQFxTJYBf5rLaECPGiGM0KXALyCP8Lw8mDulIj4mNNaEQoXT.grlEqYwJtNCPmXCkq2GNRqIgO3llrlUIu45S2MziERxZq1J4ZkMyewwnbKKucMIBvTof949WScJKWSBW4DjpzDdbkzaa2dwyKXBFQ8k9gNZBkqkIAZhlo.j0XIMKHR9T9EsvWB2wU76ELyl.oPVDM..2Htf5WSJE.HreC2rMbqGdtjlJH402MpvKE.7Lr4E0eI+w8fde2f1+tAGzxf2jimhpVjxOMKrmdsasWM3++sY6fKmAND3543poyCBv1EW8w4OEse.2rEMXA&quot;, &quot;Table Envelope&quot;: &quot;&quot;, &quot;Midi CC Attack Envelope&quot;: &quot;&quot;, &quot;Simple Gain&quot;: &quot;306.3oc0RFjRDCCEF98l1fHnvnmf4HLEW3RKcpJyhQJFQWJwlfMPljRSJZck2Iu.dj7FnMcZmwAQvkNYU9+eIu78mjrJStvZMU.t2MMkB.OfPkKKUhKYRMLOEvC6Mlz4jzTxrVAGPLny.2OD.H9j2N88Tgh0r1H3k36jbWQuA.udebBSwz4hMVowXv4boyTQcLmvBXPhg2PKLO015.RDbqzJePIVInFkwOaJ.yJjJd1.9V.vvrMgIbUXFSVX30JVa+mULDniHdvmzWQZ1NTy0Ng1JcMqgD93Lbz1PF96PN8aPdgQw8c0ujeBL7G48XR2E6tDvcO76N.Oljw9O7g3ZSsSpebAyUIeFPxU0Kol5pbQKpZsP0dPDbD32ZmdpW6AhJz7Nwmsi9hQdM1WLZnH7EfHC.gs&quot;}"/>
                                          <Control type="ScriptButton" id="Load Preset" value="0"/>
                                          <Control type="ScriptButton" id="Save Preset" value="0"/>
                                        </Content>
                                      </Processor>
                                    </ChildProcessors>
                                  </Processor>
                                  <Processor Type="ModulatorChain" ID="GainModulation" Bypassed="0" Intensity="1">
                                    <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                    <ChildProcessors/>
                                  </Processor>
                                  <Processor Type="ModulatorChain" ID="PitchModulation" Bypassed="1" Intensity="0">
                                    <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                    <ChildProcessors/>
                                  </Processor>
                                  <Processor Type="EffectChain" ID="FX" Bypassed="0">
                                    <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                    <ChildProcessors/>
                                  </Processor>
                                  <Processor Type="StreamingSampler" ID="Sampler" Bypassed="0" Gain="1" Balance="0"
                                             VoiceLimit="128" KillFadeTime="20" IconColour="0" PreloadSize="8192"
                                             BufferSize="4096" VoiceAmount="128" SamplerRepeatMode="1.0470319e+09"
                                             RRGroupAmount="1" PitchTracking="1" OneShot="0" CrossfadeGroups="0"
                                             Purged="0" NumChannels="1" SampleMap="">
                                    <EditorStates BodyShown="0" Visible="1" Solo="0" MapPanelShown="1" BigSampleMap="1"
                                                  GainModulationShown="1" CrossfadeTableShown="0"/>
                                    <ChildProcessors>
                                      <Processor Type="MidiProcessorChain" ID="Midi Processor" Bypassed="0">
                                        <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                        <ChildProcessors/>
                                      </Processor>
                                      <Processor Type="ModulatorChain" ID="GainModulation" Bypassed="0" Intensity="1">
                                        <EditorStates BodyShown="1" Visible="1" Solo="0" Folded="0"/>
                                        <ChildProcessors>
                                          <Processor Type="SimpleEnvelope" ID="DefaultEnvelope" Bypassed="0" Intensity="1"
                                                     Attack="254" Release="20000" LinearMode="1">
                                            <EditorStates BodyShown="1" Visible="1" Solo="0"/>
                                            <ChildProcessors>
                                              <Processor Type="ModulatorChain" ID="Attack Time Modulation" Bypassed="0"
                                                         Intensity="1">
                                                <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                                <ChildProcessors/>
                                              </Processor>
                                            </ChildProcessors>
                                          </Processor>
                                          <Processor Type="AHDSR" ID="AHDSR Envelope" Bypassed="0" Intensity="1" AttackCurve="0.72000003"
                                                     DecayCurve="1" Attack="12443" AttackLevel="0" Hold="349" Decay="25"
                                                     Sustain="-5.900001" Release="1">
                                            <EditorStates BodyShown="1" Visible="1" Solo="0"/>
                                            <ChildProcessors>
                                              <Processor Type="ModulatorChain" ID="Attack Time" Bypassed="0" Intensity="1">
                                                <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                                <ChildProcessors/>
                                              </Processor>
                                              <Processor Type="ModulatorChain" ID="Attack Level" Bypassed="0" Intensity="1">
                                                <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                                <ChildProcessors/>
                                              </Processor>
                                              <Processor Type="ModulatorChain" ID="Decay Time" Bypassed="0" Intensity="1">
                                                <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                                <ChildProcessors/>
                                              </Processor>
                                              <Processor Type="ModulatorChain" ID="Sustain Level" Bypassed="0" Intensity="1">
                                                <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                                <ChildProcessors/>
                                              </Processor>
                                              <Processor Type="ModulatorChain" ID="Release Time" Bypassed="0" Intensity="1">
                                                <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                                <ChildProcessors/>
                                              </Processor>
                                            </ChildProcessors>
                                          </Processor>
                                        </ChildProcessors>
                                      </Processor>
                                      <Processor Type="ModulatorChain" ID="PitchModulation" Bypassed="0" Intensity="0">
                                        <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                        <ChildProcessors/>
                                      </Processor>
                                      <Processor Type="EffectChain" ID="FX" Bypassed="0">
                                        <EditorStates BodyShown="1" Visible="1" Solo="0" Folded="0"/>
                                        <ChildProcessors>
                                          <Processor Type="SimpleGain" ID="Simple Gain" Bypassed="0" Gain="-23.700001"
                                                     Delay="416.20001" Width="126" Balance="41">
                                            <EditorStates BodyShown="1" Visible="1" Solo="0"/>
                                            <ChildProcessors>
                                              <Processor Type="ModulatorChain" ID="Gain Modulation" Bypassed="0" Intensity="1">
                                                <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                                <ChildProcessors/>
                                              </Processor>
                                              <Processor Type="ModulatorChain" ID="Delay Modulation" Bypassed="0" Intensity="1">
                                                <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                                <ChildProcessors/>
                                              </Processor>
                                              <Processor Type="ModulatorChain" ID="Width Modulation" Bypassed="0" Intensity="1">
                                                <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                                <ChildProcessors/>
                                              </Processor>
                                              <Processor Type="ModulatorChain" ID="Pan Modulation" Bypassed="0" Intensity="1">
                                                <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                                <ChildProcessors/>
                                              </Processor>
                                            </ChildProcessors>
                                            <RoutingMatrix NumSourceChannels="2" Channel0="0" Send0="-1" Channel1="1" Send1="-1"/>
                                          </Processor>
                                        </ChildProcessors>
                                      </Processor>
                                      <Processor Type="ModulatorChain" ID="Sample Start" Bypassed="0" Intensity="1">
                                        <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                        <ChildProcessors/>
                                      </Processor>
                                      <Processor Type="ModulatorChain" ID="Group Fade" Bypassed="0" Intensity="1">
                                        <EditorStates BodyShown="1" Visible="0" Solo="0" Folded="1"/>
                                        <ChildProcessors/>
                                      </Processor>
                                    </ChildProcessors>
                                    <RoutingMatrix NumSourceChannels="2" Channel0="0" Send0="-1" Channel1="1" Send1="-1"/>
                                    <channels>
                                      <channelData enabled="1" level="0" suffix=""/>
                                    </channels>
                                    <samplemap ID="" SaveMode="0" RRGroupAmount="1" MicPositions=";"/>
                                  </Processor>
                                </ChildProcessors>
                                <RoutingMatrix NumSourceChannels="2" Channel0="0" Send0="-1" Channel1="1" Send1="-1"/>
                                <macro_controls>
                                  <macro name="Macro 1" value="0" midi_cc="-1"/>
                                  <macro name="Macro 2" value="0" midi_cc="-1"/>
                                  <macro name="Macro 3" value="0" midi_cc="-1"/>
                                  <macro name="Macro 4" value="0" midi_cc="-1"/>
                                  <macro name="Macro 5" value="0" midi_cc="-1"/>
                                  <macro name="Macro 6" value="0" midi_cc="-1"/>
                                  <macro name="Macro 7" value="0" midi_cc="-1"/>
                                  <macro name="Macro 8" value="0" midi_cc="-1"/>
                                </macro_controls>
                                <MidiAutomation/>
                              </Processor>
                              

                              Libre Wave - Freedom respecting instruments and effects
                              My Patreon - HISE tutorials
                              YouTube Channel - Public HISE tutorials

                              1 Reply Last reply Reply Quote 0
                              • Christoph HartC
                                Christoph Hart
                                last edited by Christoph Hart

                                Alright I added the missing functions (along with the functions for restoring synths as a whole).

                                I also spent another tool that creates such a Base64 String from the currently selected module (Edit -> Create Base64 string).

                                This solution is not yet 100% clean because it recompiles the scripts which is actually not something you want when restoring presets. I'll have to change it so that the string only contains the content values.

                                It's commited so feel free to check it out.

                                1 Reply Last reply Reply Quote 1
                                • d.healeyD
                                  d.healey
                                  last edited by

                                  Awesome, thanks Christoph!

                                  Libre Wave - Freedom respecting instruments and effects
                                  My Patreon - HISE tutorials
                                  YouTube Channel - Public HISE tutorials

                                  1 Reply Last reply Reply Quote 0
                                  • Christoph HartC
                                    Christoph Hart
                                    last edited by

                                    Alright, I just commited the improvement for the script processors - it just restores the content values without recompiling the script - the onControl Callbacks get executed of course.

                                    Check out the example that switches the table values of another script processor:

                                    HiseSnippet 1271.3ocsW82aZaDF9bRr1h6XpcZ+4jlk+KhRpKNgzjrpoU9QngTf.AhCjtnNi8Y3B19PmOHPp5mj8kbeC1tyFGLAHML0ZIv9d+wcO988dd3nJAaB88wDfvyZLtODH7Ch0G6Q6lqqAxCTLOP3GEKa3SgD4PSYG22v2GZADDV+cbCBatAH35e9irFNFdlvol..cLxDVB4hnSs9Wu88HGmBFVvFH2XQm9sEMwd4vN3AL7rtXJPeCydFcfUL3gslHXHBdqOPHk3d6pR5o09tLppp20db4cerOk.lCHDnGUmkNPPT3eYWBhGagnXRcpAExly0yhsFWuK9VuvkVG4iZ6.4Cz.0YXJzLHWWjiU0nxlO.HrQ0oEw0CKh+rXYjE5d6SKlOOvg7zLhWNEVaVHswLPRaYPp.1whOAKAdBwf2Fgv6Eh0MIn9zod3X6mlXcInKzIXM80ESHw5S9T4gFDYVocHzW92k+fhl19p6gOrcksO3zhoN3zNYJz7lZtYFQ7NXLaPK7Mm99StfY7R8bUR2cDw97rEu8lQEunvnRGyrap2YHkjeLtg8o100apd5I8x+9h0Jz7tKzKea1CqdbCmsq0vZuLW05hiZzplyqK07nVtWnejmY9z4aUwIamyp18t6Jby494yBKzTU8cWVoX5LJ6jPZS9kh1to+lgyRMzKOVMDmszupPuqpwgUS88X3jiuZWU77QuF6Zsum1Eoq2ywnxIoKODZmGiKeBlju69srynhOYXQbNkqeSBo3U6vl.m1naPPFdzxXqANFrMMrNP.wUsCbpwjJSZo7Ljmjh78tU1JX5SHEaExgcaiyhGwlubXOJi0nZXYEYMoRzSJ6Hqkh+Yq2H8pWI+gSqeVk6S9Zonb8g7cY8gDJB5Wffc4wMyr7oDRxxJHJz0W42jUxw2OIq8mdgOrqRBoOOYId0rqg8.OSJB6Ii8pfovy7Rtkzmj1T5yROzis8hbwgHA63.IKxKuhQdjzR5MvsMjrCqn4L.xhis6Z4cGUBzmcCFPsSFxY9PPluT6Z1q2mkX72YY+ROM1uYXgNVfXuhdH5Y8gSTxhJOyYw1Ntooki3VCJCKHrollWxALo4yEelDNKTZfzyymHxD0EAHl3hj38CCpIw+MEv7xWLQzn5ZbkU9uFMwAqSMi1UQNd7Qzwwm4u8xshg38WDW9Fi.r+qhOJM8K+pDoM+2BhwnxMLXveVdbfojJA2VHCNvyWj9FkeH28VjEsKi6t6go1IvPWHpSWJyxgodH6Mb9SDeANIH5jZoRwkitmo0m.6aPfMvUcLFmz2vsuC7bVmZG4vm8qBIYcvl8lii1OrCD3LY6A11PxxTF95pYrLogf3lif+rm19sGRmmotD27zW5uRb+4n5yq07DI+aDR9SDQD3aBBX9emX3yOf1C.VFTCfvwhoOTc1qgm071KqczckFSNHWv3d2bSosa5zxY+vwrur2lG5QgiAOUIjWHVEQM6tXMj0V.wi8N9z0PRsPMjEVBm+.kIDOlsM1jNEraHVn4+2SOtBP4b7.JxqSYCJAMhonUYfac1wyMgLj34Ac74mmdMdaObbJ9XdkoNzyJUzgsm3TiOVXhSsHm.WCSB9ilgaV3ZneefEFl7BN3+lr+ABarrVz1DNtcYmi9ill7BwKYHewYr6JmwdqbFoW4L1eky30qbFGrxYb3ijA+OsjY.E6FRK.f+CjAFVbL
                                    
                                    1 Reply Last reply Reply Quote 1
                                    • d.healeyD
                                      d.healey
                                      last edited by

                                      Thanks, going to build this now :D

                                      Libre Wave - Freedom respecting instruments and effects
                                      My Patreon - HISE tutorials
                                      YouTube Channel - Public HISE tutorials

                                      1 Reply Last reply Reply Quote 0
                                      • d.healeyD
                                        d.healey
                                        last edited by d.healey

                                        "(along with the functions for restoring synths as a whole)."
                                        Could you tell me a bit more about this?

                                        Also I noticed an issue with the script I'd made, if you add a modulator to an envelope and then click the save button, then you remove the modulator and then hit load the saved modulator won't reappear until you add another modulator to the envelope. Playing around with this and changing the values in the modulator etc can also cause HISE to crash and close.

                                        Libre Wave - Freedom respecting instruments and effects
                                        My Patreon - HISE tutorials
                                        YouTube Channel - Public HISE tutorials

                                        1 Reply Last reply Reply Quote 0
                                        • Christoph HartC
                                          Christoph Hart
                                          last edited by

                                          Just use Synth.getChildSynth() and call the export / restore methods on this object to restore whole sound generators (and even samplers with sample maps).

                                          Adding modulators programmatically is a bit difficult because it sometimes doesn't update the interface (if it's of any help, the compiled versions won't have this problem...)

                                          I'll need to check this a bit more thoroughly. Can you reproduce a crash with certain steps or is it just random?

                                          1 Reply Last reply Reply Quote 1
                                          • d.healeyD
                                            d.healey
                                            last edited by

                                            I made a quick video to demonstrate how to cause the crash using the script I posted yesterday. Also how do you post code here so it's on one line like you do? I use the ``` but it's always placed in a large box.

                                            Libre Wave - Freedom respecting instruments and effects
                                            My Patreon - HISE tutorials
                                            YouTube Channel - Public HISE tutorials

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post

                                            11

                                            Online

                                            1.7k

                                            Users

                                            11.9k

                                            Topics

                                            103.5k

                                            Posts