Audio System Design Tool++ update

Hi,
* You define the array like this:
arrayOfVoices.png

* static class member's value?

* I have now included a option that is found in the rename class(tab/workspace) dialog.
(it's opened by double clicking the tab)
Rename_tab_workspace_sheet.png

I have also created a field to add extra class declarations when having inheritance.

There is also a new object called destructor code @ special category
this makes it possible to add additional destructor code

* When a project is given a specific name @ settings - arduino - project name
(and then applied/saved)
all unique saved projects are available at the main menu (top right) - projects

note. all projects are stored in the browser indexedDB which will be deleted when clearing the browser cache

When exporting as a zip this zip can then be imported again (it will look for the GUI_TOOL.json inside that zip, and use that)

* I have created a example that should mostly reassemble your example
"On the use of a base class, consider the following:"

Code:
{"version":1,"settings":{"arduino":{"IOcheckAtExport":false,"Board":{"Platform":"","Board":"","Options":""}},"BiDirDataWebSocketBridge":{},"workspaces":{},"sidebar":{},"palette":{},"editor":{},"devTest":{},"IndexedDBfiles":{"testFileNames":"testFile.txt"},"NodeDefGenerator":{},"NodeDefManager":{},"NodeHelpManager":{}},"workspaces":[{"type":"tab","id":"Main","label":"SynthVoice","inputs":0,"outputs":0,"export":true,"isMain":false,"mainNameType":"tabName","mainNameExt":".ino","generateCppDestructor":false,"extraClassDeclarations":"","settings":{},"nodes":[{"id":"SynthVoice_code1","type":"Function","name":"code","comment":"private:\r\n  AudioConnection outputCord;\r\n  virtual AudioStream& getOutputStream(void) = 0;\r\npublic:\r\n  virtual ~SynthVoice(){};\r\n  virtual void noteOn(float freq, float vel, int chan=-1) = 0;\r\n  virtual void noteOn(int MIDInote, int MIDIvel, int chan=-1) = 0;\r\n  virtual void noteOff(void) = 0;\r\n  virtual bool isPlaying(void) = 0;\r\n  int connect(AudioStream& str) { return connect(str,0);}","x":140,"y":65,"z":"Main","bgColor":"#DDFFBB","wires":[]}]},{"type":"tab","id":"f061342f.9b8268","label":"WaveAndEnvVoice","inputs":0,"outputs":0,"export":true,"isMain":false,"mainNameType":"tabName","mainNameExt":".ino","generateCppDestructor":true,"extraClassDeclarations":"final : public SynthVoice","settings":{},"nodes":[{"id":"WaveAndEnvVoice_includeDef1","type":"IncludeDef","name":"\"SynthVoice.h\"","comment":"","x":240,"y":70,"z":"f061342f.9b8268","bgColor":"#DDFFBB","wires":[]},{"id":"WaveAndEnvVoice_waveform1","type":"AudioSynthWaveform","name":"wave","comment":"","x":245,"y":130,"z":"f061342f.9b8268","bgColor":"#E6E0F8","wires":[["WaveAndEnvVoice_exp env1:0"]]},{"id":"WaveAndEnvVoice_code1","type":"Function","name":"code1","comment":"private:\n  bool isNew;\n  \n  static short wave_type[4];\n  AudioStream& getOutputStream(void) {AudioStream& result {amp}; return result;};\n\npublic:  \nvoid noteOn(int MIDInote, int MIDIvel, int chan=-1){}; // don't support this\nvoid noteOn(float freq, float vel, int chan=-1)\n{\n    // ... do some stuff\n}\nvoid noteOff(void){env.noteOff();};\nbool isPlaying(void) {return env.isActive();};\n    ","x":255,"y":210,"z":"f061342f.9b8268","bgColor":"#DDFFBB","wires":[]},{"id":"WaveAndEnvVoice_constructor code1","type":"ConstructorCode","name":"constructor code","comment":"env.attack(129.2);\n// .. etc.\n\nwave_type[] = {\n    WAVEFORM_PULSE,\n    WAVEFORM_SQUARE,\n    WAVEFORM_SAWTOOTH,\n    WAVEFORM_TRIANGLE\n};","x":226,"y":274,"z":"f061342f.9b8268","bgColor":"#DDFFBB","wires":[]},{"id":"WaveAndEnvVoice_exp env1","type":"AudioEffectExpEnvelope","name":"env","comment":"","x":345,"y":130,"z":"f061342f.9b8268","bgColor":"#E6E0F8","wires":[["WaveAndEnvVoice_amp1:0"]]},{"id":"WaveAndEnvVoice_amp1","type":"AudioAmplifier","name":"amp","comment":"","x":450,"y":130,"z":"f061342f.9b8268","bgColor":"#E6E0F8","wires":[["WaveAndEnvVoice_Out1:0"]]},{"id":"WaveAndEnvVoice_Out1","type":"TabOutput","name":"Out","comment":"","x":575,"y":130,"z":"f061342f.9b8268","bgColor":"#cce6ff","wires":[]}]},{"type":"tab","id":"a6317b06.79ff28","label":"SomeOtherTopologyVoice","inputs":0,"outputs":0,"export":true,"isMain":false,"mainNameType":"tabName","mainNameExt":".ino","generateCppDestructor":true,"extraClassDeclarations":"final : public SynthVoice","settings":{},"nodes":[{"id":"SomeOtherTopologyVoice_includeDef1","type":"IncludeDef","name":"\"SynthVoice.h\"","comment":"","x":210,"y":75,"z":"a6317b06.79ff28","bgColor":"#DDFFBB","wires":[]}]},{"type":"tab","id":"32dd68c9.e73c58","label":"Main","inputs":0,"outputs":0,"export":true,"isMain":true,"mainNameType":"projectName","mainNameExt":".ino","generateCppDestructor":false,"extraClassDeclarations":"","settings":{},"nodes":[{"id":"Main_includeDef1","type":"IncludeDef","name":"\"SynthVoice.h\"","comment":"","x":190,"y":125,"z":"32dd68c9.e73c58","bgColor":"#DDFFBB","wires":[]},{"id":"Main_includeDef2","type":"IncludeDef","name":"\"WaveAndEnvVoice.h\"","comment":"","x":180,"y":165,"z":"32dd68c9.e73c58","bgColor":"#DDFFBB","wires":[]},{"id":"Main_includeDef3","type":"IncludeDef","name":"\"SomeOtherTopologyVoice.h\"","comment":"","x":170,"y":203,"z":"32dd68c9.e73c58","bgColor":"#DDFFBB","wires":[]},{"id":"Main_code1","type":"Function","name":"code2","comment":"\r\n\r\n#define POLYPHONY 12\r\nSynthVoice* voices[POLYPHONY] = {NULL};\r\n\r\nmakerFunction(void)\r\n{\r\n   voices[0] = new SomeOtherTopologyVoice;\r\n   voices[1] = new WaveAndEnvVoice;\r\n}\r\n\r\n\r\nvoid breakerFunction(int v)\r\n{\r\n  if (NULL != voices[v])\r\n  {\r\n    delete voices[v];\r\n    voices[v] = NULL;\r\n  }\r\n}\r\n\r\nvoid setup() {\r\n    \r\n}\r\n\r\nvoid loop() {\r\n    \r\n}","x":160,"y":275,"z":"32dd68c9.e73c58","bgColor":"#DDFFBB","wires":[]}]},{"type":"tab","id":"f8aa3d4.01479c","label":"ArrayOfVoicesExample","inputs":0,"outputs":0,"export":true,"isMain":false,"mainNameType":"main","mainNameExt":".ino","generateCppDestructor":true,"extraClassDeclarations":"","settings":{},"nodes":[{"id":"SynthExample_WaveAndEnvVoice1","type":"WaveAndEnvVoice","name":"waev[8]","x":261,"y":180,"z":"f8aa3d4.01479c","bgColor":"#CCFFCC","wires":[["SynthExample_mixer1:0"]]},{"id":"SynthExample_mixer1","type":"AudioMixer","name":"mixer","inputs":"1","comment":"","x":430,"y":180,"z":"f8aa3d4.01479c","bgColor":"#E6E0F8","wires":[[]]}]}],"nodeAddons":{"expEnvelope":{"isAddon":true,"label":"exp envelope","description":"","credits":"","homepage":"","url":"https://api.github.com/repos/[user]/[repository]/contents/[subpath if any]","types":{"AudioEffectExpEnvelope":{"defaults":{"name":{"value":"WaveAndEnvVoice_exp env1"},"comment":{},"color":{"value":"#E6E0F8"}},"shortName":"exp env","inputs":1,"outputs":1,"inputTypes":{"0":"i16"},"outputTypes":{"0":"i16"},"category":"effect","help":"","color":"#E6E0F8","icon":"arrow-in.png"}}}}
}

} is at new line to make coping easier don't forget to include it
 
That's great, I think it'll be really helpful - thanks. It's so useful to have the demo JSON easy to load, makes everything very clear.

One thing I've been struggling with (hence the delayed response) is the proper definition of static class members. I don't think your way of initialising it in the constructor is valid syntax, or "correct" C++: as I understand it static class members are common to all instantiations of a class, and rarely changed. An example is AudioStream::first_update, which is the one and only pointer to the first AudioStream object to be updated on the 2.9ms update interrupt; every AudioStream object has its own next_update which refers to the next one to update, until they're all done. In statically-defined Teensy audio systems first_update is set early in the run-time and never changed: in my dynamic version, it does get changed, but only if a new object is logically the one which should get updated first .

However, I did find a way of doing what I want to. Here's a code object:
Code:
// Start of voice class manually-entered code
    void noteOn(int MIDInote, int MIDIvel, int chan=-1){};
    void noteOn(float freq, float vel, int chan=-1)
    {
      if (isNew)
        wave.begin(vel,freq,(chan<0)?WAVEFORM_SINE:(wave_type[chan&3]));
      else
      {
        wave.amplitude(vel);
        wave.frequency(freq);
      }
      env.noteOn();
      isNew = false;
    }

    void noteOff(void){env.noteOff();};
    bool isPlaying(void) {return env.isActive();};
[COLOR="#FF0000"][B]}; // terminates class[/B][/COLOR]

static short WaveformVoice::wave_type[] = {
    WAVEFORM_SINE,
    WAVEFORM_SQUARE,
    WAVEFORM_SAWTOOTH,
    WAVEFORM_TRIANGLE // no closing brace, GUI tool puts it in
// End of voice class manually-entered code
You'll see I put in my own class terminator, and then defined the static class member without a closing brace, as your tool will put it in for me. It's a bit of a hack, but works OK.
 
Hi,

I have now included a new node object called
"eof code" available at the special category
(so that no workaround is needed).

with that you can define code that should be "outside" the class
(the code is placed at the end of the file and after the class declaration)

here is the json that you can import (pretty simple but I include it anyway)
(don't forget to uncheck the replace flow checkbox)
Code:
[{"id":"WaveAndEnvVoice_constructor code1","type":"ConstructorCode","name":"constructor code","comment":"env.attack(129.2);\n// .. etc.","x":226,"y":274,"z":"f061342f.9b8268","bgColor":"#DDFFBB","wires":[]},{"id":"WaveAndEnvVoice_eof code1","type":"EndOfFileCode","name":"eof code","comment":"static short WaveAndEnvVoice::wave_type[] = {\n    WAVEFORM_PULSE,\n    WAVEFORM_SQUARE,\n    WAVEFORM_SAWTOOTH,\n    WAVEFORM_TRIANGLE\n};","x":251,"y":320,"z":"f061342f.9b8268","bgColor":"#DDFFBB","wires":[]}
]


There is more demo examples at the "main menu" - Examples

My own project is called "Manicken Poly Synth"
which is a complete and working project,
only need to download the huge wavetable instruments separately.


/Jannik
 
Fixed now, it was a small bug.

It was occurring when the Tool was loaded the very first time, a workaround was to refresh the page.

But now it should(of what I have been testing) be working the very first time as well, i.e. after clearing browser cache.

A tip for all who use this tool is to open the browser dev-tools to view the javascript console-log, when errors like this occur,
and post the log contents in a zip,
it can be faster for me to pinpoint specific errors.
 
Fixed now, it was a small bug.

It was occurring when the Tool was loaded the very first time, a workaround was to refresh the page.

But now it should(of what I have been testing) be working the very first time as well, i.e. after clearing browser cache.

A tip for all who use this tool is to open the browser dev-tools to view the javascript console-log, when errors like this occur,
and post the log contents in a zip,
it can be faster for me to pinpoint specific errors.

I think's its working now, the problem persist when i'm using a 'private mode' browser, the suspect is IndexedDB process seems not working in private mode browser, but the original Audio System Design Tool code is working on both in normal and private mode browser, its will be great if your mod can also working in 'private mode' browser, thanks for this fantastic mods.
 

Attachments

  • console-export-2021-7-30_23-21-45.zip
    3.4 KB · Views: 57
Last edited:
Ok now it works in "private mode" as well

But when using "private mode" the indexedDB functionality is not available,

which means that the following functionalities are not available:

* multiple project saving/loading (using browser storage)
* loading and use node addons help
 
This is a work of pure genius - rather curiously Paul Stoffregen posted on Twitter over Christmas saying he should look at doing a "multi voice" audio tool and when I tweeted back about this (your older version) he wasn't aware of it but really this should become the main audio design tool that everyone uses.

@wrightflyer What exactly would it mean to have a multi-voice audio tool? I know a lot of folks have built poly synths using the current library, myself included, that could be considered multi-voice. I'm really curious what the implications would be.

Also, @manicksan, this is so cool! Thanks so much for sharing it. I'm excited to try it out.
 
Ok now it works in "private mode" as well

But when using "private mode" the indexedDB functionality is not available,

which means that the following functionalities are not available:

* multiple project saving/loading (using browser storage)
* loading and use node addons help

Ok ok, it's an excellent input for me as a beginner web programmer, still thinking the possibilities or feature to use external DB from your code to enable the IndexedDB funtion such as Redis or other tools... once more im really appreciate with your excellent works...., thanks in advance.
 
To answer "What exactly would it mean to have a multi-voice audio tool?"

Also it's just more than a multi-voice audio tool now:

* allow for complex designs to be separated into "tabs" (actually classes)
* by using the "c++ template mixer" a array of voices can have any size without need to stack several mixers.
* the whole design can be created directly in the tool by using code objects
* by using a "java program" the synth can be controlled in the tool using special ui-objects (just like pure data but easier)
this "java program" is just a web server + websocket server which makes it possible for the tool to talk to midi devices.

* the code export contains all audio connections for the connections between "tabs"
manually edit is not needed

* in the export items are sorted by column
1 4 7
2 5 8
3 6 9

* plus more improvements


Better to just describe how it's done:

first it starts with an empty project:
EmptyProject.png

to first create the voice class
here you rename it by double click the main-tab

second you can add and second tab by clicking the top right '+' sign
this new tab is renamed the same way

third switch to the Voice class
and edit the design

note. the input and output objects they are found in the special category

VoiceClass.png

the input and output objects are just placeholders do define the inputs/outputs
for the Voice class.

last create the synth class
SynthClass.png

the new Voice class is found in the "tabs" category

here I'm using the "template mixer" but for designs using only 4 voices the standard mixer can be used
then only connect the voices[4] output to the first mixer input, the tool takes care of the rest.

This is the most basic design of what I can think of.

Then in your main "sketch" the whole Synth can be initialized by using

Code:
Synth synth;
 
Ok ok, it's an excellent input for me as a beginner web programmer, still thinking the possibilities or feature to use external DB from your code to enable the IndexedDB funtion such as Redis or other tools... once more im really appreciate with your excellent works...., thanks in advance.

I have created plugins to both Arduino IDE and VSCODE that make it possible to save/load the design by using a sketch/project stored JSON file
 
To answer "What exactly would it mean to have a multi-voice audio tool?"

Also it's just more than a multi-voice audio tool now:

* allow for complex designs to be separated into "tabs" (actually classes)
* by using the "c++ template mixer" a array of voices can have any size without need to stack several mixers.
* the whole design can be created directly in the tool by using code objects
* by using a "java program" the synth can be controlled in the tool using special ui-objects (just like pure data but easier)
this "java program" is just a web server + websocket server which makes it possible for the tool to talk to midi devices.
* the code export contains all audio connections for the connections between "tabs"
manually edit is not needed

Wow. So you wouldn't have to repeat the code for each voice?! This sounds awesome. Looking forward to trying this out when I get home.
 
Update for the Node Definitions Manager Manual (i.e. adding new custom AudioObjects to the tool)

open node def. mgr.
NewType0.png

click add group
NewType1.png

fill in the details
(note there is a popup text for each of the fields describing what it is)
NewType2.png

then select the new group (here I choose the UID newGroup in the prev step)
NewType3.png

click add new node type
NewType4.png

here the TypeName is your custom AudioObject class name
(example AudioMixer4 is the class name for the mixer4 object)

Specially check and change (if needed) the following json variables
shortName, inputs, outputs,
inputTypes and outputTypes should be removed if not used
also note that inputs and outputs have no use if inputTypes and outputTypes are defined
as the inputs and outputs are set from inputTypes and outputTypes if available

if you still want to use the iotypes the syntax for inputTypes and outputTypes
is:
Code:
"inputTypes": {
        "x4": "i16"
    },
here it means there are 4 inputs
NewType5.png

then you have the new AudioObject to play with
NewType6.png

note you can always change the node def. afterwards
just select the type
make the changes and press Apply
 
Some updates:

* Fixed my "Flexible" AudioMixer object (just called mixer in the mixer category)
Now it autogenerates mixer code for every mixer variant that you use.
that is included at the top of the generated code in both "flat" simple and class exports,
when exporting as zip two files are generated mixers.cpp and mixers.h

+ supported at simple export
("flat" exports right now generates multiline code but I plan to do some one liner compact code of it)

+ don't generate code for the 4 input variant that already exists in the Audio Lib


* Simple export can now handle arrays (only support standard Library Audio objects)

so the following design can now be exported
SimpleExportArray.png

here the junctions are only to make the design easier to follow
and the group box is to clarify what belongs to the "voice"

also note that I have used the "Flexible" mixer both in the voice and as the "external" main mixer.
To use the mixer with a array the "autosize" only works if the mixer have one input.
Also note that the maximum allowed inputs of the mixer is 255
so if a "sourcing" array is bigger than that it will truncate at 255.
So if you want to do a 1000 mega drone
https://www.youtube.com/watch?v=c3wk9WWTfNs
you have to do it like this:
1000megadrone.png

note. this is however only intended for simple designs

for bigger complex designs I recommend to use "class based export to zip"
which will separate all the parts of the design into multiple files
and thus make it much easier to read and maintain.

There is also a ongoing development to make it possible for live edit and update of the design
using OSC (Open Sound Control) transport layer.
https://forum.pjrc.com/threads/68798-Open-Sound-Control-(OSC)-Teensy-Audio-Library-Implementation

Documentation will be posted when that is in a more stable state
right now I'm struggling with "class" based designs.

* Fix code autocomplete to also scan and use Variables object nodes/blocks
note. it will not include "globally" variables declared inside Function code objects
 
There are some new improvements to the tool:

* Now it only do a IO check when there is any audio objects
also now the IO check dialog is just a warning,
so that you can still export if you choose so.

(the IO check setting is still there for some very rare situations)

* Also I have make it possible to export files into a subfolder in the zip file
There is a setting to enable that
@ settings-arduino-"Zip file subfolder"

the name is firstly taken from the main tab if set
then if there is no main tab it uses the name from:
settings-arduino-projectname

this functionality is useful when anyone want to export complete Arduino sketches.

* On Node-RED there is a neat feature, but caused some problems on this tool
When a link is drawn from a object output to another object you don't actually have
to drop the link on a port, instead you can just drop it anywhere on the 'target' node
this did make it possible (still on the official tool, so you can try it there)
to connect multiple signals to the first input of any object.
this above also make it possible to drop a 'input' (when a link is drawn from a input)
to objects not having any IO (that means all control objects)

the all above problems are now fixed in my tool
* you can't drop any link to any object not having any IO
* now when a 'output' (when a link is drawn from a output)
link is drawn it can just be dropped to a object and it will automatically add itself to the first free input
This "auto add" feature can be turned off in settings-"Workspace/view"-Nodes-"Auto append dropped links"
if you find it annoying

note. the opposite is not yet possible i.e. adding a 'input'-link automatically to outputs of any node

here is how I drop a new link to a mixer

AutoAddDroppedLinks.png

note. if the second input was free (not connected to)
then the new link would be connected to that instead of the last input

here is a diagram showing how it could look like before
AutoAddDroppedLinks_bug.png
 
Is the Node Definitions Manager broken at the moment? I don't seem to be able to add a new node type to my group...

This may be academic, as it's a new implementation of AudioEffectDelayExternal I want to test, which requires two parameters on construction: int (storage type), float (max delay length [ms]). And I don't think there's an easy way of specifying those in the GUI, and then passing them to the OSC uploader on export.
 
are you trying to add it to the h4yn0nnym0u5e "category"?
as that is "hardcoded" and readonly
(and currently used to hold the AudioStereoMixer)

also note that the name
AudioEffectDelayExternal
cannot be used
and you need to use a different name
(just saying)

on my side still working:
NodedefmgrStillWorking.png
 
Just done a PR with speculative code to allow custom nodes to add extra parameters to the OSC message at creation time. I haven't implemented that for the audio mixers, but if we did, it would probably remove a few lines of code from the GUI, and replace it with a tweak to the node definitions.

Referring to line numbers relative to my new OSC-export.js, I'm not 100% sure what's going on at lines 227 and 231. I can't see what design features might trigger their execution, but they look a bit odd to me, as if they're trying to create arrays of non-class objects.

EDIT: this will start working properly for you when I commit my latest OSCAudio changes - haven't done that yet...
 
I'm not 100% sure what's going on at lines 227 and 231. I can't see what design features might trigger their execution, but they look a bit odd to me, as if they're trying to create arrays of non-class objects.

They are used when creating arrays of non class objects inside a class,
can be used when one want to create a array of for example simple AudioSynthWaveForm or similar

Yes I want to support nearly every possible situation.


Have also now merged your changes to my main branch

I have looked at the makeConstructor thingy
to make it more general and much easier to maintain

Code:
line 189: eval(node._def.makeConstructor.group);
line 205: eval(node._def.makeConstructor.root);

can be change into:
Code:
line 189: 
packets.add(OSC.GetCreateObjectAddr(),"sss"+node._def.makeConstructor.valueTypes, n.type, grpName, fixLeadingSlash(name), ...get_makeConstructor_values(node));
line 205: 
packets.add(OSC.GetCreateObjectAddr(),"ss"+node._def.makeConstructor.valueTypes, n.type, n.name, ...get_makeConstructor_values(node));

by using a helper function:
Code:
function get_makeConstructor_values(node)
{
    var values = [];
    var names = node._def.makeConstructor.valueNames.split(",");
    for (var i=0;i<names.length;i++)
    {
        values.push(node[names[i].trim()]);
    }
    return values;
}
which avoids using the 'slow' eval function at all

then the node def. can be changed into the much easier format:

Code:
"makeConstructor": {
    "valueTypes": "if", 
    "valueNames": "memtype, length"
}

note the name 'length' should be avoided, as in some cases it's a reserved word

maybe better to rename it to something more suiting
like delayMs
or just delay



sidenote.
Also by looking at my own code I can see that I mix using n and node respective
that is not needed anymore because the internal structure, has been changed to the better.
(and actually both n and node do actually refer to the same object can surely be verified by n===node which should return true in all cases)
I will fix that sometime soon, ie. to only use node or n everywhere.
 
That’s great: please do simplify the makeConstructor approach as you say - easier to maintain! I’ll change my custom object to suit. Do you agree it can also be used for mixers? Should allow you to remove some code, I think.

Agree about n / node, I think using node would be better, I tend to use one-letter variables for short lifespan or small scope purposes, whereas the node often “lasts for” many lines of code.
 
No need to change your custom object
I have now implemented it into the official AudioEffectDelayExternal node def.
also there is now a checkbox to select if it (makeConstructor) should be used or not

here is the changed AudioEffectDelayExternal definition:
(just to clarify how it looks like)
Code:
"AudioEffectDelayExternal":{...AudioTypeArrayBase,"shortName":"delayExt","inputs":1,"outputs":8,"category":"effect",
    "defaults":{
        ...AudioTypeArrayBase.defaults,"outputs":{"value":"8"},
        "useMakeConstructor": {
            "value": false,
            "editor": {
                "label":"Make Constructor",
                "type":"boolean",
                "rowClass":"form-row-long"
            }
            
        },
        "memtype": {
            "type": "int",
            "value": "3",
            "editor": {
                "label": "Mem Type",
                "help": "Currently only used by h4yn0nnym0u5e OSC library<br><br>"+
                        "AUDIO_MEMORY_23LC1024 = 0,    // 128k x 8 S-RAM<br>"+
                        "AUDIO_MEMORY_MEMORYBOARD = 1,<br>"+
                        "AUDIO_MEMORY_CY15B104 = 2,    // 512k x 8 F-RAM<br>"+
                        "<br>Following only at h4yn0nnym0u5e updated audio-lib.<br>"+
                        "AUDIO_MEMORY_PSRAM64 = 3, // 64Mb / 8MB PSRAM (95s @ 44kHz / 16 bit)<br>"+
                        "AUDIO_MEMORY_INTERNAL = 4,  // 8000 samples (181ms), for test only!<br>"+
                        "AUDIO_MEMORY_HEAP = 5,<br>"+
                        "AUDIO_MEMORY_EXTMEM = 6,<br>"+
                        "AUDIO_MEMORY_UNDEFINED > 6"+
                        "<br><br>all above would later be easier by using a combobox selector"
             }
        },
        "maxDelay": {
            "type": "float",
            "value": "2000.0",
            "editor": {
                "label": "Max Delay(ms)",
                "help": "Currently only used by h4yn0nnym0u5e OSC library<br><br>"+
                        "the max delay in milliseconds that is allowed for this instance"
            }
        }
    },
    "makeConstructor": {
        "valueTypes": "if", 
        "valueNames": "memtype, maxDelay"
    }
},

did also made changes to OSC-export so that every case allows the makeConstructor thingy,
even dynmixers
 
That's great - seems to be working fine for me!

What's the best set of .js files for me to tinker with in order to try to make this work for C++ export as well as OSC? Looks like you have Export and Export2 buttons, and maybe these use arduino-export.js and arduino-export2.js? So I should use the v2 files?
 
I've had a bit of a play, and you can find the result in a branch in my fork of your code. It's possibly not worthy of a PR, as I've only really improved on Export2/Class; the result for Export2/Simple is definitely broken! My test design is
Code:
{"version":1,"settings":{"main":{},"OSC":{"RedirectDebugToConsole":false},"arduino":{"ExportForOSC":true,"useExportDialog":true,"ProjectName":"TestDelayExtClass","StandardIncludeHeader":"#include <Arduino.h>\n#include <Audio.h>\n#include <Wire.h>\n#include <SPI.h>\n#include <SD.h>\n#include <SerialFlash.h>\n\n#include <OSCAudioBase.h>\n","Board":{"Platform":"","Board":"teensy41","Options":""}},"BiDirDataWebSocketBridge":{},"workspaces":{},"sidebar":{},"palette":{},"editor":{},"devTest":{},"IndexedDBfiles":{"testFileNames":"testFile.txt"},"NodeDefGenerator":{},"NodeDefManager":{},"NodeHelpManager":{}},"workspaces":[{"type":"tab","id":"Main","label":"AudioMain","nodes":[{"id":"20220403T101520_519Z_b5ff","type":"UI_Button","name":"enable","tag":"","comment":"","w":59,"h":30,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"","x":815,"y":315,"z":"Main","bgColor":"#F6F8BC","wires":[]},{"id":"20220406T084810_432Z_9fb2","type":"AudioSynthWaveform","name":"waveform1","comment":"","arraySize":1,"x":329,"y":428,"z":"Main","bgColor":"#E6E0F8","wires":[["20220403T144247_683Z_d069:0","20220406T165807_908Z_70b:0"]]},{"id":"20220404T073750_610Z_ef7c","type":"AudioEffectDelayExternal","name":"delayExt","comment":"","arraySize":1,"outputs":"8","useMakeConstructor":true,"memtype":"3","maxDelay":"2000.0","x":447,"y":324,"z":"Main","bgColor":"#E6E0F8","wires":[["20220403T101126_926Z_fdb0:1"],["20220403T101126_926Z_fdb0:2"],["20220403T101126_926Z_fdb0:3"],[],[],[],[],[]]},{"id":"20220403T144247_683Z_d069","type":"Looper","name":"looper[6]","comment":"","arraySize":6,"x":480,"y":425,"z":"Main","bgColor":"#CCFFCC","wires":[["20220403T101126_926Z_fdb0:4"],["20220403T101126_926Z_fdb0:5"]]},{"id":"20220406T165807_908Z_70b","type":"Looper","name":"leaper[2]","comment":"","arraySize":2,"x":480,"y":505,"z":"Main","bgColor":"#CCFFCC","wires":[["20220403T101126_926Z_fdb0:7"],["20220403T101126_926Z_fdb0:6"]]},{"id":"20220403T101152_742Z_188a","type":"AudioSynthWaveform","name":"waveform","comment":"","arraySize":1,"x":510,"y":175,"z":"Main","bgColor":"#E6E0F8","wires":[["20220403T101126_926Z_fdb0:0","20220403T101052_022Z_d9d8:0"]]},{"id":"20220403T101126_926Z_fdb0","type":"AudioMixer","name":"mixer","comment":"","arraySize":1,"inputs":8,"ExtraInputs":0,"RealInputs":20,"x":706,"y":198,"z":"Main","bgColor":"#E6E0F8","wires":[["20220403T101052_022Z_d9d8:1","20220404T073750_610Z_ef7c:0"]]},{"id":"20220403T101105_747Z_c59e","type":"AudioControlSGTL5000","name":"sgtl5000","comment":"","x":720,"y":315,"z":"Main","bgColor":"#E6E0F8","wires":[]},{"id":"20220403T101052_022Z_d9d8","type":"AudioOutputI2S","name":"i2s","comment":"","x":840,"y":190,"z":"Main","bgColor":"#E6E0F8","wires":[]}],"links":[],"export":true,"isMain":false,"mainNameType":"tabName","mainNameExt":".ino","isAudioMain":true,"generateCppDestructor":true,"extraClassDeclarations":"","settings":{}},{"type":"tab","id":"20220403T144054_680Z_dbe1","label":"Looper","nodes":[{"id":"20220403T144134_869Z_5d8f","type":"TabInput","name":"In","comment":"","outputs":1,"x":285,"y":60,"z":"20220403T144054_680Z_dbe1","bgColor":"#cce6ff","wires":[["20220404T132211_328Z_1163:0","20220406T130144_493Z_8845:0"]]},{"id":"20220403T144140_901Z_edd7","type":"TabOutput","name":"MixOut","comment":"","inputs":1,"x":730,"y":75,"z":"20220403T144054_680Z_dbe1","bgColor":"#cce6ff","wires":[]},{"id":"20220406T130500_552Z_17e8","type":"TabOutput","name":"DelayOut","comment":"","inputs":1,"x":720,"y":135,"z":"20220403T144054_680Z_dbe1","bgColor":"#cce6ff","wires":[]},{"id":"20220404T132211_328Z_1163","type":"AudioEffectDelayExternal","name":"delay","comment":"","arraySize":1,"outputs":"8","useMakeConstructor":true,"memtype":"6","maxDelay":"30000.0","x":430,"y":130,"z":"20220403T144054_680Z_dbe1","bgColor":"#E6E0F8","wires":[["20220406T130144_493Z_8845:1"],["20220406T130144_493Z_8845:2"],["20220406T130144_493Z_8845:3"],["20220406T130500_552Z_17e8:0"],[],[],[],[]]},{"id":"20220406T182118_313Z_37e8","type":"ConstructorCode","name":"constructor code","comment":"//constructor code","x":491,"y":270,"z":"20220403T144054_680Z_dbe1","bgColor":"#DDFFBB","wires":[]},{"id":"20220406T130144_493Z_8845","type":"AudioMixer","name":"mixer","comment":"","arraySize":1,"inputs":4,"ExtraInputs":0,"RealInputs":4,"x":600,"y":75,"z":"20220403T144054_680Z_dbe1","bgColor":"#E6E0F8","wires":[["20220403T144140_901Z_edd7:0"]]}],"links":[],"export":true,"isMain":false,"mainNameType":"tabName","mainNameExt":".ino","isAudioMain":false,"generateCppDestructor":true,"extraClassDeclarations":"","settings":{}}],"nodeAddons":{"mine":{"isAddon":true,"label":"mine","description":"mine","credits":"me","homepage":"","url":"https://api.github.com/repos/[user]/[repository]/contents/[subpath if any]","types":{"AudioEffectDelayExternal2":{"defaults":{"name":{"type":"c_cpp_name","value":"20220403T144120_253Z_b198"},"id":{"noEdit":""},"comment":{},"color":{"editor":{"type":"color"},"value":"#E6E0F8"},"arraySize":{"value":1,"maxval":255,"minval":1,"type":"int","editor":{"label":"Array Size","help":"(not in use yet, as there is a lot of dependencies on the old style)<br>selects the array size,<br>a value of 0 or 1 mean no array<br>the max value is 255"}},"outputs":{"value":"8"},"memtype":{"type":"int","value":"3"},"length":{"type":"float","value":"2000.0"}},"makeConstructor":{"root":"packets.add(OSC.GetCreateObjectAddr(),\"ssif\",  \"AudioEffectDelayExternal\", n.name,          node.memtype,node.length);","group":"packets.add(OSC.GetCreateObjectAddr(),\"sssif\", \"AudioEffectDelayExternal\", n.name, grpName, node.memtype,node.length);"},"editor":"autogen","shortName":"delayExt2","editorhelp":"","inputs":1,"outputs":8,"category":"effect","color":"#d6d0e8","icon":"arrow-in.png"}}}}
}
Note that this uses two different-sized arrays based on the Looper object in AudioMain, and still manages to get the connectivity right (I think). Full disclosure - I've not actually run anything built with this exporter code, but I have compiled it successfully, barring a couple of warnings.

I see you've done a combobox for enumerated parameters, which is nice. It would be good to send the numeric value to OSC servers, but put in a symbol in when exporting to C++. This is the reason I get warnings from the exported code, because AUDIO_MEMORY_PSRAM64 is an enum; it has the value 3, but C++ quite rightly would rather you use the symbolic name. That's obviously not possible for the OSC messages; I need to work a bit on my class creator to put in the correct casts to remove the warnings...
 
Have done a PR for GUI++ to make boolean OSC parameters work better, I think. Here's an example, see the code in the LED button in the system group:
Code:
{"version":1,"settings":{"main":{},"arduino":{"ProjectName":"AudioPassThrough","Board":{"Platform":"","Board":"","Options":""}},"BiDirDataWebSocketBridge":{},"workspaces":{},"sidebar":{"autoSwitchTabToInfoTab":false},"palette":{},"editor":{},"devTest":{},"IndexedDBfiles":{"testFileNames":"testFile.txt"},"NodeDefGenerator":{},"NodeDefManager":{},"NodeHelpManager":{},"OSC":{"LiveUpdate":true,"RedirectDebugToConsole":false,"UseDebugLinkName":true}},"workspaces":[{"type":"tab","id":"3629fcd9.ccc604","label":"Main","nodes":[{"id":"Main_Button1","type":"UI_Button","name":"use connection to connect wafo to mixer1 input 1","comment":"","w":360,"h":34,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"var addr = \"/teensy1/audio/wafo2mixer1/connect*\"\nvar data = OSC.GetSimpleOSCdata(addr,\"sisi\", \"wafo\", 0, \"mixer1\", 1);\nOSC.SendAsSlipToSerial(data);","x":2200,"y":170,"z":"3629fcd9.ccc604","bgColor":"#F6F8BC","wires":[]},{"id":"Main_Slider1","type":"UI_Slider","name":"ch1","tag":"ga 0","comment":"","w":32,"h":281,"textSize":16,"midiCh":"","midiId":"29","orientation":"v","label":"d.val/d.maxVal","minVal":0,"maxVal":100,"val":75,"divVal":1,"fval":75,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var tags = d.tag.split(' ');\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+tags[0]+\"*\";\nOSC.SendData(OSC.CreateMessageData(addr,\"if\", tags[1], d.val/d.maxVal));","parentGroup":"Main_group1","x":805,"y":164.2857208251953,"z":"3629fcd9.ccc604","bgColor":"#808080","wires":[]},{"id":"Main_Slider2","type":"UI_Slider","name":"ch2","tag":"ga 1","comment":"","w":30,"h":280,"textSize":16,"midiCh":"","midiId":"29","orientation":"v","label":"d.val/d.maxVal","minVal":0,"maxVal":100,"val":59,"divVal":1,"fval":59,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var tags = d.tag.split(' ');\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+tags[0]+\"*\";\nOSC.SendData(OSC.CreateMessageData(addr,\"if\", tags[1], d.val/d.maxVal));","parentGroup":"Main_group1","x":855,"y":165,"z":"3629fcd9.ccc604","bgColor":"#808080","wires":[]},{"id":"Main_Slider3","type":"UI_Slider","name":"ch3","tag":"ga 2","comment":"","w":30,"h":280,"textSize":16,"midiCh":"","midiId":"29","orientation":"v","label":"d.val/d.maxVal","minVal":0,"maxVal":100,"val":0,"divVal":1,"fval":0,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var tags = d.tag.split(' ');\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+tags[0]+\"*\";\nOSC.SendData(OSC.CreateMessageData(addr,\"if\", tags[1], d.val/d.maxVal));","parentGroup":"Main_group1","x":905,"y":164.2857208251953,"z":"3629fcd9.ccc604","bgColor":"#808080","wires":[]},{"id":"Main_Slider4","type":"UI_Slider","name":"ch4","tag":"ga 3","comment":"","w":30,"h":280,"textSize":16,"midiCh":"","midiId":"29","orientation":"v","label":"d.val/d.maxVal","minVal":0,"maxVal":100,"val":0,"divVal":1,"fval":0,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var tags = d.tag.split(' ');\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+tags[0]+\"*\";\nOSC.SendData(OSC.CreateMessageData(addr,\"if\", tags[1], d.val/d.maxVal));","parentGroup":"Main_group1","x":955,"y":164.2857208251953,"z":"3629fcd9.ccc604","bgColor":"#808080","wires":[]},{"id":"Main_Button2","type":"UI_Button","name":"create new AudioSynthWaveForm wafo","comment":"","w":275,"h":34,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"var addr = \"/teensy1/dynamic/createObject*\"\nvar data = OSC.GetSimpleOSCdata(addr,\"ss\", \"AudioSynthWaveform\", \"wafo\");\nOSC.SendAsSlipToSerial(data);","x":2260,"y":90,"z":"3629fcd9.ccc604","bgColor":"#F6F8BC","wires":[]},{"id":"Main_Button3","type":"UI_Button","name":"create connection wafo2mixer1","comment":"","w":223,"h":30,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"var addr = \"/teensy1/dynamic/createConn*\"\nvar data = OSC.GetSimpleOSCdata(addr,\"s\", \"wafo2mixer1\");\nOSC.SendAsSlipToSerial(data);","x":2260,"y":130,"z":"3629fcd9.ccc604","bgColor":"#F6F8BC","wires":[]},{"id":"Main_Button4","type":"UI_Button","name":"do all above in one go","comment":"","w":157,"h":34,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"var data = osc.writeBundle({\r\n        timeTag: osc.timeTag(0),\r\n        packets: [\r\n            {\r\n                address: \"/teensy1/dynamic/createObject*\",\r\n                args: [\r\n\t\t\t\t\t{type: \"s\", value: \"AudioSynthWaveform\"},\r\n\t\t\t\t\t{type: \"s\", value: \"wafo\"}\r\n                ]\r\n            },\r\n            {\r\n                address: \"/teensy1/dynamic/createConn*\",\r\n                args: [\r\n                    {type: \"s\", value: \"wafo2mixer1\"}\r\n                ]\r\n            },\r\n            {\r\n                address: \"/teensy1/audio/wafo2mixer1/connect*\",\r\n                args: [\r\n                    {type: \"s\", value: \"wafo\"},\r\n\t\t\t\t\t{type: \"i\", value: 0},\r\n\t\t\t\t\t{type: \"s\", value: \"mixer1\"},\r\n\t\t\t\t\t{type: \"i\", value: 1}\r\n                ]\r\n            }\r\n\t\t\t\r\n        ]\r\n    });\r\nOSC.SendAsSlipToSerial(data);","x":2280,"y":210,"z":"3629fcd9.ccc604","bgColor":"#F6F8BC","wires":[]},{"id":"Main_group1","type":"group","name":"mixerS","tag":"","comment":"","w":354,"h":472,"textSize":14,"nodes":["Main_Slider1","Main_Slider2","Main_Slider3","Main_Slider4","Main_Button6","Main_Button13","Main_Slider8","20220220T140211_223Z_d5fa"],"border_color":"rgba(153,153,153,1)","individualListBoxMode":true,"exportAsClass":true,"x":785,"y":110,"z":"3629fcd9.ccc604","bgColor":"rgba(221,255,187,1)","wires":[]},{"id":"Main_Button6","type":"UI_Button","name":"set all mixer gains to 0.10","tag":"gain","comment":"","w":176,"h":34,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"var parentName = d.parentGroup.name;\r\nvar gain = 0.10;\r\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+d.tag+\"*\";\r\n\r\nvar bundle = OSC.CreateBundle(0);\r\nbundle.packets.push(OSC.CreatePacket(addr,\"if\",0,gain));\r\nbundle.packets.push(OSC.CreatePacket(addr,\"if\",1,gain));\r\nbundle.packets.push(OSC.CreatePacket(addr,\"if\",2,gain));\r\nbundle.packets.push(OSC.CreatePacket(addr,\"if\",3,gain));\r\nOSC.SendData(OSC.CreateBundleData(bundle));\r\n\r\n// update sliders in ui\r\nfor (var i=0; i<d.parentGroup.nodes.length; i++) {\r\n    d.parentGroup.nodes[i].val = gain*d.parentGroup.nodes[i].maxVal;\r\n    d.parentGroup.nodes[i].dirty=true;\r\n}\r\nRED.view.redraw();","parentGroup":"Main_group1","x":805,"y":485,"z":"3629fcd9.ccc604","bgColor":"#F6F8BC","wires":[]},{"id":"Main_Button7","type":"UI_Button","name":"Button","comment":"","w":100,"h":34,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"var addr = \"/teensy1/dynamic/createObject*\"\nvar data = OSC.GetSimpleOSCdata(addr,\"ss\", \"AudioSynthWaveform\", \"   \");\nOSC.SendAsSlipToSerial(data);","x":2340,"y":280,"z":"3629fcd9.ccc604","bgColor":"#F6F8BC","wires":[]},{"id":"Main_Button8","type":"UI_Button","name":"rename waveform2 to wafo1","comment":"","w":275,"h":34,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"var addr = \"/teensy1/dynamic/ren*\"\nvar data = OSC.GetSimpleOSCdata(addr,\"ss\", \"waveform2\", \"wafo\");\nOSC.SendAsSlipToSerial(data);","x":2295,"y":370,"z":"3629fcd9.ccc604","bgColor":"#F6F8BC","wires":[]},{"id":"Main_Button9","type":"UI_Button","name":"enable","tag":"enabl","comment":"","w":56,"h":34,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"var addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+d.tag+\"*\";\nOSC.SendData(OSC.CreateMessageData(addr,''));","parentGroup":"Main_group7","x":1180,"y":150,"z":"3629fcd9.ccc604","bgColor":"#F6F8BC","wires":[]},{"id":"Main_Slider15","type":"UI_Slider","name":"volume","tag":"vol","comment":"","w":30,"h":265,"textSize":14,"midiCh":"0","midiId":"0","orientation":"v","label":"d.val","minVal":0,"maxVal":100,"val":66,"divVal":1,"fval":66,"sendMode":"r","autoReturn":false,"returnValue":"mid","barFGcolor":"#F6F8BC","sendFormat":"","sendCommand":"var addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+d.tag+\"*\";\nOSC.SendData(OSC.CreateMessageData(addr,'f',d.val/d.maxVal));","parentGroup":"Main_group7","x":1190,"y":220,"z":"3629fcd9.ccc604","bgColor":"#808080","wires":[]},{"id":"Main_group7","type":"group","name":"sgtl_5000","tag":"","comment":"","w":122,"h":403,"textSize":14,"nodes":["Main_Button9","Main_Slider15","20220314T083531_620Z_8b66"],"border_color":"rgba(153,153,153,1)","individualListBoxMode":true,"exportAsClass":true,"x":1170,"y":115,"z":"3629fcd9.ccc604","bgColor":"rgba(221,255,187,1)","wires":[]},{"id":"Main_Button13","type":"UI_Button","name":"set all mixer gains to 0","tag":"gain","comment":"","w":176,"h":34,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"var parentName = d.parentGroup.name;\r\nvar gain = 0;\r\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+d.tag+\"*\";\r\n\r\nvar bundle = OSC.CreateBundle(0);\r\nbundle.packets.push(OSC.CreatePacket(addr,\"if\",0,gain));\r\nbundle.packets.push(OSC.CreatePacket(addr,\"if\",1,gain));\r\nbundle.packets.push(OSC.CreatePacket(addr,\"if\",2,gain));\r\nbundle.packets.push(OSC.CreatePacket(addr,\"if\",3,gain));\r\nbundle.packets.push(OSC.CreatePacket(addr,\"if\",4,gain));\r\nOSC.SendData(OSC.CreateBundleData(bundle));\r\n\r\n// update sliders in ui\r\nfor (var i=0; i<d.parentGroup.nodes.length; i++) {\r\n    d.parentGroup.nodes[i].val = gain*d.parentGroup.nodes[i].maxVal;\r\n    d.parentGroup.nodes[i].dirty=true;\r\n}\r\nRED.view.redraw();","parentGroup":"Main_group1","x":805,"y":530,"z":"3629fcd9.ccc604","bgColor":"#F6F8BC","wires":[]},{"id":"Main_Slider8","type":"UI_Slider","name":"ch5","tag":"ga 4","comment":"","w":30,"h":280,"textSize":16,"midiCh":"","midiId":"29","orientation":"v","label":"d.val/d.maxVal","minVal":0,"maxVal":100,"val":76,"divVal":1,"fval":76,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var tags = d.tag.split(' ');\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+tags[0]+\"*\";\nOSC.SendData(OSC.CreateMessageData(addr,\"if\", tags[1], d.val/d.maxVal));","parentGroup":"Main_group1","x":1010,"y":165,"z":"3629fcd9.ccc604","bgColor":"#808080","wires":[]},{"id":"Main_group2","type":"group","name":"mixerS","tag":"","comment":"","w":726,"h":293,"textSize":14,"nodes":["Main_Slider5","Main_Button10","Main_Slider6","Main_Slider7","Main_Slider9","Main_Slider10","Main_Slider11","Main_Slider12"],"border_color":"rgba(153,153,153,1)","individualListBoxMode":true,"exportAsClass":true,"x":30,"y":290,"z":"3629fcd9.ccc604","bgColor":"rgba(221,255,187,1)","wires":[]},{"id":"Main_Slider5","type":"UI_Slider","name":"bal 1+2","tag":"bal 0","comment":"","w":222,"h":34,"textSize":16,"midiCh":"","midiId":"29","orientation":"h","label":"d.val/d.maxVal","minVal":-100,"maxVal":100,"val":0,"divVal":1,"fval":0,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var tags = d.tag.split(' ');\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+tags[0]+\"*\";\nOSC.SendData(OSC.CreateMessageData(addr,\"if\", tags[1], d.val/d.maxVal));","parentGroup":"Main_group2","x":40,"y":335,"z":"3629fcd9.ccc604","bgColor":"#808080","wires":[]},{"id":"Main_Button10","type":"UI_Button","name":"pan all to centre","tag":"pan","comment":"","w":119,"h":34,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"var parentName = d.parentGroup.name;\r\nvar gain = 0;\r\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+d.tag+\"*\";\r\n\r\nvar bundle = OSC.CreateBundle(0);\r\nbundle.packets.push(OSC.CreatePacket(addr,\"if\",0,gain));\r\nbundle.packets.push(OSC.CreatePacket(addr,\"if\",1,gain));\r\nbundle.packets.push(OSC.CreatePacket(addr,\"if\",2,gain));\r\nbundle.packets.push(OSC.CreatePacket(addr,\"if\",3,gain));\r\nbundle.packets.push(OSC.CreatePacket(addr,\"if\",4,gain));\r\nOSC.SendData(OSC.CreateBundleData(bundle));\r\n\r\n// update sliders in ui\r\nfor (var i=0; i<d.parentGroup.nodes.length; i++) {\r\n    d.parentGroup.nodes[i].val = gain*d.parentGroup.nodes[i].maxVal / 2;\r\n    d.parentGroup.nodes[i].dirty=true;\r\n}\r\nRED.view.redraw();","parentGroup":"Main_group2","x":55,"y":505,"z":"3629fcd9.ccc604","bgColor":"#F6F8BC","wires":[]},{"id":"Main_Slider6","type":"UI_Slider","name":"bal 3+4","tag":"bal 2","comment":"","w":222,"h":34,"textSize":16,"midiCh":"","midiId":"29","orientation":"h","label":"d.val/d.maxVal","minVal":-100,"maxVal":100,"val":0,"divVal":1,"fval":0,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var tags = d.tag.split(' ');\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+tags[0]+\"*\";\nOSC.SendData(OSC.CreateMessageData(addr,\"if\", tags[1], d.val/d.maxVal));","parentGroup":"Main_group2","x":40,"y":425,"z":"3629fcd9.ccc604","bgColor":"#808080","wires":[]},{"id":"Main_Slider7","type":"UI_Slider","name":"pan 1","tag":"pan 0","comment":"","w":222,"h":34,"textSize":16,"midiCh":"","midiId":"29","orientation":"h","label":"d.val/d.maxVal","minVal":-100,"maxVal":100,"val":0,"divVal":1,"fval":0,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var tags = d.tag.split(' ');\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+tags[0]+\"*\";\nOSC.SendData(OSC.CreateMessageData(addr,\"if\", tags[1], d.val/d.maxVal));","parentGroup":"Main_group2","x":275,"y":335,"z":"3629fcd9.ccc604","bgColor":"#808080","wires":[]},{"id":"Main_Slider9","type":"UI_Slider","name":"pan 2","tag":"pan 1","comment":"","w":222,"h":34,"textSize":16,"midiCh":"","midiId":"29","orientation":"h","label":"d.val/d.maxVal","minVal":-100,"maxVal":100,"val":0,"divVal":1,"fval":0,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var tags = d.tag.split(' ');\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+tags[0]+\"*\";\nOSC.SendData(OSC.CreateMessageData(addr,\"if\", tags[1], d.val/d.maxVal));","parentGroup":"Main_group2","x":510,"y":335,"z":"3629fcd9.ccc604","bgColor":"#808080","wires":[]},{"id":"Main_Slider10","type":"UI_Slider","name":"pan 3","tag":"pan 2","comment":"","w":222,"h":34,"textSize":16,"midiCh":"","midiId":"29","orientation":"h","label":"d.val/d.maxVal","minVal":-100,"maxVal":100,"val":0,"divVal":1,"fval":0,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var tags = d.tag.split(' ');\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+tags[0]+\"*\";\nOSC.SendData(OSC.CreateMessageData(addr,\"if\", tags[1], d.val/d.maxVal));","parentGroup":"Main_group2","x":275,"y":425,"z":"3629fcd9.ccc604","bgColor":"#808080","wires":[]},{"id":"Main_Slider11","type":"UI_Slider","name":"pan 4","tag":"pan 3","comment":"","w":222,"h":34,"textSize":16,"midiCh":"","midiId":"29","orientation":"h","label":"d.val/d.maxVal","minVal":-100,"maxVal":100,"val":0,"divVal":1,"fval":0,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var tags = d.tag.split(' ');\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+tags[0]+\"*\";\nOSC.SendData(OSC.CreateMessageData(addr,\"if\", tags[1], d.val/d.maxVal));","parentGroup":"Main_group2","x":510,"y":425,"z":"3629fcd9.ccc604","bgColor":"#808080","wires":[]},{"id":"Main_Slider12","type":"UI_Slider","name":"pan 5","tag":"pan 4","comment":"","w":222,"h":34,"textSize":16,"midiCh":"","midiId":"29","orientation":"h","label":"d.val/d.maxVal","minVal":-100,"maxVal":100,"val":0,"divVal":1,"fval":0,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var tags = d.tag.split(' ');\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+tags[0]+\"*\";\nOSC.SendData(OSC.CreateMessageData(addr,\"if\", tags[1], d.val/d.maxVal));","parentGroup":"Main_group2","x":275,"y":505,"z":"3629fcd9.ccc604","bgColor":"#808080","wires":[]},{"id":"20220220T140211_223Z_d5fa","type":"UI_Slider","name":"knee","tag":"setSoft x","comment":"","w":30,"h":280,"textSize":16,"midiCh":"","midiId":"29","orientation":"v","label":"d.val/d.maxVal","minVal":0,"maxVal":100,"val":67,"divVal":1,"fval":67,"sendMode":"m","autoReturn":false,"returnValue":"mid","barFGcolor":"#F87A00","sendFormat":"\"midisend(0xB0,\"+d.midiId+\",\" + d.val + \");\"","sendCommand":"var tags = d.tag.split(' ');\nvar addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+tags[0];\nOSC.SendData(OSC.CreateMessageData(addr,\"f\", d.val/d.maxVal));","parentGroup":"Main_group1","x":1085,"y":165,"z":"3629fcd9.ccc604","bgColor":"#808080","wires":[]},{"id":"20220313T112625_472Z_9c7a","type":"group","name":"system","tag":"","comment":"","w":129,"h":186,"textSize":14,"nodes":["20220313T112652_109Z_345a","20220313T113326_320Z_c2ba","20220313T113349_839Z_8177","20220528T145257_534Z_c444"],"border_color":"rgba(153,153,153,1)","individualListBoxMode":true,"exportAsClass":true,"x":1325,"y":115,"z":"3629fcd9.ccc604","bgColor":"rgba(221,255,187,1)","wires":[]},{"id":"20220313T112652_109Z_345a","type":"UI_Button","name":"list","tag":"listObjects","comment":"","w":100,"h":34,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"var addr = RED.OSC.settings.RootAddress + \"/\"+d.parentGroup.name+\"/\"+d.tag;\nOSC.SendData(OSC.CreateMessageData(addr,''));","parentGroup":"20220313T112625_472Z_9c7a","x":1339.75,"y":152,"z":"3629fcd9.ccc604","bgColor":"#F6F8BC","wires":[]},{"id":"20220313T113326_320Z_c2ba","type":"UI_Button","name":"heap","tag":"heap","comment":"","w":100,"h":34,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"var addr = RED.OSC.settings.RootAddress + \"/\"+d.parentGroup.name+\"/\"+d.tag;\nOSC.SendData(OSC.CreateMessageData(addr,''));","parentGroup":"20220313T112625_472Z_9c7a","x":1339.75,"y":202,"z":"3629fcd9.ccc604","bgColor":"#F6F8BC","wires":[]},{"id":"20220313T113349_839Z_8177","type":"UI_Button","name":"reset","tag":"reset","comment":"","w":43,"h":34,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"var addr = RED.OSC.settings.RootAddress + \"/\"+d.parentGroup.name+\"/\"+d.tag;\nOSC.SendData(OSC.CreateMessageData(addr,''));","parentGroup":"20220313T112625_472Z_9c7a","x":1339.75,"y":252,"z":"3629fcd9.ccc604","bgColor":"#F87E7E","wires":[]},{"id":"20220314T083531_620Z_8b66","type":"UI_Slider","name":"out","tag":"lineOutLevel","comment":"","w":30,"h":265,"textSize":14,"midiCh":"0","midiId":"0","orientation":"v","label":"d.val","minVal":13,"maxVal":31,"val":23,"divVal":1,"fval":23,"sendMode":"r","autoReturn":false,"returnValue":"mid","barFGcolor":"#F6F8BC","sendFormat":"","sendCommand":"var addr = RED.OSC.settings.RootAddress + \"/audio/\"+d.parentGroup.name+\"/\"+d.tag;\nOSC.SendData(OSC.CreateMessageData(addr,'i',d.val));","parentGroup":"Main_group7","x":1245,"y":220,"z":"3629fcd9.ccc604","bgColor":"#808080","wires":[]},{"id":"20220528T145257_534Z_c444","type":"UI_Button","name":"led","tag":"LED","comment":"","w":43,"h":34,"textSize":14,"midiCh":"0","midiId":"0","pressAction":"","repeatPressAction":false,"releaseAction":"","repeatReleaseAction":false,"local":"true","sendCommand":"var addr = RED.OSC.settings.RootAddress + \"/\"+d.parentGroup.name+\"/\"+d.tag;\nif (0xF8C00E == d.color) // currently appears \"on\"\n{\n    d.color = 0xF8E5AA;\n    d.bgColor = 0xF8E5AA;\n    OSC.SendData(OSC.CreateMessageData(addr,'F',0));\n}\nelse\n{\n    d.color = 0xF8C00E;\n    d.bgColor = 0xF8C00E;\n    OSC.SendMessage(addr,'T');\n}\nd.changed = true\nd.dirty = true\n","parentGroup":"20220313T112625_472Z_9c7a","x":1400,"y":250,"z":"3629fcd9.ccc604","bgColor":16311722,"wires":[]},{"id":"Main_adc1","type":"AudioInputAnalog","name":"adc","comment":"","x":75,"y":95,"z":"3629fcd9.ccc604","bgColor":"#E6E0F8","wires":[["Main_mixerStereo1:4"]]},{"id":"20220413T154449_639Z_e435","type":"AsyncAudioInputSPDIF3","name":"spdif_async","comment":"","x":70,"y":140,"z":"3629fcd9.ccc604","bgColor":"#E6E0F8","wires":[["Main_mixerStereo1:0"],["Main_mixerStereo1:1"]]},{"id":"20220410T142952_047Z_830f","type":"AudioInputI2S","name":"i2si","comment":"","x":75,"y":190,"z":"3629fcd9.ccc604","bgColor":"#E6E0F8","wires":[["Main_mixerStereo1:2"],["Main_mixerStereo1:3"]]},{"id":"20220314T140814_784Z_46a8","type":"Comment","name":"ADC object position","comment":"adc needs to be top left for now, so the variable delay from AsyncSPDIF doesn't cause dropouts","x":140,"y":70,"z":"3629fcd9.ccc604","bgColor":"#DDFFBB","wires":[]},{"id":"Main_mixerStereo1","type":"AudioMixerStereo","name":"mixerS","comment":"","inputs":5,"RealInputs":5,"x":305,"y":145,"z":"3629fcd9.ccc604","bgColor":"#E6E0F8","wires":[["Main_i2s1:0","20220313T164142_612Z_c2f1:0","20220314T141146_538Z_1b84:0","20220410T130753_013Z_2a4d:0"],["Main_i2s1:1","20220314T141146_538Z_1b84:1","20220410T130753_013Z_2a4d:1"]]},{"id":"20220313T164142_612Z_c2f1","type":"AudioOutputPWM","name":"pwm","comment":"","x":490,"y":85,"z":"3629fcd9.ccc604","bgColor":"#E6E0F8","wires":[]},{"id":"Main_i2s1","type":"AudioOutputI2S","name":"i2so","comment":"","x":490,"y":140,"z":"3629fcd9.ccc604","bgColor":"#E6E0F8","wires":[]},{"id":"20220314T141146_538Z_1b84","type":"AudioOutputUSB","name":"usb","comment":"","x":495,"y":190,"z":"3629fcd9.ccc604","bgColor":"#E6E0F8","wires":[]},{"id":"20220410T130753_013Z_2a4d","type":"AudioOutputSPDIF3","name":"spdif3","comment":"","x":480,"y":240,"z":"3629fcd9.ccc604","bgColor":"#E6E0F8","wires":[]},{"id":"Main_sgtl5000_1","type":"AudioControlSGTL5000","name":"sgtl_5000","comment":"","x":1175,"y":535,"z":"3629fcd9.ccc604","bgColor":"#E6E0F8","wires":[]}],"links":[],"export":true,"isMain":false,"mainNameType":"tabName","mainNameExt":".ino","isAudioMain":true,"generateCppDestructor":false,"extraClassDeclarations":"","settings":{"guiEditMode":false,"workspaceBgColor":"#EDFFDF","scaleFactor":0.8,"showGridHminor":false,"showGridHmajor":false,"showGridVminor":false,"showGridVmajor":false,"useCenterBasedPositions":false}}],"nodeAddons":{}
}
The /system/LED command (not currently pushed to a github example) takes a single boolean to turn the built-in LED on or off - this didn't work before, but seems OK now.

As an aside, I can't see a way to make the UI button change colour to track the LED state; the JavaScript code changes both the color and bgColor values, and uses them to determine whether to send a T or F value, but I can't get the button to show correctly - it tends to be either black or white! I can see the value change in the info tab, just the button itself doesn't change.
 
Back
Top