Forum Rule: Always post complete source code & details to reproduce any issue!
Page 3 of 3 FirstFirst 1 2 3
Results 51 to 75 of 75

Thread: Audio System Design Tool++ update

  1. #51
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    606
    Hi,
    * You define the array like this:
    Name:  arrayOfVoices.png
Views: 554
Size:  2.0 KB

    * 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)
    Click image for larger version. 

Name:	Rename_tab_workspace_sheet.png 
Views:	49 
Size:	12.8 KB 
ID:	24782

    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

  2. #52
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    379
    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();};
    }; // terminates class
    
    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.

  3. #53
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    606
    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

  4. #54
    Junior Member
    Join Date
    Jun 2021
    Posts
    3
    It's fantastic works!, need informaiton about how to install it locally, i'm trying to clone from repository https://github.com/manicken/manicken.github.io, no error but seems all sidebar is blank white and unfinished loading.

  5. #55
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    606
    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.

  6. #56
    Junior Member
    Join Date
    Jun 2021
    Posts
    3
    Quote Originally Posted by manicksan View Post
    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.
    Attached Files Attached Files
    Last edited by sttel; 07-30-2021 at 04:44 PM. Reason: Typo

  7. #57
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    606
    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

  8. #58
    Quote Originally Posted by wrightflyer View Post
    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.

  9. #59
    Junior Member
    Join Date
    Jun 2021
    Posts
    3
    Quote Originally Posted by manicksan View Post
    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.

  10. #60
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    606
    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:
    Click image for larger version. 

Name:	EmptyProject.png 
Views:	38 
Size:	12.3 KB 
ID:	25489

    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

    Click image for larger version. 

Name:	VoiceClass.png 
Views:	52 
Size:	30.5 KB 
ID:	25490

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

    last create the synth class
    Click image for larger version. 

Name:	SynthClass.png 
Views:	49 
Size:	15.8 KB 
ID:	25491

    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;

  11. #61
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    606
    Quote Originally Posted by sttel View Post
    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

  12. #62
    Quote Originally Posted by manicksan View Post
    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.

  13. #63
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    606
    Update for the Node Definitions Manager Manual (i.e. adding new custom AudioObjects to the tool)

    open node def. mgr.
    Click image for larger version. 

Name:	NewType0.png 
Views:	16 
Size:	25.7 KB 
ID:	27038

    click add group
    Name:  NewType1.png
Views: 247
Size:  7.3 KB

    fill in the details
    (note there is a popup text for each of the fields describing what it is)
    Click image for larger version. 

Name:	NewType2.png 
Views:	18 
Size:	14.6 KB 
ID:	27033

    then select the new group (here I choose the UID newGroup in the prev step)
    Name:  NewType3.png
Views: 253
Size:  10.1 KB

    click add new node type
    Name:  NewType4.png
Views: 248
Size:  10.4 KB

    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
    Click image for larger version. 

Name:	NewType5.png 
Views:	15 
Size:	23.3 KB 
ID:	27036

    then you have the new AudioObject to play with
    Click image for larger version. 

Name:	NewType6.png 
Views:	18 
Size:	38.0 KB 
ID:	27037

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

  14. #64
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    606
    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
    Click image for larger version. 

Name:	SimpleExportArray.png 
Views:	16 
Size:	19.4 KB 
ID:	27089

    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:
    Click image for larger version. 

Name:	1000megadrone.png 
Views:	16 
Size:	9.5 KB 
ID:	27088

    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...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

  15. #65
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    606
    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

    Click image for larger version. 

Name:	AutoAddDroppedLinks.png 
Views:	14 
Size:	6.3 KB 
ID:	27169

    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
    Click image for larger version. 

Name:	AutoAddDroppedLinks_bug.png 
Views:	11 
Size:	15.8 KB 
ID:	27170

  16. #66
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    379
    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.

  17. #67
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    606
    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:
    Name:  NodedefmgrStillWorking.png
Views: 142
Size:  10.3 KB

  18. #68
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    379
    Ah, that would be it - last time I was adding node types, I could use my own (online) name...

  19. #69
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    379
    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...

  20. #70
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    606
    Quote Originally Posted by h4yn0nnym0u5e View Post
    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.

  21. #71
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    379
    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.

  22. #72
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    606
    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

  23. #73
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    379
    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?

  24. #74
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    379
    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...

  25. #75
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    379
    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •