Dynamic Knob Range (How?)
-
I'm making a multiband plugin (3 bands). My doubt concerns how to create dynamic ranges to prevent the crossover from overlapping, the only alternative I have found is to limit the min and max values, but this does not allow me to have some ranges.
Since there are 3 bands and therefore two controls, I believe that the minimum value of the second parameter and the maximum value of the first parameter must be dynamic.
What solutions can I use to activate this?
-
@Mighty23 I'm not in front of my computer right now, but what I did is simply :
If the 1st knob reaches the value of the 2nd knob, it 'pushes' the 2nd knob up. On the contrary, if the 2nd knob reaches the value of the 1st one, it pushes the 1st one down. -
@Matt_SF Thanks for the reply, I'm currently stuck on this implementation; It doesn't work as I expected.
// BANDS MANAGER const var knbBand1 = Content.getComponent("knbBand1"); const var knbBand2 = Content.getComponent("knbBand2"); reg currentValueBand1 = knbBand1.getValue(); reg currentValueBand2 = knbBand2.getValue(); inline function onknbBand1Control(component, value) { saturator1.setAttribute(saturator1.Band1, value); currentValueBand1 = value; knbBand1.setRange(20.00, currentValueBand2, 0.1); }; Content.getComponent("knbBand1").setControlCallback(onknbBand1Control); inline function onknbBand2Control(component, value) { saturator1.setAttribute(saturator1.Band2, value); currentValueBand2 = value; knbBand2.setRange(currentValueBand1, 20000.00, 0.1); }; Content.getComponent("knbBand2").setControlCallback(onknbBand2Control);
-
This is a refined version, but I still can't achieve the desired result.
// BANDS MANAGER const var knbBand1 = Content.getComponent("knbBand1"); const var knbBand2 = Content.getComponent("knbBand2"); const var minFrequency = 20.0; const var maxFrequency = 20000.0; // Initial values reg currentValueBand1 = knbBand1.getValue(); reg currentValueBand2 = knbBand2.getValue(); // Function to update ranges dynamically inline function updateRanges() { knbBand1.setRange(minFrequency, currentValueBand2 - 1, 0.1); // Ensure Band1 max is always less than Band2 min knbBand2.setRange(currentValueBand1 + 1, maxFrequency, 0.1); // Ensure Band2 min is always more than Band1 max } // Initial setup updateRanges(); inline function onknbBand1Control(component, value) { currentValueBand1 = value; saturator1.setAttribute(saturator1.Band1, value); updateRanges(); // Debug output Console.print("Band1 Value: " + value); Console.print("Band1 Range: [" + minFrequency + ", " + (currentValueBand2 - 1) + "]"); } knbBand1.setControlCallback(onknbBand1Control); inline function onknbBand2Control(component, value) { currentValueBand2 = value; saturator1.setAttribute(saturator1.Band2, value); updateRanges(); // Debug output Console.print("Band2 Value: " + value); Console.print("Band2 Range: [" + (currentValueBand1 + 1) + ", " + maxFrequency + "]"); } knbBand2.setControlCallback(onknbBand2Control);
-
Well first this looks like you are using the std filters and the std HISE interface, if you want to make a multiband product you really really really need to use the Linkwitz Reily filters - and these are available in scriptnode - there's even a 3, and 4, band example in there somewhere I think.
-
@Lindon Hi! I'm using this from scriptnode (for multiband splitting and oversampling):
'jdsp.jlinkwitzriley'
...and I'm using Faust for Saturation functions.
-
@Mighty23 well then for any given "band pair" you should set the freq the same and it should "just work"
So you have low mid and high bands...
set low and mid band the same (looks like lr1_1 and lr2_1 in your picture)and set mid and high bands the same...(guessing this would be lr2_2 and lr3_2)
I think I just used a percentage of the value for the offsets...
so if (band2freq <= band1Freq) band2freq = band1freq + (band1freq * 0.1)
-
@Lindon I'm having issues, I think I've already done it.
ScriptNode1266.3oc6Ys0TaiCEVFh.5VfNc6t8YdYeZm0ajjsi8iExxNLyxkYBS2GYDIJE25Xm0W.R+0Wo3bQxINWbLozk3GfH6i046bUeV5hfVLf1NmRaFGD16JZ7c.s2BaF3GSc8Yg5Mui+evY0AZuFFQiSBob4.G2qKMJh0Bnosci6Bd3JZHsCKlEFAz1Fh.Wvm0SB7BRBAZPM.+5jfNcX9w.ssfbQDOOBvGbQe0CEyOD1tcLPAHG.o9TudQLcwiFqzsgUmqJ3i55wdrNMlxUjVc2ntdzdGmzts.kYuCe7Y9sXOlN2.I6gOHLnKKL1UfXPJf2Q.3CfsCY+2M7YwM1.jqGr+yASyKsbFjLlz1ZzHtvm65+QpWh.WPbU8pfyoON3FuheC9E+dM9B6gTLBz9EXUcL1wopgoosgksEwF2OFuG7XpeqiPfOjDGzgFmhMD26bRfuOqYrafuP8UFObPP7Ltj6B8BQ2fF68D270vS4doDleydBKJmWCWrWir7u1Avlza8X2DK9q5KuKL0qAdRct3Uw4hKlyEWLm6R+ZGJ6bI43cGV7usTsz9vf64Y1TQMqZoz6kJkjjQs1YU5AoI0CZW3s7PDBLm1gKWg6PEAUTTZohhh9U3maE0U+ydt9e4A23uF55w5oL86CMv1FN0bLcryfhY186TWuAMNF7StXR869qN2xZ0h0pu3hI.7zzrwBiIF10rMGrfx3zoLkD4TABgpJDBwBkEy51v8q8Gi3iEy8Nvq60kATduo0HWJXfeFDLp.+CzKfnAdVQC0FzYhIhJwv.OcYQVppwJYBFWKlhnQ+ZV0E+FDanqdc+k7+z926+61lOhRtLSvRSx0UYVttgtpgcImHDH6sNOnUhGUz68ZZ3mXwY7f6AakzoSuLcW9IHe9tSuSh2DYwNFNV0vNlyJKdqxwtTdvLpHaSShxvFbedzOjSEr+SVRtSR5gaIoi5IB10EEJm3wmK9ZTC.2giY5VuwUiP4P4eC7hjNRdiAu0DDG0pL85l2Ir8zKjgSUDxBI4x1AhppTFIpXQYkO0IUOz8dVAqVESqS5UsZVF1XSNMkwZ88BwqNg.o9q5g89y+kEWR8Ix0.O.dYRb2j3i9awhtYxbVPUYjSKo2BajFi4EQG0u6TVioAuqey6FWfk62DvKFTSP1GdVzGEOsI0aHr01J+FCEx.NDd4P1Pt9eZl8KVT.p7sMi4Zg9tSHC+zPHqRFN.3BRHiWZfvDmRiP1KAJ.n4QHCWPBYkcv.+Rmc7.1D3ebYSrWJaBzF5DanSrgNwZlNgzx3j0y9pPVk8UwFs4S4KsOke3tH98OZrMj7RmTUl8lcsuwJZR7ae9rIIje3o0f2PqYCsl+GQqQNaWIQ4PYqIMzdb+SqobNhtQ4cNVV5DSd8NFYaZYiISbBcZ4bxhxmGrxYeM5bUAS2FvksMfpZYTU2.IxUpQPlNklMfmzFj3NxtQNbrXIZJBuXvT43BUPYFdryFq30AVU2JshCVRoB1Iz0qfokxqk32v82WwaLYylbA4ZIvMZaCJJJIqQThWZTtCeEgGmUzdpq8or9xbWHbExFFu94zQN94.xmdJx7fN4YDzwKLz2C9Or6YdxYLKDGsAi9YHQ2JUVShkgAxddjaVgjmgj9xyHvEzHdG2HvoxZTyxlTCYUNVwzSjlmYPVAyfLvLbP0H1DboZF37LiBvG7afPE+Gy
@Lindon said in Dynamic Knob Range (How?):
I think I just used a percentage of the value for the offsets...
// Function to update ranges dynamically inline function updateRanges() { knbBand1.setRange(minFrequency, currentValueBand2 - 1, 0.1); // Ensure Band1 max is always less than Band2 min knbBand2.setRange(currentValueBand1 + 1, maxFrequency, 0.1); // Ensure Band2 min is always more than Band1 max }
Update: It would appear that my last posted code (almost) works correctly. If I change values and then recompile each time, the values don't seem to overlap (Oh! a noob). I still have to see how it performs once the whole project is compiled.
-
@Mighty23 Don't use
setRange()
. The frequency range will always be 20Hz-20kHz.
Simply use this (pseudo-code) :// When the Knob1 reaches the same value as Knob2 if(valueKnob1 > valueKnob2) { valueKnob2.setValue(valueKnob1); valueKnob2.changed(); } // Same when Knob2 reaches the same value as Knob1 else if(valueKnob2 <valueKnob1) { valueKnob1.setValue(valueKnob2); valueKnob1.changed(); }
-
@Matt_SF without using .setRange I tried to use .set and manage min and max like this. I would like to better understand the logic you are proposing, for the moment I am at this point and it seems to work; It's not pretty to look at but apparently it works
// BANDS MANAGER const var knbBand1 = Content.getComponent("knbBand1"); const var knbBand2 = Content.getComponent("knbBand2"); // Function to set dynamic ranges for the knobs function setDynamicRanges() { // Ensure knbBand1's max is not more than knbBand2's value knbBand1.set("max", knbBand2.getValue()); // Ensure knbBand2's min is not less than knbBand1's value knbBand2.set("min", knbBand1.getValue()); } // Callback for knbBand1 inline function onknbBand1Control(component, value) { saturator1.setAttribute(saturator1.Band1, value); setDynamicRanges(); // Update ranges dynamically } knbBand1.setControlCallback(onknbBand1Control); // Callback for knbBand2 inline function onknbBand2Control(component, value) { saturator1.setAttribute(saturator1.Band2, value); setDynamicRanges(); // Update ranges dynamically } knbBand2.setControlCallback(onknbBand2Control); // Initial setup for dynamic ranges setDynamicRanges();
-
@Mighty23 No need to set min/max values. Only the knobs' values :
HiseSnippet 1796.3oc6Zs0aaTDEdVmrI0lKhJAuupuTWQUHdSnfHbw4ZwpjTCNDUIdHZ7tiim5c2YYuzDWZehW3M3MDOweA9Ive.dheE7F+CJmyLq2KdctsBBETbjh7Ly4Ly2412Y7Z2MPXwBCEADs56O1mQzdU8di8hFt4PJ2izYKh1qquKMLhEXnlZiw9zvPlMQSat6iSnUedh70e9IaPcndVrroHjCDbK1mwc4QYy1s8C3NN6PsY6ycyI8ps6XI71T3HhA7Lm9xDep0H5Qr8nnX0zIZKrsMORDzKhFwBAY1PXOt2PwwdJ4OfGx66vvAsH8fMRMMYygbG6tSr0PBQa9tYV9bJK+M02kaySmOyC7FxELxzHuOPq1YAoVWBHokCRyqfzM06YEv8ixVAwyqn2wCBHCnfqNOTTxRp8n402T.R3EsjKcDam.XPpFMu2xKeWC3e2YsFM.2cXjQHMJNfB1fwGYHC9KcDKZ6ACXVQMuU5h2BTPI+SnAFi7D82f5Y2BzYxgAZsov0W3ACZdqTIlshlmqhlnhM3dNbOlwfXOqHtvyP3ktwn5ABmlVSz8tvI3DytSiuoQ824cLtOKxHZHyP.+KvnOnxsCMFDv95Xlm0XkrMp6HrnNxUMO.mAvUJBPjImrI.k5xMsy.iG.K2xXmhajQ.iZMjEJW0r7wvGzTI2Gm6rtSi5.Tws81ciCGdaIbUafRXXwLvDNALJqbMkl6vCRzArNvTb5CEMEzyZH06HlszFddi5oQTbCWOJJf2ONh0LaZoychubsFOesFotbTkD29lIGUyxQjyNtYddwsdP4tAMLwOCfyX.jaJMw7gqVSGtZMc3J0m+g4THwmWvjl1slsXU7clyz2Yd19NyLeWNe1dhH1C8ZJ8LMddCioWZvfYtVxd4vBl4xHsavYoXSuX29rf7wETPfWpHY2BWLxNKUcdNAEdc73QOzmkLdGgiMRhguuL0HIgn.HIqkfPPzHIE4qmPQ1ygayBHbajeLM9QjFPVKl2uM4RsAlSsAuxuzl7kc1hFQQB6DXAP0mEDwQOh1Vrm.c7Tz2002hENJR3KwcRxNQqwEB4mjdn+Z+1iyOvUXyPYSYfHt46CuZaWZlxe2u2F5d62i+TV9V0gwCFvAoz0M9zmB5aa6v5JB4Xd.JmFJl+OhtqKEtMyi6f+Ewc4loPabgcrCVllu2NdIljEv8HeCUrooGr2iyifKQC+kOyF9WTHdS8t7HqgyFi0lAFwxj+AvXx0jdMc0UCx.37567npdmnkuz2IpQR5GblpKCkR9NqKCo8c5Y7a9ALeZ.aeQWG5Xfz102g8E.DuqQensxHLWqLonuBAafRzDaG3wbBqB24B+McQQxWHhi3dGsKEZ+fkB6E61CtxrEayDzAyoUCoMUiWFGioE8Xd1xAu.dkrXKbrVxhslrXFiKYOVzwhfQxnQx6IZKht9WUOT5jObvIsHq63HNFIK3IIoPLPNWWgyX+gBOtENkRhIHccWQLxrnf6mRC2mxcvr5dwgPuA6G50CDV9QJzl6.VPnbiWTe4kf+fr78jLJKrC0Bbri6RiFhkKX6FH2jEfcuSxQKf074I3VL4ibn7R.Dck7cvG3.iOcoAvERfqOiz60zlKGcuJAEGAke0TmSmvCvUgaoPNP06.LN7TTdPEhQQeMc7RhGF56viVkbp1fb8Y.jKtQ.PNSSXlzQfqbWt2AEaQtZ6comTbNfKtWItXHiYD6XErwY+sm8Gu2259aeBZZ2PG6EXzhjtOa+Cu8G7Uy+4sWONR3BE.RtKYGTOlr.BQ1bYCSBtcrwvsSPqCaQRgcG6hcQHmpZlUSsUNS0txbeljh6S6uu5tOyp49Lql66rTaRovbpRAczfWTWd+bx4THeYR4m5XVPcLpLoBGyao+X6P+kdL7wUFcLO5oA.iyXR9su9BG88+zKviXx0TKV8MUsVN5A4smbXmL4Bi6vcRJBSdKxZ3YyNYBu61PqCa3HjJLgK9pn5ESulj9kObMUF3OWHCbt70BKTFLDRIv.6QuYbstRfQNKBlEzks8KsyjRwUyqiq+2Ot1ljiV3F51wttimpfsgNfygK4F6LUzT5TgWmZLrVgXXA2u1k2hAq6h39Ss3E0UaPosgTkaTjG8jRTolWETolUgJ8YGccI2KUkbP9Wo3p40w0++zhLOUp40ToWVpzUtJnRWoJTo9+zQWWx8R4sWxEWMuNt9+mVj4oRW4ZpzygJ8zsq7oUI0Jpuzi+9edJkrqoepIZy74XT7gyU3oYj9vsHy1JL+ujUXBIlBwHWp7I7VouaqqjmGsK0JPbnk5QriF7Mjy.LfdxebH002EGaT5a7ifeIQ7CsrJtUkTzrpJtRUUb0pp36VUEuWUU78pphu+4qH9aqIglGSdANstaqZHossGsuSB2+e49GyKK
-
@Matt_SF This version also seems to work reasonably well. Thanks for your time, it's time to add breakpoints and understand better. Thanks again for your time
-
-