Audio Lib Manicken design tool

Status
Not open for further replies.

Jean-ClaudeF

Active member
Hi,
First of all: oh wow, what a super tool:
https://manicken.github.io/#
I hadn't yet the time to use it, just loaded the synth example, but it seems clear to me that there is much work done here and that it will be very useful.

There is only one caveat that might be good to know for others also: I couldn't get it to work in Firefox.
Then I tried Chromium: no problem.

I am looking forward to experiment with it...
 
Thanks

It did work on firefox
but after I did some implementation
using Web Serial API
I forgot to add checks against "Web Serial API" availability

It's now fixed, and the tool now works on all browsers that I know off.

Internet Explorer don't work (and I don't know why, but the official tool do)

If you want to play with the (in development) new OSC system
then it's Chrome,Edge or Opera that supports Web Serial API
 
Thank you! Effectively I get it to work in Firefox now :)

However as I am new to all this, it is not easy to get started. The Examples are fine, but complex.
Is there a source of information on getting started, or are there simpler examples anywhere?

As a simple example I tried to make a Fourier synthesis with 4 oscillators, and a mixer.

The first questions I have are:

- How do I define a waveform as array? (I suppose it is not enough to define it in the name as e.g. wave[4]) ?

- Do I have to do something extra to include the special elements like mixer with n inputs to my Arduino IDE or code?
 
- How do I define a waveform as array? (I suppose it is not enough to define it in the name as e.g. wave[4]) ?
Yes that is exactly how you define a array, it's not harder than that (but you can't have different size arrays in the same tab/class/workspace)

- Do I have to do something extra to include the special elements like mixer with n inputs to my Arduino IDE or code?

here is the most simple example
copy that URL and paste it into the tool @ import-json

https://raw.githubusercontent.com/manicken/manicken.github.io/master/examples/MostSimpleSynth.json

the mixer n code is included into that and if you do a export
Class-based to Zip
and then extract that into your sketch folder
you are ready to go

and in the "sketchname".ino
have the following

Code:
#include "synth.h"

Synth synth;

setup () {

synth.begin();

}

In the voice tab you can see the structure of that
the Out object can be found in the special category
there is also a In object
these (In & Out) objects are only virtual placeholder objects,
they are replaced by simple audio connections when a export is made

notice the audio connections made are "outside" of the "Voice" class and are created and connected in the "Synth" class

simple example (inside synth class, outside Voice class)
AudioMixer<8> mixer; // mixer is in Synth class namespace
AudioConnection(voices[0].mixer, 0, mixer, 0); // voices[0].mixer here mixer is in the Voice class namespace so they can have the same name



How it works:
When a new tab is created there will also be a new object available in the tabs category (@left panel is the categories)
At first the object contains no inputs or outputs
They are in the special category as In and Out
they can be named whatever you like
but when used the order "top to bottom" is important

IOorder.png

Also notice there is currently no way of locking a "inside" Out to a "outside" Out pin
so for example if you move the OutB object above OutC then the "outside" order will change as well.

Hope that all will describe how it all works.
Please feel free to ask more specific questions if something is unclear.
 
Thanks for the quick answer!
I have succeeded in
- creating a wave array (sine)
- getting the mixer to work, though not exactly the way you described.

I have extracted the mixer code, put it into a tab in the Arduino IDE and coded my Fourier example like this:

Code:
#include <Audio.h>
#include "themixer.h"

AudioSynthWaveform               wave[4];        //xy=650,325
AudioMixer<4>                    mixer;    //xy=815,325
AudioOutputI2S                   i2s1;           //xy=940,330


AudioConnection          patchCord1(wave[4], 0, mixer, 0);
AudioConnection          patchCord2(mixer, 0, i2s1, 0);
AudioConnection          patchCord3(mixer, 0, i2s1, 1);

AudioControlSGTL5000     sgtl5000_1;     //xy=815,405

AudioConnection  *patchCord[10]; 


void setup() {
    AudioMemory(10);
    sgtl5000_1.enable();
    sgtl5000_1.volume(0.9);

    
    for(int i=0; i<=3; i++){
        patchCord[i] = new AudioConnection(wave[i], 0, mixer, i);
        wave[i].begin(WAVEFORM_SINE);  
        wave[i].frequency((i+1) * 440);
        wave[i].amplitude(0.3);
    }      

}

void loop() {
  
}

If I understand well, this is not exactly as it was meant to be done.

From the original Audio GUI I'm used to do only the declarations of the audio objects in the GUI and then write the code in the IDE.

Your aim seems to be to do EVERYTHING in the GUI and then export it to the IDE.
So I should rework my example and put the code into function blocks in the GUI? Is that how it should be done?

------

Two more questions:
- Could the mixer code be somehow embedded in the GUI, so that you wouldn't have to manually add it? (or put into a lib)
- Once the mixer is defined in the GUI with for example 4 inputs, is this a fixed number or can it be changed in the IDE? I tried to edit the code for more harmonics but that didn't work.
 
Ok of what I understand this is what you want

onlyArray.png

it generates the following code (if the tab is named Synth)

Code:
class Synth
{
public:
    AudioSynthWaveform         wave[4];
    AudioMixer4                      mixer4;
    AudioOutputI2S                 i2s;
    AudioControlSGTL5000       sgtl5000;
    AudioConnection                *patchCord[6]; // total patchCordCount:6 including array typed ones.

    Main() { // constructor (this is called when class-object is created)
        int pci = 0; // used only for adding new patchcords


        patchCord[pci++] = new AudioConnection(mixer4, 0, i2s, 0);
        patchCord[pci++] = new AudioConnection(mixer4, 0, i2s, 1);
        for (int i = 0; i < 4; i++) {
            patchCord[pci++] = new AudioConnection(wave[i], 0, mixer4, i);
        }
        
    }
    // this function just makes cleaner looking main code
    void begin() { // begin, init or what name you prefer
        AudioMemory(10);
        sgtl5000_1.enable();
        sgtl5000_1.volume(0.9);

        for(int i=0; i < 4; i++){
            wave[i].begin(WAVEFORM_SINE);  
            wave[i].frequency((i+1) * 440);
            wave[i].amplitude(0.3);
        }
    }
};

then in your sketch main file

Code:
#include <Audio.h>
#include "Synth.h"

Synth synth;

setup() 
{
     // either do some coding inside the Tool++ and just call the functions here
     synth.begin();


     // or if you want you can also do the init stuff "external" here
    AudioMemory(10);
    synth.sgtl5000_1.enable();
    synth.sgtl5000_1.volume(0.9);

    for(int i=0; i < 4; i++){
        synth.wave[i].begin(WAVEFORM_SINE);  
        synth.wave[i].frequency((i+1) * 440);
        synth.wave[i].amplitude(0.3);
    }
}

loop()
{

}
 
Ok of what I understand this is what you want
Exactly (but with TheMixer), and I'm doing this not for any practical purpose, but only as an exercise to learn how to use Audio object arrays.

Ok, now I understand that the class name comes from the tab name, fine.

What confuses me is the doubling of code in the first code piece and the second one:
Code:
AudioMemory(10);
        sgtl5000_1.enable();
        sgtl5000_1.volume(0.9);

        for(int i=0; i < 4; i++){
            wave[i].begin(WAVEFORM_SINE);  
            wave[i].frequency((i+1) * 440);
            wave[i].amplitude(0.3);
        }

I would expect that if you define the begin function with the for loop in the class definition it would be enough to do
Code:
synth.begin();
in the setup().
Or did you want to show me different possibilities of doing it in one code segment?
 
I tried something different now. Wanted to build an 8 input mixer out of 3 standard ones:
mixer.png
However the export is not successful, see error message.
I thought I could build new objects by using the virtual in / out.
What error did I make?
 
Or did you want to show me different possibilities of doing it in one code segment?

Yes I wanted to show different possibilities.

However the export is not successful, see error message.
I thought I could build new objects by using the virtual in / out.
What error did I make?

If you get that message then you have no i2s USB and similar I/O
in your design.

What export method did you use?

for example
Simple export
do create the same structure as the official tool

and the class based variants use a class hierarchy

The virtual I/O are only supported in the class export modes.
 
Here is a minimalistic example how it should/could look like

The "Voice" tab
Tab_Voice.png

The "Main" tab
Tab_Main.png

here the main tab contains at least one type of IO node
it's the same as the official tool
there the system don't work without the IO nodes
 
and you cannot design a 8 input mixer like that

it would look more like this
Tab_MixerX8.png

And also you cannot use that with arrays
like this
Tab_MixerX8_use.png

as the resulting code look like this when using that mixer "outside"

Code:
for (int i = 0; i < 8; i++) {
     patchCord[pci++] = new AudioConnection(voice[i].mixer4, 0, mixerx8.mixer1_4, i); // here it's only using the first mixer and also 'i' gonna kind of overflow the amount of inputs the standard mixer has
}

but you can use it like this

Tab_MixerX8_use_alternative.png

which generates the following code
Code:
for (int i = 0; i < 4; i++) {
    patchCord[pci++] = new AudioConnection(voices_A[i].mixer4, 0, mixerx8.mixer1_4, i);
    patchCord[pci++] = new AudioConnection(voices_B[i].mixer4, 0, mixerx8.mixer5_8, i);
}
here you can see that voices_A uses mixer1_4 (port0-3)
and voices_B uses mixer5_8 (port0-3)

I would however recommend to use the n mixer for situations like this as you can expand it up to the limits of the lib which is 255 inputs.
 
and you cannot design a 8 input mixer like that
That's what I just noticed!
I have tried and edited the code afterwards like this to get the 8 input mixer:

Code:
class Mixer_8 
{
public:
    AudioMixer4                      mixer4_1;
    AudioMixer4                      mixer4_2;
    AudioMixer4                      mixer;
    AudioOutputI2S                   i2s;
    AudioConnection                  *patchCord[4]; // total patchCordCount:4 including array typed ones.

    Mixer_8() { // constructor (this is called when class-object is created)
        int pci = 0; // used only for adding new patchcords


        patchCord[pci++] = new AudioConnection(mixer4_1, 0, mixer, 0);
        patchCord[pci++] = new AudioConnection(mixer4_2, 0, mixer, 1);
        patchCord[pci++] = new AudioConnection(mixer, 0, i2s, 0);
        patchCord[pci++] = new AudioConnection(mixer, 0, i2s, 1);
        
    }
};
//-------------------------------------------------------------------------------------
class Osc_8 
{
public:
    AudioSynthWaveform               waveform[8];
    Mixer_8                          mixer_8;
    AudioConnection                  *patchCord[64]; // total patchCordCount:64 including array typed ones.

    Osc_8() { // constructor (this is called when class-object is created)
        int pci = 0; // used only for adding new patchcords


        for (int i = 0; i < 8; i++) {
           if(i<4){
                patchCord[pci++] = new AudioConnection(waveform[i], 0, mixer_8.mixer4_1, i);
                }
           else{
                patchCord[pci++] = new AudioConnection(waveform[i], 0, mixer_8.mixer4_2, i-4);     
           }
            /*   Code generated by the tool:       
            patchCord[pci++] = new AudioConnection(waveform[i], 0, mixer_8.mixer4_1, i);
            patchCord[pci++] = new AudioConnection(waveform[i], 0, mixer_8.mixer4_1, i);
            patchCord[pci++] = new AudioConnection(waveform[i], 0, mixer_8.mixer4_1, i);
            patchCord[pci++] = new AudioConnection(waveform[i], 0, mixer_8.mixer4_1, i);
            patchCord[pci++] = new AudioConnection(waveform[i], 0, mixer_8.mixer4_2, i);
            patchCord[pci++] = new AudioConnection(waveform[i], 0, mixer_8.mixer4_2, i);
            patchCord[pci++] = new AudioConnection(waveform[i], 0, mixer_8.mixer4_2, i);
            patchCord[pci++] = new AudioConnection(waveform[i], 0, mixer_8.mixer4_2, i);
            */
        }
        
    }
};

----------------

I would however recommend to use the n mixer

Wouldn't it be a good idea for the Tool to automatically integrate the "theMixer.h" function into the diagram when you put a mixer on the drawing?
 
The other question I have is: what exactly is the tool for?
I see that I have just scraped on the surface, but you use it for big things.

It looks a bit like a nicer version of PureData.
However for me it is not clear how this should work, as there is a controller I program with a fix firmware, and there is a kind of GUI that is used to control the instrument on the Teensy?
 
Wouldn't it be a good idea for the Tool to automatically integrate the "theMixer.h" function into the diagram when you put a mixer on the drawing?

have done that now it's available as a special object in the mixer category
just drag n drop
(no automatically drop yet)


The other question I have is: what exactly is the tool for?
At the beginning it was to simplify big hierarchy designs
and to simplify the usage of arrays

then it grow to do much more

the Control GUI part of the Tool is to make it simpler to test designs without wiring a lot of pots and creating additional hardware to control the
design.

Yes it's like pure data but easier and you have everything in one place.
 
About the mixer code
I think I will have it export the mixer code automatically when having a such mixer present in the design, that will solve it for every design. I will do that after the 9th January.
 
The planned vacation is cancelled (for the moment).

So I have now made some changes to the tool

Now it autogenerates mixer code for every mixer variant that you use.
(only available for export to class variants)


This is just how the C++ template mixer works
but using the C++ template mixer had some issues,
* it did sometimes not include the static functions used by the mixer
* to make it work a standard AudioMixer4 had to be used somewhere in the design.

But now it generates standard non "C++ template" code, that force inclusion of the static methods.

Best result is to use the export to class based zip
as it generates the cleanest code.
 
Sorry for your vacation!

Fine that you integrated the mixer code.
Fine also that the zip file generated contains the code as separate files (-> separate tabs in the IDE. That makes the code much more readable)

I am still experimenting with simple examples and I have not wholly understood everything (what makes it not more easy is that I am not used to program in C++. But that way I am learning this too.)

I have taken your example (left : Main, right: Voice):
Voice.pngMain.png
The begin function contains this:
Code:
waveform.begin(WAVEFORM_SINE);
    waveform.frequency(440);
    waveform.amplitude(0.5);
    
    waveformMod.begin(WAVEFORM_SINE);
    waveformMod.frequency(660);
    waveformMod.amplitude(0.5);

The generated code didn't work, I saw no begin funtion, only the code that it should contain, and I had to put this code manually into the Voice class to make it work:
Code:
class Voice 
{
public:
    AudioSynthWaveformModulated      waveformMod;
    AudioSynthWaveform               waveform;
    AudioMixer4                      mixer4;
    AudioConnection                  *patchCord[2]; // total patchCordCount:2 including array typed ones.

    Voice() { // constructor (this is called when class-object is created)
        int pci = 0; // used only for adding new patchcords


        patchCord[pci++] = new AudioConnection(waveformMod, 0, mixer4, 1);
        patchCord[pci++] = new AudioConnection(waveform, 0, mixer4, 0);

    waveform.begin(WAVEFORM_SINE);
    waveform.frequency(440);
    waveform.amplitude(0.5);
    
    waveformMod.begin(WAVEFORM_SINE);
    waveformMod.frequency(660);
    waveformMod.amplitude(0.5);
    }
};

What have I done wrong?
 
the begin function must also contain the "function declaration"

void begin() {
...code here
}

like this:
Code:
void begin() {
    waveform.begin(WAVEFORM_SINE);
    waveform.frequency(440);
    waveform.amplitude(0.5);
    
    waveformMod.begin(WAVEFORM_SINE);
    waveformMod.frequency(660);
    waveformMod.amplitude(0.5);
}

there is a snippet in the autocomplete functionality
if you begin to write be
and if you select the first one in the list
beginSnippet.png

the following will automatically appear
Code:
void begin()
{
    
}

note. the code "block" object can contain multiple functions with different names
also it can contain global variable definitions (but the vars object should be used for that to clarify the generated code)

note. the autocomplete don't yet work for variables that is declared inside such objects
I will take a look at it now

Code:
void begin()
{

}
void begin(uint_8 someparam)
{
    // do some stuff with someparam here
}
uint8_t somevar = 0;
void init()
{

}

you can also check the Tool++ thread for other updates
https://forum.pjrc.com/threads/65740-Audio-System-Design-Tool-update
 
I have tryed another one that should do a simple Fourier synthesis:
Tab Fourier:
Fourier.png
with begin function:
Code:
void begin(){
    for (int i=0; i<4; i++){
             wave[i].begin(WAVEFORM_SINE);
             wave[i].frequency((i+1)*440);
             wave[i].amplitude(0.5);
        }
}
and Main tab
Main.png
with begin function:
Code:
void begin(){
    AudioMemory(10);
    sgtl5000.enable();
    sgtl.volume(0.9);
}

Then I want to have a tab test.ino that should be the main Arduino tab in the IDE. How do I do that?
(Supposed I want to do every coding in your tool)
If I am right this tab should also contain the variable declaration and code
Code:
#include "Main.h"
AudioControlSGTL5000 sgtl5000;
Main main;
main.begin();

Maybe the problem is that I am not used to thinking in C++ [I love Python !]

I tried several things but didn't succeed in getting this example to work.
 
just a little note
in your Tab Fourier begin function
you have written
for (int i=0; i<4; i++){

should it not be 8 instead of 4?


To define the main tab
just double-click that tab
and check the isMain checkbox
like this:

SetMainFile.png

then you can select how the name + extension should be like
main is just plain main.ino/main.cpp

"Tab Name" uses the name from the tab
"Project Name" uses the name from right panel "settings tab"-Arduino-"Project Name"

in this main tab no AudioObjects are included in the exported code
here is my example of my main tab
MainFileExample.png

here is the json for that (don't forget the trailing ])
copy that and use json import (DON'T FORGET to uncheck replace flow checkbox)

you can also select this text and drag drop it into the design
Code:
[{"id":"main.cpp_includeDef1","type":"IncludeDef","name":"<MIDI.h>","comment":"","x":410,"y":20,"z":"14f24e29.494642","bgColor":"#DDFFBB","wires":[]},{"id":"main.cpp_Synth1","type":"Synth","name":"synth","x":410,"y":70,"z":"14f24e29.494642","bgColor":"#CCFFCC","wires":[]},{"id":"main.cpp_vars1","type":"Variables","name":"global variables & function forward declarations","comment":"const int ledPin = 13;\r\nint ledState = LOW;             // ledState used to set the LED\r\nunsigned long previousMillis = 0;        // will store last time LED was updated\r\nunsigned long currentMillis = 0;\r\nunsigned long currentInterval = 0;\r\nunsigned long ledBlinkOnInterval = 100;\r\nunsigned long ledBlinkOffInterval = 2000;\r\n\r\n#define btnInEnablePin 9\r\n#define btnSustainPin 23\r\n#define btnSostenutoPin 22\r\n#define btnSoftPedalPin 21\r\nuint8_t btnSustain = 0;\r\nuint8_t btnSostenuto = 0;\r\nuint8_t btnSoftPedal = 0;\r\nuint8_t btnSustainWasPressed = 0;\r\nuint8_t btnSostenutoWasPressed = 0;\r\nuint8_t btnSoftPedalWasPressed = 0;\r\n\r\n#define btnNextInstrumentPin 20\r\nuint8_t btnNextInstrument = 0;\r\nuint8_t btnNextInstrumentWasPressed = 0;\r\n\r\n#define KEYBOARD_NOTE_SHIFT_CORRECTION 21//-12\r\n\r\nvoid uartMidi_NoteOn(byte channel, byte note, byte velocity);\r\nvoid uartMidi_NoteOff(byte channel, byte note, byte velocity);\r\nvoid uartMidi_ControlChange(byte channel, byte control, byte value);\r\nvoid uartMidi_PitchBend(byte channel, int value);\r\n\r\nvoid usbMidi_NoteOn(byte channel, byte note, byte velocity);\r\nvoid usbMidi_NoteOff(byte channel, byte note, byte velocity);\r\nvoid usbMidi_ControlChange(byte channel, byte control, byte value);\r\nvoid usbMidi_PitchBend(byte channel, int value);\r\n\r\nvoid blinkLedTask(void);\r\nvoid btnInputProcessTask(void);\r\n\r\n","x":410,"y":120,"z":"14f24e29.494642","bgColor":"#DDFFBB","wires":[]},{"id":"main.cpp_vars2","type":"Variables","name":"MIDI_CREATE_INSTANCE","comment":"MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);","x":410,"y":170,"z":"14f24e29.494642","bgColor":"#DDFFBB","wires":[]},{"id":"main.cpp_code2","type":"Function","name":"setup() function","comment":"\r\n// Arduino setup() function\r\nvoid setup()\r\n{\r\n  AudioMemory(96);\r\n\r\n  MIDI.begin();\r\n  MIDI.setHandleNoteOn(uartMidi_NoteOn);\r\n  MIDI.setHandleNoteOff(uartMidi_NoteOff);\r\n  MIDI.setHandleControlChange(uartMidi_ControlChange);\r\n  MIDI.setHandlePitchBend(uartMidi_PitchBend);\r\n\r\n  usbMIDI.setHandleNoteOn(usbMidi_NoteOn);\r\n  usbMIDI.setHandleNoteOff(usbMidi_NoteOff);\r\n  usbMIDI.setHandleControlChange(usbMidi_ControlChange);\r\n  usbMIDI.setHandlePitchChange(usbMidi_PitchBend);\r\n\r\n  synth.begin();\r\n\r\n  pinMode(btnSustainPin, INPUT);\r\n  pinMode(btnSostenutoPin, INPUT);\r\n  pinMode(btnSoftPedalPin, INPUT);\r\n  pinMode(btnNextInstrumentPin, INPUT);\r\n\r\n  pinMode(btnInEnablePin, OUTPUT);\r\n  digitalWrite(btnInEnablePin, LOW);\r\n\r\n  pinMode(ledPin, OUTPUT);\r\n  digitalWrite(ledPin, LOW);\r\n\r\n  btnSustainWasPressed = 0;\r\n  btnSoftPedalWasPressed = 0;\r\n  btnSostenutoWasPressed = 0;\r\n  btnNextInstrumentWasPressed = 0;\r\n  \r\n}\r\n","x":410,"y":220,"z":"14f24e29.494642","bgColor":"#DDFFBB","wires":[]},{"id":"main.cpp_code3","type":"Function","name":"loop() function","comment":"\r\n// Arduino loop() function\r\nvoid loop()\r\n{\r\n    usbMIDI.read();\r\n    MIDI.read();\r\n\r\n    btnInputProcessTask();\r\n    \r\n    blinkLedTask();\r\n}","x":410,"y":270,"z":"14f24e29.494642","bgColor":"#DDFFBB","wires":[]},{"id":"main.cpp_code4","type":"Function","name":"uartMidi handler functions","comment":"\r\n// uartMidi handler functions\r\nvoid uartMidi_NoteOn(byte channel, byte note, byte velocity) {\r\n    note += KEYBOARD_NOTE_SHIFT_CORRECTION;\r\n    velocity = 127 - velocity;\r\n    synth.noteOn(note, velocity);\r\n    usbMIDI.sendNoteOn(note, velocity, channel, 0);\r\n}\r\n\r\nvoid uartMidi_NoteOff(byte channel, byte note, byte velocity) {\r\n    note += KEYBOARD_NOTE_SHIFT_CORRECTION;\r\n    velocity = 127 - velocity;\r\n    synth.noteOff(note);\r\n    usbMIDI.sendNoteOff(note, velocity, channel, 0);\r\n}\r\n\r\nvoid uartMidi_ControlChange(byte channel, byte control, byte value) {\r\n    usbMIDI.sendControlChange(control, value, channel, 0x00);\r\n}\r\n\r\nvoid uartMidi_PitchBend(byte channel, int value) {\r\n    usbMIDI.sendPitchBend(value, channel, 0x00);\r\n}","x":410,"y":320,"z":"14f24e29.494642","bgColor":"#DDFFBB","wires":[]},{"id":"main.cpp_code5","type":"Function","name":"usbMidi handler functions","comment":"\r\n// usbMidi handler functions\r\nvoid usbMidi_NoteOn(byte channel, byte note, byte velocity) {\r\n    synth.noteOn(note, velocity);\r\n}\r\n\r\nvoid usbMidi_NoteOff(byte channel, byte note, byte velocity) {\r\n    synth.noteOff(note);    \r\n}\r\n\r\nvoid usbMidi_PitchBend(byte channel, int value) {\r\n  \r\n}\r\n\r\nvoid usbMidi_ControlChange(byte channel, byte control, byte value) {\r\n    switch (control) { // cases 20-31,102-119 is undefined in midi spec\r\n        case 64:\r\n          if (value == 0)\r\n            synth.deactivateSustain();\r\n          else if (value == 127)\r\n            synth.activateSustain();\r\n          break;\r\n        case 0:\r\n          synth.set_InstrumentByIndex(value);\r\n          break;\r\n        case 20: // OSC A waveform select\r\n          synth.set_OSC_A_waveform(value);\r\n          break;\r\n        case 21: // OSC B waveform select\r\n          synth.set_OSC_B_waveform(value);\r\n          break;\r\n        case 22: // OSC C waveform select\r\n          synth.set_OSC_C_waveform(value);\r\n          break;\r\n\r\n        case 23:\r\n          synth.set_OSC_A_pulseWidth(value);\r\n          break;\r\n        case 24:\r\n          synth.set_OSC_B_pulseWidth(value);\r\n          break;\r\n        case 25:\r\n          synth.set_OSC_C_pulseWidth(value);\r\n          break;\r\n\r\n        case 26:\r\n          synth.set_OSC_A_phase(value);\r\n          break;\r\n        case 27:\r\n          synth.set_OSC_B_phase(value);\r\n          break;\r\n        case 28:\r\n          synth.set_OSC_C_phase(value);\r\n          break;\r\n\r\n        case 29:\r\n          synth.set_OSC_A_amplitude(value);\r\n          break;\r\n        case 30:\r\n          synth.set_OSC_B_amplitude(value);\r\n          break;\r\n        case 31:\r\n          synth.set_OSC_C_amplitude(value);\r\n          break;\r\n        case 32: //(\"LSB for Control 0 (Bank Select)\" @ midi spec.)\r\n          synth.set_OSC_D_amplitude(value);\r\n          break;\r\n\r\n        case 33: \r\n          synth.set_mixVoices_gains(value);\r\n          break;\r\n        \r\n        case 100:\r\n          synth.set_envelope_delay(value);\r\n          break;\r\n        case 101:\r\n          synth.set_envelope_attack(value);\r\n          break;\r\n        case 102:\r\n          synth.set_envelope_hold(value);\r\n          break;\r\n        case 103:\r\n          synth.set_envelope_decay(value);\r\n          break;\r\n        case 104:\r\n          synth.set_envelope_sustain(value);\r\n          break;\r\n        case 105:\r\n          synth.set_envelope_release(value);\r\n          break;\r\n                 \r\n        case 108:\r\n          synth.set_OSC_A_freqMult(value);\r\n          break;\r\n        case 109:\r\n          synth.set_OSC_B_freqMult(value);\r\n          break;\r\n        case 110:\r\n          synth.set_OSC_C_freqMult(value);\r\n          break;\r\n\r\n        case 115: // set wavetable as primary (Piano mode)\r\n          synth.SetWaveTable_As_Primary();\r\n          break;\r\n        case 116:\r\n          synth.SetWaveForm_As_Primary();\r\n          break;\r\n          \r\n        case 117: // EEPROM read settings\r\n          synth.EEPROM_ReadSettings();\r\n          break;\r\n        case 118: // EEPROM save settings\r\n          synth.EEPROM_SaveSettings();\r\n          break;\r\n\r\n        case 119: // get all values\r\n          synth.sendAllSettings();\r\n        break;\r\n    }\r\n}","x":410,"y":370,"z":"14f24e29.494642","bgColor":"#DDFFBB","wires":[]},{"id":"main.cpp_code6","type":"Function","name":"btnInputProcessTask() function","comment":"\r\n// btnInputProcessTask() function\r\nvoid btnInputProcessTask(void)\r\n{\r\n  btnSustain = digitalRead(btnSustainPin);\r\n  btnSostenuto = digitalRead(btnSostenutoPin);\r\n  btnSoftPedal = digitalRead(btnSoftPedalPin);\r\n  btnNextInstrument = digitalRead(btnNextInstrumentPin);\r\n\r\n    // Sustain pedal\r\n    if ((btnSustain == LOW) && (btnSustainWasPressed == 0))\r\n    {\r\n        btnSustainWasPressed = 1;\r\n        usbMIDI.sendControlChange(0x40, 0x7F, 0x00);\r\n        synth.activateSustain();\r\n\r\n        uint16_t memory_used = AudioMemoryUsageMax();\r\n        uint16_t cpu_used = AudioProcessorUsageMax();\r\n        uint8_t data[11];\r\n        data[0] = 0x30 + memory_used/10000;\r\n        data[1] = 0x30 + memory_used%10000/1000;\r\n        data[2] = 0x30 + memory_used%10000%1000/100;\r\n        data[3] = 0x30 + memory_used%10000%1000%100/10;\r\n        data[4] = 0x30 + memory_used%10000%1000%100%10;\r\n        data[5] = ':';\r\n        data[6] = 0x30 + cpu_used/10000;\r\n        data[7] = 0x30 + cpu_used%10000/1000;\r\n        data[8] = 0x30 + cpu_used%10000%1000/100;\r\n        data[9] = 0x30 + cpu_used%10000%1000%100/10;\r\n        data[10] = 0x30 + cpu_used%10000%1000%100%10;\r\n        usbMIDI.sendSysEx(11, data);\r\n    }\r\n    else if ((btnSustain == HIGH) && (btnSustainWasPressed == 1))\r\n    {\r\n        btnSustainWasPressed = 0;\r\n        usbMIDI.sendControlChange(0x40, 0x00, 0x00);\r\n        synth.deactivateSustain();\r\n    }\r\n    // Sostenuto Pedal\r\n    if ((btnSostenuto == LOW) && (btnSostenutoWasPressed == 0))\r\n    {\r\n        btnSostenutoWasPressed = 1;\r\n        usbMIDI.sendControlChange(0x42, 0x7F, 0x00);\r\n    }\r\n    else if ((btnSostenuto == HIGH) && (btnSostenutoWasPressed == 1))\r\n    {\r\n        btnSostenutoWasPressed = 0;\r\n        usbMIDI.sendControlChange(0x42, 0x00, 0x00);\r\n    }\r\n    // Soft Pedal\r\n    if ((btnSoftPedal == LOW) && (btnSoftPedalWasPressed == 0))\r\n    {\r\n        btnSoftPedalWasPressed = 1;\r\n        usbMIDI.sendControlChange(0x43, 0x7F, 0x00);\r\n    }\r\n    else if ((btnSoftPedal == HIGH) && (btnSoftPedalWasPressed == 1))\r\n    {\r\n        btnSoftPedalWasPressed = 0;\r\n        usbMIDI.sendControlChange(0x43, 0x00, 0x00);\r\n    }\r\n    // Next Instrument button\r\n    if ((btnNextInstrument == LOW) && (btnNextInstrumentWasPressed == 0))\r\n    {\r\n        btnNextInstrumentWasPressed = 1;\r\n        if (synth.currentWTinstrument == (InstrumentCount - 1)) synth.currentWTinstrument = 0;\r\n        else synth.currentWTinstrument++;\r\n        synth.set_InstrumentByIndex(synth.currentWTinstrument);\r\n        usbMIDI.sendControlChange(0, synth.currentWTinstrument, 0x00);\r\n    }\r\n    else if ((btnNextInstrument == HIGH) && (btnNextInstrumentWasPressed == 1))\r\n    {\r\n        btnNextInstrumentWasPressed = 0;\r\n    }\r\n}","x":410,"y":410,"z":"14f24e29.494642","bgColor":"#DDFFBB","wires":[]},{"id":"main.cpp_code1","type":"Function","name":"blinkLedTask() function","comment":"\r\n// blinkLedTask() function\r\nvoid blinkLedTask(void)\r\n{\r\n    currentMillis = millis();\r\n    currentInterval = currentMillis - previousMillis;\r\n    \r\n    if (ledState == LOW)\r\n    {\r\n        if (currentInterval > ledBlinkOffInterval)\r\n        {\r\n            previousMillis = currentMillis;\r\n            ledState = HIGH;\r\n            digitalWrite(ledPin, HIGH);\r\n        }\r\n    }\r\n    else\r\n    {\r\n        if (currentInterval > ledBlinkOnInterval)\r\n        {\r\n            previousMillis = currentMillis;\r\n            ledState = LOW;\r\n            digitalWrite(ledPin, LOW);\r\n        }\r\n    }\r\n}","x":410,"y":470,"z":"14f24e29.494642","bgColor":"#DDFFBB","wires":[]}
]
 
in your Tab Fourier begin function
you have written
for (int i=0; i<4; i++){

should it not be 8 instead of 4?

I tried different values to see if it worked. What was very strange: I got the same output (maybe with 8 additions, I didn't count) for any value there.

you can select how the name + extension should be like...
main is just plain main.ino/main.cpp
Oh, fine! I didn't see that.

I would really like to use the Tool in the way that I do all the programming in the GUI, that is really nice!
(If only I succeeded with a small example).
 
OK, now I succeeded in realising a blinking sketch:
Code:
{"version":1,"settings":{"arduino":{"Board":{"Platform":"","Board":"","Options":""}},"BiDirDataWebSocketBridge":{},"workspaces":{},"sidebar":{},"palette":{},"editor":{},"devTest":{},"IndexedDBfiles":{"testFileNames":"testFile.txt"},"NodeDefGenerator":{},"NodeDefManager":{},"NodeHelpManager":{},"OSC":{}},"workspaces":[{"type":"tab","id":"Main","label":"blink","inputs":0,"outputs":0,"export":true,"isMain":true,"mainNameType":"tabName","mainNameExt":".ino","generateCppDestructor":false,"extraClassDeclarations":"","settings":{},"nodes":[{"id":"blink_i2s1","type":"AudioOutputI2S","name":"i2s","comment":"","x":410,"y":55,"z":"Main","bgColor":"#E6E0F8","wires":[]},{"id":"main.cpp_vars1","type":"Variables","name":"global variables & function forward declarations","comment":"const int ledPin = 13;\nint ledState = LOW;             // ledState used to set the LED\nunsigned long previousMillis = 0;        // will store last time LED was updated\nunsigned long currentMillis = 0;\nunsigned long currentInterval = 0;\nunsigned blinkInterval = 200;","x":405,"y":160,"z":"Main","bgColor":"#DDFFBB","wires":[]},{"id":"main.cpp_code2","type":"Function","name":"setup() function","comment":"void setup()\r\n{\r\n  pinMode(ledPin, OUTPUT);\r\n  digitalWrite(ledPin, LOW);\r\n}\r\n","x":410,"y":220,"z":"Main","bgColor":"#DDFFBB","wires":[]},{"id":"main.cpp_code3","type":"Function","name":"loop() function","comment":"void loop()\r\n{\r\n    blinkLedTask();\r\n}","x":410,"y":270,"z":"Main","bgColor":"#DDFFBB","wires":[]},{"id":"main.cpp_code1","type":"Function","name":"blinkLedTask() function","comment":"void blinkLedTask(void)\n{\n    currentInterval =  millis() - previousMillis;\n    if (currentInterval > blinkInterval){\n               digitalWrite(ledPin, !digitalRead(ledPin));\n               previousMillis = millis() ;\n    }\n}","x":405,"y":325,"z":"Main","bgColor":"#DDFFBB","wires":[]}]}],"nodeAddons":{}}
Wow, what a success! :)

Maybe this would be good to add to your examples?

However I had to add an i2s block, otherwise I couldn't export it
I suppose this is a restriction due to Paul's underlying GUI?
 
Just now I had a problem: could not edit function blocks anymore by double klicking on them (in Firefox and Chromium)

That happens after importing this:
Code:
{"version":1,"settings":{"arduino":{"Board":{"Platform":"","Board":"","Options":""}},"BiDirDataWebSocketBridge":{},"workspaces":{},"sidebar":{},"palette":{},"editor":{},"devTest":{},"IndexedDBfiles":{"testFileNames":"testFile.txt"},"NodeDefGenerator":{},"NodeDefManager":{},"NodeHelpManager":{},"OSC":{}},"workspaces":[{"type":"tab","id":"Main","label":"helloworld_audio2","inputs":0,"outputs":0,"export":true,"isMain":true,"mainNameType":"tabName","mainNameExt":".ino","generateCppDestructor":false,"extraClassDeclarations":"","settings":{},"nodes":[{"id":"helloworld_audio2_vars1","type":"Variables","name":"declarations","comment":"const int ledPin = 13;\n#include \"MyTone.h\"\n\nTone mytone;\n","x":140,"y":55,"z":"Main","bgColor":"#DDFFBB","wires":[]},{"id":"helloworld_audio2_code1","type":"Function","name":"setup function","comment":"void setup()\n{\n    pinMode(ledPin, OUTPUT);\n    digitalWrite(ledPin, LOW);\n  \n    AudioMemory(10);\n    sgtl5000.enable();\n    sgtl5000.volume(0.3);\n    \n    tone.sine.frequency(440);\n}","x":295.25,"y":131.25,"z":"Main","bgColor":"#DDFFBB","wires":[]},{"id":"helloworld_audio2_code2","type":"Function","name":"code","comment":"void loop()\n{\n    digitalWrite(ledPin, 1);\n    tone.sine.amplitude(0.9);\n    delay(250);\n    digitalWrite(ledPin, 0);\n    tone.sine.amplitude(0);\n    delay(1750);\n}","x":308.25,"y":185.25,"z":"Main","bgColor":"#DDFFBB","wires":[]}]},{"type":"tab","id":"6f633541.989e4c","label":"MyTone","inputs":0,"outputs":0,"export":true,"isMain":false,"mainNameType":"main","mainNameExt":".ino","generateCppDestructor":false,"extraClassDeclarations":"","settings":{},"nodes":[{"id":"Tone_sine1","type":"AudioSynthWaveformSine","name":"sine","comment":"","x":355,"y":155,"z":"6f633541.989e4c","bgColor":"#E6E0F8","wires":[["Tone_i2s1:0","Tone_i2s1:1"]]},{"id":"Tone_i2s1","type":"AudioOutputI2S","name":"i2s","comment":"","x":542.25,"y":155.25,"z":"6f633541.989e4c","bgColor":"#E6E0F8","wires":[]},{"id":"Tone_sgtl5000_1","type":"AudioControlSGTL5000","name":"sgtl5000","comment":"","x":561.25,"y":215.25,"z":"6f633541.989e4c","bgColor":"#E6E0F8","wires":[]}]}],"nodeAddons":{}}
 
Last edited:
Just now I had a problem: could not edit function blocks anymore by double klicking on them (in Firefox and Chromium)
Maybe this is because I have a wrong understanding of the "vars" block??? Anyway, it happens when I put this into the vars block:
Code:
#include "MyTone.h"
AudioControlSGTL5000 sgtl5000;
const int ledPin = 13;
MyTone mytone;
I thought "vars" was for declaration of variables.
I put the same code into a code block: no problem!
 
Status
Not open for further replies.
Back
Top