Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 20 of 20

Thread: USB Host turning envelopes on and off?

  1. #1

    USB Host turning envelopes on and off?

    Hello everyone. I hope the below ramble makes sense.

    I am coding a synth using your audio board and a Teensy 3.6. So far everything has worked flawlessly but I have hit a wall. My synth has 8 buttons that can be played on the actual unit, but I also am trying to add USB Host support so an external midi controller can be used as well. So far I have everything working great, reading the external midi device just fine, I am just burnt out on code and can't for the life of me figure out how to turn off envelopes in the order they are released.

    I have two functions at the bottom of the main code ( myNoteOn, and myNoteOff ) that are turned on when a key is pressed and released on the midi controller. So far so good. But how do I keep track of which notes are played and then released, and set the waveform frequency and turn the envelope on and then off? I have 16 waveforms, 2 voices per key, 8 note polyphony is what I am trying to achieve. Forgive the rambling nature of this post I am code-fried atm...lol. Below I am posting the main code, and SynthArch (AudioTool code). Any help would be massively appreciated. Thanks so much!

    MAIN CODE:
    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"
    
    #include <USBHost_t36.h>
    
    USBHost myusb;
    MIDIDevice midi1(myusb);
    
    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() {
      myusb.begin();
      midi1.setHandleNoteOn(myNoteOn);
      midi1.setHandleNoteOff(myNoteOff);
      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() {
      midi1.read();
      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);
      */
    }
    
    //---------NEED HELP BELOW---------------------------------------------------------------->
    void myNoteOn(byte channel, byte note, byte velocity) {
      if (noteNum <= 7) {
    
        //const char prognum = myProg;
        AudioSynthWaveformModulated *myWaveformUSB[]  = { &waveform1, &waveform2, &waveform3, &waveform4, &waveform5, &waveform6, &waveform7, &waveform8};
        myWaveformUSB[noteNum]->frequency(noteFreqs[note]);
    
        AudioEffectEnvelope *myEnvelopeUSB[]  = { &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8, &envelope9, &envelope10, &envelope11, &envelope12, &envelope13, &envelope14, &envelope15, &envelope16 };
        myEnvelopeUSB[noteNum]->noteOn();
    
        noteNum++;
      }
    
    }
    void myNoteOff(byte channel, byte note, byte velocity) {
      AudioEffectEnvelope *myEnvelopeUSB[]  = { &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8, &envelope9, &envelope10, &envelope11, &envelope12, &envelope13, &envelope14, &envelope15, &envelope16 };
    
      myEnvelopeUSB[noteNum]->noteOff();
    
      noteNum--;
      Serial.println(noteNum);
    }
    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       modWave1;     //xy=62,158
    AudioMixer4              mixer5;         //xy=78,246
    AudioSynthWaveformModulated waveform14;     //xy=183,1372
    AudioSynthWaveformModulated waveform16;     //xy=186,1555
    AudioSynthWaveformModulated waveform15;     //xy=188,1473
    AudioSynthWaveformModulated waveform12;     //xy=195,1155
    AudioSynthWaveformModulated waveform13;     //xy=198,1242
    AudioSynthWaveformModulated waveform9;      //xy=200,872
    AudioSynthWaveformModulated waveform10;     //xy=201,964
    AudioSynthWaveformModulated waveform11;     //xy=201,1051
    AudioSynthWaveformModulated waveform6;      //xy=232,541
    AudioSynthWaveformModulated waveform5;      //xy=240,434
    AudioSynthWaveformModulated waveform4;      //xy=244,338
    AudioSynthWaveformModulated waveform8;      //xy=247,739
    AudioSynthWaveformModulated waveform7;      //xy=253,646.0000095367432
    AudioSynthWaveformModulated waveform3;      //xy=257,244
    AudioSynthWaveformModulated waveform1;      //xy=264,63
    AudioSynthWaveformModulated waveform2;      //xy=269,146
    AudioFilterStateVariable filter12;       //xy=345,1149
    AudioFilterStateVariable filter13;       //xy=353,1245
    AudioFilterStateVariable filter10;       //xy=355,959
    AudioFilterStateVariable filter9;        //xy=356,877
    AudioFilterStateVariable filter16;       //xy=358,1550
    AudioFilterStateVariable filter14;       //xy=361,1368
    AudioFilterStateVariable filter11;       //xy=366,1052
    AudioFilterStateVariable filter15;       //xy=365,1474
    AudioFilterStateVariable filter4;        //xy=391,343
    AudioFilterStateVariable filter5;        //xy=399,439
    AudioFilterStateVariable filter1;        //xy=401,73
    AudioFilterStateVariable filter2;        //xy=401,153
    AudioFilterStateVariable filter8;        //xy=404,744
    AudioFilterStateVariable filter6;        //xy=407,562
    AudioFilterStateVariable filter3;        //xy=412,246
    AudioFilterStateVariable filter7;        //xy=411,668
    AudioEffectEnvelope      envelope12;     //xy=525,1136
    AudioEffectEnvelope      envelope13;     //xy=533,1232
    AudioEffectEnvelope      envelope10;     //xy=535,946
    AudioEffectEnvelope      envelope16;     //xy=538,1537
    AudioEffectEnvelope      envelope9;      //xy=542,880
    AudioEffectEnvelope      envelope14;     //xy=541,1352
    AudioEffectEnvelope      envelope11;     //xy=546,1039
    AudioEffectEnvelope      envelope15;     //xy=545,1461
    AudioEffectEnvelope      envelope1;      //xy=557,56
    AudioEffectEnvelope      envelope4;      //xy=571,330
    AudioEffectEnvelope      envelope5;      //xy=579,426
    AudioEffectEnvelope      envelope2;      //xy=581,140
    AudioEffectEnvelope      envelope8;      //xy=584,731
    AudioEffectEnvelope      envelope6;      //xy=587,549
    AudioEffectEnvelope      envelope3;      //xy=592,233
    AudioEffectEnvelope      envelope7;      //xy=591,655
    AudioMixer4              mixer1;         //xy=797,715
    AudioMixer4              mixer2;         //xy=804,824
    AudioMixer4              mixer3;         //xy=806,965
    AudioMixer4              mixer4;         //xy=809,1107
    AudioMixer4              mixerFinal;     //xy=1006,888
    AudioEffectFreeverbStereo freeverbs1;     //xy=1164.199966430664,819.0000133514404
    AudioMixer4              verbMix;         //xy=1329.1999702453613,885.0000133514404
    AudioOutputI2S           i2s1;           //xy=1459.9999713897705,880.0000133514404
    AudioConnection          patchCord1(modWave1, 0, mixer5, 0);
    AudioConnection          patchCord2(mixer5, 0, waveform1, 0);
    AudioConnection          patchCord3(mixer5, 0, waveform2, 0);
    AudioConnection          patchCord4(mixer5, 0, waveform3, 0);
    AudioConnection          patchCord5(mixer5, 0, waveform4, 0);
    AudioConnection          patchCord6(mixer5, 0, waveform5, 0);
    AudioConnection          patchCord7(mixer5, 0, waveform6, 0);
    AudioConnection          patchCord8(mixer5, 0, waveform7, 0);
    AudioConnection          patchCord9(mixer5, 0, waveform8, 0);
    AudioConnection          patchCord10(waveform14, 0, filter14, 0);
    AudioConnection          patchCord11(waveform16, 0, filter16, 0);
    AudioConnection          patchCord12(waveform15, 0, filter15, 0);
    AudioConnection          patchCord13(waveform12, 0, filter12, 0);
    AudioConnection          patchCord14(waveform13, 0, filter13, 0);
    AudioConnection          patchCord15(waveform9, 0, filter9, 0);
    AudioConnection          patchCord16(waveform9, 0, filter9, 1);
    AudioConnection          patchCord17(waveform10, 0, filter10, 0);
    AudioConnection          patchCord18(waveform11, 0, filter11, 0);
    AudioConnection          patchCord19(waveform6, 0, filter6, 0);
    AudioConnection          patchCord20(waveform5, 0, filter5, 0);
    AudioConnection          patchCord21(waveform4, 0, filter4, 0);
    AudioConnection          patchCord22(waveform8, 0, filter8, 0);
    AudioConnection          patchCord23(waveform7, 0, filter7, 0);
    AudioConnection          patchCord24(waveform3, 0, filter3, 0);
    AudioConnection          patchCord25(waveform1, 0, filter1, 0);
    AudioConnection          patchCord26(waveform1, 0, filter1, 1);
    AudioConnection          patchCord27(waveform2, 0, filter2, 0);
    AudioConnection          patchCord28(filter12, 0, envelope12, 0);
    AudioConnection          patchCord29(filter13, 0, envelope13, 0);
    AudioConnection          patchCord30(filter10, 0, envelope10, 0);
    AudioConnection          patchCord31(filter9, 0, envelope9, 0);
    AudioConnection          patchCord32(filter16, 0, envelope16, 0);
    AudioConnection          patchCord33(filter14, 0, envelope14, 0);
    AudioConnection          patchCord34(filter11, 0, envelope11, 0);
    AudioConnection          patchCord35(filter15, 0, envelope15, 0);
    AudioConnection          patchCord36(filter4, 0, envelope4, 0);
    AudioConnection          patchCord37(filter5, 0, envelope5, 0);
    AudioConnection          patchCord38(filter1, 0, envelope1, 0);
    AudioConnection          patchCord39(filter2, 0, envelope2, 0);
    AudioConnection          patchCord40(filter8, 0, envelope8, 0);
    AudioConnection          patchCord41(filter6, 0, envelope6, 0);
    AudioConnection          patchCord42(filter3, 0, envelope3, 0);
    AudioConnection          patchCord43(filter7, 0, envelope7, 0);
    AudioConnection          patchCord44(envelope12, 0, mixer3, 3);
    AudioConnection          patchCord45(envelope13, 0, mixer4, 0);
    AudioConnection          patchCord46(envelope10, 0, mixer3, 1);
    AudioConnection          patchCord47(envelope16, 0, mixer4, 3);
    AudioConnection          patchCord48(envelope9, 0, mixer3, 0);
    AudioConnection          patchCord49(envelope14, 0, mixer4, 1);
    AudioConnection          patchCord50(envelope11, 0, mixer3, 2);
    AudioConnection          patchCord51(envelope15, 0, mixer4, 2);
    AudioConnection          patchCord52(envelope1, 0, mixer1, 0);
    AudioConnection          patchCord53(envelope4, 0, mixer1, 3);
    AudioConnection          patchCord54(envelope5, 0, mixer2, 0);
    AudioConnection          patchCord55(envelope2, 0, mixer1, 1);
    AudioConnection          patchCord56(envelope8, 0, mixer2, 3);
    AudioConnection          patchCord57(envelope6, 0, mixer2, 1);
    AudioConnection          patchCord58(envelope3, 0, mixer1, 2);
    AudioConnection          patchCord59(envelope7, 0, mixer2, 2);
    AudioConnection          patchCord60(mixer1, 0, mixerFinal, 0);
    AudioConnection          patchCord61(mixer2, 0, mixerFinal, 1);
    AudioConnection          patchCord62(mixer3, 0, mixerFinal, 2);
    AudioConnection          patchCord63(mixer4, 0, mixerFinal, 3);
    AudioConnection          patchCord64(mixerFinal, freeverbs1);
    AudioConnection          patchCord65(mixerFinal, 0, verbMix, 2);
    AudioConnection          patchCord66(freeverbs1, 0, verbMix, 0);
    AudioConnection          patchCord67(freeverbs1, 1, verbMix, 1);
    AudioConnection          patchCord68(verbMix, 0, i2s1, 0);
    AudioConnection          patchCord69(verbMix, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=866,598
    // GUItool: end automatically generated code
    
    #endif // _SYNTHARCH_H

  2. #2
    Ok this isnt working because case cant be an array, but I feel like I'm on the right track...

    Code:
    //---------NEED HELP BELOW---------------------------------------------------------------->
    const int noteArray[8];
    int noteFlag = 0;
    void myNoteOn(byte channel, byte note, byte velocity) {
      AudioSynthWaveformModulated *myWaveformUSB[]  = { &waveform1, &waveform2, &waveform3, &waveform4, &waveform5, &waveform6, &waveform7, &waveform8};
      myWaveformUSB[noteFlag]->frequency(noteFreqs[note]);
    
      AudioEffectEnvelope *myEnvelopeUSB[]  = { &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8, &envelope9, &envelope10, &envelope11, &envelope12, &envelope13, &envelope14, &envelope15, &envelope16 };
      myEnvelopeUSB[noteFlag]->noteOn();
    
      const int noteArray[noteFlag] = note;
      noteFlag++;
    }
    
    void myNoteOff(byte channel, byte note, byte velocity) {
      switch (note) {
    case noteArray[1]:
          envelope1.noteOff();
          noteFlag--;
          break;
    case noteArray[2]:
          envelope2.noteOff();
          noteFlag--;
          break;
    case noteArray[3]:
          envelope3.noteOff();
          noteFlag--;
          break;
    case noteArray[4]:
          envelope45.noteOff();
          noteFlag--;
          break;
    case noteArray[5]:
          envelope5.noteOff();
          noteFlag--;
          break;
    case noteArray[6]:
          envelope6.noteOff();
          noteFlag--;
          break;
    case noteArray[7]:
          envelope7.noteOff();
          noteFlag--;
          break;
    case noteArray[8]:
          envelope8.noteOff();
          noteFlag--;
          break;
        default:
          // if nothing else matches, do the default
          // default is optional
          break;
      }
    }

  3. #3
    I'm starting to see my code may be slightly more problematic than I thought. I have the waveform .begin statements in the loop of my code, so it looks like they are overwriting any value I try to assign them with a midi controller. Am I right? I'd be so bummed if I basically have to start from scratch... I've put a lot of work into this.

  4. #4
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,234
    You need a voice management system to steal the least objectionable running voice or the first available free one. (I don't know of any examples.)

    If you want to keep the built-in buttons and scale feature I think it would be best to have each button look up a MIDI number from a 2D array and send that to your NoteOn/Off code just as incoming MIDI messages will do.

  5. #5
    Quote Originally Posted by oddson View Post
    You need a voice management system to steal the least objectionable running voice or the first available free one. (I don't know of any examples.)

    If you want to keep the built-in buttons and scale feature I think it would be best to have each button look up a MIDI number from a 2D array and send that to your NoteOn/Off code just as incoming MIDI messages will do.

    Thanks oddson, that's a great idea forthe button feature, that way I can handle all note playing with the myNoteOn and myNoteOff functions. I have noticed the last voice/free voice thing in some other synth codes I've seen, but I don't really understand it fully. Could you possibly explain it a little more when you have a moment? Thanks again for the reply and great suggestions.

  6. #6
    Senior Member
    Join Date
    Feb 2015
    Posts
    100
    This is basically the system that I am using. It does not allow note stealing. This code is edited a bit for clarity so there may be errors.

    Code:
    bool idleVoices[12] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
    byte voiceToNote[12] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
    
    // you must provide NUM_VOICES
    AudioSynthWaveformModulated *oscs[NUM_VOICES] = { &osc1, &osc2, ... };
    AudioEffectEnvelope *envelopes[NUM_VOICES] = { &env1, &env2, ... };
    
    void NoteOn(byte note) {
        for(int i=0; i<NUM_VOICES; i++) {
            if(idleVoices[i]) {
                idleVoices[i] = false;
                voiceToNote[i] = note;
                AudioNoInterrupts();
                oscs[i]->freq = getFreq(note); // you must provide getFreq()
                oscs[i]->amplitude(1.0);
                envelopes[i]->noteOn();
                AudioInterrupts();
                break;
            }
        }
    }
    
    void NoteOff(byte note) {
        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()) {
                oscs[i]->amplitude(0);
                idleVoices[i] = true;
            } else {
                idleVoices[i] = false;
            }
        }
    }
    Make sure to call IdleCheck() in your loop(). The button presses and midi commands would both flow into the NoteOn and NoteOff methods. Hope that helps, good luck.

  7. #7
    Thanks wcalvert! Two questions when you have a moment, I dont quite understand what the arrays with the 1's and -1's are doing...

    Code:
    bool idleVoices[12] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
    byte voiceToNote[12] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
    And also I'm not sure what you mean by note stealing? Forgive my ignorance this is my first foray into coding a synth. Thanks so much for your reply!

  8. #8
    Also am I wrong or should this

    Code:
            if(voiceNote[i] == note) {
                envelopes[i]->noteOff();
                voiceToNote[i] = -1;
    be this:

    Code:
    
    
    Code:
            if(voiceToNote[i] == note) {
                envelopes[i]->noteOff();
                voiceToNote[i] = -1;

  9. #9
    Senior Member
    Join Date
    Feb 2015
    Posts
    100
    Code:
    bool idleVoices[12] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
    The "1" is very sloppy of me there. It should be "true" but I was just being lazy and my compiler doesn't seem to care.

    Code:
    byte voiceToNote[12] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
    The "-1" is also me being sloppy. A byte can't hold -1. -1 is really 255. I just needed a dummy value so that the logic later on would work.

    Note stealing basically means that an oscillator which is currently busy playing one note is immediately fed another note to play without waiting for it to become idle first. I'm an engineer first and foremost, so I don't know if musicians prefer note stealing or not.

  10. #10
    Quote Originally Posted by wcalvert View Post
    Code:
    bool idleVoices[12] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
    The "1" is very sloppy of me there. It should be "true" but I was just being lazy and my compiler doesn't seem to care.

    Code:
    byte voiceToNote[12] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
    The "-1" is also me being sloppy. A byte can't hold -1. -1 is really 255. I just needed a dummy value so that the logic later on would work.

    Note stealing basically means that an oscillator which is currently busy playing one note is immediately fed another note to play without waiting for it to become idle first. I'm an engineer first and foremost, so I don't know if musicians prefer note stealing or not.
    Thanks so muich! One last thing, what exactly is idleCheck? Is that a built in function? Sorry to bombard you my friend, I am very hungry for knowledge in this area.

  11. #11
    Senior Member
    Join Date
    Feb 2015
    Posts
    100
    Scroll down in my code, IdleCheck is listed there. It deactivates the oscillators (sets the amplitude to 0) once the corresponding envelope has finished. Setting the oscillator amplitude to 0 saves CPU cycles. It also marks the oscillator as idle, which is needed by the other logic.

    Quote Originally Posted by halogravity View Post
    Also am I wrong or should this
    That was a typo, good eye. I corrected it.

  12. #12
    Got it! Thanks so much wcalvert! When I get home from work I'm going to implement all this then post when I get the whole thing working. Bt the way I am musician first and a pretty new coder second so learning from an engineer is a very cool perspective for me. Thanks for all your time, I'm sure I'll have questions in the future, I'll try not to bug you! lol

  13. #13
    Actually I do have one last question. I always thought an if statement needed a condition... like if something = something then...

    Code:
    if(idleVoices[i]) {
                idleVoices[i] = false;
                voiceToNote[i] = note;
                AudioNoInterrupts();
                oscs[i]->freq = getFreq(note); // you must provide getFreq()
                oscs[i]->amplitude(1.0);
                envelopes[i]->noteOn();
                AudioInterrupts();
                break;
            }
    So that just says if(true) ... right? How does this if statement work exactly?

  14. #14
    Senior Member
    Join Date
    Feb 2015
    Posts
    100
    idleVoices is an array of bools, so it's perfectly valid syntax. You don't need to explicitly type "if(idleVoices[i] == true)", the compiler knows what you mean.

  15. #15
    OK Got it working! Here's the basic USB Host engine, now I have to work backwards and add each feature from the other version in. Thanks again to wcalvert and oddson, I couldn't have done it without you guys! Any suggestions on the code so far? I will continue to post updates if that's alright. I'm so excited!

    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"
    
    // 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};
    
    // Set number of voices
    const int NUM_VOICES = 8;
    
    float mixGain = 0.5;
    const float DIV127 = (1.0 / 127.0);
    byte globalVelocity = 0;
    bool idleVoices[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };
    
    // Set to 255 so it didn't throw an error :)
    byte voiceToNote[8] = { 255, 255, 255, 255, 255, 255, 255, 255 }; 
    
    void setup() {
    
      myusb.begin();
    
      Serial.begin(9600);
    
      // Detect USB slave key presses, call functions to handle presses
      midi1.setHandleNoteOn(onNoteOn);
      midi1.setHandleNoteOff(onNoteOff);
    
      // MUST set Audio Memory
      AudioMemory(80);
    
      sgtl5000_1.enable();
      sgtl5000_1.volume(0.5);
    
      // Initialize Waveforms
      AudioSynthWaveformModulated *oscsStart[NUM_VOICES] = { &waveform1, &waveform2, &waveform3, &waveform4, &waveform5, &waveform6, &waveform7, &waveform8 };
      for (int i = 0; i < 8; i++) {
        oscsStart[i]->begin(mixGain, 144, WAVEFORM_SQUARE);
      }
    
      //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);
    
      mixerFinal.gain(0, mixGain);
      mixerFinal.gain(1, mixGain);
    
      verbMix.gain(0, mixGain);
      verbMix.gain(1, mixGain);
      verbMix.gain(2, mixGain);
    }
    
    void loop() {
      // Check USB input
      midi1.read();
    
      // Check if notes are playing
      IdleCheck();
    }
    
    AudioSynthWaveformModulated *oscs[NUM_VOICES] = { &waveform1, &waveform2, &waveform3, &waveform4, &waveform5, &waveform6, &waveform7, &waveform8 };
    AudioEffectEnvelope *envelopes[NUM_VOICES] = { &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8 };
    
    void onNoteOn(byte channel, byte note, byte velocity) {
    
      // Set Velocity to global variable
      globalVelocity = velocity;
      float velo = (globalVelocity * DIV127);
      
      for (int i = 0; i < NUM_VOICES; i++) {
        if (idleVoices[i]) {
          idleVoices[i] = false;
          voiceToNote[i] = note;
          AudioNoInterrupts();
          oscs[i]->frequency(noteFreqs[note]);
          oscs[i]->amplitude(velo);
          envelopes[i]->noteOn();
          AudioInterrupts();
          break;
        }
      }
    }
    
    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;
        }
      }
    }
    
    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;
        }
      }
    }
    SynthArch.h
    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       modWave1;     //xy=62,158
    AudioMixer4              mixer5;         //xy=78,246
    AudioSynthWaveformModulated waveform14;     //xy=183,1372
    AudioSynthWaveformModulated waveform16;     //xy=186,1555
    AudioSynthWaveformModulated waveform15;     //xy=188,1473
    AudioSynthWaveformModulated waveform12;     //xy=195,1155
    AudioSynthWaveformModulated waveform13;     //xy=198,1242
    AudioSynthWaveformModulated waveform9;      //xy=200,872
    AudioSynthWaveformModulated waveform10;     //xy=201,964
    AudioSynthWaveformModulated waveform11;     //xy=201,1051
    AudioSynthWaveformModulated waveform6;      //xy=232,541
    AudioSynthWaveformModulated waveform5;      //xy=240,434
    AudioSynthWaveformModulated waveform4;      //xy=244,338
    AudioSynthWaveformModulated waveform8;      //xy=247,739
    AudioSynthWaveformModulated waveform7;      //xy=253,646.0000095367432
    AudioSynthWaveformModulated waveform3;      //xy=257,244
    AudioSynthWaveformModulated waveform1;      //xy=264,63
    AudioSynthWaveformModulated waveform2;      //xy=269,146
    AudioFilterStateVariable filter12;       //xy=345,1149
    AudioFilterStateVariable filter13;       //xy=353,1245
    AudioFilterStateVariable filter10;       //xy=355,959
    AudioFilterStateVariable filter9;        //xy=356,877
    AudioFilterStateVariable filter16;       //xy=358,1550
    AudioFilterStateVariable filter14;       //xy=361,1368
    AudioFilterStateVariable filter11;       //xy=366,1052
    AudioFilterStateVariable filter15;       //xy=365,1474
    AudioFilterStateVariable filter4;        //xy=391,343
    AudioFilterStateVariable filter5;        //xy=399,439
    AudioFilterStateVariable filter1;        //xy=401,73
    AudioFilterStateVariable filter2;        //xy=401,153
    AudioFilterStateVariable filter8;        //xy=404,744
    AudioFilterStateVariable filter6;        //xy=407,562
    AudioFilterStateVariable filter3;        //xy=412,246
    AudioFilterStateVariable filter7;        //xy=411,668
    AudioEffectEnvelope      envelope12;     //xy=525,1136
    AudioEffectEnvelope      envelope13;     //xy=533,1232
    AudioEffectEnvelope      envelope10;     //xy=535,946
    AudioEffectEnvelope      envelope16;     //xy=538,1537
    AudioEffectEnvelope      envelope9;      //xy=542,880
    AudioEffectEnvelope      envelope14;     //xy=541,1352
    AudioEffectEnvelope      envelope11;     //xy=546,1039
    AudioEffectEnvelope      envelope15;     //xy=545,1461
    AudioEffectEnvelope      envelope1;      //xy=557,56
    AudioEffectEnvelope      envelope4;      //xy=571,330
    AudioEffectEnvelope      envelope5;      //xy=579,426
    AudioEffectEnvelope      envelope2;      //xy=581,140
    AudioEffectEnvelope      envelope8;      //xy=584,731
    AudioEffectEnvelope      envelope6;      //xy=587,549
    AudioEffectEnvelope      envelope3;      //xy=592,233
    AudioEffectEnvelope      envelope7;      //xy=591,655
    AudioMixer4              mixer1;         //xy=797,715
    AudioMixer4              mixer2;         //xy=804,824
    AudioMixer4              mixer3;         //xy=806,965
    AudioMixer4              mixer4;         //xy=809,1107
    AudioMixer4              mixerFinal;     //xy=1006,888
    AudioEffectFreeverbStereo freeverbs1;     //xy=1164.199966430664,819.0000133514404
    AudioMixer4              verbMix;         //xy=1329.1999702453613,885.0000133514404
    AudioOutputI2S           i2s1;           //xy=1459.9999713897705,880.0000133514404
    AudioConnection          patchCord1(modWave1, 0, mixer5, 0);
    AudioConnection          patchCord2(mixer5, 0, waveform1, 0);
    AudioConnection          patchCord3(mixer5, 0, waveform2, 0);
    AudioConnection          patchCord4(mixer5, 0, waveform3, 0);
    AudioConnection          patchCord5(mixer5, 0, waveform4, 0);
    AudioConnection          patchCord6(mixer5, 0, waveform5, 0);
    AudioConnection          patchCord7(mixer5, 0, waveform6, 0);
    AudioConnection          patchCord8(mixer5, 0, waveform7, 0);
    AudioConnection          patchCord9(mixer5, 0, waveform8, 0);
    AudioConnection          patchCord10(waveform14, 0, filter14, 0);
    AudioConnection          patchCord11(waveform16, 0, filter16, 0);
    AudioConnection          patchCord12(waveform15, 0, filter15, 0);
    AudioConnection          patchCord13(waveform12, 0, filter12, 0);
    AudioConnection          patchCord14(waveform13, 0, filter13, 0);
    AudioConnection          patchCord15(waveform9, 0, filter9, 0);
    AudioConnection          patchCord16(waveform9, 0, filter9, 1);
    AudioConnection          patchCord17(waveform10, 0, filter10, 0);
    AudioConnection          patchCord18(waveform11, 0, filter11, 0);
    AudioConnection          patchCord19(waveform6, 0, filter6, 0);
    AudioConnection          patchCord20(waveform5, 0, filter5, 0);
    AudioConnection          patchCord21(waveform4, 0, filter4, 0);
    AudioConnection          patchCord22(waveform8, 0, filter8, 0);
    AudioConnection          patchCord23(waveform7, 0, filter7, 0);
    AudioConnection          patchCord24(waveform3, 0, filter3, 0);
    AudioConnection          patchCord25(waveform1, 0, filter1, 0);
    AudioConnection          patchCord26(waveform1, 0, filter1, 1);
    AudioConnection          patchCord27(waveform2, 0, filter2, 0);
    AudioConnection          patchCord28(filter12, 0, envelope12, 0);
    AudioConnection          patchCord29(filter13, 0, envelope13, 0);
    AudioConnection          patchCord30(filter10, 0, envelope10, 0);
    AudioConnection          patchCord31(filter9, 0, envelope9, 0);
    AudioConnection          patchCord32(filter16, 0, envelope16, 0);
    AudioConnection          patchCord33(filter14, 0, envelope14, 0);
    AudioConnection          patchCord34(filter11, 0, envelope11, 0);
    AudioConnection          patchCord35(filter15, 0, envelope15, 0);
    AudioConnection          patchCord36(filter4, 0, envelope4, 0);
    AudioConnection          patchCord37(filter5, 0, envelope5, 0);
    AudioConnection          patchCord38(filter1, 0, envelope1, 0);
    AudioConnection          patchCord39(filter2, 0, envelope2, 0);
    AudioConnection          patchCord40(filter8, 0, envelope8, 0);
    AudioConnection          patchCord41(filter6, 0, envelope6, 0);
    AudioConnection          patchCord42(filter3, 0, envelope3, 0);
    AudioConnection          patchCord43(filter7, 0, envelope7, 0);
    AudioConnection          patchCord44(envelope12, 0, mixer3, 3);
    AudioConnection          patchCord45(envelope13, 0, mixer4, 0);
    AudioConnection          patchCord46(envelope10, 0, mixer3, 1);
    AudioConnection          patchCord47(envelope16, 0, mixer4, 3);
    AudioConnection          patchCord48(envelope9, 0, mixer3, 0);
    AudioConnection          patchCord49(envelope14, 0, mixer4, 1);
    AudioConnection          patchCord50(envelope11, 0, mixer3, 2);
    AudioConnection          patchCord51(envelope15, 0, mixer4, 2);
    AudioConnection          patchCord52(envelope1, 0, mixer1, 0);
    AudioConnection          patchCord53(envelope4, 0, mixer1, 3);
    AudioConnection          patchCord54(envelope5, 0, mixer2, 0);
    AudioConnection          patchCord55(envelope2, 0, mixer1, 1);
    AudioConnection          patchCord56(envelope8, 0, mixer2, 3);
    AudioConnection          patchCord57(envelope6, 0, mixer2, 1);
    AudioConnection          patchCord58(envelope3, 0, mixer1, 2);
    AudioConnection          patchCord59(envelope7, 0, mixer2, 2);
    AudioConnection          patchCord60(mixer1, 0, mixerFinal, 0);
    AudioConnection          patchCord61(mixer2, 0, mixerFinal, 1);
    AudioConnection          patchCord62(mixer3, 0, mixerFinal, 2);
    AudioConnection          patchCord63(mixer4, 0, mixerFinal, 3);
    AudioConnection          patchCord64(mixerFinal, freeverbs1);
    AudioConnection          patchCord65(mixerFinal, 0, verbMix, 2);
    AudioConnection          patchCord66(freeverbs1, 0, verbMix, 0);
    AudioConnection          patchCord67(freeverbs1, 1, verbMix, 1);
    AudioConnection          patchCord68(verbMix, 0, i2s1, 0);
    AudioConnection          patchCord69(verbMix, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=866,598
    // GUItool: end automatically generated code
    
    #endif // _SYNTHARCH_H

  16. #16
    Saw a couple errant connections and made a couple small tweaks to the SynthArch 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       modWave2; //xy=157.50005340576172,1175.0000157356262
    AudioSynthWaveform       modWave1;       //xy=178.50005340576172,367.00001430511475
    AudioMixer4              mixer6; //xy=317.0000534057617,1191.000015258789
    AudioMixer4              mixer5;         //xy=337.0000534057617,383.00002670288086
    AudioSynthWaveformModulated waveform14;     //xy=579.0000648498535,1381.0000133514404
    AudioSynthWaveformModulated waveform16;     //xy=582.0000648498535,1564.0000133514404
    AudioSynthWaveformModulated waveform15;     //xy=584.0000648498535,1482.0000133514404
    AudioSynthWaveformModulated waveform12;     //xy=591.0000648498535,1164.0000133514404
    AudioSynthWaveformModulated waveform13;     //xy=594.0000648498535,1251.0000133514404
    AudioSynthWaveformModulated waveform9;      //xy=596.0000648498535,881.0000133514404
    AudioSynthWaveformModulated waveform10;     //xy=597.0000648498535,973.0000133514404
    AudioSynthWaveformModulated waveform11;     //xy=597.0000648498535,1060.0000133514404
    AudioSynthWaveformModulated waveform6;      //xy=628.0000648498535,550.0000133514404
    AudioSynthWaveformModulated waveform5;      //xy=636.0000648498535,443.00001335144043
    AudioSynthWaveformModulated waveform4;      //xy=640.0000648498535,347.00001335144043
    AudioSynthWaveformModulated waveform8;      //xy=643.0000648498535,748.0000133514404
    AudioSynthWaveformModulated waveform7;      //xy=649.0000648498535,655.0000133514404
    AudioSynthWaveformModulated waveform3;      //xy=653.0000648498535,253.00001335144043
    AudioSynthWaveformModulated waveform2;      //xy=654.0000648498535,176.00001525878906
    AudioSynthWaveformModulated waveform1;      //xy=660.0000648498535,72.00001335144043
    AudioFilterStateVariable filter12;       //xy=741.0000648498535,1158.0000133514404
    AudioFilterStateVariable filter13;       //xy=749.0000648498535,1254.0000133514404
    AudioFilterStateVariable filter10;       //xy=751.0000648498535,968.0000133514404
    AudioFilterStateVariable filter9;        //xy=752.0000648498535,886.0000133514404
    AudioFilterStateVariable filter16;       //xy=754.0000648498535,1559.0000133514404
    AudioFilterStateVariable filter14;       //xy=757.0000648498535,1377.0000133514404
    AudioFilterStateVariable filter11;       //xy=762.0000648498535,1061.0000133514404
    AudioFilterStateVariable filter15;       //xy=761.0000648498535,1483.0000133514404
    AudioFilterStateVariable filter4;        //xy=787.0000648498535,352.00001335144043
    AudioFilterStateVariable filter5;        //xy=795.0000648498535,448.00001335144043
    AudioFilterStateVariable filter1;        //xy=797.0000648498535,82.00001335144043
    AudioFilterStateVariable filter2;        //xy=797.0000648498535,162.00001335144043
    AudioFilterStateVariable filter8;        //xy=800.0000648498535,753.0000133514404
    AudioFilterStateVariable filter6;        //xy=803.0000648498535,571.0000133514404
    AudioFilterStateVariable filter3;        //xy=808.0000648498535,255.00001335144043
    AudioFilterStateVariable filter7;        //xy=807.0000648498535,677.0000133514404
    AudioEffectEnvelope      envelope12;     //xy=921.0000648498535,1145.0000133514404
    AudioEffectEnvelope      envelope13;     //xy=929.0000648498535,1241.0000133514404
    AudioEffectEnvelope      envelope10;     //xy=931.0000648498535,955.0000133514404
    AudioEffectEnvelope      envelope16;     //xy=934.0000648498535,1546.0000133514404
    AudioEffectEnvelope      envelope9;      //xy=938.0000648498535,889.0000133514404
    AudioEffectEnvelope      envelope14;     //xy=937.0000648498535,1361.0000133514404
    AudioEffectEnvelope      envelope11;     //xy=942.0000648498535,1048.0000133514404
    AudioEffectEnvelope      envelope15;     //xy=941.0000648498535,1470.0000133514404
    AudioEffectEnvelope      envelope1;      //xy=953.0000648498535,65.00001335144043
    AudioEffectEnvelope      envelope4;      //xy=967.0000648498535,339.00001335144043
    AudioEffectEnvelope      envelope5;      //xy=975.0000648498535,435.00001335144043
    AudioEffectEnvelope      envelope2;      //xy=977.0000648498535,149.00001335144043
    AudioEffectEnvelope      envelope8;      //xy=980.0000648498535,740.0000133514404
    AudioEffectEnvelope      envelope6;      //xy=983.0000648498535,558.0000133514404
    AudioEffectEnvelope      envelope3;      //xy=988.0000648498535,242.00001335144043
    AudioEffectEnvelope      envelope7;      //xy=987.0000648498535,664.0000133514404
    AudioMixer4              mixer1;         //xy=1193.0000648498535,724.0000133514404
    AudioMixer4              mixer2;         //xy=1200.0000648498535,833.0000133514404
    AudioMixer4              mixer3;         //xy=1202.0000648498535,974.0000133514404
    AudioMixer4              mixer4;         //xy=1205.0000648498535,1116.0000133514404
    AudioMixer4              mixerFinal;     //xy=1402.0000648498535,897.0000133514404
    AudioEffectFreeverbStereo freeverbs1;     //xy=1560.0000648498535,828.0000133514404
    AudioMixer4              verbMix;        //xy=1725.0000648498535,894.0000133514404
    AudioOutputI2S           i2s1;           //xy=1855.0000648498535,889.0000133514404
    AudioConnection          patchCord1(modWave2, 0, mixer6, 0);
    AudioConnection          patchCord2(modWave1, 0, mixer5, 0);
    AudioConnection          patchCord3(mixer6, 0, waveform9, 0);
    AudioConnection          patchCord4(mixer6, 0, waveform10, 0);
    AudioConnection          patchCord5(mixer6, 0, waveform11, 0);
    AudioConnection          patchCord6(mixer6, 0, waveform12, 0);
    AudioConnection          patchCord7(mixer6, 0, waveform13, 0);
    AudioConnection          patchCord8(mixer6, 0, waveform14, 0);
    AudioConnection          patchCord9(mixer6, 0, waveform15, 0);
    AudioConnection          patchCord10(mixer6, 0, waveform16, 1);
    AudioConnection          patchCord11(mixer5, 0, waveform1, 0);
    AudioConnection          patchCord12(mixer5, 0, waveform2, 0);
    AudioConnection          patchCord13(mixer5, 0, waveform3, 0);
    AudioConnection          patchCord14(mixer5, 0, waveform4, 0);
    AudioConnection          patchCord15(mixer5, 0, waveform5, 0);
    AudioConnection          patchCord16(mixer5, 0, waveform6, 0);
    AudioConnection          patchCord17(mixer5, 0, waveform7, 0);
    AudioConnection          patchCord18(mixer5, 0, waveform8, 0);
    AudioConnection          patchCord19(waveform14, 0, filter14, 0);
    AudioConnection          patchCord20(waveform16, 0, filter16, 0);
    AudioConnection          patchCord21(waveform15, 0, filter15, 0);
    AudioConnection          patchCord22(waveform12, 0, filter12, 0);
    AudioConnection          patchCord23(waveform13, 0, filter13, 0);
    AudioConnection          patchCord24(waveform9, 0, filter9, 0);
    AudioConnection          patchCord25(waveform10, 0, filter10, 0);
    AudioConnection          patchCord26(waveform11, 0, filter11, 0);
    AudioConnection          patchCord27(waveform6, 0, filter6, 0);
    AudioConnection          patchCord28(waveform5, 0, filter5, 0);
    AudioConnection          patchCord29(waveform4, 0, filter4, 0);
    AudioConnection          patchCord30(waveform8, 0, filter8, 0);
    AudioConnection          patchCord31(waveform7, 0, filter7, 0);
    AudioConnection          patchCord32(waveform3, 0, filter3, 0);
    AudioConnection          patchCord33(waveform2, 0, filter2, 0);
    AudioConnection          patchCord34(waveform1, 0, filter1, 0);
    AudioConnection          patchCord35(filter12, 0, envelope12, 0);
    AudioConnection          patchCord36(filter13, 0, envelope13, 0);
    AudioConnection          patchCord37(filter10, 0, envelope10, 0);
    AudioConnection          patchCord38(filter9, 0, envelope9, 0);
    AudioConnection          patchCord39(filter16, 0, envelope16, 0);
    AudioConnection          patchCord40(filter14, 0, envelope14, 0);
    AudioConnection          patchCord41(filter11, 0, envelope11, 0);
    AudioConnection          patchCord42(filter15, 0, envelope15, 0);
    AudioConnection          patchCord43(filter4, 0, envelope4, 0);
    AudioConnection          patchCord44(filter5, 0, envelope5, 0);
    AudioConnection          patchCord45(filter1, 0, envelope1, 0);
    AudioConnection          patchCord46(filter2, 0, envelope2, 0);
    AudioConnection          patchCord47(filter8, 0, envelope8, 0);
    AudioConnection          patchCord48(filter6, 0, envelope6, 0);
    AudioConnection          patchCord49(filter3, 0, envelope3, 0);
    AudioConnection          patchCord50(filter7, 0, envelope7, 0);
    AudioConnection          patchCord51(envelope12, 0, mixer3, 3);
    AudioConnection          patchCord52(envelope13, 0, mixer4, 0);
    AudioConnection          patchCord53(envelope10, 0, mixer3, 1);
    AudioConnection          patchCord54(envelope16, 0, mixer4, 3);
    AudioConnection          patchCord55(envelope9, 0, mixer3, 0);
    AudioConnection          patchCord56(envelope14, 0, mixer4, 1);
    AudioConnection          patchCord57(envelope11, 0, mixer3, 2);
    AudioConnection          patchCord58(envelope15, 0, mixer4, 2);
    AudioConnection          patchCord59(envelope1, 0, mixer1, 0);
    AudioConnection          patchCord60(envelope4, 0, mixer1, 3);
    AudioConnection          patchCord61(envelope5, 0, mixer2, 0);
    AudioConnection          patchCord62(envelope2, 0, mixer1, 1);
    AudioConnection          patchCord63(envelope8, 0, mixer2, 3);
    AudioConnection          patchCord64(envelope6, 0, mixer2, 1);
    AudioConnection          patchCord65(envelope3, 0, mixer1, 2);
    AudioConnection          patchCord66(envelope7, 0, mixer2, 2);
    AudioConnection          patchCord67(mixer1, 0, mixerFinal, 0);
    AudioConnection          patchCord68(mixer2, 0, mixerFinal, 1);
    AudioConnection          patchCord69(mixer3, 0, mixerFinal, 2);
    AudioConnection          patchCord70(mixer4, 0, mixerFinal, 3);
    AudioConnection          patchCord71(mixerFinal, freeverbs1);
    AudioConnection          patchCord72(mixerFinal, 0, verbMix, 2);
    AudioConnection          patchCord73(freeverbs1, 0, verbMix, 0);
    AudioConnection          patchCord74(freeverbs1, 1, verbMix, 1);
    AudioConnection          patchCord75(verbMix, 0, i2s1, 0);
    AudioConnection          patchCord76(verbMix, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=1262.0000648498535,607.0000133514404
    // GUItool: end automatically generated code
    
    #endif // _SYNTHARCH_H

  17. #17
    Senior Member
    Join Date
    Feb 2015
    Posts
    100
    Looking good...

    The next level is multiple detuned oscillators per voice... that's on my todo list for my synth at some point.

  18. #18
    Yup, that's on my todo list too. Two oscillators per voice (detune-able) and a noise source as well. I also want to add separate ADSR controls for each oscillator. And the buttons on the unit itself so the synth can be played even when no controller is present. I'm also going to add a text file that will be read from an SD card so the scale the buttons can play will be fully customizable. *Big Sigh* Here we go...

    Thanks again, wcalvert!

  19. #19
    Senior Member
    Join Date
    Feb 2015
    Posts
    100
    Glad I could help!

  20. #20
    Tonight's edition of the Panda Synth is the synth with working test buttons using oddson's super clean and awesome idea. Also filter and reverb have been implemented.

    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 = 8;
    
    float mixGain = 0.5;
    float resonance = 3.8;
    const float DIV127 = (1.0 / 127.0);
    byte globalVelocity = 127;
    
    bool idleVoices[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };
    
    // Set to 255 so it didn't throw an error :)
    byte voiceToNote[8] = { 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 *oscsStart[NUM_VOICES] = { &waveform1, &waveform2, &waveform3, &waveform4, &waveform5, &waveform6, &waveform7, &waveform8 };
      for (int i = 0; i < 8; i++) {
        oscsStart[i]->begin(mixGain, 144, WAVEFORM_SQUARE);
      }
    
      //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);
    
      mixerFinal.gain(0, mixGain);
      mixerFinal.gain(1, mixGain);
    
      verbMix.gain(0, mixGain);
      verbMix.gain(1, mixGain);
      verbMix.gain(2, mixGain);
    }
    
    void loop() {
      // Check USB input
      midi1.read();
    
      // Check if notes are playing
      IdleCheck();
    
      //Lowpass Filter
      int filterKnob = 10000 * analogRead(A3) / 1023;
      // 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(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);
      }
    
      Bounce *mybutton[]  = { &button0, &button1, &button2, &button3, &button4, &button5, &button6, &button7};
      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 };
    AudioEffectEnvelope *envelopes[NUM_VOICES] = { &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8 };
    
    void onNoteOn(byte channel, byte note, byte velocity) {
    
      // Set Velocity to global variable
      globalVelocity = velocity;
      float velo = (globalVelocity * DIV127);
    
      for (int i = 0; i < NUM_VOICES; i++) {
        if (idleVoices[i]) {
          idleVoices[i] = false;
          voiceToNote[i] = note;
          AudioNoInterrupts();
          oscs[i]->frequency(noteFreqs[note]);
          oscs[i]->amplitude(velo);
          envelopes[i]->noteOn();
          AudioInterrupts();
          break;
        }
      }
    }
    
    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;
        }
      }
    }
    
    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;
        }
      }
    }

Posting Permissions

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