Notes and Volts Synth tutorial, polyphonic expansion

Status
Not open for further replies.

RABB17

Well-known member
Hey all,

I threw together a quick and dirty polyphonic example of the synth outlined on Notes and Volts. I just frankensteined the midi synth example to the synth to demonstrate how to do so, maybe it will help someone! Certainly room for improvement, specifically with the mixer levels outputting uniformly and such. Number of voices can be expanded easily, although you will need to manually update the connections. You can control midi using the Pure Data template here: https://www.notesandvolts.com/2018/09/teensy-synth-part-8-lfo.html. If you don't have a midi controller you will also want to use something like midi ox to play notes via your keyboard.


Code:
// Teensy-Synth Part 8
// LFO Test
// By Notes and Volts
// www.notesandvolts.com
// components from MidiSynth example
// polyphonic edition by 12ABB17

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
/*
  // Left connections for importation into Audio Design Tool for visual examination.  Uncommenting will break code.
  AudioSynthNoisePink      pink1;          //xy=55,87
  AudioSynthNoisePink      pink2; //xy=55,212
  AudioSynthNoisePink      pink3; //xy=55,339
  AudioSynthNoisePink      pink4;          //xy=55,464
  AudioSynthWaveform       waveform1;      //xy=64,21
  AudioSynthWaveform       waveform2;      //xy=64,54
  AudioSynthWaveform       waveform4; //xy=64,146
  AudioSynthWaveform       waveform3; //xy=64,179
  AudioSynthWaveform       waveform5; //xy=64,273
  AudioSynthWaveform       waveform6; //xy=64,306
  AudioSynthWaveform       waveform7;      //xy=64,398
  AudioSynthWaveform       waveform8;      //xy=64,431
  AudioMixer4              mixer1;         //xy=199,61
  AudioMixer4              mixer2; //xy=199,185
  AudioMixer4              mixer3; //xy=199,313
  AudioMixer4              mixer4;         //xy=199,437
  AudioFilterStateVariable filter1;        //xy=320,67
  AudioFilterStateVariable filter3; //xy=319,319
  AudioFilterStateVariable filter2; //xy=323,191
  AudioFilterStateVariable filter4;        //xy=323,443
  AudioEffectEnvelope      envelope1;      //xy=460,54
  AudioEffectEnvelope      envelope2; //xy=460,307
  AudioEffectEnvelope      envelope3; //xy=461,178
  AudioEffectEnvelope      envelope4;      //xy=461,430
  AudioMixer4              mixer5;         //xy=653,244
  AudioOutputI2S           i2s1;           //xy=779,245
  AudioConnection          patchCord1(pink1, 0, mixer1, 2);
  AudioConnection          patchCord2(pink2, 0, mixer2, 2);
  AudioConnection          patchCord3(pink3, 0, mixer3, 2);
  AudioConnection          patchCord4(pink4, 0, mixer4, 2);
  AudioConnection          patchCord5(waveform1, 0, mixer1, 0);
  AudioConnection          patchCord6(waveform2, 0, mixer1, 1);
  AudioConnection          patchCord7(waveform4, 0, mixer2, 0);
  AudioConnection          patchCord8(waveform3, 0, mixer2, 1);
  AudioConnection          patchCord9(waveform5, 0, mixer3, 0);
  AudioConnection          patchCord10(waveform6, 0, mixer3, 1);
  AudioConnection          patchCord11(waveform7, 0, mixer4, 0);
  AudioConnection          patchCord12(waveform8, 0, mixer4, 1);
  AudioConnection          patchCord13(mixer1, 0, filter1, 0);
  AudioConnection          patchCord14(mixer2, 0, filter2, 0);
  AudioConnection          patchCord15(mixer3, 0, filter3, 0);
  AudioConnection          patchCord16(mixer4, 0, filter4, 0);
  AudioConnection          patchCord17(filter1, 0, envelope1, 0);
  AudioConnection          patchCord18(filter3, 0, envelope3, 0);
  AudioConnection          patchCord19(filter2, 0, envelope2, 0);
  AudioConnection          patchCord20(filter4, 0, envelope4, 0);
  AudioConnection          patchCord21(envelope1, 0, mixer5, 0);
  AudioConnection          patchCord22(envelope3, 0, mixer5, 2);
  AudioConnection          patchCord23(envelope2, 0, mixer5, 1);
  AudioConnection          patchCord24(envelope4, 0, mixer5, 3);
  AudioConnection          patchCord25(mixer5, 0, i2s1, 0);
  AudioConnection          patchCord26(mixer5, 0, i2s1, 1);
  AudioControlSGTL5000     sgtl5000_1;     //xy=1023,20
  // GUItool: end automatically generated code

  AudioSynthNoisePink noiseBank[] = {pink1, pink2, pink3, pink4};
  AudioSynthWaveform oscBank1[] = {waveform1, waveform3, waveform5, waveform7};
  AudioSynthWaveform oscBank2[] = {waveform2, waveform4, waveform6, waveform8};
  AudioFilterStateVariable filterBank[] = {filter1, filter2, filter3, filter4};
  AudioEffectEnvelope envelopeBank[] = {envelope1, envelope2, envelope3, envelope4};
  AudioMixer4 oscMixerBank[] = {mixer1, mixer2, mixer3, mixer4};
*/

AudioSynthWaveform*      oscBank1 = new AudioSynthWaveform[4]; //xy=653,244
AudioSynthWaveform*      oscBank2 = new AudioSynthWaveform[4]; //xy=653,244
AudioSynthNoisePink*     noiseBank = new AudioSynthNoisePink[4]; //xy=653,244
AudioMixer4*             mixerBank = new AudioMixer4[4]; //xy=653,244
AudioEffectEnvelope*     envelopeBank = new AudioEffectEnvelope[4]; //xy=653,244
AudioFilterStateVariable* filterBank = new AudioFilterStateVariable[4]; //xy=653,244
AudioMixer4              mixer5;         //xy=653,244
AudioOutputI2S           i2s1;           //xy=779,245

AudioConnection          patchCord1(noiseBank[0], 0, mixerBank[0], 2);
AudioConnection          patchCord2(noiseBank[1], 0, mixerBank[1], 2);
AudioConnection          patchCord3(noiseBank[2], 0, mixerBank[2], 2);
AudioConnection          patchCord4(noiseBank[3], 0, mixerBank[3], 2);
AudioConnection          patchCord5(oscBank1[0], 0, mixerBank[0], 0);
AudioConnection          patchCord6(oscBank2[0], 0, mixerBank[0], 1);
AudioConnection          patchCord7(oscBank1[1], 0, mixerBank[1], 0);
AudioConnection          patchCord8(oscBank2[1], 0, mixerBank[1], 1);
AudioConnection          patchCord9(oscBank1[2], 0, mixerBank[2], 0);
AudioConnection          patchCord10(oscBank2[2], 0, mixerBank[2], 1);
AudioConnection          patchCord11(oscBank1[3], 0, mixerBank[3], 0);
AudioConnection          patchCord12(oscBank2[3], 0, mixerBank[3], 1);
AudioConnection          patchCord13(mixerBank[0], 0, filterBank[0], 0);
AudioConnection          patchCord14(mixerBank[1], 0, filterBank[1], 0);
AudioConnection          patchCord15(mixerBank[2], 0, filterBank[2], 0);
AudioConnection          patchCord16(mixerBank[3], 0, filterBank[3], 0);
AudioConnection          patchCord17(filterBank[0], 0, envelopeBank[0], 0);
AudioConnection          patchCord18(filterBank[1], 0, envelopeBank[1], 0);
AudioConnection          patchCord19(filterBank[2], 0, envelopeBank[2], 0);
AudioConnection          patchCord20(filterBank[3], 0, envelopeBank[3], 0);
AudioConnection          patchCord21(envelopeBank[0], 0, mixer5, 0);
AudioConnection          patchCord22(envelopeBank[1], 0, mixer5, 1);
AudioConnection          patchCord23(envelopeBank[2], 0, mixer5, 2);
AudioConnection          patchCord24(envelopeBank[3], 0, mixer5, 3);
AudioConnection          patchCord25(mixer5, 0, i2s1, 0);
AudioConnection          patchCord26(mixer5, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=1023,20
// GUItool: end automatically generated code


const int TOTAL_VOICES = 4;
int last_id = 0;
struct voice_t {
  int wavetable_id;
  byte channel;
  byte note;
};
voice_t voices[TOTAL_VOICES];
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 = 0;
int octave = 0;
const float DIV127 = (1.0 / 127.0);
float detuneFactor = 1;
float bendFactor = 1;
int bendRange = 12;
unsigned int LFOspeed = 2000;
float LFOpitch = 1;
float LFOdepth = 0;
byte LFOmodeSelect = 0;
int FILfreq =  10000;
float FILfactor = 1;

void setup() {
  Init();
}

void loop() {
  usbMIDI.read();
  LFOupdate(false, LFOmodeSelect, FILfactor, LFOdepth);
}

int allocateVoice(byte channel, byte note);
int findVoice(byte channel, byte note);
void freeVoices();

int used_voices = 0;
int stopped_voices = 0;
int evict_voice = 0;
int notes_played = 0;

void myNoteOn(byte channel, byte note, byte velocity) {
  //if ( note > 23 && note < 108 ) {
  notes_played++;

  //Serial.printf("**** NoteOn: channel==%hhu,note==%hhu ****\n", channel, note);
  //printVoices();

  freeVoices();
  int wavetable_id = allocateVoice(channel, note);
  last_id = wavetable_id;
  globalNote = note;
  globalVelocity = velocity;

  oscPlay(note, wavetable_id);
  LFOupdate(true, LFOmodeSelect, FILfactor, LFOdepth);
  printVoices();

  //}
}

void myNoteOff(byte channel, byte note, byte velocity) {

  //Serial.printf("\n**** NoteOff: channel==%hhu,note==%hhu ****", channel, note);
  //printVoices();

  int wavetable_id = findVoice(channel, note);
  if (wavetable_id != TOTAL_VOICES)
    envelopeBank[wavetable_id].noteOff();

  //printVoices();
}

void myPitchBend(byte channel, int bend) {
  float bendF = bend;
  bendF = bendF / 8192;
  bendF = bendF * bendRange;
  bendF = bendF / 12;
  bendFactor = pow(2, bendF);
  oscSet(last_id);
}

void oscPlay(byte note, int wavetable_id) {

  oscBank1[wavetable_id].frequency(noteFreqs[note] * bendFactor * LFOpitch);
  oscBank2[wavetable_id].frequency(noteFreqs[note + octave] * detuneFactor * bendFactor * LFOpitch);
  float velo = (globalVelocity * DIV127);
  oscBank1[wavetable_id].amplitude(velo);
  oscBank2[wavetable_id].amplitude(velo);
  noiseBank[wavetable_id].amplitude(velo);

  envelopeBank[wavetable_id].noteOn();

  Serial.print("Velocity in OscPlay: ");
  Serial.print(velo);
  Serial.println();
  Serial.print("envelope is active after noteOn: ");
  Serial.print(envelopeBank[0].isActive());
  Serial.println();

}

void oscStop(int wavetable_id) {
  //envelope1.noteOff();
  envelopeBank[wavetable_id].noteOff();
}

void oscSet(int wavetable_id) {
  for (int i = 0; i < TOTAL_VOICES; i++)
  {
    oscBank1[last_id].frequency(noteFreqs[globalNote] * bendFactor * LFOpitch);
    oscBank2[last_id].frequency(noteFreqs[globalNote + octave] * detuneFactor * bendFactor * LFOpitch);
  }

}

void myControlChange(byte channel, byte control, byte value) {
  switch (control) {
    case 100:
      //mixerBank[0].gain(0, (value * DIV127));
      for (int i = 0; i < TOTAL_VOICES; i++)
      {
        mixerBank[i].gain(0, (value * DIV127));
      }
      break;

    case 101:
      //mixerBank[0].gain(1, (value * DIV127));
      for (int i = 0; i < TOTAL_VOICES; i++)
      {
        mixerBank[i].gain(1, (value * DIV127));
      }
      break;

    case 102:
      //mixerBank[0].gain(2, (value * DIV127));
      for (int i = 0; i < TOTAL_VOICES; i++)
      {
        mixerBank[i].gain(2, (value * DIV127));
      }
      break;

    case 103:
      switch (value) {
        case 0:
          octave = 24;
          break;
        case 1:
          octave = 12;
          break;
        case 2:
          octave = 0;
          break;
        case 3:
          octave = -12;
          break;
        case 4:
          octave = -24;
          break;
      }
      oscSet(last_id);
      break;

    case 104:
      //envelopeBank[0].attack(3000 * (value * DIV127));
      for (int i = 0; i < TOTAL_VOICES; i++)
      {
        envelopeBank[i].attack(3000 * (value * DIV127));
      }
      break;

    case 105:
      for (int i = 0; i < TOTAL_VOICES; i++)
      {
        envelopeBank[i].decay(3000 * (value * DIV127));
      }
      break;
    case 106:
      for (int i = 0; i < TOTAL_VOICES; i++)
      {
        envelopeBank[i].sustain(3000 * (value * DIV127));
      }
      break;

    case 107:
      for (int i = 0; i < TOTAL_VOICES; i++)
      {
        envelopeBank[i].attack(3000 * (value * DIV127));
      }
      break;

    case 108:
      switch (value) {
        case 0:
          for (int i = 0; i < TOTAL_VOICES; i++)
          {
            oscBank1[i].begin(WAVEFORM_SINE);
          }
          break;
        case 1:
          for (int i = 0; i < TOTAL_VOICES; i++)
          {
            oscBank1[i].begin(WAVEFORM_TRIANGLE);
          }
          break;
        case 2:
          for (int i = 0; i < TOTAL_VOICES; i++)
          {
            oscBank1[i].begin(WAVEFORM_SAWTOOTH);
          }
          break;
        case 3:
          for (int i = 0; i < TOTAL_VOICES; i++)
          {
            oscBank1[i].begin(WAVEFORM_PULSE);
          }
          break;
      }


    case 109:
      switch (value) {
        case 0:
          //oscBank1[0].begin(WAVEFORM_SINE);
          for (int i = 0; i < TOTAL_VOICES; i++)
          {
            oscBank2[i].begin(WAVEFORM_SINE);
          }
          break;
        case 1:
          for (int i = 0; i < TOTAL_VOICES; i++)
          {
            oscBank1[i].begin(WAVEFORM_TRIANGLE);
          }
          break;
        case 2:
          for (int i = 0; i < TOTAL_VOICES; i++)
          {
            oscBank2[i].begin(WAVEFORM_SAWTOOTH);
          }
          break;
        case 3:
          for (int i = 0; i < TOTAL_VOICES; i++)
          {
            oscBank2[i].begin(WAVEFORM_PULSE);
          }
          break;
      }

    case 110:
      detuneFactor = 1 - (0.05 * (value * DIV127));
      oscSet(last_id);
      break;

    case 111:
      FILfactor = value * DIV127;
      FILfreq = 10000 * (value * DIV127);
      if (LFOmodeSelect < 1 || LFOmodeSelect > 5)filterBank[0].frequency(FILfreq);
      break;

    case 112:
      //filterBank[0].resonance((4.3 * (value * DIV127)) + 0.7);
      for (int i = 0; i < TOTAL_VOICES; i++)
      {
        filterBank[i].resonance((4.3 * (value * DIV127)) + 0.7);
      }
      break;

    case 113:
      if (value <= 12 && value > 0) bendRange = value;
      break;

    case 114:
      {
        float xSpeed = value * DIV127;
        xSpeed = pow(100, (xSpeed - 1));
        LFOspeed = (70000 * xSpeed);
        break;
      }

    case 115:
      LFOdepth = value * DIV127;
      break;

    case 116:
      LFOmodeSelect = value;
      break;
  }
}

void LFOupdate(bool retrig, byte mode, float FILtop, float FILbottom) {
  static float LFO = 0;
  static unsigned long LFOtime = 0;
  static bool LFOdirection = false;
  unsigned long currentMicros = micros();
  static bool LFOstop = false;
  static float LFOrange = 0;
  static byte oldMode = 0;
  static bool retriggered = false;

  if (retrig == true) retriggered = true;


  if (currentMicros - LFOtime >= LFOspeed) {
    LFOtime = currentMicros;

    if (mode != oldMode) {
      if (mode == 0 || mode == 8) {
        LFOpitch = 1;
        oscSet(last_id);
        filterBank[0].frequency(FILfreq);
      }
      else if (mode >= 1 || mode <= 7) {
        LFOpitch = 1;
        oscSet(last_id);
      }
      else if (mode >= 9 || mode <= 13) {
        filterBank[0].frequency(FILfreq);
      }
      oldMode = mode;
    }

    LFOrange = FILtop - FILbottom;
    if (LFOrange < 0) LFOrange = 0;

    // LFO Modes
    switch (mode) {

      case 0: //Filter OFF
        return;
        break;
      case 1: //Filter FREE
        filterBank[0].frequency(10000 * ((LFOrange * LFO) + LFOdepth));
        break;
      case 2: //Filter DOWN
        if (retriggered == true) {
          LFOdirection = true;
          LFO = 1.0;
        }
        filterBank[0].frequency(10000 * ((LFOrange * LFO) + LFOdepth));
        break;
      case 3: //Filter UP
        if (retriggered == true) {
          LFOdirection = false;
          LFO = 0;
        }
        filterBank[0].frequency(10000 * ((LFOrange * LFO) + LFOdepth));
        break;
      case 4: //Filter 1-DN
        if (retriggered == true) {
          LFOstop = false;
          LFOdirection = true;
          LFO = 1.0;
        }
        if (LFOstop == false) filterBank[0].frequency(10000 * ((LFOrange * LFO) + LFOdepth));
        break;
      case 5: //Filter 1-UP
        if (retriggered == true) {
          LFOstop = false;
          LFOdirection = false;
          LFO = 0;
        }
        if (LFOstop == false) filterBank[0].frequency(10000 * ((LFOrange * LFO) + LFOdepth));
        break;
      case 8: //Pitch OFF
        return;
        break;
      case 9: //Pitch FREE
        LFOpitch = (LFO * LFOdepth) + 1;
        oscSet(last_id);
        break;
      case 10: //Pitch DOWN
        if (retriggered == true) {
          LFOdirection = true;
          LFO = 1.0;
        }
        LFOpitch = (LFO * LFOdepth) + 1;
        oscSet(last_id);
        break;
      case 11: //Pitch UP
        if (retriggered == true) {
          LFOdirection = false;
          LFO = 0;
        }
        LFOpitch = (LFO * LFOdepth) + 1;
        oscSet(last_id);
        break;
      case 12: //Pitch 1-DN
        if (retriggered == true) {
          LFOstop = false;
          LFOdirection = true;
          LFO = 1.0;
        }
        if (LFOstop == false) {
          LFOpitch = (LFO * LFOdepth) + 1;
          oscSet(last_id);
        }
        break;
      case 13: //Pitch 1-UP
        if (retriggered == true) {
          LFOstop = false;
          LFOdirection = false;
          LFO = 0;
        }
        if (LFOstop == false) {
          LFOpitch = (LFO * LFOdepth) + 1;
          oscSet(last_id);
        }
        break;
    }

    retriggered = false;

    // Update LFO
    if (LFOdirection == false) { //UP
      LFO = (LFO + 0.01);
      if (LFO >= 1) {
        LFOdirection = true;
        LFOstop = true;
      }
    }

    if (LFOdirection == true) { //Down
      LFO = (LFO - 0.01);
      if (LFO <= 0) {
        LFOdirection = false;
        LFOstop = true;
      }
    }
  }
}

int allocateVoice(byte channel, byte note) {
  int i;
  int nonfree_voices = stopped_voices + used_voices;
  Serial.print("Nonfree voices: ");
  Serial.print(nonfree_voices);
  Serial.println();
  if (nonfree_voices < TOTAL_VOICES) {
    for (i = nonfree_voices; i < TOTAL_VOICES && voices[i].channel != channel; ++i);
    if (i < TOTAL_VOICES) {
      voice_t temp = voices[i];
      voices[i] = voices[nonfree_voices];
      voices[nonfree_voices] = temp;
    }
    i = nonfree_voices;
    used_voices++;
  }
  else {
    if (stopped_voices) {
      i = evict_voice % stopped_voices;
      voice_t temp = voices[i];
      stopped_voices--;
      voices[i] = voices[stopped_voices];
      voices[stopped_voices] = temp;
      used_voices++;
      i = stopped_voices;
    }
    else
      i = evict_voice;
  }

  voices[i].channel = channel;
  voices[i].note = note;

  evict_voice++;
  evict_voice %= TOTAL_VOICES;

  return voices[i].wavetable_id;
}

int findVoice(byte channel, byte note) {
  int i;
  //find match
  int nonfree_voices = stopped_voices + used_voices;
  for (i = stopped_voices; i < nonfree_voices && !(voices[i].channel == channel && voices[i].note == note); ++i);
  //return TOTAL_VOICES if no match
  if (i == (nonfree_voices)) return TOTAL_VOICES;

  voice_t temp = voices[i];
  voices[i] = voices[stopped_voices];
  voices[stopped_voices] = temp;
  --used_voices;

  return voices[stopped_voices++].wavetable_id;
}

void freeVoices() {
  for (int i = 0; i < stopped_voices; i++)
    if (!true) {
      voice_t temp = voices[i];
      --stopped_voices;
      voices[i] = voices[stopped_voices];
      int nonfree_voices = stopped_voices + used_voices;
      voices[stopped_voices] = voices[nonfree_voices];
      voices[nonfree_voices] = temp;
    }
}

const char* note_map[] = {
  "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
};

void printVoices() {
  static int last_notes_played = notes_played;
  if (last_notes_played == notes_played)
    return;
  last_notes_played = notes_played;
  int usage = AudioProcessorUsage();
  Serial.printf("\nCPU:%03i voices:%02i CPU/Voice:%02i evict:%02i", usage, used_voices, usage / used_voices, evict_voice);
  for (int i = 0; i < used_voices; ++i)
    Serial.printf(" %02hhu %-2s", voices[i].channel, note_map[voices[i].note % 12]);
}

void Init()
{
  AudioMemory(120);
  usbMIDI.setHandleControlChange(myControlChange);
  usbMIDI.setHandleNoteOff(myNoteOff);
  usbMIDI.setHandleNoteOn(myNoteOn);
  usbMIDI.setHandlePitchChange(myPitchBend);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.52);
  sgtl5000_1.dacVolumeRamp();

  for (int i = 0; i < TOTAL_VOICES; i++)
  {
    voices[i].wavetable_id = i;
    voices[i].channel = voices[i].note = 0xFF;

    oscBank1[i].begin(WAVEFORM_SINE);
    oscBank1[i].amplitude(1.0);
    oscBank1[i].frequency(82.41);
    oscBank1[i].pulseWidth(1);

    oscBank2[i].begin(WAVEFORM_TRIANGLE);
    oscBank2[i].amplitude(1.0);
    oscBank2[i].frequency(82.41);
    oscBank2[i].pulseWidth(.5);

    for (int j = 0; j < 2; j++)
    {
      mixerBank[i].gain(j, 1.0);
    }
    mixerBank[i].gain(2, 0.0);

    noiseBank[i].amplitude(0.0);

    envelopeBank[i].delay(0);
    envelopeBank[i].attack(0);
    envelopeBank[i].decay(0);
    envelopeBank[i].sustain(1);
    envelopeBank[i].release(100.0 * DIV127);
    //envelopeBank[i].releaseNoteOn(5.0);
    mixer5.gain(i, 1.0);
  }
}
 
Status
Not open for further replies.
Back
Top