HISE Logo Forum
    • Categories
    • Register
    • Login

    Many knobs to control even more pitch modulators in a scalable fashion. How?

    Scheduled Pinned Locked Moved General Questions
    21 Posts 5 Posters 858 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.
    • gorangroovesG
      gorangrooves
      last edited by

      I am trying to connect a whole lot of Pitch Knobs to even more Pitch Modulators in a scalable fashion, without setting up callbacks for each individual knob manually. It would be straightforward if the number of knobs was matching the number of pitch modulators, but they are not. Some knobs need to control several modulators.

      If my knobs are called:

      PitchTuneKnob1
      PitchTuneKnob2
      PitchTuneKnob3
      PitchTuneKnob4
      etc.

      How do I programmatically connect them to modulators with names like:

      PitchModule1
      PitchModule2a
      PitchModule2b
      PitchModule3a
      PitchModule3b
      PitchModule3c
      PitchModule3d
      PitchModule4

      So, PitchTuneKnob2 would control both PitchModule2a and PitchModule2b, and so on.

      I have PitchModulator Constant modules loaded for all sample libraries and this single script works for a single knob/sampler.

      const var PitchTuneKnob1 = Content.getComponent("PitchTuneKnob1");
      const var PitchModule1 = Synth.getModulator("PitchModule1");
      inline function onPitchTuneKnob1Control(component, value)
      {
      	PitchModule1.setIntensity(value);
      };
      
      Content.getComponent("PitchTuneKnob1").setControlCallback(onPitchTuneKnob1Control);
      

      I tried several ways but didn't manage to connect to any modulators that have letter suffixes.

      Goran Rista
      https://gorangrooves.com

      Handy Drums and Handy Grooves
      https://library.gorangrooves.com

      ulrikU 1 Reply Last reply Reply Quote 0
      • ulrikU
        ulrik @gorangrooves
        last edited by

        @gorangrooves is this not working?:

        const var PitchTuneKnob1 = Content.getComponent("PitchTuneKnob1");
        const var PitchModule1 = Synth.getModulator("PitchModule1");
        
        //	
        
        const PitchModules2 = Synth.getAllModulators("PitchModule2");
        const PitchModules3 = Synth.getAllModulators("PitchModule3");
        
        
        inline function onPitchTuneKnob1Control(component, value)
        {
        	PitchModule1.setIntensity(value);
        };
        
        Content.getComponent("PitchTuneKnob1").setControlCallback(onPitchTuneKnob1Control);
        
        
        inline function onPitchTuneKnob2Control(component, value)
        {
        	for (p in PitchModules2)
        		p.setIntensity(value);
        };
        
        Content.getComponent("PitchTuneKnob2").setControlCallback(onPitchTuneKnob2Control);
        
        inline function onPitchTuneKnob3Control(component, value)
        {
        	for (p in PitchModules3)
        		p.setIntensity(value);
        };
        
        Content.getComponent("PitchTuneKnob3").setControlCallback(onPitchTuneKnob3Control);
        

        Hise Develop branch
        MacOs 15.3.1, Xcode 16.2
        http://musikboden.se

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

          You can use loops combined with the getId function and the contains function to see what number is in the knob or modules ID and make the correct connections.

          You might also be able to avoid scripting it and use the macro system.

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

          gorangroovesG 1 Reply Last reply Reply Quote 0
          • gorangroovesG
            gorangrooves @d.healey
            last edited by

            @ulrik Thank you. Yes, that would work for sure. I am just hoping that there is a simpler way to accomplish this where I don't have to specify an array for each set of modulators and each knob. I have 17 plugins to implement this in, and some have quite a few components, so this would take a very long time.

            @d-healey I am going to try to use 'contains' as you suggest. I haven't touched macro system and am not sure how exactly it works, but considering the number of my components and plugins, doing some programmatically would certainly be a much better path.

            I'll report back. Thanks a lot, guys!

            Goran Rista
            https://gorangrooves.com

            Handy Drums and Handy Grooves
            https://library.gorangrooves.com

            ulrikU 1 Reply Last reply Reply Quote 1
            • ulrikU
              ulrik @gorangrooves
              last edited by

              @gorangrooves I see, could you do something like this maybe

              const AllPitchTuneKnobs = Content.getAllComponents("PitchTuneKnob");
              
              
              inline function onPitchKnobCallback(component, value)
              {
              	
              	local id = component.get("id");
              	local fxid = id.substring(0, 5) + "Module" + id.charAt(id.indexOf("Knob")+4);
              	local mods = Synth.getAllModulators(fxid);
              	
              	for (m in mods)
              		m.setIntensity(value);
              }
              
              for (k in AllPitchTuneKnobs)
              	k.setControlCallback(onPitchKnobCallback);
              

              Hise Develop branch
              MacOs 15.3.1, Xcode 16.2
              http://musikboden.se

              gorangroovesG 1 Reply Last reply Reply Quote 0
              • gorangroovesG
                gorangrooves @ulrik
                last edited by

                @ulrik This looks very promising. Thank you so very much! I am going to play around with it and will report back. :beaming_face_with_smiling_eyes:

                Goran Rista
                https://gorangrooves.com

                Handy Drums and Handy Grooves
                https://library.gorangrooves.com

                gorangroovesG 1 Reply Last reply Reply Quote 0
                • gorangroovesG
                  gorangrooves @gorangrooves
                  last edited by

                  @ulrik Your script was massively helpful and very successful!

                  To get around quirks with knob 1 controlling all modulators from 10-19, I renamed components to use double digits: 01, 02, 03...

                  Here is the slightly modified, working version of the code, 100% scalable.

                  //! Connecting pitch knobs to pitch modules
                  const var PitchModules = Synth.getAllModulators("PitchModule");
                  const AllPitchTuneKnobs = Content.getAllComponents("PitchTuneKnob");
                  
                  inline function onPitchKnobCallback(component, value)
                  {
                  	
                  	local id = component.get("id");
                  	local fxid = "PitchModule" + id.substring(id.length - 2, id.length);
                  	local mods = Synth.getAllModulators(fxid);
                  	
                  	for (m in mods)
                  		m.setIntensity(value);
                  }
                  
                  for (k in AllPitchTuneKnobs)
                  	k.setControlCallback(onPitchKnobCallback);
                  

                  Really brilliant work, @ulrik which has helped me a lot. I owe you!
                  Thank you soooo much! 🙏

                  Goran Rista
                  https://gorangrooves.com

                  Handy Drums and Handy Grooves
                  https://library.gorangrooves.com

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

                    @gorangrooves I hate to be the party pooper but if you‘re planning to automate these controls you need to implement this differently or you‘ll end up with audio glitches.

                    I would go for a predefined array of sources and targets.

                    gorangroovesG 1 Reply Last reply Reply Quote 0
                    • gorangroovesG
                      gorangrooves @Christoph Hart
                      last edited by

                      @Christoph-Hart Please tell me more.

                      Goran Rista
                      https://gorangrooves.com

                      Handy Drums and Handy Grooves
                      https://library.gorangrooves.com

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

                        HiseSnippet 1711.3oc6as0SabDEdWfMM1IMpoJppONB0GLJDpM2ZknUXvXRsR.rvNWjPDz30ismxtyrc1wjXUk+K889SHOz7XqTdnOzeBsum+AsmYmcwqAiw3BI.ZsPHOWNm46bYNem0VtrfaS784BCyTU63QLLusUkNLYqBsvTlQo0LLui0FXeIQfzSsZGOruOotgo43OTMgYpILBd89kWE6fY1jtSYX7TN0l7XpKU1c1x4eD0wYcbcRUparcOe9R1bVAtCuMfmwsxZ3gs2G2jrIVsswrLLuQw5TIWTQhkDeXOqxq2oRK9KY58+TpOslCQMHmQEPQ5oMJzh5Tubjs5aXX9Ik6Z4iqs76YsAsN8v465A9rfEPckHtOvbrAAobmAHYFCRSngzcspXKndxtqnvysrJwf.RCL3piCE8dMF6ulvp.G1ASNiKdex5BXvgRjYwrYmFA+apkRm9q+ZjcKLqIAIaQ8QM3BD4.hnCxSv+QhsLMDO7knCvBT4RUK7C6UZy0J97hUPeOZmIwSNMZxZp+YO4tKgN1dqtx1OrX03hrStcmFsyrSilaZz7p2t.fjc2UCjpJD7RHw.0h6TGgQNTPc7FHLL09LdM+XmfGUZ25QpIU58jzvrq8.rPf6DoEIVzjH8QY74fAikv+HHJqN4UpcnFnNGjMlgpQPvow.e.oNRxQtscjTOGRjNl5nfoZnt6BmsXfNfisFjDqTgnsR7VDWEVRSYNTXCMZyrkTNCwYkiroL1bWONCheSC52oMYpz+b5TfFgCHFjaH3tACUNpzob3vggn0eE.gttmYB16VM5pSHtmJPa9f1h6Unr.soGp89pDB0bMoGPX5iMcJXxLR0tia26.G7tSkNUJ4LfdUYaLeprSFM9WJ8q6FgNzjCBU1BBbwQexujiBhW9n1PJcDfh7gGykQYTYl.eiBRTvtytDhh9tdyUmwgvZJaAqb+6C.D1cpXtGu19sxDcaALjBQtoLSFDO1aRz86Ue6P2cJkOLlVfoTVsRMBtSgP7lIVHMP.3OcPR1StRvBJKvSYw86ti5Hg8jJTNMnCJSqf7F75scvPInLSVPkShYREn8lJ5PiGmzxFkDCa30pPi1SBosoikOtIWR1hocvvlPGcoFM56ZgdAGhnuKqJ4KFjfYXscqQDwS8UaDpI1ag1aLbEZs0w1XajyJAl6VdjvwqCEKTEPUu+3kkMBSNfBziGhP3cxfxy2Ir7bEGZchvfBJIkkNsAaD.+Pxs29t282KabFDuVOhmO8yPu8rHtcOhqe8jRqgkXEOSnEAVoGQHoJmo4ZjC.hZMqSJq0H96K4dAlb38AfxbHL5W08HKkuS2AuHuKsdcGRYNTU.B2wQla7lHx7VWbLkjIuwYBA0THvx72AQ+Hb515S+ElmWm9w6H.5EI55d7FTTchEtf5Dh2Uvg0hi2o1Q6ZYhS9xT1XWlNkqJCIbuq1c0e7NVevKjzdQi2vd.+TqhMZ.j9cA6DVq+7A1v24NTtiFJ2xpBv1ETkO.HeQvXzyvGPPOjvHBkSM2.5G+OG19w8F59w2xVBGeUAl46w86QwUHtzpvME+3S9Den6SxOssJJGe9BbrnuK89kWGLx9JSErrsHHcYEWdalrmziwGTL4Detfdu0DKF1mtym3h5AF9fd06+ekhwGN3dJOeSpHLVg5BcUWjc.wAXiBv3mCzOMvP+1Qy1aR9FbF2qEmQsimArMQJnMaRDwwdeMnUjRn4rtybu7aSbH33YyeU9GCYgXA3mHinu3r+rd8Md8kVZ3hT2LQWOpvO9PUg+7w2ZoAYZqnNiCe.5ng4FHv9k27lec4UodbGrPQMctgwKSLOayaKorlafgKPp1W1rsaEnfuMAPB7.vN9pVZFSUzVONqZrthOqdvf+EdEtXN0XyvEyEsXby8lmvGyzsC9LKfQjARp89yeRsiRdbI7CU5JFGQR2jWM6lb1jtIS5l75d2jylzMYR2jWLcSN6fAl8e7O+VR2jmqcSdVX2lKgc6zY2xkvtcklcatD1sD1sQKO6zX2lKgc6RL617IraIraW2Y2lOgcKgc6hgca9D1sODraW991Fl8p521vMR3gR91FtB+sMrPRGqIcrdcui0ER5XMoi0KlNVW3zAVRGqez97XVLgcKgc65N61hIraIraWLraKlvtcc4yi4CwY3hsE78r0+DoT4Z2LXFv2xB9wCmxZC0XTtneYTVVYmIqgKvFrmssJj9.HFzeYlcDjYtQPl4GAYVXDjYwQPluYDj4aGnLJh3UZK4t5xPvDkKF7KTyzrHCC2VBtYY7e5yrqA.
                        
                        // change this for every project
                        const var PITCH_INDEXES = ["a", "b", "c"]; 
                        const var PITCH_TARGET_INDEXES = [[1], [2, 3, 4], [5, 6]];
                        
                        // This will hold a list of all knobs
                        const var pitchKnobs = [];
                        
                        // This will hold a 2D-array of all targets (so that the index of the knob can be connected to multiple targets)
                        const var pitchTargets = [];
                        
                        // One callback to rule them all
                        inline function onPitchKnob(component, value)
                        {
                        	// get the index from the list
                        	local idx = pitchKnobs.indexOf(component);
                        	
                        	// set all targets in the target list for the given index
                        	for(t in pitchTargets[idx])
                        		t.setIntensity(value);
                        }
                        
                        // This function will create the two arrays used in the callback
                        inline function init()
                        {
                        	for(i = 0; i < PITCH_INDEXES.length; i++)
                        	{
                        		pitchKnobs.push(Content.getComponent("Pitch_" + PITCH_INDEXES[i]));
                        		pitchKnobs[i].setControlCallback(onPitchKnob);
                        		
                        		local targets = [];
                        		
                        		for(p in PITCH_TARGET_INDEXES[i])
                        			targets.push(Synth.getModulator("Constant" + p));
                        		
                        		pitchTargets.push(targets);
                        	}
                        }
                        
                        init();
                        
                        ulrikU 1 Reply Last reply Reply Quote 1
                        • ulrikU
                          ulrik @Christoph Hart
                          last edited by

                          @Christoph-Hart I guess the difference is that in your example, all references are already made pre callback, and it will be faster? Is there a big difference in runtime?

                          Hise Develop branch
                          MacOs 15.3.1, Xcode 16.2
                          http://musikboden.se

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

                            @ulrik yes when you automate a control in the daw it will be called in the audio thread so going through the module tree and comparing strings to add to a array is absolutely out of the question.

                            If it‘s not automated it still might clog the scripting thread more than necessary.

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

                              I usually try to create all references on init or when you load a preset or other singular events.

                              ulrikU gorangroovesG 2 Replies Last reply Reply Quote 1
                              • ulrikU
                                ulrik @Christoph Hart
                                last edited by

                                @Christoph-Hart good to know! 👍

                                Hise Develop branch
                                MacOs 15.3.1, Xcode 16.2
                                http://musikboden.se

                                1 Reply Last reply Reply Quote 0
                                • gorangroovesG
                                  gorangrooves @Christoph Hart
                                  last edited by

                                  @Christoph-Hart Thanks, Christoph.

                                  I do get why it is a much better idea to connect everything at initializing rather than doing it on the fly. However, I haven't come across any issue with the simpler script, as the intention is not to automate and change pitches while playing, but rather "set and forget."

                                  I'll look into this more closely and run some tests.

                                  My primary concern is "change this for every project."

                                  Why did you write this line like this?

                                  const var PITCH_TARGET_INDEXES = [[1], [2, 3, 4], [5, 6]];
                                  

                                  And not like this?

                                  const var PITCH_TARGET_INDEXES = [1, 2, 3, 4, 5, 6];
                                  

                                  Goran Rista
                                  https://gorangrooves.com

                                  Handy Drums and Handy Grooves
                                  https://library.gorangrooves.com

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

                                    @gorangrooves this way you can define how many targets you want to control with each slider.

                                    gorangroovesG 1 Reply Last reply Reply Quote 0
                                    • gorangroovesG
                                      gorangrooves @Christoph Hart
                                      last edited by

                                      For reference, here is the scalable working script that doesn't mess up with Pro Tools' onNoteOn and timers.

                                      It creates arrays onInit by pulling all components and synth modulators with matching names. Then, in the callback, it iterates through the arrays to match portions of names. It works like a charm.

                                      const var PitchModules = Synth.getAllModulators("PitchModule");
                                      const AllPitchTuneKnobs = Content.getAllComponents("PitchTuneKnob");
                                      
                                      inline function onPitchKnobCallback(component, value)
                                      {
                                          local id = component.get("id");
                                          local fxid = "PitchModule" + id.substring(id.length - 2, id.length);
                                          
                                          for (m in PitchModules)
                                          {
                                              // Check if the modulator's ID starts with the fxid
                                              if (m.getId().contains(fxid))
                                                  m.setIntensity(value);
                                          }
                                      }
                                      
                                      for (k in AllPitchTuneKnobs)
                                          k.setControlCallback(onPitchKnobCallback);
                                      

                                      Goran Rista
                                      https://gorangrooves.com

                                      Handy Drums and Handy Grooves
                                      https://library.gorangrooves.com

                                      LindonL 1 Reply Last reply Reply Quote 0
                                      • LindonL
                                        Lindon @gorangrooves
                                        last edited by

                                        @gorangrooves

                                        are you saying this doesnt work inProTools?

                                        const var PitchModules = Synth.getAllModulators("PitchModule");
                                        const AllPitchTuneKnobs = Content.getAllComponents("PitchTuneKnob");
                                        
                                        inline function onPitchKnobCallback(component, value)
                                        {
                                            local pos = AllPitchTuneKnobs.indexOf(component);
                                            PitchModules[pos].setIntensity(value);
                                        }
                                        
                                        for (k in AllPitchTuneKnobs)
                                            k.setControlCallback(onPitchKnobCallback);
                                        

                                        HISE Development for hire.
                                        www.channelrobot.com

                                        gorangroovesG 1 Reply Last reply Reply Quote 0
                                        • gorangroovesG
                                          gorangrooves @Lindon
                                          last edited by

                                          @Lindon This line was causing an issue in PT, when included within a knob callback:

                                          local mods = Synth.getAllModulators(fxid);
                                          

                                          Your code is fine, although it wouldn't work in my use case, as I have a single knob like PitchTuneKnob01 controlling several modulators like PitchModulator01a, PitchModulator01b, etc.

                                          The line with the issue doesn't allow onNoteOn callback and timers to run until the GUI is closed and re-opened.

                                          Goran Rista
                                          https://gorangrooves.com

                                          Handy Drums and Handy Grooves
                                          https://library.gorangrooves.com

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

                                            @gorangrooves said in Many knobs to control even more pitch modulators in a scalable fashion. How?:

                                            local mods = Synth.getAllModulators(fxid);

                                            You should get all module references in on init rather than doing it dynamically like this.

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

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

                                            50

                                            Online

                                            1.7k

                                            Users

                                            11.7k

                                            Topics

                                            101.9k

                                            Posts