USB Host turning envelopes on and off?

Status
Not open for further replies.

halogravity

Well-known member
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
 
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;
  }
}
 
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.
 
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.
 
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.
 
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.
 
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!
 
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;
[/CODE]
 
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.
 
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. :)
 
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.

Also am I wrong or should this

That was a typo, good eye. I corrected it.
 
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
 
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?
 
idleVoices is an array of bools, so it's perfectly valid syntax. You don't need to explicitly type "if(idleVoices == true)", the compiler knows what you mean.
 
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
 
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
 
Looking good...

The next level is multiple detuned oscillators per voice... that's on my todo list for my synth at some point.
 
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!
 
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;
    }
  }
}
 
One minor thing, you might want to move the declarations "Bounce *mybutton[]" and "AudioFilterStateVariable *myfilter[]" outside of your loop() method.
 
One minor thing, you might want to move the declarations "Bounce *mybutton[]" and "AudioFilterStateVariable *myfilter[]" outside of your loop() method.

Thanks wcalvert! Like this? Quick question, I first tried putting those lines in setup(); and it didn't work until I moved them outside of the loop and setup functions. Is that a scope thing? Thanks for the advice!

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);
}

AudioFilterStateVariable *myfilter[]  = { &filter1, &filter2, &filter3, &filter4, &filter5, &filter6, &filter7, &filter8, &filter9, &filter10, &filter11, &filter12, &filter13, &filter14, &filter15, &filter16 };
Bounce *mybutton[]  = { &button0, &button1, &button2, &button3, &button4, &button5, &button6, &button7};

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
  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);
  }


  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;
    }
  }
}
 
That looks better.

Yes, that would be a scope problem. The variables defined inside setup() are only in scope for that method, and once that method is finished executing, they're no longer in scope... and could no longer be used.
 
So I implemented the envelope pots today (for attack and release) and I'm running into a problem I think is related to the inability of this system to voice steal that I need help with. When I turn up the release a bit, and then play, say, a three note chord, I can only play the chord twice in a row and while the notes are fading out I cant play more notes. This wont do for my purposes... any idea how I can fix this so I can still play while other notes are fading out and still active?

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);


}

AudioFilterStateVariable *myfilter[]  = { &filter1, &filter2, &filter3, &filter4, &filter5, &filter6, &filter7, &filter8, &filter9, &filter10, &filter11, &filter12, &filter13, &filter14, &filter15, &filter16 };
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 };

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
  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 = 11880 *  analogRead(A0) / 1023;
    int knob2 = 11880 * 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 };
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;
    }
  }
}
 
You will need to implement voice stealing in your onNoteOn function. If an idleVoice is not found for the incoming note, find the oldest note that is playing, shut it off, give the newly freed voice to the incoming note.
 
Status
Not open for further replies.
Back
Top