No internet connection
  1. Home
  2. Macro and Script Help

Three-Body Technology's Kirchhoff EQ: Curve Randomizer

By Nathan Salefski @nathansalefski
    2023-12-27 06:25:11.401Z

    Title

    Three-Body Technology's Kirchhoff EQ: Curve Randomizer

    What do you expect to happen when you run the script/macro?

    There's a plug-in called the Kirchhoff EQ which has several different modeled curves that you can assign per band. I wanted to make something that could randomize the shapes of the EQ bands I used. Each instance of the Kirchhoff EQ is instantiated with my user default preset. This preset consists of 12 bands -- two filters (inactive by default), two shelves (active by default) and eight bells (active by default). I have managed to make great progress with this idea. The script can already establish which bands have been moved, what the shape of that band is and what corresponding shapes exist that i can choose from at random. I don't get any errors when running the script however it is not function as intended. I believe this may simply be a result of trying to change parameter values too quickly. Currently I am using elementClick({ actionName: AXIncrement )} and the corresponding Decrement to adjust for the delta. Any help would be amazing. It would be really handy to see if broader Qs or slightly different curves could be better.

    Are you seeing an error?

    What happens when you run this script?

    The parameter changes but incorrectly

    How were you running this script?

    I used a Stream Deck button

    How important is this issue to you?

    5

    Details

    {
        "inputExpected": "There's a plug-in called the Kirchhoff EQ which has several different modeled curves that you can assign per band. I wanted to make something that could randomize the shapes of the EQ bands I used. Each instance of the Kirchhoff EQ is instantiated with my user default preset. This preset consists of 12 bands -- two filters (inactive by default), two shelves (active by default) and eight bells (active by default). I have managed to make great progress with this idea. The script can already establish which bands have been moved, what the shape of that band is and what corresponding shapes exist that i can choose from at random. I don't get any errors when running the script however it is not function as intended. I believe this may simply be a result of trying to change parameter values too quickly. Currently I am using elementClick({ actionName: AXIncrement )} and the corresponding Decrement to adjust for the delta. Any help would be amazing. It would be really handy to see if broader Qs or slightly different curves could be better.",
        "inputIsError": false,
        "inputWhatHappens": "The parameter changes but incorrectly",
        "inputHowRun": {
            "key": "-MpfwmPg-2Sb-HxHQAff",
            "title": "I used a Stream Deck button"
        },
        "inputImportance": 5,
        "inputTitle": "Three-Body Technology's Kirchhoff EQ: Curve Randomizer"
    }

    Source

    function getUsedEqBands(kirchhoffEq, allEqBands) {
    
        let enabledBands = []
    
        for (let i = 0; i < allEqBands.length; i++) {
    
            let bandEnabled = kirchhoffEq.sliders.whoseTitle.is(`Band${allEqBands[i]} Enabled`).first.value.invalidate().intValue;
            // 0.03 dB = +1 in intValue. 0 dB = 1024 intValue
    
            if (bandEnabled === 1) {
                enabledBands.push(allEqBands[i])
            }
        }
    
        let usedEqBands = []
    
        for (let i = 0; i < enabledBands.length; i++) {
    
            let eqBandType = kirchhoffEq.sliders.whoseTitle.is(`Band${enabledBands[i]} Type`).first;
    
            let eqBandTypeIntValue = eqBandType.value.invalidate().intValue
    
            // Band# Type intValues: 
            // High Pass Filter: Default - 1, Type E - 11, Type G - 19, British N - 25, Vintage Tube - 32
            // Low Pass Filter: Default - 0, Type E - 18, Type G - 24, Vintage Tube - 33
    
            let eqBandGain = kirchhoffEq.sliders.whoseTitle.is(`Band${enabledBands[i]} Gain`).first;
    
            let eqBandGainIntValue = eqBandGain.value.invalidate().intValue;
            // 0.03 dB = +1 in intValue of 1024
    
            if ([0, 1, 11, 18, 19, 24, 25, 32, 33].indexOf(eqBandTypeIntValue) > -1 || eqBandGainIntValue !== 1024) {
                usedEqBands.push(enabledBands[i])
            }
        }
    
        return usedEqBands
    }
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    
    function main() {
    
        sf.ui.proTools.appActivateMainWindow();
        sf.ui.proTools.mainWindow.invalidate();
    
        const kirchhoffEq = sf.ui.proTools.windows.whoseTitle.is('Plug-in: TBTECH Kirchhoff-EQ').first.groups.whoseTitle.is('FXTDMEditView').first;
    
        let allEqBands = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
    
        let usedEqBands = getUsedEqBands(kirchhoffEq, allEqBands);
    
        for (let i = 0; i < usedEqBands.length; i++) {
    
            let eqBandType = kirchhoffEq.sliders.whoseTitle.is(`Band${usedEqBands[i]} Type`).first
    
            let eqBandTypeIntValue = eqBandType.value.invalidate().intValue
    
            let lowShelfTypesList = [4, 12, 20, 26, 29, 34, 39]
    
            let highShelfTypesList = [5, 17, 23, 28, 31, 40, 46]
    
            let bellTypesList = [3, 13, 14, 15, 16, 21, 22, 27, 30, 37, 38, 45]
    
            // Band# Type intValues: 
            // Low Shelves: Default - 4, Type E - 12, Type G - 20, British N - 26, EQ 250 - 29, Vintage Tube - 34, Tone Stack - 39 
            // High Shelves: Default - 5, Type E - 17, Type G - 23, British N - 28, EQ 250 - 31, Vintage Tube (attn) - 36 DON'T INCLUDE, Tone Stack - 40, Blue - 46
            // Bells:
            //////// Default - 3, 
            //////// Type E Low - 13, Type E Low Mid - 14, Type E High Mid - 15, Type E High - 16 
            //////// Type G Low Mid - 21, Type G High Mid - 22
            //////// British N - 27 
            //////// EQ 250 - 30 
            //////// Vintage Tube Boost - 35 DON'T INCLUDE, Vintage Tube Low Mid - 37, Vintage Tube High Mid - 38
            //////// Blue Low - 45
    
            if (lowShelfTypesList.indexOf(eqBandTypeIntValue) > -1) {
                let shelfType = lowShelfTypesList[(Math.random() * 6).toFixed(0)]
    
                let delta = eqBandTypeIntValue - shelfType
    
                log(`Band: ${usedEqBands[i]}, Random Shape: lowShelfTypesList[${shelfType}], Delta: ${delta}`);
    
                if (delta > 0) {
                    for (let i = 0; i < delta; i++) {
                        eqBandType.elementClick({ actionName: 'AXIncrement' });
                    }
                } else if (delta < 0) {
                    for (let i = 0; i < Math.abs(delta); i++) {
                        eqBandType.elementClick({ actionName: 'AXDecrement' });
                    }
                }
            }
    
            if (highShelfTypesList.indexOf(eqBandTypeIntValue) > -1) {
                let shelfType = highShelfTypesList[(Math.random() * 6).toFixed(0)]
    
                let delta = eqBandTypeIntValue - shelfType
    
                log(`Band: ${usedEqBands[i]}, Random Shape: highShelfTypesList[${shelfType}], Delta: ${delta}`);
    
                if (delta > 0) {
                    for (let i = 0; i < delta; i++) {
                        eqBandType.elementClick({ actionName: 'AXIncrement' });
                    }
                } else if (delta < 0) {
                    for (let i = 0; i < Math.abs(delta); i++) {
                        eqBandType.elementClick({ actionName: 'AXDecrement' });
                    }
                }
            }
    
            if (bellTypesList.indexOf(eqBandTypeIntValue) > -1) {
                let bellType = bellTypesList[(Math.random() * 11).toFixed(0)]
    
                let delta = eqBandTypeIntValue - bellType
    
                log(`Band: ${usedEqBands[i]}, Random Shape: bellTypesList[${bellType}], Delta: ${delta}`);
    
                if (delta > 0) {
                    for (let i = 0; i < delta; i++) {
                        eqBandType.elementClick({ actionName: 'AXIncrement' });
                    }
                } else if (delta < 0) {
                    for (let i = 0; i < Math.abs(delta); i++) {
                        eqBandType.elementClick({ actionName: 'AXDecrement' });
                    }
                }
            }
        }
    
    }
    
    main();
    

    Links

    User UID: EoVu20w2ZRTvmJvgozc57ZXuAhU2

    Feedback Key: sffeedback:EoVu20w2ZRTvmJvgozc57ZXuAhU2:-NmdwgrK7Ayd4auJNewy

    Feedback ZIP: hzofMdW0h0ggDPnOpMAKaguDttzjDq8w3kBIzw098EfDdcnjsqBuFbRqGjBfqWeE8DXH8wxJyRlY1UHx3eOAHlYTAu7b3B1XdtfhX7FHvHTvkB1nmJ8chD7+7Pw8pm2nI57tkIVY9/gIDGoovph9+xzUOEjvqoYmFIYFTO7CwQeTkExC51a8+iL5H6zqa/PmfnDtiNcOSCSXjkQhbsg1jXAzNAZQHKjAearIALZ45iOJWguhjIrorW/R/1rRf2OC6zhSFslGWGDcdNViumyvZs2mw6u61disfiR7HKt05VKeLyqjLyXqTJ9kYSVvQSUbFKRvKOO2gcNelOOBBNmeT3EsTzcjzBeDT8Ew1oNPRNc=

    Solved in post #3, click to view
    • 12 replies

    There are 12 replies. Estimated reading time: 15 minutes

    1. Nathan Salefski @nathansalefski
        2023-12-27 06:34:45.640Z

        Here's the aforementioned preset. It should be placed here before launching Pro Tools.

        ~/Documents/Pro Tools/Plug-In Settings/TBTECH Kirchhoff

        https://www.dropbox.com/scl/fi/6x32ssl0wxegla6yvyf15/Default.tfx?rlkey=o605n9bmh7lgtomr9o7l97tad&dl=0

        1. In reply tonathansalefski:
          Nathan Salefski @nathansalefski
            2023-12-27 17:36:54.166Z2023-12-29 20:27:34.020Z

            I figured it out lol. I was calculating the delta incorrectly of course:

            // Band# Type intValues:
            // High Pass Filter: Default - 1, Type E - 11, Type G - 19, British N - 25, Vintage Tube - 32
            // Low Pass Filter: Default - 0, Type E - 18, Type G - 24, Vintage Tube - 33 
            // Low Shelves: Default - 4, Type E - 12, Type G - 20, British N - 26, EQ 250 - 29, Vintage Tube - 34, Tone Stack - 39 
            // High Shelves: Default - 5, Type E - 17, Type G - 23, British N - 28, EQ 250 - 31, Vintage Tube (attn) - 36 DON'T INCLUDE, Tone Stack - 40, Blue - 46
            // Bells:
            //////// Default - 3, 
            //////// Type E Low - 13, Type E Low Mid - 14, Type E High Mid - 15, Type E High - 16 
            //////// Type G Low Mid - 21, Type G High Mid - 22
            //////// British N - 27 
            //////// EQ 250 - 30 
            //////// Vintage Tube Boost - 35 DON'T INCLUDE, Vintage Tube Low Mid - 37, Vintage Tube High Mid - 38
            //////// Blue Low - 45
            // All BANDS
            // 'Band1', 'Band2', 'Band3', 'Band4', 'Band5', 'Band6',
            // 'Band7', 'Band8', 'Band9', 'Band10', 'Band11', 'Band12',
            // 'Band13', 'Band14', 'Band15', 'Band16', 'Band17', 'Band18',
            // 'Band19', 'Band20', 'Band21', 'Band22', 'Band23', 'Band24', 
            // 'Band25', 'Band26', 'Band27', 'Band28', 'Band29', 'Band30', 
            // 'Band31', 'Band32'
            
            ////////////////////////////////////////////////////////////////////////////////////////////////////
            
            function getUsedEqBands(kirchhoffEq) {
            
                let allEqBands = ['Band1', 'Band2', 'Band3', 'Band4', 'Band5', 'Band6', 'Band7', 'Band8', 'Band9', 'Band10', 'Band11', 'Band12']
            
                let enabledBands = allEqBands.filter((value) => {
            
                    let bandEnabled = kirchhoffEq.sliders.whoseTitle.is(`${value} Enabled`).first.value.invalidate().intValue;
            
                    if (bandEnabled === 1) {
                        return value;
                    }
                });
            
                let usedEqBands = enabledBands.filter((value) => {
            
                    let filterTypesList = [0, 1, 11, 18, 19, 24, 25, 32, 33]
            
                    let eqBandTypeIntValue = kirchhoffEq.sliders.whoseTitle.is(`${value} Type`).first.value.invalidate().intValue
            
                    let eqBandGainIntValue = kirchhoffEq.sliders.whoseTitle.is(`${value} Gain`).first.value.invalidate().intValue;
            
                    if (filterTypesList.indexOf(eqBandTypeIntValue) > -1 || eqBandGainIntValue !== 1024) {
                        return value;
                    }
                });
            
                return usedEqBands
            };
            
            ////////////////////////////////////////////////////////////////////////////////////////////////////
            
            function main() {
            
                sf.ui.proTools.appActivateMainWindow();
                sf.ui.proTools.mainWindow.invalidate();
            
                const kirchhoffEq = sf.ui.proTools.windows.whoseTitle.is('Plug-in: TBTECH Kirchhoff-EQ').first.groups.whoseTitle.is('FXTDMEditView').first;
            
                let usedEqBands = getUsedEqBands(kirchhoffEq);
            
                for (let i = 0; i < usedEqBands.length; i++) {
            
                    let eqBandType = kirchhoffEq.sliders.whoseTitle.is(`${usedEqBands[i]} Type`).first
            
                    let eqBandTypeIntValue = eqBandType.value.invalidate().intValue
            
                    let hpfTypesList = [1, 11, 19, 25, 32]
            
                    let lowShelfTypesList = [4, 12, 20, 26, 29, 34, 39]
            
                    let highShelfTypesList = [5, 17, 23, 28, 31, 40, 46]
            
                    let lpfTypesList = [0, 18, 24, 33]
            
                    let bellTypesList = [3, 13, 14, 15, 16, 21, 22, 27, 30, 37, 38, 45]
            
                    let delta;
            
                    if (hpfTypesList.indexOf(eqBandTypeIntValue) > -1) {
                        let filterType = hpfTypesList[(Math.random() * 4).toFixed(0)]
            
                        delta = filterType - eqBandTypeIntValue
            
                        if (delta > 0) {
                            for (let i = 0; i < delta; i++) {
                                eqBandType.elementClick({ actionName: 'AXIncrement' });
                            }
                        } else if (delta < 0) {
                            for (let i = 0; i < Math.abs(delta); i++) {
                                eqBandType.elementClick({ actionName: 'AXDecrement' });
                            }
                        }
                    }
            
                    ////////////////////////////////////////////////////////////////////////////////////////////////////
            
                    if (lowShelfTypesList.indexOf(eqBandTypeIntValue) > -1) {
                        let shelfType = lowShelfTypesList[(Math.random() * 6).toFixed(0)]
            
                        delta = shelfType - eqBandTypeIntValue
            
                        if (delta > 0) {
                            for (let i = 0; i < delta; i++) {
                                eqBandType.elementClick({ actionName: 'AXIncrement' });
                            }
                        } else if (delta < 0) {
                            for (let i = 0; i < Math.abs(delta); i++) {
                                eqBandType.elementClick({ actionName: 'AXDecrement' });
                            }
                        }
                    }
            
                    ////////////////////////////////////////////////////////////////////////////////////////////////////
            
                    if (highShelfTypesList.indexOf(eqBandTypeIntValue) > -1) {
                        let shelfType = highShelfTypesList[(Math.random() * 6).toFixed(0)]
            
                        delta = shelfType - eqBandTypeIntValue
            
                        if (delta > 0) {
                            for (let i = 0; i < delta; i++) {
                                eqBandType.elementClick({ actionName: 'AXIncrement' });
                            }
                        } else if (delta < 0) {
                            for (let i = 0; i < Math.abs(delta); i++) {
                                eqBandType.elementClick({ actionName: 'AXDecrement' });
                            }
                        }
                    }
            
                    ////////////////////////////////////////////////////////////////////////////////////////////////////
            
                    if (lpfTypesList.indexOf(eqBandTypeIntValue) > -1) {
                        let filterType = lpfTypesList[(Math.random() * 3).toFixed(0)]
            
                        delta = filterType - eqBandTypeIntValue
            
                        if (delta > 0) {
                            for (let i = 0; i < delta; i++) {
                                eqBandType.elementClick({ actionName: 'AXIncrement' });
                            }
                        } else if (delta < 0) {
                            for (let i = 0; i < Math.abs(delta); i++) {
                                eqBandType.elementClick({ actionName: 'AXDecrement' });
                            }
                        }
                    }
            
                    ////////////////////////////////////////////////////////////////////////////////////////////////////
            
                    if (bellTypesList.indexOf(eqBandTypeIntValue) > -1) {
                        let bellType = bellTypesList[(Math.random() * 11).toFixed(0)]
            
                        delta = bellType - eqBandTypeIntValue
            
                        if (delta > 0) {
                            for (let i = 0; i < delta; i++) {
                                eqBandType.elementClick({ actionName: 'AXIncrement' });
                            }
                        } else if (delta < 0) {
                            for (let i = 0; i < Math.abs(delta); i++) {
                                eqBandType.elementClick({ actionName: 'AXDecrement' });
                            }
                        }
                    }
                }
            }
            
            main();
            
            ReplySolution
            1. Nathan Salefski @nathansalefski
                2023-12-29 20:12:02.187Z2023-12-29 20:28:03.177Z

                We need an @avengers for all the geniuses on here. @Chad @Dustin_Harris @Chris_Shaw @raphaelsepulveda or @Kitch, completely at your leisure/if at all interested: this works great but is kinda slow. Are there ways you can see that this could be optimized? I believe that the getUsedEqBands(kirchhoffEq); function is what's slowing it down but without it, I feel like the large "for" loop in the main function would be incredibly inefficient.

                Any ideas at all would be greatly appreciated. I hope you've had a Happy Holidays and have a great New Year!

                1. Kitch Membery @Kitch2023-12-29 21:00:04.176Z

                  Unfortunately, I don't have the "Kirchhoff EQ". So that counts me out.

                  1. In reply tonathansalefski:
                    Dustin Harris @Dustin_Harris
                      2023-12-29 21:15:26.383Z

                      Is it slow -before- doing the AXIncrement/Decrement? because those actions are the things I'd assume are the slow ones (the band intValues themselves are not directly settable, so there is no choice there)

                      1. Dustin Harris @Dustin_Harris
                          2023-12-29 21:46:51.303Z

                          at any rate, here's a quick refactor of getUsedBands, but I've modified it to use all bands, and there is a filter to limit the bands to below a certain number:

                          /**@param {AxElement} kirchhoffEq */
                          function getUsedEqBands(kirchhoffEq) {
                          
                              const enabledBands = kirchhoffEq.children.whoseTitle.contains("Enabled")
                                  .filter(e => e.value.intValue === 1).map(b => b.title.value.split(" ")[0]);
                              //end enabledBands
                          
                              const usedEqBands = enabledBands.filter((bandNumber) => {
                          
                                  //enable limit if desired
                                  //if (Number(bandNumber.replace('Band', "")) > 12) return
                          
                                  const filterTypesList = [0, 1, 11, 18, 19, 24, 25, 32, 33];
                          
                                  let eqBandTypeIntValue = kirchhoffEq.sliders.whoseTitle.is(`${bandNumber} Type`).first.value.invalidate().intValue;
                                  let eqBandGainIntValue = kirchhoffEq.sliders.whoseTitle.is(`${bandNumber} Gain`).first.value.invalidate().intValue;
                          
                                  if (filterTypesList.includes(eqBandTypeIntValue) || eqBandGainIntValue !== 1024) {
                                      return bandNumber;
                                  }
                              });
                          
                              return usedEqBands
                          };
                          
                          1. Nathan Salefski @nathansalefski
                              2023-12-29 22:47:07.606Z

                              Once the script is run there's probably about 3000ms before it starts to perform the AXIncrement or AXDecrement actions. Plugging in this refactor has sped it up some. That rework of the enabledBands is elegant. I didn't realize you could .filter and .map like that

                              1. Dustin Harris @Dustin_Harris
                                  2023-12-30 06:01:24.214Z

                                  changing the final if statement in the function to
                                  if (eqBandGainIntValue !== 1024 ||filterTypesList.includes(eqBandTypeIntValue))
                                  might be a little quicker too since it skips iterating over the filterTypesList array if it doesn't need to...

                                  1. Nathan Salefski @nathansalefski
                                      2023-12-30 07:23:24.423Z

                                      Thanks man. I’ll try that out in the am and see how it goes. The if (eqBandGainIntValue !== 1024 ||filterTypesList.includes(eqBandTypeIntValue)) is to determine if there’s filters so I think you’re right, only two filters would ever exist so it would likely speed it up tremendously

                                      1. In reply toDustin_Harris:
                                        Nathan Salefski @nathansalefski
                                          2024-01-17 20:14:14.316Z

                                          Hey Dustin,

                                          I was playing around with the accessibility inspector and noticed that there is a fourth way to interact with some plugin parameters that I haven't seen before, it's 'pick'. Is that a way to set parameters directly using .elementClick({ actionName: 'AXPick' }); in some capacity?

                                          1. Dustin Harris @Dustin_Harris
                                              2024-01-17 20:19:22.077Z

                                              Heyya Nathan! I’m not sure what AXPick does, I haven’t come across it yet… I’m away at the moment but I can mess around with it next week…

                                              1. Nathan Salefski @nathansalefski
                                                  2024-01-17 22:36:00.231Z

                                                  Thanks man