Forum Rule: Always post complete source code & details to reproduce any issue!
Page 2 of 4 FirstFirst 1 2 3 4 LastLast
Results 26 to 50 of 88

Thread: USB Host turning envelopes on and off?

  1. #26
    I have to really study the code to figure out exactly how its working as I'm still not 100% sure what wcalverts contribution is doing exactly. I appreciate your advice tele_player I'm just having some trouble wrapping my head around how that will work... do I set a variable just storing note in it called oldNote at the top of onNoteOn()? Then I'd imagine add an id add an if idleVoice = false loop... man I was working late and my brain is mush...lol. I just want it to play as naturally as a polyphonic synth lol who knew how complicated that actually was haha.

  2. #27
    Also maybe instead of freeing up the note when it totally finished there is some way to test if a note is in the release phase of its envelope... maybe I'm overthinking this.

  3. #28
    There are certainly variations possible in a note stealing scheme: Oldest note, oldest note in release phase, same note # as new note... maybe others.

    But they’ll probably all need oldest note as a last resort. So, you’d need to keep track of when each note came in.

    Maybe somebody else will write this for you.

  4. #29
    Senior Member
    Join Date
    Feb 2015
    Posts
    163
    Well, one thing first, I see your max release time is nearly 12 seconds which seems pretty high to me, but then again I don't know what's considered normal.

    The other thing, these oscillators don't take a lot of CPU resources. If you're on a T3.6, or especially on a T4, you could add quite a few more voices.

    Having said that, here is a way it can be done. The oldest voice (based on when the note was initially played) will be stolen. I tested it on my synth and it works, but notice I had to add a new global variable called voiceOnTimes.

    Code:
    unsigned long voiceOnTimes[NUM_VOICES] = {0,0...};
    
    void onNoteOn(byte channel, byte note, byte velocity) {
    
      // Set Velocity to global variable
      globalVelocity = velocity;
      float velo = (globalVelocity * DIV127);
      bool found = false;
      int voiceToUse = 0;
    
      // Acquire an idle voice if possible.
      for (int i = 0; i < NUM_VOICES; i++) {
        if (idleVoices[i]) {
          voiceToUse = i;
          found = true;
          break;
        }
      }
    
      // Steal voice if needed.
      if(!found) {
        unsigned long oldest = millis();
        for(int i=0; i<NUM_VOICES; i++) {
          if(voiceOnTimes[i] < oldest) {
            oldest = voiceOnTimes[i];
            voiceToUse = i;
          }
        }
      }
    
      // Now use the acquired voice.
      idleVoices[voiceToUse] = false;
      voiceToNote[voiceToUse] = note;
      AudioNoInterrupts();
      oscs[voiceToUse]->frequency(noteFreqs[note]);
      oscs[voiceToUse]->amplitude(velo);
      envelopes[voiceToUse]->noteOn();
      AudioInterrupts();
      voiceOnTimes[voiceToUse] = millis();
    }
    Edit... it would be pretty easy to add "steal the same note". To add "steal by oldest in release" you would need an additional array to track release times.
    Last edited by wcalvert; 12-08-2019 at 02:08 AM.

  5. #30
    First of all thanks again wcalvert you have been a godsend! I still am having a bit of a problem that I cant understand fully. So lets say I play a chord with my left hand ... 2 or three notes, lets say 3 to be safe. While thats ringing in my right hand I play and release three notes over and over again while the left hand chord is still pressed down I need those notes to continue to sustain. How do I guarantee notes I keep held down are not stolen? Or should I just bite the bullet and add a crapload of voices? lol And again, thanks SO much wcalvert I've learned more since yesterday than I have in weeks of lone study.

  6. #31
    For that you’ll need to test if voice is active, but in the release phase.

  7. #32
    Senior Member
    Join Date
    Feb 2015
    Posts
    163
    Hey no worries, to be honest I am learning a ton hearing a musician's perspective, and voice stealing is something I really needed to address on my synth.

    The way I showed above is very naive about still-held notes. If the longest held voice is in the sustain phase, it doesn't care, it just steals it anyway. I didn't really think about that.

    Try this little change and see what you think. It should let the the still-held chord play, and steal other voices. Just change the one line in the voice stealing part:

    Code:
    if(voiceOnTimes[i] < oldest && !envelopes[i]->isSustain()) {

  8. #33
    "Thank you" isn't even close to a strong enough phrase at this point. That one addition made the synth beautifully, perfectly playable! A million times, thank you so much! Now I'm off to add on my last few additions, including selectable waveforms, doubling up on the voices and making the second oscillator detunable, and adding a noise oscillator. If I could possibly trouble you even further and you have a free moment, could you look at my old code and see if my implementation of those features will translate or if I will run into issues that you could see? Sorry to ask for so much but its rare I get the opportunity to pick the brain of someone that so fully grasps a skill I am a noob at. Thanks again my new friend I really appreciate everything!

    Here's my old code I am moving over to piece by piece:

    Code:
    // PANDA SYNTH ALPHA
    // aka SupaSynth aka Dirty Little Synth
    // Coded by Chris Gardella
    // 12/14/2018
    // Last Edited 11/29/2019
    
    //TODO:
    
    // Add more interesting scales, at least a few major :)
    // Add monochrome screen and rotary encoder
    // Add multiplexer
    // Add amp and speaker
    // Rechargable Lithium battery UPDATE: Working on a 9v Battery!
    // Add harware filter, delay, and looper, all low-fi
    // Add https://electricdruid.net/adding-vintage-hiss-crackle-and-pop/ OR create a duplicate in Arduino code
    //    To that end, possible store wav files with hiss, crackle, and pop loops. long enough to not sound like loops. Maybe even jump around
    //    inside loops radnomly with granular module. Add SD Card integration.
    // Add Noise Oscillator
    // 5 Pin Midi In
    // USBHost plug soldered to Teensy 3.6 DONE!
    // USBMidi without PC ALMOST DONE!
    // Velocity
    // LFO
    
    // Audio GUITool (synth architecture) code in seperate file
    
    #include "SYNTHARCH.H"
    
    Bounce button0 = Bounce(25, 15);
    Bounce button1 = Bounce(26, 15);
    Bounce button2 = Bounce(27, 15);
    Bounce button3 = Bounce(28, 15);
    Bounce button4 = Bounce(29, 15);
    Bounce button5 = Bounce(30, 15);
    Bounce button6 = Bounce(31, 15);
    Bounce button7 = Bounce(32, 15);
    
    //8x8 array to store scales
    float noteFrequencies[8][8] = {
      //Am
      {220.00, 246.94, 261.63, 293.66, 329.63, 349.23, 392.00, 440.00},
      //C Hungarian Folk
      {261.63, 277.18, 329.63, 349.23, 392.00, 415.30, 493.88, 523.25},
      //Cm
      {261.63, 293.66, 311.13, 349.23, 392.00, 415.30, 466.16, 523.25},
      //Dm
      {293.66, 329.63, 349.23, 392.00, 440.00, 466.16, 523.25, 587.33},
      //Em
      {329.63, 369.99, 392.00, 440.00, 493.88, 523.25, 587.33, 659.25},
      //Fm
      {349.23, 392.00, 415.30, 466.16, 523.25, 554.37, 622.25, 698.46},
      //Gm
      {392.00, 440.00, 466.16, 523.25, 587.33, 622.25, 698.46, 783.99},
      //Chromatic
      {220.00, 233.08, 246.94, 261.63, 277.18, 293.66, 311.13, 329.63},
    };
    
    // Define Variables
    int NPROGS = 4;
    int NPROGS2 = 4;
    float mixGain = 0.4;
    float attack = 500;
    float decay = 500;
    float sustain = 0.5;
    float release = 1000;
    float resonance = 3.8;
    const byte BUFFER = 8; //Size of keyboard buffer
    const float noteFreqs[128] = {8.176, 8.662, 9.177, 9.723, 10.301, 10.913, 11.562, 12.25, 12.978, 13.75, 14.568, 15.434, 16.352, 17.324, 18.354, 19.445, 20.602, 21.827, 23.125, 24.5, 25.957, 27.5, 29.135, 30.868, 32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55, 58.27, 61.735, 65.406, 69.296, 73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110, 116.541, 123.471, 130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220, 233.082, 246.942, 261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440, 466.164, 493.883, 523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880, 932.328, 987.767, 1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982, 1661.219, 1760, 1864.655, 1975.533, 2093.005, 2217.461, 2349.318, 2489.016, 2637.02, 2793.826, 2959.955, 3135.963, 3322.438, 3520, 3729.31, 3951.066, 4186.009, 4434.922, 4698.636, 4978.032, 5274.041, 5587.652, 5919.911, 6271.927, 6644.875, 7040, 7458.62, 7902.133, 8372.018, 8869.844, 9397.273, 9956.063, 10548.08, 11175.3, 11839.82, 12543.85};
    byte globalNote = 0;
    byte globalVelocity = 10;
    int noteNum = 0;
    float noteFlags[8];
    int knob1 = 11880 *  analogRead(A0) / 1023;
    int knob2 = 11880 * analogRead(A1) / 1023;
    int knob3 = analogRead(A2);
    int scale = map(knob3, 0, 1024, 0, 7);
    int knob4 = 11880 * analogRead(A3) / 1023;
    int knobD = 256 * analogRead(A17) / 1023;
    float knobR = 1.0 * analogRead(A18) / 1023;
    float knobA = 1.0 * analogRead(A19) / 1023;
    
    void setup() {
    
      Serial.begin(9600);
      // Full Synth requires some serious memory
      AudioMemory(50);
      sgtl5000_1.enable();
      // Full volume is 1.0 which will damage speakers or ears in most cases :)
      sgtl5000_1.volume(mixGain);
    
      // Set keys pinmode
      pinMode(25, INPUT_PULLUP);
      pinMode(26, INPUT_PULLUP);
      pinMode(27, INPUT_PULLUP);
      pinMode(28, INPUT_PULLUP);
      pinMode(29, INPUT_PULLUP);
      pinMode(30, INPUT_PULLUP);
      pinMode(31, INPUT_PULLUP);
      pinMode(32, INPUT_PULLUP);
    
      // Set all mixer volumes to the above declared value, mixGain
      mixer1.gain(0, mixGain);
      mixer1.gain(1, mixGain);
      mixer1.gain(2, mixGain);
      mixer1.gain(3, mixGain);
    
      mixer2.gain(0, mixGain);
      mixer2.gain(1, mixGain);
      mixer2.gain(2, mixGain);
      mixer2.gain(3, mixGain);
    
      mixer3.gain(0, mixGain);
      mixer3.gain(1, mixGain);
      mixer3.gain(2, mixGain);
      mixer3.gain(3, mixGain);
    
      mixer4.gain(0, mixGain);
      mixer4.gain(1, mixGain);
      mixer4.gain(2, mixGain);
      mixer4.gain(3, mixGain);
    
      mixerFinal.gain(0, mixGain);
      mixerFinal.gain(1, mixGain);
    
      verbMix.gain(0, mixGain);
      verbMix.gain(1, mixGain);
      verbMix.gain(2, mixGain);
    }
    
    void loop() {
      AudioNoInterrupts();
    
      int knob1 = 11880 *  analogRead(A0) / 1023;
      int knob2 = 11880 * analogRead(A1) / 1023;
      int knob3 = analogRead(A2);
      int scale = map(knob3, 0, 1024, 0, 7);
      int knob4 = 11880 * analogRead(A3) / 1023;
      int knobD = 256 * analogRead(A17) / 1023;
      float knobR = 1.0 * analogRead(A18) / 1023;
      float knobA = 1.0 * analogRead(A19) / 1023;
    
      // Future Volume Knob
      // float knobVol = 1.0 * analogRead(A20) / 1023;
      // float mixGain = knobVol;
    
      // Debug Code to view knob values
      //Serial.println(knobR);
    
      // Reverb! If statements to set mixer volume with freeverb to zero to approximate turning reverb off. 0.03 to allow for shitty pot jitter.
      freeverbs1.roomsize(knobR);
      freeverbs1.damping(knobA);
    
      if (knobR > 0.03) {
        verbMix.gain(1, mixGain);
        verbMix.gain(2, mixGain - knobR);
      }
      if (knobR <= 0.03) {
        verbMix.gain(0, 0);
        verbMix.gain(1, 0);
      }
    
      uint8_t progs[NPROGS] = {
        WAVEFORM_SINE,
        WAVEFORM_SQUARE,
        WAVEFORM_TRIANGLE,
        WAVEFORM_SAWTOOTH,
      };
    
      int val = analogRead(A14);
      int index = map(val, 0, 1024, 0, 3);
      int myProg = progs[index];
    
      // Pointer Array to begin waveforms Voice 1
      const char prognum = myProg;
      AudioSynthWaveformModulated *myWaveform[]  = { &waveform1, &waveform2, &waveform3, &waveform4, &waveform5, &waveform6, &waveform7, &waveform8};
      for (int i = 0; i < 8; i++) {
        myWaveform[i]->begin(mixGain, noteFrequencies[scale][i], prognum);
      }
    
      uint8_t progs2[NPROGS2] = {
        WAVEFORM_SINE,
        WAVEFORM_SQUARE,
        WAVEFORM_TRIANGLE,
        WAVEFORM_SAWTOOTH,
      };
    
      int val2 = analogRead(A16);
      int index2 = map(val2, 0, 1024, 0, 3);
      int myProg2 = progs2[index2];
    
      // Pointer Array to begin waveforms Voice 2
      const char prognum2 = myProg2;
      // Detune
      int detune = knobD;
      AudioSynthWaveformModulated *myWaveform2[]  = { &waveform9, &waveform10, &waveform11, &waveform12, &waveform13, &waveform14, &waveform15, &waveform16};
      for (int i = 0; i < 8; i++) {
        myWaveform2[i]->begin(mixGain, noteFrequencies[scale][i] - detune, prognum2);
      }
    
      // Pointer Array to set the envelope value to knobs value
      AudioEffectEnvelope *myEnvelope[]  = { &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8, &envelope9, &envelope10, &envelope11, &envelope12, &envelope13, &envelope14, &envelope15, &envelope16 };
      for (int i = 0; i < 16; i++) {
        myEnvelope[i]->attack(knob1);
        myEnvelope[i]->release(knob2);
      }
    
      // Pointer Array for filter settings
      AudioFilterStateVariable *myfilter[]  = { &filter1, &filter2, &filter3, &filter4, &filter5, &filter6, &filter7, &filter8, &filter9, &filter10, &filter11, &filter12, &filter13, &filter14, &filter15, &filter16 };
      for (int i = 0; i < 16; i++) {
        myfilter[i]->frequency(knob4);
        //Resonace will be controlled by its own knob
        myfilter[i]->resonance(resonance);
      }
    
      // Pointer Arrays to update buttons and trigger notes
      AudioEffectEnvelope *myEnvelope2[]  = { &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8, &envelope9, &envelope10, &envelope11, &envelope12, &envelope13, &envelope14, &envelope15, &envelope16 };
      Bounce *mybutton2[]  = { &button0, &button1, &button2, &button3, &button4, &button5, &button6, &button7};
      for (int i = 0; i < 8; i++) {
        mybutton2[i]->update();
    
        if (mybutton2[i]->fallingEdge()) {
          myEnvelope2[i]->noteOn();
          myEnvelope2[i + 8]->noteOn();
        }
        if (mybutton2[i]->risingEdge()) {
          myEnvelope2[i]->noteOff();
          myEnvelope2[i + 8]->noteOff();
        }
      }
      AudioInterrupts();
      /*
        // Below is the code to activate wave modulation at a fixed rate. TODO: Make rate Variable
        modWave1.begin(0.6, 2, WAVEFORM_SINE);
        modWave2.begin(0.6, 2, WAVEFORM_SINE);
      */
    }

  9. #34
    Hey no worries, to be honest I am learning a ton hearing a musician's perspective, and voice stealing is something I really needed to address on my synth.
    Anytime, and I mean anytim e at all you need a musicians perspective or you need someone to test out something you are working feel free to send it my way, I am honored I could help!

  10. #35
    Hey everyone. Here is the new version of my synth code. I am having some problems figuring out how to pass current potentiometer values to the onNoteOn() function. My solution to change the waveform types was to put the selection code directly in the function as you can see below. This has the effect, though, of one having to trigger a note every time you want to hear a new waveform, when ideally I would like someone to be able to hold down a note or chord while scanning through the waveforms. This same problem is sure to rear its head when I implement detuning as well. So my question is, how do I pass values from the loop() section of the code to an outside function like onNoteOn()? Is this even possible? And if not, how would you get around a problem like this? Any help would be greatly appreciated.

    I also took wcalverts advice and doubled up the amount of voices, there are now 32. I'll include all the code below.


    Main code
    Code:
    // PANDA SYNTH
    // Coded by Chris Gardella
    // HUGE thanks to wcalvert and oddson at the PJRC Forum!
    // https://forum.pjrc.com/threads/58586-USB-Host-turning-envelopes-on-and-off?p=222794
    
    // Include Audio System Designer Tool Code
    #include "SYNTHARCH.H"
    
    Bounce button0 = Bounce(25, 15);
    Bounce button1 = Bounce(26, 15);
    Bounce button2 = Bounce(27, 15);
    Bounce button3 = Bounce(28, 15);
    Bounce button4 = Bounce(29, 15);
    Bounce button5 = Bounce(30, 15);
    Bounce button6 = Bounce(31, 15);
    Bounce button7 = Bounce(32, 15);
    
    // Include USBHost Library
    #include <USBHost_t36.h>
    
    USBHost myusb;
    MIDIDevice midi1(myusb);
    
    // GLOBAL VARIABLES
    
    // Array to covert MIDI notes to frequencies
    const float noteFreqs[128] = {8.176, 8.662, 9.177, 9.723, 10.301, 10.913, 11.562, 12.25, 12.978, 13.75, 14.568, 15.434, 16.352, 17.324, 18.354, 19.445, 20.602, 21.827, 23.125, 24.5, 25.957, 27.5, 29.135, 30.868, 32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55, 58.27, 61.735, 65.406, 69.296, 73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110, 116.541, 123.471, 130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220, 233.082, 246.942, 261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440, 466.164, 493.883, 523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880, 932.328, 987.767, 1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982, 1661.219, 1760, 1864.655, 1975.533, 2093.005, 2217.461, 2349.318, 2489.016, 2637.02, 2793.826, 2959.955, 3135.963, 3322.438, 3520, 3729.31, 3951.066, 4186.009, 4434.922, 4698.636, 4978.032, 5274.041, 5587.652, 5919.911, 6271.927, 6644.875, 7040, 7458.62, 7902.133, 8372.018, 8869.844, 9397.273, 9956.063, 10548.08, 11175.3, 11839.82, 12543.85};
    
    // Array for button MIDI notes
    const float buttonFreqs[8] = {48, 50, 52, 53, 55, 57, 59, 60};
    
    // Set number of voices
    const int NUM_VOICES = 32;
    
    const int NPROGS = 4;
    const int NPROGS2 = 4;
    float mixGain = 0.5;
    float resonance = 3.8;
    const float DIV127 = (1.0 / 127.0);
    byte globalVelocity = 127;
    
    bool idleVoices[32] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
    
    // Set to 255 so it didn't throw an error :)
    byte voiceToNote[32] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
    
    void setup() {
    
      myusb.begin();
    
      Serial.begin(9600);
    
      pinMode(25, INPUT_PULLUP);
      pinMode(26, INPUT_PULLUP);
      pinMode(27, INPUT_PULLUP);
      pinMode(28, INPUT_PULLUP);
      pinMode(29, INPUT_PULLUP);
      pinMode(30, INPUT_PULLUP);
      pinMode(31, INPUT_PULLUP);
      pinMode(32, INPUT_PULLUP);
    
      // Detect USB slave key presses, call functions to handle presses
      midi1.setHandleNoteOn(onNoteOn);
      midi1.setHandleNoteOff(onNoteOff);
    
      // MUST set Audio Memory
      AudioMemory(120);
    
      sgtl5000_1.enable();
      sgtl5000_1.volume(0.5);
    
      // Initialize Waveforms
      AudioSynthWaveformModulated *oscsStart1[NUM_VOICES] = { &waveform1, &waveform2, &waveform3, &waveform4, &waveform5, &waveform6, &waveform7, &waveform8, &waveform9, &waveform10, &waveform11, &waveform12, &waveform13, &waveform14, &waveform15, &waveform16 };
      for (int i = 0; i < 16; i++) {
        oscsStart1[i]->begin(mixGain, 144, WAVEFORM_SQUARE);
      }
    
    
      // Initialize Waveforms
      AudioSynthWaveformModulated *oscsStart2[NUM_VOICES] = { &waveform17, &waveform18, &waveform19, &waveform20, &waveform21, &waveform22, &waveform23, &waveform24, &waveform25, &waveform26, &waveform27, &waveform28, &waveform29, &waveform30, &waveform31, &waveform32 };
      for (int i = 0; i < 16; i++) {
        oscsStart2[i]->begin(mixGain, 144, WAVEFORM_TRIANGLE);
      }
    
      //Turn on all mixers
      mixer1.gain(0, mixGain);
      mixer1.gain(1, mixGain);
      mixer1.gain(2, mixGain);
      mixer1.gain(3, mixGain);
    
      mixer2.gain(0, mixGain);
      mixer2.gain(1, mixGain);
      mixer2.gain(2, mixGain);
      mixer2.gain(3, mixGain);
    
      mixer3.gain(0, mixGain);
      mixer3.gain(1, mixGain);
      mixer3.gain(2, mixGain);
      mixer3.gain(3, mixGain);
    
      mixer4.gain(0, mixGain);
      mixer4.gain(1, mixGain);
      mixer4.gain(2, mixGain);
      mixer4.gain(3, mixGain);
    
      mixer5.gain(0, mixGain);
      mixer5.gain(1, mixGain);
      mixer5.gain(2, mixGain);
      mixer5.gain(3, mixGain);
    
      mixer6.gain(0, mixGain);
      mixer6.gain(1, mixGain);
      mixer6.gain(2, mixGain);
      mixer6.gain(3, mixGain);
    
      mixer7.gain(0, mixGain);
      mixer7.gain(1, mixGain);
      mixer7.gain(2, mixGain);
      mixer7.gain(3, mixGain);
    
      mixer8.gain(0, mixGain);
      mixer8.gain(1, mixGain);
      mixer8.gain(2, mixGain);
      mixer8.gain(3, mixGain);
    
      mixer9.gain(0, mixGain);
      mixer9.gain(1, mixGain);
      mixer9.gain(2, mixGain);
      mixer9.gain(3, mixGain);
    
      mixer10.gain(0, mixGain);
      mixer10.gain(1, mixGain);
      mixer10.gain(2, mixGain);
      mixer10.gain(3, mixGain);
    
      mixer11.gain(0, mixGain);
      mixer11.gain(1, mixGain);
      mixer11.gain(2, mixGain);
      mixer11.gain(3, mixGain);
    
      mixer12.gain(0, mixGain);
      mixer12.gain(1, mixGain);
      mixer12.gain(2, mixGain);
      mixer12.gain(3, mixGain);
    
      mixerFinal.gain(0, mixGain);
      mixerFinal.gain(1, mixGain);
      mixerFinal.gain(2, mixGain);
      mixerFinal.gain(3, mixGain);
    
      mixerFinal1.gain(0, mixGain);
      mixerFinal1.gain(1, mixGain);
      mixerFinal1.gain(2, mixGain);
      mixerFinal1.gain(3, mixGain);
    
      verbMix.gain(0, mixGain);
      verbMix.gain(1, mixGain);
      verbMix.gain(2, mixGain);
    
      lastMix.gain(0, mixGain);
      lastMix.gain(1, mixGain);
    }
    
    AudioFilterStateVariable *myfilter[]  = { &filter1, &filter2, &filter3, &filter4, &filter5, &filter6, &filter7, &filter8, &filter9, &filter10, &filter11, &filter12, &filter13, &filter14, &filter15, &filter16, &filter17, &filter18, &filter19, &filter20, &filter21, &filter22, &filter23, &filter24, &filter25, &filter26, &filter27, &filter28, &filter29, &filter30, &filter31, &filter32 };
    Bounce *mybutton[]  = { &button0, &button1, &button2, &button3, &button4, &button5, &button6, &button7};
    AudioEffectEnvelope *myEnvelope[]  = { &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8, &envelope9, &envelope10, &envelope11, &envelope12, &envelope13, &envelope14, &envelope15, &envelope16, &envelope17, &envelope18, &envelope19, &envelope20, &envelope21, &envelope22, &envelope23, &envelope24, &envelope25, &envelope26, &envelope27, &envelope28, &envelope29, &envelope30, &envelope31, &envelope32 };
    
    void loop() {
    
    int knobD = 256 * analogRead(A17) / 1023;
     
      // Check USB input
      midi1.read();
    
      // Check if notes are playing
      IdleCheck();
    
      //Lowpass Filter
      int filterKnob = 10000 * analogRead(A3) / 1023;
      // Pointer Array for filter settings
      for (int i = 0; i < 16; i++) {
        myfilter[i]->frequency(filterKnob);
        //Resonace will be controlled by its own knob
        myfilter[i]->resonance(resonance);
      }
    
      // Reverb!
      float knobR = 1.0 * analogRead(A18) / 1023;
      float knobA = 1.0 * analogRead(A19) / 1023;
    
      freeverbs1.roomsize(knobR);
      freeverbs1.damping(knobA);
    
      // If statements to set mixer volume with freeverb to zero to approximate turning reverb off
      // 0.03 to allow for shitty pot jitter
    
      if (knobR > 0.03) {
        verbMix.gain(1, mixGain);
        verbMix.gain(2, mixGain - knobR);
      }
      if (knobR <= 0.03) {
        verbMix.gain(0, 0);
        verbMix.gain(1, 0);
    
        // Envelope Settings
        int knob1 = 10000 *  analogRead(A0) / 1023;
        int knob2 = 20000 * analogRead(A1) / 1023;
        for (int i = 0; i < 16; i++) {
          myEnvelope[i]->attack(knob1);
          myEnvelope[i]->release(knob2);
        }
      }
    
      for (int i = 0; i < 8; i++) {
        mybutton[i]->update();
    
        if (mybutton[i]->fallingEdge()) {
          onNoteOn(1, buttonFreqs[i], globalVelocity);
        }
        if (mybutton[i]->risingEdge()) {
          onNoteOff(1, buttonFreqs[i], globalVelocity);
        }
      }
    
    }
      
    AudioSynthWaveformModulated *oscs[NUM_VOICES] = { &waveform1, &waveform2, &waveform3, &waveform4, &waveform5, &waveform6, &waveform7, &waveform8, &waveform9, &waveform10, &waveform11, &waveform12, &waveform13, &waveform14, &waveform15, &waveform16, &waveform17, &waveform18, &waveform19, &waveform20, &waveform21, &waveform22, &waveform23, &waveform24, &waveform25, &waveform26, &waveform27, &waveform28, &waveform29, &waveform30, &waveform31, &waveform32 };
    AudioEffectEnvelope *envelopes[NUM_VOICES] = { &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8, &envelope9, &envelope10, &envelope11, &envelope12, &envelope13, &envelope14, &envelope15, &envelope16, &envelope17, &envelope18, &envelope19, &envelope20, &envelope21, &envelope22, &envelope23, &envelope24, &envelope25, &envelope26, &envelope27, &envelope28, &envelope29, &envelope30, &envelope31, &envelope32 };
    unsigned long voiceOnTimes[NUM_VOICES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
    void onNoteOn(byte channel, byte note, byte velocity) {
    
    uint8_t progs[NPROGS] = {
        WAVEFORM_SINE,
        WAVEFORM_SQUARE,
        WAVEFORM_TRIANGLE,
        WAVEFORM_SAWTOOTH,
      };
    
      int  val = analogRead(A14);
      int  numprogs = map(val, 0, 1024, 0, 3);
      int myProg = progs[numprogs];
      const char prognum = myProg;
    
       uint8_t progs2[NPROGS2] = {
        WAVEFORM_SINE,
        WAVEFORM_SQUARE,
        WAVEFORM_TRIANGLE,
        WAVEFORM_SAWTOOTH,
      };
    
      int val2 = analogRead(A16);
      int numprogs2 = map(val2, 0, 1024, 0, 3);
      int myProg2 = progs2[numprogs2];
      const char prognum2 = myProg2;
    
      // Set Velocity to global variable
      globalVelocity = velocity;
      float velo = (globalVelocity * DIV127);
      bool found = false;
      int voiceToUse = 0;
    
      // Acquire an idle voice if possible.
      for (int i = 0; i < NUM_VOICES; i++) {
        if (idleVoices[i]) {
          voiceToUse = i;
          found = true;
          break;
        }
      }
    
      // Steal voice if needed.
      if (!found) {
        unsigned long oldest = millis();
        for (int i = 0; i < NUM_VOICES; i++) {
          if (voiceOnTimes[i] < oldest && !envelopes[i]->isSustain()) {
            oldest = voiceOnTimes[i];
            voiceToUse = i;
          }
        }
      }
    
      // Now use the acquired voice.
      idleVoices[voiceToUse] = false;
      voiceToNote[voiceToUse] = note;
      AudioNoInterrupts();
      oscs[voiceToUse]->begin(prognum);
      oscs[voiceToUse]->frequency(noteFreqs[note]);
      oscs[voiceToUse]->amplitude(velo);
      envelopes[voiceToUse]->noteOn();
      oscs[voiceToUse + 8]->begin(prognum2);
      oscs[voiceToUse + 8]->frequency(noteFreqs[note]);
      oscs[voiceToUse + 8]->amplitude(velo);
      envelopes[voiceToUse + 8]->noteOn();
      AudioInterrupts();
      voiceOnTimes[voiceToUse] = millis();
    }
    
    void onNoteOff(byte channel, byte note, byte velocity) {
      for (int i = 0; i < NUM_VOICES; i++) {
        if (voiceToNote[i] == note) {
          envelopes[i]->noteOff();
          voiceToNote[i] = -1;
          envelopes[i + 8]->noteOff();
          voiceToNote[i + 8] = -1;
        }
      }
    }
    
    void IdleCheck(void) {
      for (uint8_t i = 0; i < NUM_VOICES; i++) {
        if (!envelopes[i]->isActive()) {
          oscs[i]->amplitude(0);
          idleVoices[i] = true;
        } else {
          idleVoices[i] = false;
        }
      }
    }
    Audiotool Code
    Code:
    #ifndef _SYNTHARCH_H
    #define _SYNTHARCH_H
    
    #include <Arduino.h>
    #include <Bounce.h>
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // GUItool: begin automatically generated code
    AudioSynthWaveform       modWave3; //xy=259.3999881744385,2860.5997371673584
    AudioSynthWaveform       modWave4; //xy=280.3999881744385,2052.5997371673584
    AudioSynthWaveform       modWave2;       //xy=323.79998779296875,1193
    AudioSynthWaveform       modWave1;       //xy=344.79998779296875,385
    AudioMixer4              mixer7; //xy=419.3999881744385,2876.5997371673584
    AudioMixer4              mixer8; //xy=458.3999881744385,2064.5996837615967
    AudioMixer4              mixer6;         //xy=483.79998779296875,1209
    AudioMixer4              mixer5;         //xy=503.79998779296875,401
    AudioSynthWaveformModulated waveform17; //xy=681.3999881744385,3066.5997371673584
    AudioSynthWaveformModulated waveform18; //xy=684.3999881744385,3249.5997371673584
    AudioSynthWaveformModulated waveform19; //xy=686.3999881744385,3167.5997371673584
    AudioSynthWaveformModulated waveform20; //xy=693.3999881744385,2849.5997371673584
    AudioSynthWaveformModulated waveform21; //xy=696.3999881744385,2936.5997371673584
    AudioSynthWaveformModulated waveform22; //xy=698.3999881744385,2566.5997371673584
    AudioSynthWaveformModulated waveform23; //xy=699.3999881744385,2658.5997371673584
    AudioSynthWaveformModulated waveform24; //xy=699.3999881744385,2745.5997371673584
    AudioSynthWaveformModulated waveform25; //xy=730.3999881744385,2235.5997371673584
    AudioSynthWaveformModulated waveform26; //xy=738.3999881744385,2128.5997371673584
    AudioSynthWaveformModulated waveform27; //xy=742.3999881744385,2032.5997371673584
    AudioSynthWaveformModulated waveform14;     //xy=745.7999877929688,1399
    AudioSynthWaveformModulated waveform16;     //xy=748.7999877929688,1582
    AudioSynthWaveformModulated waveform28; //xy=745.3999881744385,2433.5997371673584
    AudioSynthWaveformModulated waveform15;     //xy=750.7999877929688,1500
    AudioSynthWaveformModulated waveform29; //xy=751.3999881744385,2340.5997371673584
    AudioSynthWaveformModulated waveform12;     //xy=757.7999877929688,1182
    AudioSynthWaveformModulated waveform30; //xy=755.3999881744385,1938.5997371673584
    AudioSynthWaveformModulated waveform31; //xy=756.3999881744385,1861.5997371673584
    AudioSynthWaveformModulated waveform13;     //xy=760.7999877929688,1269
    AudioSynthWaveformModulated waveform9;      //xy=762.7999877929688,899
    AudioSynthWaveformModulated waveform10;     //xy=763.7999877929688,991
    AudioSynthWaveformModulated waveform11;     //xy=763.7999877929688,1078
    AudioSynthWaveformModulated waveform32; //xy=762.3999881744385,1757.5997371673584
    AudioSynthWaveformModulated waveform6;      //xy=794.7999877929688,568
    AudioSynthWaveformModulated waveform5;      //xy=802.7999877929688,461
    AudioSynthWaveformModulated waveform4;      //xy=806.7999877929688,365
    AudioSynthWaveformModulated waveform8;      //xy=809.7999877929688,766
    AudioSynthWaveformModulated waveform7;      //xy=815.7999877929688,673
    AudioSynthWaveformModulated waveform3;      //xy=819.7999877929688,271
    AudioSynthWaveformModulated waveform2;      //xy=820.7999877929688,194
    AudioSynthWaveformModulated waveform1;      //xy=826.7999877929688,90
    AudioFilterStateVariable filter17; //xy=843.3999881744385,2843.5997371673584
    AudioFilterStateVariable filter18; //xy=851.3999881744385,2939.5997371673584
    AudioFilterStateVariable filter19; //xy=853.3999881744385,2653.5997371673584
    AudioFilterStateVariable filter20; //xy=854.3999881744385,2571.5997371673584
    AudioFilterStateVariable filter21; //xy=856.3999881744385,3244.5997371673584
    AudioFilterStateVariable filter22; //xy=859.3999881744385,3062.5997371673584
    AudioFilterStateVariable filter23; //xy=864.3999881744385,2746.5997371673584
    AudioFilterStateVariable filter24; //xy=863.3999881744385,3168.5997371673584
    AudioFilterStateVariable filter25; //xy=889.3999881744385,2037.5997371673584
    AudioFilterStateVariable filter26; //xy=897.3999881744385,2133.5997371673584
    AudioFilterStateVariable filter27; //xy=899.3999881744385,1767.5997371673584
    AudioFilterStateVariable filter28; //xy=899.3999881744385,1847.5997371673584
    AudioFilterStateVariable filter29; //xy=902.3999881744385,2438.5997371673584
    AudioFilterStateVariable filter12;       //xy=907.7999877929688,1176
    AudioFilterStateVariable filter30; //xy=905.3999881744385,2256.5997371673584
    AudioFilterStateVariable filter31; //xy=910.3999881744385,1940.5997371673584
    AudioFilterStateVariable filter32; //xy=909.3999881744385,2362.5997371673584
    AudioFilterStateVariable filter13;       //xy=915.7999877929688,1272
    AudioFilterStateVariable filter10;       //xy=917.7999877929688,986
    AudioFilterStateVariable filter9;        //xy=918.7999877929688,904
    AudioFilterStateVariable filter16;       //xy=920.7999877929688,1577
    AudioFilterStateVariable filter14;       //xy=923.7999877929688,1395
    AudioFilterStateVariable filter11;       //xy=928.7999877929688,1079
    AudioFilterStateVariable filter15;       //xy=927.7999877929688,1501
    AudioFilterStateVariable filter4;        //xy=953.7999877929688,370
    AudioFilterStateVariable filter5;        //xy=961.7999877929688,466
    AudioFilterStateVariable filter1;        //xy=963.7999877929688,100
    AudioFilterStateVariable filter2;        //xy=963.7999877929688,180
    AudioFilterStateVariable filter8;        //xy=966.7999877929688,771
    AudioFilterStateVariable filter6;        //xy=969.7999877929688,589
    AudioFilterStateVariable filter3;        //xy=974.7999877929688,273
    AudioFilterStateVariable filter7;        //xy=973.7999877929688,695
    AudioEffectEnvelope      envelope17; //xy=1023.3999881744385,2830.5997371673584
    AudioEffectEnvelope      envelope18; //xy=1031.3999881744385,2926.5997371673584
    AudioEffectEnvelope      envelope19; //xy=1033.3999881744385,2640.5997371673584
    AudioEffectEnvelope      envelope20; //xy=1032.4000186920166,3234.5996017456055
    AudioEffectEnvelope      envelope21; //xy=1040.3999881744385,2574.5997371673584
    AudioEffectEnvelope      envelope22; //xy=1039.3999881744385,3046.5997371673584
    AudioEffectEnvelope      envelope24; //xy=1042.4000186920166,3132.5996017456055
    AudioEffectEnvelope      envelope23; //xy=1044.3999881744385,2733.5997371673584
    AudioEffectEnvelope      envelope25;  //xy=1055.3999881744385,1750.5997371673584
    AudioEffectEnvelope      envelope26; //xy=1069.3999881744385,2024.5997371673584
    AudioEffectEnvelope      envelope27; //xy=1077.3999881744385,2120.5997371673584
    AudioEffectEnvelope      envelope28; //xy=1079.3999881744385,1834.5997371673584
    AudioEffectEnvelope      envelope29; //xy=1082.3999881744385,2425.5997371673584
    AudioEffectEnvelope      envelope12;     //xy=1087.7999877929688,1163
    AudioEffectEnvelope      envelope30; //xy=1085.3999881744385,2243.5997371673584
    AudioEffectEnvelope      envelope31; //xy=1090.3999881744385,1927.5997371673584
    AudioEffectEnvelope      envelope32; //xy=1089.3999881744385,2349.5997371673584
    AudioEffectEnvelope      envelope13;     //xy=1095.7999877929688,1259
    AudioEffectEnvelope      envelope10;     //xy=1097.7999877929688,973
    AudioEffectEnvelope      envelope16;     //xy=1100.7999877929688,1564
    AudioEffectEnvelope      envelope9;      //xy=1104.7999877929688,907
    AudioEffectEnvelope      envelope14;     //xy=1103.7999877929688,1379
    AudioEffectEnvelope      envelope11;     //xy=1108.7999877929688,1066
    AudioEffectEnvelope      envelope15;     //xy=1107.7999877929688,1488
    AudioEffectEnvelope      envelope1;      //xy=1119.7999877929688,83
    AudioEffectEnvelope      envelope4;      //xy=1133.7999877929688,357
    AudioEffectEnvelope      envelope5;      //xy=1141.7999877929688,453
    AudioEffectEnvelope      envelope2;      //xy=1143.7999877929688,167
    AudioEffectEnvelope      envelope8;      //xy=1146.7999877929688,758
    AudioEffectEnvelope      envelope6;      //xy=1149.7999877929688,576
    AudioEffectEnvelope      envelope3;      //xy=1154.7999877929688,260
    AudioEffectEnvelope      envelope7;      //xy=1153.7999877929688,682
    AudioMixer4              mixer10; //xy=1313.400016784668,2057.599447250366
    AudioMixer4              mixer9; //xy=1320.4000186920166,1899.5993881225586
    AudioMixer4              mixer12; //xy=1334.400016784668,2423.599645614624
    AudioMixer4              mixer11; //xy=1337.400016784668,2267.5998401641846
    AudioMixer4              mixer1;         //xy=1359.7999877929688,742
    AudioMixer4              mixer2;         //xy=1366.7999877929688,851
    AudioMixer4              mixer3;         //xy=1368.7999877929688,992
    AudioMixer4              mixer4;         //xy=1371.7999877929688,1134
    AudioMixer4              mixerFinal1; //xy=1532.3999710083008,1680.5995864868164
    AudioMixer4              mixerFinal;     //xy=1536.799877166748,1571.0000686645508
    AudioMixer4              lastMix;         //xy=1712.1999778747559,1626.1999740600586
    AudioEffectFreeverbStereo freeverbs1;     //xy=1859.7999801635742,1552.9999732971191
    AudioMixer4              verbMix;        //xy=2016.7999801635742,1622.000072479248
    AudioOutputI2S           i2s1;           //xy=2200.799980163574,1605.9999713897705
    AudioConnection          patchCord1(modWave3, 0, mixer7, 0);
    AudioConnection          patchCord2(modWave4, 0, mixer8, 0);
    AudioConnection          patchCord3(modWave2, 0, mixer6, 0);
    AudioConnection          patchCord4(modWave1, 0, mixer5, 0);
    AudioConnection          patchCord5(mixer7, 0, waveform22, 0);
    AudioConnection          patchCord6(mixer7, 0, waveform23, 0);
    AudioConnection          patchCord7(mixer7, 0, waveform20, 0);
    AudioConnection          patchCord8(mixer7, 0, waveform21, 0);
    AudioConnection          patchCord9(mixer7, 0, waveform17, 0);
    AudioConnection          patchCord10(mixer7, 0, waveform19, 0);
    AudioConnection          patchCord11(mixer7, 0, waveform18, 0);
    AudioConnection          patchCord12(mixer7, 0, waveform24, 0);
    AudioConnection          patchCord13(mixer8, 0, waveform32, 0);
    AudioConnection          patchCord14(mixer8, 0, waveform31, 0);
    AudioConnection          patchCord15(mixer8, 0, waveform30, 0);
    AudioConnection          patchCord16(mixer8, 0, waveform27, 0);
    AudioConnection          patchCord17(mixer8, 0, waveform26, 0);
    AudioConnection          patchCord18(mixer8, 0, waveform25, 0);
    AudioConnection          patchCord19(mixer8, 0, waveform29, 0);
    AudioConnection          patchCord20(mixer8, 0, waveform28, 0);
    AudioConnection          patchCord21(mixer6, 0, waveform9, 0);
    AudioConnection          patchCord22(mixer6, 0, waveform10, 0);
    AudioConnection          patchCord23(mixer6, 0, waveform11, 0);
    AudioConnection          patchCord24(mixer6, 0, waveform12, 0);
    AudioConnection          patchCord25(mixer6, 0, waveform13, 0);
    AudioConnection          patchCord26(mixer6, 0, waveform14, 0);
    AudioConnection          patchCord27(mixer6, 0, waveform15, 0);
    AudioConnection          patchCord28(mixer6, 0, waveform16, 1);
    AudioConnection          patchCord29(mixer5, 0, waveform1, 0);
    AudioConnection          patchCord30(mixer5, 0, waveform2, 0);
    AudioConnection          patchCord31(mixer5, 0, waveform3, 0);
    AudioConnection          patchCord32(mixer5, 0, waveform4, 0);
    AudioConnection          patchCord33(mixer5, 0, waveform5, 0);
    AudioConnection          patchCord34(mixer5, 0, waveform6, 0);
    AudioConnection          patchCord35(mixer5, 0, waveform7, 0);
    AudioConnection          patchCord36(mixer5, 0, waveform8, 0);
    AudioConnection          patchCord37(waveform17, 0, filter22, 0);
    AudioConnection          patchCord38(waveform18, 0, filter21, 0);
    AudioConnection          patchCord39(waveform19, 0, filter24, 0);
    AudioConnection          patchCord40(waveform20, 0, filter17, 0);
    AudioConnection          patchCord41(waveform21, 0, filter18, 0);
    AudioConnection          patchCord42(waveform22, 0, filter20, 0);
    AudioConnection          patchCord43(waveform23, 0, filter19, 0);
    AudioConnection          patchCord44(waveform24, 0, filter23, 0);
    AudioConnection          patchCord45(waveform25, 0, filter30, 0);
    AudioConnection          patchCord46(waveform26, 0, filter26, 0);
    AudioConnection          patchCord47(waveform27, 0, filter25, 0);
    AudioConnection          patchCord48(waveform14, 0, filter14, 0);
    AudioConnection          patchCord49(waveform16, 0, filter16, 0);
    AudioConnection          patchCord50(waveform28, 0, filter29, 0);
    AudioConnection          patchCord51(waveform15, 0, filter15, 0);
    AudioConnection          patchCord52(waveform29, 0, filter32, 0);
    AudioConnection          patchCord53(waveform12, 0, filter12, 0);
    AudioConnection          patchCord54(waveform30, 0, filter31, 0);
    AudioConnection          patchCord55(waveform31, 0, filter28, 0);
    AudioConnection          patchCord56(waveform13, 0, filter13, 0);
    AudioConnection          patchCord57(waveform9, 0, filter9, 0);
    AudioConnection          patchCord58(waveform10, 0, filter10, 0);
    AudioConnection          patchCord59(waveform11, 0, filter11, 0);
    AudioConnection          patchCord60(waveform32, 0, filter27, 0);
    AudioConnection          patchCord61(waveform6, 0, filter6, 0);
    AudioConnection          patchCord62(waveform5, 0, filter5, 0);
    AudioConnection          patchCord63(waveform4, 0, filter4, 0);
    AudioConnection          patchCord64(waveform8, 0, filter8, 0);
    AudioConnection          patchCord65(waveform7, 0, filter7, 0);
    AudioConnection          patchCord66(waveform3, 0, filter3, 0);
    AudioConnection          patchCord67(waveform2, 0, filter2, 0);
    AudioConnection          patchCord68(waveform1, 0, filter1, 0);
    AudioConnection          patchCord69(filter17, 0, envelope17, 0);
    AudioConnection          patchCord70(filter18, 0, envelope18, 0);
    AudioConnection          patchCord71(filter19, 0, envelope19, 0);
    AudioConnection          patchCord72(filter20, 0, envelope21, 0);
    AudioConnection          patchCord73(filter21, 0, envelope20, 0);
    AudioConnection          patchCord74(filter22, 0, envelope22, 0);
    AudioConnection          patchCord75(filter23, 0, envelope23, 0);
    AudioConnection          patchCord76(filter24, 0, envelope24, 0);
    AudioConnection          patchCord77(filter25, 0, envelope26, 0);
    AudioConnection          patchCord78(filter26, 0, envelope27, 0);
    AudioConnection          patchCord79(filter27, 0, envelope25, 0);
    AudioConnection          patchCord80(filter28, 0, envelope28, 0);
    AudioConnection          patchCord81(filter29, 0, envelope29, 0);
    AudioConnection          patchCord82(filter12, 0, envelope12, 0);
    AudioConnection          patchCord83(filter30, 0, envelope30, 0);
    AudioConnection          patchCord84(filter31, 0, envelope31, 0);
    AudioConnection          patchCord85(filter32, 0, envelope32, 0);
    AudioConnection          patchCord86(filter13, 0, envelope13, 0);
    AudioConnection          patchCord87(filter10, 0, envelope10, 0);
    AudioConnection          patchCord88(filter9, 0, envelope9, 0);
    AudioConnection          patchCord89(filter16, 0, envelope16, 0);
    AudioConnection          patchCord90(filter14, 0, envelope14, 0);
    AudioConnection          patchCord91(filter11, 0, envelope11, 0);
    AudioConnection          patchCord92(filter15, 0, envelope15, 0);
    AudioConnection          patchCord93(filter4, 0, envelope4, 0);
    AudioConnection          patchCord94(filter5, 0, envelope5, 0);
    AudioConnection          patchCord95(filter1, 0, envelope1, 0);
    AudioConnection          patchCord96(filter2, 0, envelope2, 0);
    AudioConnection          patchCord97(filter8, 0, envelope8, 0);
    AudioConnection          patchCord98(filter6, 0, envelope6, 0);
    AudioConnection          patchCord99(filter3, 0, envelope3, 0);
    AudioConnection          patchCord100(filter7, 0, envelope7, 0);
    AudioConnection          patchCord101(envelope17, 0, mixer11, 3);
    AudioConnection          patchCord102(envelope18, 0, mixer12, 0);
    AudioConnection          patchCord103(envelope19, 0, mixer11, 1);
    AudioConnection          patchCord104(envelope20, 0, mixer12, 3);
    AudioConnection          patchCord105(envelope21, 0, mixer11, 0);
    AudioConnection          patchCord106(envelope22, 0, mixer12, 1);
    AudioConnection          patchCord107(envelope24, 0, mixer12, 2);
    AudioConnection          patchCord108(envelope23, 0, mixer11, 2);
    AudioConnection          patchCord109(envelope25, 0, mixer9, 0);
    AudioConnection          patchCord110(envelope26, 0, mixer9, 3);
    AudioConnection          patchCord111(envelope27, 0, mixer10, 0);
    AudioConnection          patchCord112(envelope28, 0, mixer9, 1);
    AudioConnection          patchCord113(envelope29, 0, mixer10, 3);
    AudioConnection          patchCord114(envelope12, 0, mixer3, 3);
    AudioConnection          patchCord115(envelope30, 0, mixer10, 1);
    AudioConnection          patchCord116(envelope31, 0, mixer9, 2);
    AudioConnection          patchCord117(envelope32, 0, mixer10, 2);
    AudioConnection          patchCord118(envelope13, 0, mixer4, 0);
    AudioConnection          patchCord119(envelope10, 0, mixer3, 1);
    AudioConnection          patchCord120(envelope16, 0, mixer4, 3);
    AudioConnection          patchCord121(envelope9, 0, mixer3, 0);
    AudioConnection          patchCord122(envelope14, 0, mixer4, 1);
    AudioConnection          patchCord123(envelope11, 0, mixer3, 2);
    AudioConnection          patchCord124(envelope15, 0, mixer4, 2);
    AudioConnection          patchCord125(envelope1, 0, mixer1, 0);
    AudioConnection          patchCord126(envelope4, 0, mixer1, 3);
    AudioConnection          patchCord127(envelope5, 0, mixer2, 0);
    AudioConnection          patchCord128(envelope2, 0, mixer1, 1);
    AudioConnection          patchCord129(envelope8, 0, mixer2, 3);
    AudioConnection          patchCord130(envelope6, 0, mixer2, 1);
    AudioConnection          patchCord131(envelope3, 0, mixer1, 2);
    AudioConnection          patchCord132(envelope7, 0, mixer2, 2);
    AudioConnection          patchCord133(mixer10, 0, mixerFinal1, 1);
    AudioConnection          patchCord134(mixer9, 0, mixerFinal1, 0);
    AudioConnection          patchCord135(mixer12, 0, mixerFinal1, 3);
    AudioConnection          patchCord136(mixer11, 0, mixerFinal1, 2);
    AudioConnection          patchCord137(mixer1, 0, mixerFinal, 0);
    AudioConnection          patchCord138(mixer2, 0, mixerFinal, 1);
    AudioConnection          patchCord139(mixer3, 0, mixerFinal, 2);
    AudioConnection          patchCord140(mixer4, 0, mixerFinal, 3);
    AudioConnection          patchCord141(mixerFinal1, 0, lastMix, 1);
    AudioConnection          patchCord142(mixerFinal, 0, lastMix, 0);
    AudioConnection          patchCord143(lastMix, freeverbs1);
    AudioConnection          patchCord144(lastMix, 0, verbMix, 2);
    AudioConnection          patchCord145(freeverbs1, 0, verbMix, 0);
    AudioConnection          patchCord146(freeverbs1, 1, verbMix, 1);
    AudioConnection          patchCord147(verbMix, 0, i2s1, 0);
    AudioConnection          patchCord148(verbMix, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=1428.7999877929688,625
    // GUItool: end automatically generated code
    
    
    #endif // _SYNTHARCH_H

  11. #36
    After some research it seems pointers may be way the way to do this but I am pretty confused on how to implement them.

  12. #37
    Senior Member
    Join Date
    Feb 2015
    Posts
    163
    All of the waveform definition and selection stuff needs to be moved out of the NoteOn function. The idea is you want to read your pots inside loop(), and if the selected waveform has changed, apply the change to the oscillators.

    Also, I'm assuming oscs 1 - 16 are changed by knob 1, and oscs 17 - 32 are changed by knob 2. I didn't verify if that is actually how you wired everything up, and I haven't tested this code. But it should be close.

    Code:
    uint8_t progs[NPROGS] = {
      WAVEFORM_SINE,
      WAVEFORM_SQUARE,
      WAVEFORM_TRIANGLE,
      WAVEFORM_SAWTOOTH,
    };
    
    // Start both waveforms in sine mode.
    int prog1 = progs[0];
    int prog2 = progs[0];
    
    void loop() {
      // ... other synth code here ...
    
      // Map analog values to waveform types.
      int prog1Temp = map(analogRead(A14), 0, 1024, WAVEFORM_SINE, WAVEFORM_SAWTOOTH);
      int prog2Temp = map(analogRead(A16), 0, 1024, WAVEFORM_SINE, WAVEFORM_SAWTOOTH);
      
      // If either program type changed, apply it.
      // Every time begin() is called, it resets the phase, so we only want to do this if the waveform actually changed.
      if(prog1Temp != prog1) {
        prog1 = prog1Temp;
        // The way I am showing it here, first knob corresponds to the first half of the voices.
        for(int i=0; i<NUM_VOICES/2; i++) {
            oscs[i]->begin(prog1);
        }
      }
      if(prog2Temp != prog2) {
        prog2 = prog2Temp;
        // The second knob corresponds to the second half of the voices.
        for(int i=NUM_VOICES/2; i<NUM_VOICES; i++) {
          oscs[i]->begin(prog2);
        }
      }
    
      // ... other synth code here ...
    }

  13. #38
    Senior Member
    Join Date
    Nov 2017
    Location
    Belgium
    Posts
    212
    Quote Originally Posted by halogravity View Post
    Hey everyone. Here is the new version of my synth code. I am having some problems figuring out how to pass current potentiometer values to the onNoteOn() function. My solution to change the waveform types was to put the selection code directly in the function as you can see below. This has the effect, though, of one having to trigger a note every time you want to hear a new waveform, when ideally I would like someone to be able to hold down a note or chord while scanning through the waveforms. This same problem is sure to rear its head when I implement detuning as well. So my question is, how do I pass values from the loop() section of the code to an outside function like onNoteOn()? Is this even possible? And if not, how would you get around a problem like this? Any help would be greatly appreciated.

    I also took wcalverts advice and doubled up the amount of voices, there are now 32. I'll include all the code below.
    Just put the code for changing the oscillator waveform in loop(), just as you did for the filter frequency.

  14. #39
    Thanks wcalvert and neurofun! I think I get it now. And yes wcalvert myI'm using knob1(a16) for the first 16 waveforms and knob2(a17) for the last 16. Thanks again man, you are a lifesaver! I don't know why I overthought it so much with pointers, etc. I'm off to work atm(guitar teacher), I'll hash this all out when I get home and post the working code then!

  15. #40
    So I'm trying to set up your code wcalvert and at first I noticed that the pot was only selecting between two waveforms, and it looked like you had it mapped that way so I changed the mapping to reflect 0 -3 and then assigned a variable to read the waveform array( progs[] )... was that wrong to change? As it stands the first pot (A14) works but it only seems to read 3 of the 4 waveforms, and the second pot (A16) has no effect at all... could this have anything to do with how I'm turning on the second oscillator in the onNoteon() function by adding 8 to i?

    Code:
      // Now use the acquired voice.
      idleVoices[voiceToUse] = false;
      voiceToNote[voiceToUse] = note;
      AudioNoInterrupts();
      oscs[voiceToUse]->frequency(noteFreqs[note]);
      oscs[voiceToUse]->amplitude(velo);
      envelopes[voiceToUse]->noteOn();
      oscs[voiceToUse + 8]->frequency(noteFreqs[note]);
      oscs[voiceToUse + 8]->amplitude(velo);
      envelopes[voiceToUse + 8]->noteOn();
      AudioInterrupts();
      voiceOnTimes[voiceToUse] = millis();
    Any thoughts you may have would be highly appreciated. I am learning so much and am truly so very grateful for all of your very valuable time wcalvert! I have posted my most recent code in full below.

    Code:
    // Include Audio System Designer Tool Code
    #include "SYNTHARCH.H"
    
    Bounce button0 = Bounce(25, 15);
    Bounce button1 = Bounce(26, 15);
    Bounce button2 = Bounce(27, 15);
    Bounce button3 = Bounce(28, 15);
    Bounce button4 = Bounce(29, 15);
    Bounce button5 = Bounce(30, 15);
    Bounce button6 = Bounce(31, 15);
    Bounce button7 = Bounce(32, 15);
    
    // Include USBHost Library
    #include <USBHost_t36.h>
    
    USBHost myusb;
    MIDIDevice midi1(myusb);
    
    // GLOBAL VARIABLES
    
    // Array to covert MIDI notes to frequencies
    const float noteFreqs[128] = {8.176, 8.662, 9.177, 9.723, 10.301, 10.913, 11.562, 12.25, 12.978, 13.75, 14.568, 15.434, 16.352, 17.324, 18.354, 19.445, 20.602, 21.827, 23.125, 24.5, 25.957, 27.5, 29.135, 30.868, 32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55, 58.27, 61.735, 65.406, 69.296, 73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110, 116.541, 123.471, 130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220, 233.082, 246.942, 261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440, 466.164, 493.883, 523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880, 932.328, 987.767, 1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982, 1661.219, 1760, 1864.655, 1975.533, 2093.005, 2217.461, 2349.318, 2489.016, 2637.02, 2793.826, 2959.955, 3135.963, 3322.438, 3520, 3729.31, 3951.066, 4186.009, 4434.922, 4698.636, 4978.032, 5274.041, 5587.652, 5919.911, 6271.927, 6644.875, 7040, 7458.62, 7902.133, 8372.018, 8869.844, 9397.273, 9956.063, 10548.08, 11175.3, 11839.82, 12543.85};
    
    // Array for button MIDI notes
    const float buttonFreqs[8] = {48, 50, 52, 53, 55, 57, 59, 60};
    
    // Set number of voices
    const int NUM_VOICES = 32;
    const int NPROGS = 4;
    float mixGain = 0.5;
    float resonance = 3.8;
    const float DIV127 = (1.0 / 127.0);
    byte globalVelocity = 127;
    
    bool idleVoices[32] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
    
    // Set to 255 so it didn't throw an error :)
    byte voiceToNote[32] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
    
    uint8_t progs[NPROGS] = {
      WAVEFORM_SINE,
      WAVEFORM_SQUARE,
      WAVEFORM_TRIANGLE,
      WAVEFORM_SAWTOOTH,
    };
    
    // Start both waveforms in sine mode.
    int prog1 = progs[0];
    int prog2 = progs[0];
    
    AudioFilterStateVariable *myfilter[]  = { &filter1, &filter2, &filter3, &filter4, &filter5, &filter6, &filter7, &filter8, &filter9, &filter10, &filter11, &filter12, &filter13, &filter14, &filter15, &filter16, &filter17, &filter18, &filter19, &filter20, &filter21, &filter22, &filter23, &filter24, &filter25, &filter26, &filter27, &filter28, &filter29, &filter30, &filter31, &filter32 };
    Bounce *mybutton[]  = { &button0, &button1, &button2, &button3, &button4, &button5, &button6, &button7};
    AudioEffectEnvelope *myEnvelope[]  = { &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8, &envelope9, &envelope10, &envelope11, &envelope12, &envelope13, &envelope14, &envelope15, &envelope16, &envelope17, &envelope18, &envelope19, &envelope20, &envelope21, &envelope22, &envelope23, &envelope24, &envelope25, &envelope26, &envelope27, &envelope28, &envelope29, &envelope30, &envelope31, &envelope32 };
    AudioSynthWaveformModulated *oscs[NUM_VOICES] = { &waveform1, &waveform2, &waveform3, &waveform4, &waveform5, &waveform6, &waveform7, &waveform8, &waveform9, &waveform10, &waveform11, &waveform12, &waveform13, &waveform14, &waveform15, &waveform16, &waveform17, &waveform18, &waveform19, &waveform20, &waveform21, &waveform22, &waveform23, &waveform24, &waveform25, &waveform26, &waveform27, &waveform28, &waveform29, &waveform30, &waveform31, &waveform32 };
    AudioEffectEnvelope *envelopes[NUM_VOICES] = { &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8, &envelope9, &envelope10, &envelope11, &envelope12, &envelope13, &envelope14, &envelope15, &envelope16, &envelope17, &envelope18, &envelope19, &envelope20, &envelope21, &envelope22, &envelope23, &envelope24, &envelope25, &envelope26, &envelope27, &envelope28, &envelope29, &envelope30, &envelope31, &envelope32 };
    unsigned long voiceOnTimes[NUM_VOICES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
    void setup() {
    
      myusb.begin();
    
      Serial.begin(9600);
    
      pinMode(25, INPUT_PULLUP);
      pinMode(26, INPUT_PULLUP);
      pinMode(27, INPUT_PULLUP);
      pinMode(28, INPUT_PULLUP);
      pinMode(29, INPUT_PULLUP);
      pinMode(30, INPUT_PULLUP);
      pinMode(31, INPUT_PULLUP);
      pinMode(32, INPUT_PULLUP);
    
      // Detect USB slave key presses, call functions to handle presses
      midi1.setHandleNoteOn(onNoteOn);
      midi1.setHandleNoteOff(onNoteOff);
    
      // MUST set Audio Memory
      AudioMemory(120);
    
      sgtl5000_1.enable();
      sgtl5000_1.volume(0.5);
    
      // Initialize Waveforms
      for (int i = 0; i < 16; i++) {
        oscs[i]->begin(mixGain, 144, prog1);
      }
    
      // Initialize Waveforms
      for (int i = 0; i < 16; i++) {
        oscs[i + 8]->begin(mixGain, 144, prog2);
      }
    
      //Turn on all mixers
      mixer1.gain(0, mixGain);
      mixer1.gain(1, mixGain);
      mixer1.gain(2, mixGain);
      mixer1.gain(3, mixGain);
    
      mixer2.gain(0, mixGain);
      mixer2.gain(1, mixGain);
      mixer2.gain(2, mixGain);
      mixer2.gain(3, mixGain);
    
      mixer3.gain(0, mixGain);
      mixer3.gain(1, mixGain);
      mixer3.gain(2, mixGain);
      mixer3.gain(3, mixGain);
    
      mixer4.gain(0, mixGain);
      mixer4.gain(1, mixGain);
      mixer4.gain(2, mixGain);
      mixer4.gain(3, mixGain);
    
      mixer5.gain(0, mixGain);
      mixer5.gain(1, mixGain);
      mixer5.gain(2, mixGain);
      mixer5.gain(3, mixGain);
    
      mixer6.gain(0, mixGain);
      mixer6.gain(1, mixGain);
      mixer6.gain(2, mixGain);
      mixer6.gain(3, mixGain);
    
      mixer7.gain(0, mixGain);
      mixer7.gain(1, mixGain);
      mixer7.gain(2, mixGain);
      mixer7.gain(3, mixGain);
    
      mixer8.gain(0, mixGain);
      mixer8.gain(1, mixGain);
      mixer8.gain(2, mixGain);
      mixer8.gain(3, mixGain);
    
      mixer9.gain(0, mixGain);
      mixer9.gain(1, mixGain);
      mixer9.gain(2, mixGain);
      mixer9.gain(3, mixGain);
    
      mixer10.gain(0, mixGain);
      mixer10.gain(1, mixGain);
      mixer10.gain(2, mixGain);
      mixer10.gain(3, mixGain);
    
      mixer11.gain(0, mixGain);
      mixer11.gain(1, mixGain);
      mixer11.gain(2, mixGain);
      mixer11.gain(3, mixGain);
    
      mixer12.gain(0, mixGain);
      mixer12.gain(1, mixGain);
      mixer12.gain(2, mixGain);
      mixer12.gain(3, mixGain);
    
      mixerFinal.gain(0, mixGain);
      mixerFinal.gain(1, mixGain);
      mixerFinal.gain(2, mixGain);
      mixerFinal.gain(3, mixGain);
    
      mixerFinal1.gain(0, mixGain);
      mixerFinal1.gain(1, mixGain);
      mixerFinal1.gain(2, mixGain);
      mixerFinal1.gain(3, mixGain);
    
      verbMix.gain(0, mixGain);
      verbMix.gain(1, mixGain);
      verbMix.gain(2, mixGain);
    
      lastMix.gain(0, mixGain);
      lastMix.gain(1, mixGain);
    }
    
    void loop() {
    
    
      // Up next ... detune!
      //int knobD = 256 * analogRead(A17) / 1023;
    
      // Check USB input
      midi1.read();
    
      // Check if notes are playing
      IdleCheck();
    
      //WAVEFORM Selection
    
      // Map analog values to waveform types.
      int prog1Temp = map(analogRead(A14), 0, 1024, 0, 3);
      int prog2Temp = map(analogRead(A16), 0, 1024, 0, 3);
      
      // If either program type changed, apply it.
      // Every time begin() is called, it resets the phase, so we only want to do this if the waveform actually changed.
      if(prog1Temp != prog1) {
        prog1 = progs[prog1Temp];
        // The way I am showing it here, first knob corresponds to the first half of the voices.
        for(int i=0; i<NUM_VOICES/2; i++) {
            oscs[i]->begin(prog1);
        }
      }
      if(prog2Temp != prog2) {
        prog2 = progs[prog2Temp];
        // The second knob corresponds to the second half of the voices.
        for(int i=NUM_VOICES/2; i<NUM_VOICES; i++) {
          oscs[i]->begin(prog2);
        }
      }
    
    
      //Lowpass Filter
      int filterKnob = 10000 * analogRead(A3) / 1023;
      // Pointer Array for filter settings
      for (int i = 0; i < 16; i++) {
        myfilter[i]->frequency(filterKnob);
        //Resonace will be controlled by its own knob
        myfilter[i]->resonance(resonance);
      }
    
      // Reverb!
      float knobR = 1.0 * analogRead(A18) / 1023;
      float knobA = 1.0 * analogRead(A19) / 1023;
    
      freeverbs1.roomsize(knobR);
      freeverbs1.damping(knobA);
    
      // If statements to set mixer volume with freeverb to zero to approximate turning reverb off
      // 0.03 to allow for shitty pot jitter
    
      if (knobR > 0.03) {
        verbMix.gain(1, mixGain);
        verbMix.gain(2, mixGain - knobR);
      }
      if (knobR <= 0.03) {
        verbMix.gain(0, 0);
        verbMix.gain(1, 0);
    
        // Envelope Settings
        int knob1 = 10000 *  analogRead(A0) / 1023;
        int knob2 = 20000 * analogRead(A1) / 1023;
        for (int i = 0; i < 16; i++) {
          myEnvelope[i]->attack(knob1);
          myEnvelope[i]->release(knob2);
        }
      }
    
      for (int i = 0; i < 8; i++) {
        mybutton[i]->update();
    
        if (mybutton[i]->fallingEdge()) {
          onNoteOn(1, buttonFreqs[i], globalVelocity);
        }
        if (mybutton[i]->risingEdge()) {
          onNoteOff(1, buttonFreqs[i], globalVelocity);
        }
      }
    }
    
    void onNoteOn(byte channel, byte note, byte velocity) {
    
      // Set Velocity to global variable
      globalVelocity = velocity;
      float velo = (globalVelocity * DIV127);
      bool found = false;
      int voiceToUse = 0;
    
      // Acquire an idle voice if possible.
      for (int i = 0; i < NUM_VOICES; i++) {
        if (idleVoices[i]) {
          voiceToUse = i;
          found = true;
          break;
        }
      }
    
      // Steal voice if needed.
      if (!found) {
        unsigned long oldest = millis();
        for (int i = 0; i < NUM_VOICES; i++) {
          if (voiceOnTimes[i] < oldest && !envelopes[i]->isSustain()) {
            oldest = voiceOnTimes[i];
            voiceToUse = i;
          }
        }
      }
    
      // Now use the acquired voice.
      idleVoices[voiceToUse] = false;
      voiceToNote[voiceToUse] = note;
      AudioNoInterrupts();
      oscs[voiceToUse]->frequency(noteFreqs[note]);
      oscs[voiceToUse]->amplitude(velo);
      envelopes[voiceToUse]->noteOn();
      oscs[voiceToUse + 8]->frequency(noteFreqs[note]);
      oscs[voiceToUse + 8]->amplitude(velo);
      envelopes[voiceToUse + 8]->noteOn();
      AudioInterrupts();
      voiceOnTimes[voiceToUse] = millis();
    }
    
    void onNoteOff(byte channel, byte note, byte velocity) {
      for (int i = 0; i < NUM_VOICES; i++) {
        if (voiceToNote[i] == note) {
          envelopes[i]->noteOff();
          voiceToNote[i] = -1;
          envelopes[i + 8]->noteOff();
          voiceToNote[i + 8] = -1;
        }
      }
    }
    
    void IdleCheck(void) {
      for (uint8_t i = 0; i < NUM_VOICES; i++) {
        if (!envelopes[i]->isActive()) {
          oscs[i]->amplitude(0);
          idleVoices[i] = true;
        } else {
          idleVoices[i] = false;
        }
      }
    }
    Audio Design Tool Code
    Code:
    #ifndef _SYNTHARCH_H
    #define _SYNTHARCH_H
    
    #include <Arduino.h>
    #include <Bounce.h>
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // GUItool: begin automatically generated code
    AudioSynthWaveform       modWave3; //xy=259.3999881744385,2860.5997371673584
    AudioSynthWaveform       modWave4; //xy=280.3999881744385,2052.5997371673584
    AudioSynthWaveform       modWave2;       //xy=323.79998779296875,1193
    AudioSynthWaveform       modWave1;       //xy=344.79998779296875,385
    AudioMixer4              mixer7; //xy=419.3999881744385,2876.5997371673584
    AudioMixer4              mixer8; //xy=458.3999881744385,2064.5996837615967
    AudioMixer4              mixer6;         //xy=483.79998779296875,1209
    AudioMixer4              mixer5;         //xy=503.79998779296875,401
    AudioSynthWaveformModulated waveform17; //xy=681.3999881744385,3066.5997371673584
    AudioSynthWaveformModulated waveform18; //xy=684.3999881744385,3249.5997371673584
    AudioSynthWaveformModulated waveform19; //xy=686.3999881744385,3167.5997371673584
    AudioSynthWaveformModulated waveform20; //xy=693.3999881744385,2849.5997371673584
    AudioSynthWaveformModulated waveform21; //xy=696.3999881744385,2936.5997371673584
    AudioSynthWaveformModulated waveform22; //xy=698.3999881744385,2566.5997371673584
    AudioSynthWaveformModulated waveform23; //xy=699.3999881744385,2658.5997371673584
    AudioSynthWaveformModulated waveform24; //xy=699.3999881744385,2745.5997371673584
    AudioSynthWaveformModulated waveform25; //xy=730.3999881744385,2235.5997371673584
    AudioSynthWaveformModulated waveform26; //xy=738.3999881744385,2128.5997371673584
    AudioSynthWaveformModulated waveform27; //xy=742.3999881744385,2032.5997371673584
    AudioSynthWaveformModulated waveform14;     //xy=745.7999877929688,1399
    AudioSynthWaveformModulated waveform16;     //xy=748.7999877929688,1582
    AudioSynthWaveformModulated waveform28; //xy=745.3999881744385,2433.5997371673584
    AudioSynthWaveformModulated waveform15;     //xy=750.7999877929688,1500
    AudioSynthWaveformModulated waveform29; //xy=751.3999881744385,2340.5997371673584
    AudioSynthWaveformModulated waveform12;     //xy=757.7999877929688,1182
    AudioSynthWaveformModulated waveform30; //xy=755.3999881744385,1938.5997371673584
    AudioSynthWaveformModulated waveform31; //xy=756.3999881744385,1861.5997371673584
    AudioSynthWaveformModulated waveform13;     //xy=760.7999877929688,1269
    AudioSynthWaveformModulated waveform9;      //xy=762.7999877929688,899
    AudioSynthWaveformModulated waveform10;     //xy=763.7999877929688,991
    AudioSynthWaveformModulated waveform11;     //xy=763.7999877929688,1078
    AudioSynthWaveformModulated waveform32; //xy=762.3999881744385,1757.5997371673584
    AudioSynthWaveformModulated waveform6;      //xy=794.7999877929688,568
    AudioSynthWaveformModulated waveform5;      //xy=802.7999877929688,461
    AudioSynthWaveformModulated waveform4;      //xy=806.7999877929688,365
    AudioSynthWaveformModulated waveform8;      //xy=809.7999877929688,766
    AudioSynthWaveformModulated waveform7;      //xy=815.7999877929688,673
    AudioSynthWaveformModulated waveform3;      //xy=819.7999877929688,271
    AudioSynthWaveformModulated waveform2;      //xy=820.7999877929688,194
    AudioSynthWaveformModulated waveform1;      //xy=826.7999877929688,90
    AudioFilterStateVariable filter17; //xy=843.3999881744385,2843.5997371673584
    AudioFilterStateVariable filter18; //xy=851.3999881744385,2939.5997371673584
    AudioFilterStateVariable filter19; //xy=853.3999881744385,2653.5997371673584
    AudioFilterStateVariable filter20; //xy=854.3999881744385,2571.5997371673584
    AudioFilterStateVariable filter21; //xy=856.3999881744385,3244.5997371673584
    AudioFilterStateVariable filter22; //xy=859.3999881744385,3062.5997371673584
    AudioFilterStateVariable filter23; //xy=864.3999881744385,2746.5997371673584
    AudioFilterStateVariable filter24; //xy=863.3999881744385,3168.5997371673584
    AudioFilterStateVariable filter25; //xy=889.3999881744385,2037.5997371673584
    AudioFilterStateVariable filter26; //xy=897.3999881744385,2133.5997371673584
    AudioFilterStateVariable filter27; //xy=899.3999881744385,1767.5997371673584
    AudioFilterStateVariable filter28; //xy=899.3999881744385,1847.5997371673584
    AudioFilterStateVariable filter29; //xy=902.3999881744385,2438.5997371673584
    AudioFilterStateVariable filter12;       //xy=907.7999877929688,1176
    AudioFilterStateVariable filter30; //xy=905.3999881744385,2256.5997371673584
    AudioFilterStateVariable filter31; //xy=910.3999881744385,1940.5997371673584
    AudioFilterStateVariable filter32; //xy=909.3999881744385,2362.5997371673584
    AudioFilterStateVariable filter13;       //xy=915.7999877929688,1272
    AudioFilterStateVariable filter10;       //xy=917.7999877929688,986
    AudioFilterStateVariable filter9;        //xy=918.7999877929688,904
    AudioFilterStateVariable filter16;       //xy=920.7999877929688,1577
    AudioFilterStateVariable filter14;       //xy=923.7999877929688,1395
    AudioFilterStateVariable filter11;       //xy=928.7999877929688,1079
    AudioFilterStateVariable filter15;       //xy=927.7999877929688,1501
    AudioFilterStateVariable filter4;        //xy=953.7999877929688,370
    AudioFilterStateVariable filter5;        //xy=961.7999877929688,466
    AudioFilterStateVariable filter1;        //xy=963.7999877929688,100
    AudioFilterStateVariable filter2;        //xy=963.7999877929688,180
    AudioFilterStateVariable filter8;        //xy=966.7999877929688,771
    AudioFilterStateVariable filter6;        //xy=969.7999877929688,589
    AudioFilterStateVariable filter3;        //xy=974.7999877929688,273
    AudioFilterStateVariable filter7;        //xy=973.7999877929688,695
    AudioEffectEnvelope      envelope17; //xy=1023.3999881744385,2830.5997371673584
    AudioEffectEnvelope      envelope18; //xy=1031.3999881744385,2926.5997371673584
    AudioEffectEnvelope      envelope19; //xy=1033.3999881744385,2640.5997371673584
    AudioEffectEnvelope      envelope20; //xy=1032.4000186920166,3234.5996017456055
    AudioEffectEnvelope      envelope21; //xy=1040.3999881744385,2574.5997371673584
    AudioEffectEnvelope      envelope22; //xy=1039.3999881744385,3046.5997371673584
    AudioEffectEnvelope      envelope24; //xy=1042.4000186920166,3132.5996017456055
    AudioEffectEnvelope      envelope23; //xy=1044.3999881744385,2733.5997371673584
    AudioEffectEnvelope      envelope25;  //xy=1055.3999881744385,1750.5997371673584
    AudioEffectEnvelope      envelope26; //xy=1069.3999881744385,2024.5997371673584
    AudioEffectEnvelope      envelope27; //xy=1077.3999881744385,2120.5997371673584
    AudioEffectEnvelope      envelope28; //xy=1079.3999881744385,1834.5997371673584
    AudioEffectEnvelope      envelope29; //xy=1082.3999881744385,2425.5997371673584
    AudioEffectEnvelope      envelope12;     //xy=1087.7999877929688,1163
    AudioEffectEnvelope      envelope30; //xy=1085.3999881744385,2243.5997371673584
    AudioEffectEnvelope      envelope31; //xy=1090.3999881744385,1927.5997371673584
    AudioEffectEnvelope      envelope32; //xy=1089.3999881744385,2349.5997371673584
    AudioEffectEnvelope      envelope13;     //xy=1095.7999877929688,1259
    AudioEffectEnvelope      envelope10;     //xy=1097.7999877929688,973
    AudioEffectEnvelope      envelope16;     //xy=1100.7999877929688,1564
    AudioEffectEnvelope      envelope9;      //xy=1104.7999877929688,907
    AudioEffectEnvelope      envelope14;     //xy=1103.7999877929688,1379
    AudioEffectEnvelope      envelope11;     //xy=1108.7999877929688,1066
    AudioEffectEnvelope      envelope15;     //xy=1107.7999877929688,1488
    AudioEffectEnvelope      envelope1;      //xy=1119.7999877929688,83
    AudioEffectEnvelope      envelope4;      //xy=1133.7999877929688,357
    AudioEffectEnvelope      envelope5;      //xy=1141.7999877929688,453
    AudioEffectEnvelope      envelope2;      //xy=1143.7999877929688,167
    AudioEffectEnvelope      envelope8;      //xy=1146.7999877929688,758
    AudioEffectEnvelope      envelope6;      //xy=1149.7999877929688,576
    AudioEffectEnvelope      envelope3;      //xy=1154.7999877929688,260
    AudioEffectEnvelope      envelope7;      //xy=1153.7999877929688,682
    AudioMixer4              mixer10; //xy=1313.400016784668,2057.599447250366
    AudioMixer4              mixer9; //xy=1320.4000186920166,1899.5993881225586
    AudioMixer4              mixer12; //xy=1334.400016784668,2423.599645614624
    AudioMixer4              mixer11; //xy=1337.400016784668,2267.5998401641846
    AudioMixer4              mixer1;         //xy=1359.7999877929688,742
    AudioMixer4              mixer2;         //xy=1366.7999877929688,851
    AudioMixer4              mixer3;         //xy=1368.7999877929688,992
    AudioMixer4              mixer4;         //xy=1371.7999877929688,1134
    AudioMixer4              mixerFinal1; //xy=1532.3999710083008,1680.5995864868164
    AudioMixer4              mixerFinal;     //xy=1536.799877166748,1571.0000686645508
    AudioMixer4              lastMix;         //xy=1712.1999778747559,1626.1999740600586
    AudioEffectFreeverbStereo freeverbs1;     //xy=1859.7999801635742,1552.9999732971191
    AudioMixer4              verbMix;        //xy=2016.7999801635742,1622.000072479248
    AudioOutputI2S           i2s1;           //xy=2200.799980163574,1605.9999713897705
    AudioConnection          patchCord1(modWave3, 0, mixer7, 0);
    AudioConnection          patchCord2(modWave4, 0, mixer8, 0);
    AudioConnection          patchCord3(modWave2, 0, mixer6, 0);
    AudioConnection          patchCord4(modWave1, 0, mixer5, 0);
    AudioConnection          patchCord5(mixer7, 0, waveform22, 0);
    AudioConnection          patchCord6(mixer7, 0, waveform23, 0);
    AudioConnection          patchCord7(mixer7, 0, waveform20, 0);
    AudioConnection          patchCord8(mixer7, 0, waveform21, 0);
    AudioConnection          patchCord9(mixer7, 0, waveform17, 0);
    AudioConnection          patchCord10(mixer7, 0, waveform19, 0);
    AudioConnection          patchCord11(mixer7, 0, waveform18, 0);
    AudioConnection          patchCord12(mixer7, 0, waveform24, 0);
    AudioConnection          patchCord13(mixer8, 0, waveform32, 0);
    AudioConnection          patchCord14(mixer8, 0, waveform31, 0);
    AudioConnection          patchCord15(mixer8, 0, waveform30, 0);
    AudioConnection          patchCord16(mixer8, 0, waveform27, 0);
    AudioConnection          patchCord17(mixer8, 0, waveform26, 0);
    AudioConnection          patchCord18(mixer8, 0, waveform25, 0);
    AudioConnection          patchCord19(mixer8, 0, waveform29, 0);
    AudioConnection          patchCord20(mixer8, 0, waveform28, 0);
    AudioConnection          patchCord21(mixer6, 0, waveform9, 0);
    AudioConnection          patchCord22(mixer6, 0, waveform10, 0);
    AudioConnection          patchCord23(mixer6, 0, waveform11, 0);
    AudioConnection          patchCord24(mixer6, 0, waveform12, 0);
    AudioConnection          patchCord25(mixer6, 0, waveform13, 0);
    AudioConnection          patchCord26(mixer6, 0, waveform14, 0);
    AudioConnection          patchCord27(mixer6, 0, waveform15, 0);
    AudioConnection          patchCord28(mixer6, 0, waveform16, 1);
    AudioConnection          patchCord29(mixer5, 0, waveform1, 0);
    AudioConnection          patchCord30(mixer5, 0, waveform2, 0);
    AudioConnection          patchCord31(mixer5, 0, waveform3, 0);
    AudioConnection          patchCord32(mixer5, 0, waveform4, 0);
    AudioConnection          patchCord33(mixer5, 0, waveform5, 0);
    AudioConnection          patchCord34(mixer5, 0, waveform6, 0);
    AudioConnection          patchCord35(mixer5, 0, waveform7, 0);
    AudioConnection          patchCord36(mixer5, 0, waveform8, 0);
    AudioConnection          patchCord37(waveform17, 0, filter22, 0);
    AudioConnection          patchCord38(waveform18, 0, filter21, 0);
    AudioConnection          patchCord39(waveform19, 0, filter24, 0);
    AudioConnection          patchCord40(waveform20, 0, filter17, 0);
    AudioConnection          patchCord41(waveform21, 0, filter18, 0);
    AudioConnection          patchCord42(waveform22, 0, filter20, 0);
    AudioConnection          patchCord43(waveform23, 0, filter19, 0);
    AudioConnection          patchCord44(waveform24, 0, filter23, 0);
    AudioConnection          patchCord45(waveform25, 0, filter30, 0);
    AudioConnection          patchCord46(waveform26, 0, filter26, 0);
    AudioConnection          patchCord47(waveform27, 0, filter25, 0);
    AudioConnection          patchCord48(waveform14, 0, filter14, 0);
    AudioConnection          patchCord49(waveform16, 0, filter16, 0);
    AudioConnection          patchCord50(waveform28, 0, filter29, 0);
    AudioConnection          patchCord51(waveform15, 0, filter15, 0);
    AudioConnection          patchCord52(waveform29, 0, filter32, 0);
    AudioConnection          patchCord53(waveform12, 0, filter12, 0);
    AudioConnection          patchCord54(waveform30, 0, filter31, 0);
    AudioConnection          patchCord55(waveform31, 0, filter28, 0);
    AudioConnection          patchCord56(waveform13, 0, filter13, 0);
    AudioConnection          patchCord57(waveform9, 0, filter9, 0);
    AudioConnection          patchCord58(waveform10, 0, filter10, 0);
    AudioConnection          patchCord59(waveform11, 0, filter11, 0);
    AudioConnection          patchCord60(waveform32, 0, filter27, 0);
    AudioConnection          patchCord61(waveform6, 0, filter6, 0);
    AudioConnection          patchCord62(waveform5, 0, filter5, 0);
    AudioConnection          patchCord63(waveform4, 0, filter4, 0);
    AudioConnection          patchCord64(waveform8, 0, filter8, 0);
    AudioConnection          patchCord65(waveform7, 0, filter7, 0);
    AudioConnection          patchCord66(waveform3, 0, filter3, 0);
    AudioConnection          patchCord67(waveform2, 0, filter2, 0);
    AudioConnection          patchCord68(waveform1, 0, filter1, 0);
    AudioConnection          patchCord69(filter17, 0, envelope17, 0);
    AudioConnection          patchCord70(filter18, 0, envelope18, 0);
    AudioConnection          patchCord71(filter19, 0, envelope19, 0);
    AudioConnection          patchCord72(filter20, 0, envelope21, 0);
    AudioConnection          patchCord73(filter21, 0, envelope20, 0);
    AudioConnection          patchCord74(filter22, 0, envelope22, 0);
    AudioConnection          patchCord75(filter23, 0, envelope23, 0);
    AudioConnection          patchCord76(filter24, 0, envelope24, 0);
    AudioConnection          patchCord77(filter25, 0, envelope26, 0);
    AudioConnection          patchCord78(filter26, 0, envelope27, 0);
    AudioConnection          patchCord79(filter27, 0, envelope25, 0);
    AudioConnection          patchCord80(filter28, 0, envelope28, 0);
    AudioConnection          patchCord81(filter29, 0, envelope29, 0);
    AudioConnection          patchCord82(filter12, 0, envelope12, 0);
    AudioConnection          patchCord83(filter30, 0, envelope30, 0);
    AudioConnection          patchCord84(filter31, 0, envelope31, 0);
    AudioConnection          patchCord85(filter32, 0, envelope32, 0);
    AudioConnection          patchCord86(filter13, 0, envelope13, 0);
    AudioConnection          patchCord87(filter10, 0, envelope10, 0);
    AudioConnection          patchCord88(filter9, 0, envelope9, 0);
    AudioConnection          patchCord89(filter16, 0, envelope16, 0);
    AudioConnection          patchCord90(filter14, 0, envelope14, 0);
    AudioConnection          patchCord91(filter11, 0, envelope11, 0);
    AudioConnection          patchCord92(filter15, 0, envelope15, 0);
    AudioConnection          patchCord93(filter4, 0, envelope4, 0);
    AudioConnection          patchCord94(filter5, 0, envelope5, 0);
    AudioConnection          patchCord95(filter1, 0, envelope1, 0);
    AudioConnection          patchCord96(filter2, 0, envelope2, 0);
    AudioConnection          patchCord97(filter8, 0, envelope8, 0);
    AudioConnection          patchCord98(filter6, 0, envelope6, 0);
    AudioConnection          patchCord99(filter3, 0, envelope3, 0);
    AudioConnection          patchCord100(filter7, 0, envelope7, 0);
    AudioConnection          patchCord101(envelope17, 0, mixer11, 3);
    AudioConnection          patchCord102(envelope18, 0, mixer12, 0);
    AudioConnection          patchCord103(envelope19, 0, mixer11, 1);
    AudioConnection          patchCord104(envelope20, 0, mixer12, 3);
    AudioConnection          patchCord105(envelope21, 0, mixer11, 0);
    AudioConnection          patchCord106(envelope22, 0, mixer12, 1);
    AudioConnection          patchCord107(envelope24, 0, mixer12, 2);
    AudioConnection          patchCord108(envelope23, 0, mixer11, 2);
    AudioConnection          patchCord109(envelope25, 0, mixer9, 0);
    AudioConnection          patchCord110(envelope26, 0, mixer9, 3);
    AudioConnection          patchCord111(envelope27, 0, mixer10, 0);
    AudioConnection          patchCord112(envelope28, 0, mixer9, 1);
    AudioConnection          patchCord113(envelope29, 0, mixer10, 3);
    AudioConnection          patchCord114(envelope12, 0, mixer3, 3);
    AudioConnection          patchCord115(envelope30, 0, mixer10, 1);
    AudioConnection          patchCord116(envelope31, 0, mixer9, 2);
    AudioConnection          patchCord117(envelope32, 0, mixer10, 2);
    AudioConnection          patchCord118(envelope13, 0, mixer4, 0);
    AudioConnection          patchCord119(envelope10, 0, mixer3, 1);
    AudioConnection          patchCord120(envelope16, 0, mixer4, 3);
    AudioConnection          patchCord121(envelope9, 0, mixer3, 0);
    AudioConnection          patchCord122(envelope14, 0, mixer4, 1);
    AudioConnection          patchCord123(envelope11, 0, mixer3, 2);
    AudioConnection          patchCord124(envelope15, 0, mixer4, 2);
    AudioConnection          patchCord125(envelope1, 0, mixer1, 0);
    AudioConnection          patchCord126(envelope4, 0, mixer1, 3);
    AudioConnection          patchCord127(envelope5, 0, mixer2, 0);
    AudioConnection          patchCord128(envelope2, 0, mixer1, 1);
    AudioConnection          patchCord129(envelope8, 0, mixer2, 3);
    AudioConnection          patchCord130(envelope6, 0, mixer2, 1);
    AudioConnection          patchCord131(envelope3, 0, mixer1, 2);
    AudioConnection          patchCord132(envelope7, 0, mixer2, 2);
    AudioConnection          patchCord133(mixer10, 0, mixerFinal1, 1);
    AudioConnection          patchCord134(mixer9, 0, mixerFinal1, 0);
    AudioConnection          patchCord135(mixer12, 0, mixerFinal1, 3);
    AudioConnection          patchCord136(mixer11, 0, mixerFinal1, 2);
    AudioConnection          patchCord137(mixer1, 0, mixerFinal, 0);
    AudioConnection          patchCord138(mixer2, 0, mixerFinal, 1);
    AudioConnection          patchCord139(mixer3, 0, mixerFinal, 2);
    AudioConnection          patchCord140(mixer4, 0, mixerFinal, 3);
    AudioConnection          patchCord141(mixerFinal1, 0, lastMix, 1);
    AudioConnection          patchCord142(mixerFinal, 0, lastMix, 0);
    AudioConnection          patchCord143(lastMix, freeverbs1);
    AudioConnection          patchCord144(lastMix, 0, verbMix, 2);
    AudioConnection          patchCord145(freeverbs1, 0, verbMix, 0);
    AudioConnection          patchCord146(freeverbs1, 1, verbMix, 1);
    AudioConnection          patchCord147(verbMix, 0, i2s1, 0);
    AudioConnection          patchCord148(verbMix, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=1428.7999877929688,625
    // GUItool: end automatically generated code
    
    
    #endif // _SYNTHARCH_H

  16. #41
    Senior Member
    Join Date
    Feb 2015
    Posts
    163
    Hmm... well, "voiceToUse + 8" certainly looks suspect.

    If voiceToUse + 8 goes beyond the size of the array, it will probably lock the Teensy up. I'm amazed it's not locking up as is.

    I loaded syntharch.h into the GUI tool to see how you've wired everything up. It might be worth pressing the pause button for a second. If you're wanting to have 2 oscillators per voice, and you have 32 oscillators, then NUM_VOICES really needs to be 16, and you'll probably want some way of grouping up the oscillators to make it easy to manage the voices, including turning notes on and off, and setting the first oscillator in the voice to one waveform, and the second oscillator in the voice to another waveform.

    I might have time to post a full working example later, once I dig up some pots... I use all encoders on mine, heh.

  17. #42
    Quote Originally Posted by wcalvert View Post
    Hmm... well, "voiceToUse + 8" certainly looks suspect.

    If voiceToUse + 8 goes beyond the size of the array, it will probably lock the Teensy up. I'm amazed it's not locking up as is.

    I loaded syntharch.h into the GUI tool to see how you've wired everything up. It might be worth pressing the pause button for a second. If you're wanting to have 2 oscillators per voice, and you have 32 oscillators, then NUM_VOICES really needs to be 16, and you'll probably want some way of grouping up the oscillators to make it easy to manage the voices, including turning notes on and off, and setting the first oscillator in the voice to one waveform, and the second oscillator in the voice to another waveform.

    I might have time to post a full working example later, once I dig up some pots... I use all encoders on mine, heh.
    Yes I always figured the way I wired it up may not be ideal, this is my first ever stab at a synth and my coding AND synthesizer skills are limited at best, though so far I think I've muddled through ok...lol. In the end what I really want are 2 oscillators and a noise source per voice(I always figured I could tack a pink noise oscillator and envelope on at the end since it doesnt need a frequency I could use just one), the ability to detune the second oscillator, and I had some notion of a global LFO for each voice as well, which is why I used AudioSynthWaveformModulated types and have the modWave's running into mixers at the beginning of each group of 8 oscillators. Anything you can do when you have time would be fantastic! Thanks again wcalvert!

  18. #43
    Wcalvert, Out of curiosity, how many oscillators per voice are using on your synth? And what is the purpose of all the encoders?

  19. #44
    Senior Member
    Join Date
    Feb 2015
    Posts
    163
    I have one oscillator per voice right now, but I'm not using the stock Teensy oscillators . My synth is about the size of an OP-1, and it kinda works in the same way. Depending on what screen you're on and what you're doing, the encoders control different things. The plan is to sell it as a commercial product eventually... I haven't even posted a picture of it online yet. It's in stealth mode.

  20. #45
    Thats fantastic man. When you're ready to share it I'd love to check it out! I'm sure a man of your skills is putting together an amazing product! And I love the op-1, btw... lol. Now you have me very curious... are the oscillators wavetables or analog in some way? Let me not sidetrack you you did say you were in stealth mode...but I am very intrigued! If you need any beta testers you let me know! haha.

  21. #46
    Senior Member
    Join Date
    Feb 2015
    Posts
    163
    Here's my tested code, 2 oscillators per voice, only 4 voices to get going. I'm using USB device rather than USB host, so you'll want to change that, and alter the analog pins to match what you are using.

    Code:
    #include <Arduino.h>
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // GUItool: begin automatically generated code
    AudioSynthWaveformModulated osc3a;   //xy=174,340.0000057220459
    AudioSynthWaveformModulated osc3b;   //xy=175,377.0000066757202
    AudioSynthWaveformModulated osc4a;   //xy=177,417.00000762939453
    AudioSynthWaveformModulated osc2a;   //xy=179.00000381469727,261.00000381469727
    AudioSynthWaveformModulated osc4b;   //xy=179.00000381469727,455.00000762939453
    AudioSynthWaveformModulated osc2b;   //xy=181,296.0000047683716
    AudioSynthWaveformModulated osc1b;   //xy=182,210.00000381469727
    AudioSynthWaveformModulated osc1a;   //xy=183,176.00000286102295
    AudioMixer4              voice1Mixer;         //xy=395,198
    AudioMixer4              voice2Mixer;         //xy=395.00000381469727,277.00000381469727
    AudioMixer4              voice3Mixer;         //xy=397.00000381469727,352.00000381469727
    AudioMixer4              voice4Mixer;         //xy=398.00000381469727,427.0000057220459
    AudioEffectEnvelope      envelope2;      //xy=587.2500152587891,276.2500066757202
    AudioEffectEnvelope      envelope3;      //xy=587.2500152587891,346.2500081062317
    AudioEffectEnvelope      envelope1;      //xy=588.5000190734863,203.75000500679016
    AudioEffectEnvelope      envelope4;      //xy=588.5000152587891,421.2500114440918
    AudioMixer4              voiceMixer;         //xy=776.500072479248,304.5000305175781
    AudioFilterStateVariable filter1;        //xy=929.0001258850098,310.00000762939453
    AudioOutputI2S           i2s1;           //xy=1090.7500305175781,305.00000762939453
    AudioConnection          patchCord1(osc3a, 0, voice3Mixer, 0);
    AudioConnection          patchCord2(osc3b, 0, voice3Mixer, 1);
    AudioConnection          patchCord3(osc4a, 0, voice4Mixer, 0);
    AudioConnection          patchCord4(osc2a, 0, voice2Mixer, 0);
    AudioConnection          patchCord5(osc4b, 0, voice4Mixer, 1);
    AudioConnection          patchCord6(osc2b, 0, voice2Mixer, 1);
    AudioConnection          patchCord7(osc1b, 0, voice1Mixer, 1);
    AudioConnection          patchCord8(osc1a, 0, voice1Mixer, 0);
    AudioConnection          patchCord9(voice1Mixer, envelope1);
    AudioConnection          patchCord10(voice2Mixer, envelope2);
    AudioConnection          patchCord11(voice3Mixer, envelope3);
    AudioConnection          patchCord12(voice4Mixer, envelope4);
    AudioConnection          patchCord13(envelope2, 0, voiceMixer, 1);
    AudioConnection          patchCord14(envelope3, 0, voiceMixer, 2);
    AudioConnection          patchCord15(envelope1, 0, voiceMixer, 0);
    AudioConnection          patchCord16(envelope4, 0, voiceMixer, 3);
    AudioConnection          patchCord17(voiceMixer, 0, filter1, 0);
    AudioConnection          patchCord18(filter1, 0, i2s1, 0);
    AudioConnection          patchCord19(filter1, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=1087.5000305175781,358.75000953674316
    // GUItool: end automatically generated code
    
    #define NUM_VOICES 4
    
    int wave1 = WAVEFORM_SINE;
    int wave2 = WAVEFORM_TRIANGLE;
    
    const float noteFreqs[128] = {8.176, 8.662, 9.177, 9.723, 10.301, 10.913, 11.562, 12.25, 12.978, 13.75, 14.568, 15.434, 16.352, 17.324, 18.354, 19.445, 20.602, 21.827, 23.125, 24.5, 25.957, 27.5, 29.135, 30.868, 32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55, 58.27, 61.735, 65.406, 69.296, 73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110, 116.541, 123.471, 130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220, 233.082, 246.942, 261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440, 466.164, 493.883, 523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880, 932.328, 987.767, 1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982, 1661.219, 1760, 1864.655, 1975.533, 2093.005, 2217.461, 2349.318, 2489.016, 2637.02, 2793.826, 2959.955, 3135.963, 3322.438, 3520, 3729.31, 3951.066, 4186.009, 4434.922, 4698.636, 4978.032, 5274.041, 5587.652, 5919.911, 6271.927, 6644.875, 7040, 7458.62, 7902.133, 8372.018, 8869.844, 9397.273, 9956.063, 10548.08, 11175.3, 11839.82, 12543.85};
    AudioSynthWaveformModulated *oscsA[NUM_VOICES] = {&osc1a, &osc2a, &osc3a, &osc4a};
    AudioSynthWaveformModulated *oscsB[NUM_VOICES] = {&osc1b, &osc2b, &osc3b, &osc4b};
    AudioEffectEnvelope *envelopes[NUM_VOICES] = {&envelope1, &envelope2, &envelope3, &envelope4};
    unsigned long voiceOnTimes[NUM_VOICES] = {0,0,0,0};
    bool idleVoices[NUM_VOICES] = {true,true,true,true};
    byte voiceToNote[NUM_VOICES] = {255,255,255,255}; // Dummy value outside range of valid notes is used to init each.
    elapsedMillis readPots=0;
    
    void NoteOn(byte channel, byte note, byte velocity) {
        bool found = false;
        int voiceToUse = 0;
    
        // Acquire an idle voice if possible.
        for (int i = 0; i < NUM_VOICES; i++) {
            if (idleVoices[i]) {
                voiceToUse = i;
                found = true;
                break;
            }
        }
    
        // Steal voice if needed.
        if(!found) {
            unsigned long oldest = millis();
            for(int i=0; i<NUM_VOICES; i++) {
                if(voiceOnTimes[i] < oldest) {
                    oldest = voiceOnTimes[i];
                    voiceToUse = i;
                }
            }
        }
    
        // Now use the acquired voice.
        idleVoices[voiceToUse] = false;
        voiceToNote[voiceToUse] = note;
        AudioNoInterrupts();
        oscsA[voiceToUse]->frequency(noteFreqs[note]);
        oscsA[voiceToUse]->amplitude(.7f);
        oscsB[voiceToUse]->frequency(noteFreqs[note]);
        oscsB[voiceToUse]->amplitude(.7f);
        envelopes[voiceToUse]->noteOn();
        AudioInterrupts();
        voiceOnTimes[voiceToUse] = millis();
    }
    
    void NoteOff(byte channel, byte note, byte velocity) {
        for(int i=0; i<NUM_VOICES; i++) {
            if(voiceToNote[i] == note) {
                envelopes[i]->noteOff();
                voiceToNote[i] = -1;
            }
        }
    }
    
    void IdleCheck(void) {
        for(uint8_t i=0; i<NUM_VOICES; i++) {
            if(!envelopes[i]->isActive()) {
                oscsA[i]->amplitude(0);
                oscsB[i]->amplitude(0);
                idleVoices[i] = true;
            } else {
                idleVoices[i] = false;
            }
        }
    }
    
    void setup() {
        AudioMemory(50);
        Serial.begin(115200);
    
        for(int i=0; i<4; i++) {
            // Set all mixers.
            voice1Mixer.gain(i, .7f);
            voice2Mixer.gain(i, .7f);
            voice3Mixer.gain(i, .7f);
            voice4Mixer.gain(i, .7f);
            voiceMixer.gain(i, .7f);
    
            // Set oscs to default waves.
            oscsA[i]->begin(wave1);
            oscsB[i]->begin(wave2);
    
            // Set envelopes to something reasonable.
            envelopes[i]->attack(5);
            envelopes[i]->decay(10);
            envelopes[i]->sustain(.7f);
            envelopes[i]->release(1000);
        }
    
        // Enable codec
        sgtl5000_1.enable();
        sgtl5000_1.volume(.7f);
    
        // Set USB MIDI device callbacks.
        usbMIDI.setHandleNoteOff(NoteOff);
        usbMIDI.setHandleNoteOn(NoteOn);
    }
    
    void loop() {
        // Only read pots every 50 milliseconds to reduce glitchiness due to noise...
        // This could be done with averaging or something instead.
        if(readPots >= 50) {
            // Reset elapsed time.
            readPots = 0;
    
            // Read waveform selection pots.
            int wave1Temp = map(analogRead(A12), 0, 1023, WAVEFORM_SINE, WAVEFORM_TRIANGLE);
            int wave2Temp = map(analogRead(A13), 0, 1023, WAVEFORM_SINE, WAVEFORM_TRIANGLE);
            
            // Update A oscs only if waveform has changed.
            // Oscillator phase will be reset by calling begin(), that's why we only want to do it when knob has changed.
            if(wave1Temp != wave1) {
                wave1 = wave1Temp;
                //Serial.printf("Knob 1: %d\n", wave1);
                for(int i=0; i<NUM_VOICES; i++) {
                    oscsA[i]->begin(wave1);
                }
            }
    
            // Same thing for B oscs.
            if(wave2Temp != wave2) {
                wave2 = wave2Temp;
                //Serial.printf("Knob 2: %d\n", wave2);
                for(int i=0; i<NUM_VOICES; i++) {
                    oscsB[i]->begin(wave2);
                }
            }
        }
    
        IdleCheck();
        usbMIDI.read();
    }
    It sounds pretty good!

    I'm noticing that sometimes notes are getting stuck on. I think that's due to USB device midi... this demo was done with a T3.6 and I don't have tons of experience with the T3.6 USB device midi. Or it might be due to the crummy "virtual piano" app I'm using to send the midi, who knows.
    Last edited by wcalvert; 12-12-2019 at 04:01 AM.

  22. #47
    WOW!!! Thanks so much wcalvert!!! I added in my USBHost code, the 8 buttons, and the lowpass filter. There's a lot to go through here otherwise, thanks so much! A few quick questions...

    What would you say for optimum amount of voices? And should I group them together in some other way or just continue adding osc5a and osc5b and have a voicemixer2 and then a final mixer? Is that the best way to do it? I hope that question makes sense... basically what is the best way to proceed wiring wise?

    And lastly, it seems the waveform knobs go through more than two waveform types, even though WAVEFORM_SINE and WAVEFORM_TRIANGLE are the only ones specifically mentioned... why is that? Does the compiler fill in the blanks or am I missing something?

    Again, HUGE thanks wcalvert! I have some work ahead of me but you have given me a massive head start! While you were away I started playing with wavetables... expect a deluge of questions soon... they sound pretty amazing! haha. Thanks again my friend! Here's the USBHost modified code:

    Code:
    #include <Arduino.h>
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    #include <Bounce.h>
    
    Bounce button0 = Bounce(25, 15);
    Bounce button1 = Bounce(26, 15);
    Bounce button2 = Bounce(27, 15);
    Bounce button3 = Bounce(28, 15);
    Bounce button4 = Bounce(29, 15);
    Bounce button5 = Bounce(30, 15);
    Bounce button6 = Bounce(31, 15);
    Bounce button7 = Bounce(32, 15);
    
    // Include USBHost Library
    #include <USBHost_t36.h>
    
    USBHost myusb;
    MIDIDevice midi1(myusb);
    
    // GUItool: begin automatically generated code
    AudioSynthWaveformModulated osc3a;   //xy=174,340.0000057220459
    AudioSynthWaveformModulated osc3b;   //xy=175,377.0000066757202
    AudioSynthWaveformModulated osc4a;   //xy=177,417.00000762939453
    AudioSynthWaveformModulated osc2a;   //xy=179.00000381469727,261.00000381469727
    AudioSynthWaveformModulated osc4b;   //xy=179.00000381469727,455.00000762939453
    AudioSynthWaveformModulated osc2b;   //xy=181,296.0000047683716
    AudioSynthWaveformModulated osc1b;   //xy=182,210.00000381469727
    AudioSynthWaveformModulated osc1a;   //xy=183,176.00000286102295
    AudioMixer4              voice1Mixer;         //xy=395,198
    AudioMixer4              voice2Mixer;         //xy=395.00000381469727,277.00000381469727
    AudioMixer4              voice3Mixer;         //xy=397.00000381469727,352.00000381469727
    AudioMixer4              voice4Mixer;         //xy=398.00000381469727,427.0000057220459
    AudioEffectEnvelope      envelope2;      //xy=587.2500152587891,276.2500066757202
    AudioEffectEnvelope      envelope3;      //xy=587.2500152587891,346.2500081062317
    AudioEffectEnvelope      envelope1;      //xy=588.5000190734863,203.75000500679016
    AudioEffectEnvelope      envelope4;      //xy=588.5000152587891,421.2500114440918
    AudioMixer4              voiceMixer;         //xy=776.500072479248,304.5000305175781
    AudioFilterStateVariable filter1;        //xy=929.0001258850098,310.00000762939453
    AudioOutputI2S           i2s1;           //xy=1090.7500305175781,305.00000762939453
    AudioConnection          patchCord1(osc3a, 0, voice3Mixer, 0);
    AudioConnection          patchCord2(osc3b, 0, voice3Mixer, 1);
    AudioConnection          patchCord3(osc4a, 0, voice4Mixer, 0);
    AudioConnection          patchCord4(osc2a, 0, voice2Mixer, 0);
    AudioConnection          patchCord5(osc4b, 0, voice4Mixer, 1);
    AudioConnection          patchCord6(osc2b, 0, voice2Mixer, 1);
    AudioConnection          patchCord7(osc1b, 0, voice1Mixer, 1);
    AudioConnection          patchCord8(osc1a, 0, voice1Mixer, 0);
    AudioConnection          patchCord9(voice1Mixer, envelope1);
    AudioConnection          patchCord10(voice2Mixer, envelope2);
    AudioConnection          patchCord11(voice3Mixer, envelope3);
    AudioConnection          patchCord12(voice4Mixer, envelope4);
    AudioConnection          patchCord13(envelope2, 0, voiceMixer, 1);
    AudioConnection          patchCord14(envelope3, 0, voiceMixer, 2);
    AudioConnection          patchCord15(envelope1, 0, voiceMixer, 0);
    AudioConnection          patchCord16(envelope4, 0, voiceMixer, 3);
    AudioConnection          patchCord17(voiceMixer, 0, filter1, 0);
    AudioConnection          patchCord18(filter1, 0, i2s1, 0);
    AudioConnection          patchCord19(filter1, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=1087.5000305175781,358.75000953674316
    // GUItool: end automatically generated code
    
    #define NUM_VOICES 4
    
    int wave1 = WAVEFORM_SINE;
    int wave2 = WAVEFORM_TRIANGLE;
    
    byte globalVelocity = 127;
    
    const float noteFreqs[128] = {8.176, 8.662, 9.177, 9.723, 10.301, 10.913, 11.562, 12.25, 12.978, 13.75, 14.568, 15.434, 16.352, 17.324, 18.354, 19.445, 20.602, 21.827, 23.125, 24.5, 25.957, 27.5, 29.135, 30.868, 32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55, 58.27, 61.735, 65.406, 69.296, 73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110, 116.541, 123.471, 130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220, 233.082, 246.942, 261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440, 466.164, 493.883, 523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880, 932.328, 987.767, 1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982, 1661.219, 1760, 1864.655, 1975.533, 2093.005, 2217.461, 2349.318, 2489.016, 2637.02, 2793.826, 2959.955, 3135.963, 3322.438, 3520, 3729.31, 3951.066, 4186.009, 4434.922, 4698.636, 4978.032, 5274.041, 5587.652, 5919.911, 6271.927, 6644.875, 7040, 7458.62, 7902.133, 8372.018, 8869.844, 9397.273, 9956.063, 10548.08, 11175.3, 11839.82, 12543.85};
    AudioSynthWaveformModulated *oscsA[NUM_VOICES] = {&osc1a, &osc2a, &osc3a, &osc4a};
    AudioSynthWaveformModulated *oscsB[NUM_VOICES] = {&osc1b, &osc2b, &osc3b, &osc4b};
    AudioEffectEnvelope *envelopes[NUM_VOICES] = {&envelope1, &envelope2, &envelope3, &envelope4};
    Bounce *mybutton[]  = { &button0, &button1, &button2, &button3, &button4, &button5, &button6, &button7};
    const float buttonFreqs[8] = {48, 50, 52, 53, 55, 57, 59, 60};
    
    unsigned long voiceOnTimes[NUM_VOICES] = {0, 0, 0, 0};
    bool idleVoices[NUM_VOICES] = {true, true, true, true};
    byte voiceToNote[NUM_VOICES] = {255, 255, 255, 255}; // Dummy value outside range of valid notes is used to init each.
    elapsedMillis readPots = 0;
    
    void NoteOn(byte channel, byte note, byte velocity) {
      bool found = false;
      int voiceToUse = 0;
    
      // Acquire an idle voice if possible.
      for (int i = 0; i < NUM_VOICES; i++) {
        if (idleVoices[i]) {
          voiceToUse = i;
          found = true;
          break;
        }
      }
    
      // Steal voice if needed.
      if (!found) {
        unsigned long oldest = millis();
        for (int i = 0; i < NUM_VOICES; i++) {
          if (voiceOnTimes[i] < oldest) {
            oldest = voiceOnTimes[i];
            voiceToUse = i;
          }
        }
      }
    
      // Now use the acquired voice.
      idleVoices[voiceToUse] = false;
      voiceToNote[voiceToUse] = note;
      AudioNoInterrupts();
      oscsA[voiceToUse]->frequency(noteFreqs[note]);
      oscsA[voiceToUse]->amplitude(.7f);
      oscsB[voiceToUse]->frequency(noteFreqs[note]);
      oscsB[voiceToUse]->amplitude(.7f);
      envelopes[voiceToUse]->noteOn();
      AudioInterrupts();
      voiceOnTimes[voiceToUse] = millis();
    }
    
    void NoteOff(byte channel, byte note, byte velocity) {
      for (int i = 0; i < NUM_VOICES; i++) {
        if (voiceToNote[i] == note) {
          envelopes[i]->noteOff();
          voiceToNote[i] = -1;
        }
      }
    }
    
    void IdleCheck(void) {
      for (uint8_t i = 0; i < NUM_VOICES; i++) {
        if (!envelopes[i]->isActive()) {
          oscsA[i]->amplitude(0);
          oscsB[i]->amplitude(0);
          idleVoices[i] = true;
        } else {
          idleVoices[i] = false;
        }
      }
    }
    
    void setup() {
      AudioMemory(120);
      Serial.begin(115200);
      Serial.begin(9600);
      myusb.begin();
    
      pinMode(25, INPUT_PULLUP);
      pinMode(26, INPUT_PULLUP);
      pinMode(27, INPUT_PULLUP);
      pinMode(28, INPUT_PULLUP);
      pinMode(29, INPUT_PULLUP);
      pinMode(30, INPUT_PULLUP);
      pinMode(31, INPUT_PULLUP);
      pinMode(32, INPUT_PULLUP);
    
      for (int i = 0; i < 4; i++) {
        // Set all mixers.
        voice1Mixer.gain(i, .7f);
        voice2Mixer.gain(i, .7f);
        voice3Mixer.gain(i, .7f);
        voice4Mixer.gain(i, .7f);
        voiceMixer.gain(i, .7f);
    
        // Set oscs to default waves.
        oscsA[i]->begin(wave1);
        oscsB[i]->begin(wave2);
    
        // Set envelopes to something reasonable.
        envelopes[i]->attack(5);
        envelopes[i]->decay(10);
        envelopes[i]->sustain(.7f);
        envelopes[i]->release(1000);
      }
    
      // Enable codec
      sgtl5000_1.enable();
      sgtl5000_1.volume(.7f);
    
      // Set USB MIDI device callbacks.
      midi1.setHandleNoteOff(NoteOff);
      midi1.setHandleNoteOn(NoteOn);
    }
    
    void loop() {
      // Only read pots every 50 milliseconds to reduce glitchiness due to noise...
      // This could be done with averaging or something instead.
      if (readPots >= 50) {
        // Reset elapsed time.
        readPots = 0;
    
        // Read waveform selection pots.
        int wave1Temp = map(analogRead(A14), 0, 1023, WAVEFORM_SINE, WAVEFORM_TRIANGLE);
        int wave2Temp = map(analogRead(A16), 0, 1023, WAVEFORM_SINE, WAVEFORM_TRIANGLE);
    
        // Update A oscs only if waveform has changed.
        // Oscillator phase will be reset by calling begin(), that's why we only want to do it when knob has changed.
        if (wave1Temp != wave1) {
          wave1 = wave1Temp;
          //Serial.printf("Knob 1: %d\n", wave1);
          for (int i = 0; i < NUM_VOICES; i++) {
            oscsA[i]->begin(wave1);
          }
        }
    
        // Same thing for B oscs.
        if (wave2Temp != wave2) {
          wave2 = wave2Temp;
          //Serial.printf("Knob 2: %d\n", wave2);
          for (int i = 0; i < NUM_VOICES; i++) {
            oscsB[i]->begin(wave2);
          }
        }
      }
      for (int i = 0; i < 8; i++) {
        mybutton[i]->update();
    
        if (mybutton[i]->fallingEdge()) {
          NoteOn(1, buttonFreqs[i], globalVelocity);
        }
        if (mybutton[i]->risingEdge()) {
          NoteOff(1, buttonFreqs[i], globalVelocity);
        }
      }
      IdleCheck();
      midi1.read();
    
      //Lowpass Filter
      int filterKnob = 10000 * analogRead(A3) / 1023;
    
      filter1.frequency(filterKnob);
      //Resonace will be controlled by its own knob
      //filter1.resonance(3.8);
    }

  23. #48
    Senior Member
    Join Date
    Feb 2015
    Posts
    163
    For number of voices.. I think most polyphonic synths these days are in the range of 4 - 16. Minilogue is 4, Deepmind comes in 6 and 12, Prophet is 16. The voice stealing really makes a huge difference, I'm glad I tried it. Even with 4 voices it responds pretty well I think.

    If you duplicate the 4 voices that I showed a total of 4 times, you'd have 16 voices, and be able to mix them all together with just one additional mixer before the filter.

  24. #49
    OH and what does 7f mean? lol

    Code:
    sgtl5000_1.volume(.7f);

  25. #50
    I’m thinking out loud here...

    Wouldn’t it be clearer if you wrote a class which encapsulates a voiceless ? oscillators,, amps, filters, envelopes? While the setups produced by the online tool are very handy, for something like this, it seems to me some basic C++ stuff could really clean things up.

Posting Permissions

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