Polyphonic FM Synthesizer Clipping when >2 Voices

Category_Fury

New member
Hey all. Name's Liv. I'm working on a polyphonic FM synthesizer using a teensy 4.1 and audio shield. It's working pretty nicely! But I am having trouble specifically when there are >1 carriers and >3 voices playing. It seems to immediately start to clip and become fuzzy. There are 4 voices connected to a mixer and the gain on each channel is 0.25, it plays all four voice perfectly without issues until there is greater than one carrier playing. The way I have written the code when I change algorithms I also change the gains of the respective mixer channels to account for the many oscillators playing all at once. Here is a picture of what a single voice looks like (it's not identical in the code because I am using a compressor from an extended library). voice.png Here, also is the entirety of my code:
Code:
#include <MIDI.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <OpenAudio_ArduinoLibrary.h>

// MODULES
AudioMixer4              mixer4[4]; //xy=662.8572082519531,588.5714302062988
AudioMixer4              mixer5[4]; //xy=662.8571891784668,652.857177734375
AudioMixer4              mixer6[4]; //xy=663.8095932006836,732.8571586608887
AudioMixer4              mixer3[4];         //xy=665.0000038146973,523.9285469055176
AudioMixer4              mixer2[4];         //xy=668.571403503418,457.1428508758545
AudioMixer4              mixer1[4];         //xy=668.9286193847656,392.4999885559082
AudioSynthWaveformModulated operator3[4]; //xy=831.2500457763672,516.2499771118164
AudioSynthWaveformModulated operator4[4]; //xy=832.1429672241211,588.0356025695801
AudioSynthWaveformModulated operator1[4];   //xy=835,401.25
AudioSynthWaveformModulated operator2[4]; //xy=836.0714416503906,460.71436309814453
AudioSynthWaveformModulated operator6[4]; //xy=837.6784896850586,730.3571128845215
AudioSynthWaveformModulated operator5[4]; //xy=840.3572082519531,651.6070899963379
AudioEffectEnvelope      envelope1[4];      //xy=976.25,402.5
AudioEffectEnvelope      envelope3[4]; //xy=981.4286918640137,517.6785659790039
AudioEffectEnvelope      envelope5[4]; //xy=982.4999713897705,651.7858791351318
AudioEffectEnvelope      envelope4[4]; //xy=984.2857894897461,587.142822265625
AudioEffectEnvelope      envelope2[4]; //xy=989.1071739196777,453.9285726547241
AudioEffectEnvelope      envelope6[4]; //xy=990.1784896850586,733.750057220459
AudioMixer4              mainMixer[4];         //xy=1236.7856979370117,458.2142791748047
AudioMixer4              mainMixer2[4];         //xy=1238.5713577270508,554.2857322692871
AudioMixer4              mixOut[4];         //xy=1375.7143325805664,500.0000267028808
AudioMixer4                 bigMix;
AudioOutputI2S           audioOut;           //xy=1513.793643951416,501.0356788635254

//f32 library
AudioEffectCompressor_F32 compressor[5];   //the compressor
AudioConvert_I16toF32     int2Float1[5];   //Converts Int16 to Float.  See class in AudioStream_F32.h
AudioConvert_F32toI16     float2Int1[5];   //Converts Float to Int16.  See class in AudioStream_F32.h

// CABLES
AudioConnection          mixToOp40(mixer4[0], 0, operator4[0], 0);
AudioConnection          mixToOp41(mixer4[1], 0, operator4[1], 0);
AudioConnection          mixToOp42(mixer4[2], 0, operator4[2], 0);
AudioConnection          mixToOp43(mixer4[3], 0, operator4[3], 0);
AudioConnection          mixToOp50(mixer5[0], 0, operator5[0], 0);
AudioConnection          mixToOp51(mixer5[1], 0, operator5[1], 0);
AudioConnection          mixToOp52(mixer5[2], 0, operator5[2], 0);
AudioConnection          mixToOp53(mixer5[3], 0, operator5[3], 0);
AudioConnection          mixToOp60(mixer6[0], 0, operator6[0], 0);
AudioConnection          mixToOp61(mixer6[1], 0, operator6[1], 0);
AudioConnection          mixToOp62(mixer6[2], 0, operator6[2], 0);
AudioConnection          mixToOp63(mixer6[3], 0, operator6[3], 0);
AudioConnection          mixToOp30(mixer3[0], 0, operator3[0], 0);
AudioConnection          mixToOp31(mixer3[1], 0, operator3[1], 0);
AudioConnection          mixToOp32(mixer3[2], 0, operator3[2], 0);
AudioConnection          mixToOp33(mixer3[3], 0, operator3[3], 0);
AudioConnection          mixToOp20(mixer2[0], 0, operator2[0], 0);
AudioConnection          mixToOp21(mixer2[1], 0, operator2[1], 0);
AudioConnection          mixToOp22(mixer2[2], 0, operator2[2], 0);
AudioConnection          mixToOp23(mixer2[3], 0, operator2[3], 0);
AudioConnection          mixToOp10(mixer1[0], 0, operator1[0], 0);
AudioConnection          mixToOp11(mixer1[1], 0, operator1[1], 0);
AudioConnection          mixToOp12(mixer1[2], 0, operator1[2], 0);
AudioConnection          mixToOp13(mixer1[3], 0, operator1[3], 0);
AudioConnection          opToEnv30(operator3[0], envelope3[0]);
AudioConnection          opToEnv31(operator3[1], envelope3[1]);
AudioConnection          opToEnv32(operator3[2], envelope3[2]);
AudioConnection          opToEnv33(operator3[3], envelope3[3]);
AudioConnection          opToEnv40(operator4[0], envelope4[0]);
AudioConnection          opToEnv41(operator4[1], envelope4[1]);
AudioConnection          opToEnv42(operator4[2], envelope4[2]);
AudioConnection          opToEnv43(operator4[3], envelope4[3]);
AudioConnection          opToEnv10(operator1[0], envelope1[0]);
AudioConnection          opToEnv11(operator1[1], envelope1[1]);
AudioConnection          opToEnv12(operator1[2], envelope1[2]);
AudioConnection          opToEnv13(operator1[3], envelope1[3]);
AudioConnection          opToEnv20(operator2[0], envelope2[0]);
AudioConnection          opToEnv21(operator2[1], envelope2[1]);
AudioConnection          opToEnv22(operator2[2], envelope2[2]);
AudioConnection          opToEnv23(operator2[3], envelope2[3]);
AudioConnection          opToEnv60(operator6[0], envelope6[0]);
AudioConnection          opToEnv61(operator6[1], envelope6[1]);
AudioConnection          opToEnv62(operator6[2], envelope6[2]);
AudioConnection          opToEnv63(operator6[3], envelope6[3]);
AudioConnection          opToEnv50(operator5[0], envelope5[0]);
AudioConnection          opToEnv51(operator5[1], envelope5[1]);
AudioConnection          opToEnv52(operator5[2], envelope5[2]);
AudioConnection          opToEnv53(operator5[3], envelope5[3]);
AudioConnection          opToMainMix10(envelope1[0], 0, mainMixer[0], 0);
AudioConnection          opToMainMix11(envelope1[1], 0, mainMixer[1], 0);
AudioConnection          opToMainMix12(envelope1[2], 0, mainMixer[2], 0);
AudioConnection          opToMainMix13(envelope1[3], 0, mainMixer[3], 0);
AudioConnection          op3to10(envelope3[0], 0, mixer1[0], 1);
AudioConnection          op3to11(envelope3[1], 0, mixer1[1], 1);
AudioConnection          op3to12(envelope3[2], 0, mixer1[2], 1);
AudioConnection          op3to13(envelope3[3], 0, mixer1[3], 1);
AudioConnection          op3to20(envelope3[0], 0, mixer2[0], 1);
AudioConnection          op3to21(envelope3[1], 0, mixer2[1], 1);
AudioConnection          op3to22(envelope3[2], 0, mixer2[2], 1);
AudioConnection          op3to23(envelope3[3], 0, mixer2[3], 1);
AudioConnection          opToMainMix30(envelope3[0], 0, mainMixer[0], 2);
AudioConnection          opToMainMix31(envelope3[1], 0, mainMixer[1], 2);
AudioConnection          opToMainMix32(envelope3[2], 0, mainMixer[2], 2);
AudioConnection          opToMainMix33(envelope3[3], 0, mainMixer[3], 2);
AudioConnection          op5to40(envelope5[0], 0, mixer4[0], 0);
AudioConnection          op5to41(envelope5[1], 0, mixer4[1], 0);
AudioConnection          op5to42(envelope5[2], 0, mixer4[2], 0);
AudioConnection          op5to43(envelope5[3], 0, mixer4[3], 0);
AudioConnection          op5to30(envelope5[0], 0, mixer3[0], 2);
AudioConnection          op5to31(envelope5[1], 0, mixer3[1], 2);
AudioConnection          op5to32(envelope5[2], 0, mixer3[2], 2);
AudioConnection          op5to33(envelope5[3], 0, mixer3[3], 2);
AudioConnection          op5to20(envelope5[0], 0, mixer2[0], 2);
AudioConnection          op5to21(envelope5[1], 0, mixer2[1], 2);
AudioConnection          op5to22(envelope5[2], 0, mixer2[2], 2);
AudioConnection          op5to23(envelope5[3], 0, mixer2[3], 2);
AudioConnection          opToMainMix50(envelope5[0], 0, mainMixer2[0], 0);
AudioConnection          opToMainMix51(envelope5[1], 0, mainMixer2[1], 0);
AudioConnection          opToMainMix52(envelope5[2], 0, mainMixer2[2], 0);
AudioConnection          opToMainMix53(envelope5[3], 0, mainMixer2[3], 0);
AudioConnection          opToMainMix40(envelope4[0], 0, mainMixer[0], 3);
AudioConnection          opToMainMix41(envelope4[1], 0, mainMixer[1], 3);
AudioConnection          opToMainMix42(envelope4[2], 0, mainMixer[2], 3);
AudioConnection          opToMainMix43(envelope4[3], 0, mainMixer[3], 3);
AudioConnection          op4to30(envelope4[0], 0, mixer3[0], 3);
AudioConnection          op4to31(envelope4[1], 0, mixer3[1], 3);
AudioConnection          op4to32(envelope4[2], 0, mixer3[2], 3);
AudioConnection          op4to33(envelope4[3], 0, mixer3[3], 3);
AudioConnection          op4to10(envelope4[0], 0, mixer1[0], 2);
AudioConnection          op4to11(envelope4[1], 0, mixer1[1], 2);
AudioConnection          op4to12(envelope4[2], 0, mixer1[2], 2);
AudioConnection          op4to13(envelope4[3], 0, mixer1[3], 2);
AudioConnection          op4to20(envelope4[0], 0, mixer2[0], 1);
AudioConnection          op4to21(envelope4[1], 0, mixer2[1], 1);
AudioConnection          op4to22(envelope4[2], 0, mixer2[2], 1);
AudioConnection          op4to23(envelope4[3], 0, mixer2[3], 1);
AudioConnection          op2to10(envelope2[0], 0, mixer1[0], 0);
AudioConnection          op2to11(envelope2[1], 0, mixer1[1], 0);
AudioConnection          op2to12(envelope2[2], 0, mixer1[2], 0);
AudioConnection          op2to13(envelope2[3], 0, mixer1[3], 0);
AudioConnection          opToMainMix20(envelope2[0], 0, mainMixer[0], 1);
AudioConnection          opToMainMix21(envelope2[1], 0, mainMixer[1], 1);
AudioConnection          opToMainMix22(envelope2[2], 0, mainMixer[2], 1);
AudioConnection          opToMainMix23(envelope2[3], 0, mainMixer[3], 1);
AudioConnection          op6to50(envelope6[0], 0, mixer5[0], 3);
AudioConnection          op6to51(envelope6[1], 0, mixer5[1], 3);
AudioConnection          op6to52(envelope6[2], 0, mixer5[2], 3);
AudioConnection          op6to53(envelope6[3], 0, mixer5[3], 3);
AudioConnection          feedback0(envelope6[0], 0, mixer6[0], 3);
AudioConnection          feedback1(envelope6[1], 0, mixer6[1], 3);
AudioConnection          feedback2(envelope6[2], 0, mixer6[2], 3);
AudioConnection          feedback3(envelope6[3], 0, mixer6[3], 3);
AudioConnection          op6to40(envelope6[0], 0, mixer4[0], 1);
AudioConnection          op6to41(envelope6[1], 0, mixer4[1], 1);
AudioConnection          op6to42(envelope6[2], 0, mixer4[2], 1);
AudioConnection          op6to43(envelope6[3], 0, mixer4[3], 1);
AudioConnection          op6to30(envelope6[0], 0, mixer3[0], 1);
AudioConnection          op6to31(envelope6[1], 0, mixer3[1], 1);
AudioConnection          op6to32(envelope6[2], 0, mixer3[2], 1);
AudioConnection          op6to33(envelope6[3], 0, mixer3[3], 1);
AudioConnection          opToMainMix60(envelope6[0], 0, mainMixer2[0], 1);
AudioConnection          opToMainMix61(envelope6[1], 0, mainMixer2[1], 1);
AudioConnection          opToMainMix62(envelope6[2], 0, mainMixer2[2], 1);
AudioConnection          opToMainMix63(envelope6[3], 0, mainMixer2[3], 1);
AudioConnection          mixA0(mainMixer[0], 0, mixOut[0], 0);
AudioConnection          mixA1(mainMixer[1], 0, mixOut[1], 0);
AudioConnection          mixA2(mainMixer[2], 0, mixOut[2], 0);
AudioConnection          mixA3(mainMixer[3], 0, mixOut[3], 0);
AudioConnection          mixB0(mainMixer2[0], 0, mixOut[0], 1);
AudioConnection          mixB1(mainMixer2[1], 0, mixOut[1], 1);
AudioConnection          mixB2(mainMixer2[2], 0, mixOut[2], 1);
AudioConnection          mixB3(mainMixer2[3], 0, mixOut[3], 1);
AudioConnection          voice0(mixOut[0],0,bigMix,0);
AudioConnection          voice1(mixOut[1],0,bigMix,1);
AudioConnection          voice2(mixOut[2],0,bigMix,2);
AudioConnection          voice3(mixOut[3],0,bigMix,3);

AudioControlSGTL5000     sgtl5000_1;     //xy=294.35682678222656,514.7738380432129
// GUItool: end automatically generated code

//f32 cables
AudioConnection_F32     convToComp0(int2Float1[0], 0, compressor[0], 0); //  connect converter to compressor
AudioConnection_F32     compToConv0(compressor[0], 0, float2Int1[0], 0); //  connect compressor to converter
AudioConnection         mixToConv0(mixOut[0],0,int2Float1[0],0);  // connect voice 0 to converter
AudioConnection         convToAud0(float2Int1[0],0,bigMix,0); // connect compressed audio to the output left

AudioConnection_F32     convToComp1(int2Float1[1], 0, compressor[1], 0); //  connect converter to compressor
AudioConnection_F32     compToConv1(compressor[1], 0, float2Int1[1], 0); //  connect compressor to converter
AudioConnection         mixToConv1(mixOut[1],0,int2Float1[1],0);  // connect voice 0 to converter
AudioConnection         convToAud1(float2Int1[1],0,bigMix,1); // connect compressed audio to the output left

AudioConnection_F32     convToComp2(int2Float1[2], 0, compressor[2], 0); //  connect converter to compressor
AudioConnection_F32     compToConv2(compressor[2], 0, float2Int1[2], 0); //  connect compressor to converter
AudioConnection         mixToConv2(mixOut[2],0,int2Float1[2],0);  // connect voice 0 to converter
AudioConnection         convToAud2(float2Int1[2],0,bigMix,2); // connect compressed audio to the output left

AudioConnection_F32     convToComp3(int2Float1[3], 0, compressor[3], 0); //  connect converter to compressor
AudioConnection_F32     compToConv3(compressor[3], 0, float2Int1[3], 0); //  connect compressor to converter
AudioConnection         mixToConv3(mixOut[3],0,int2Float1[3],0);  // connect voice 0 to converter
AudioConnection         convToAud3(float2Int1[3],0,bigMix,3); // connect compressed audio to the output left

// AudioConnection         allAudioOutL(bigMix,0,audioOut,0);  //all compressed audio out L
// AudioConnection         allAudioOutR(bigMix,0,audioOut,1);  //all compressed audio out R
AudioConnection         mixToConv4(bigMix,0,int2Float1[4],0);
AudioConnection_F32     convToComp4(int2Float1[4],0,compressor[4],0);
AudioConnection_F32     compToConv4(compressor[4],0,float2Int1[4],0);
AudioConnection         allAudioOutR(float2Int1[4],0,audioOut,1);
AudioConnection         allAudioOutL(float2Int1[4],0,audioOut,0);

//Global variables
const byte BUFFER = 4; //4 voice polyphony
const float noteFreqs[106] = {20,20.946,21.936,22.974,24.061,25.199,26.390,27.638,28.945,30.314,31.748,33.250,34.822,36.469,38.194,40,41.892,43.873,45.948,48.121,50.497,52.780,55.277,57.891,60.629,63.496,66.499,69.644,72.938,76.387,80,83.784,87.746,91.896,96.242,100.794,105.561,110.553,115.782,121.257,126.992,132.998,139.288,145.876,152.775,160,167.567,175.492,183.792,192.484,201.587,211.122,221.106,231.563,242.515,253.984,265.996,278.576,291.751,305.549,320,335.134,350.984,367.583,384.968,403.175,422.243,442.212,463.126,485.029,507.968,531.992,557.152,583.502,611.099,640,670.268,701.968,735.167,769.936,806.349,844.485,884.424,926.252,970.059,1015.937,1063.985,1114.305,1167.005,1222.197,1280,1340.536,1403.936,1470.334,1539.872,1612.699,1688.970,1768.848,1852.505,1940.117,2031.873,2127.969,2228.609,2334.010,2444.395,2560};
byte globalNote[4] = {0,0,0,0};
byte globalVelocity = 0;
const float DIV127 = (1.0 / 127.0);
float bendFactor;
int carrierCountA;
int carrierCountB;

//keep track of current patch
int currentAlgorithm = 0;
float attack[6] = {0,0,0,0,0,0};
float decay[6] = {0,0,0,0,0,0};
float sustain[6] = {1,1,1,1,1,1};
float release[6] = {500,500,500,500,500,500};
float amplitude[6] = {1,0,0,0,0,0};
float octave[6] = {1,1,1,1,1,1};
float feedback = 0;

//keep track of if a voice is a carrier
bool carriers[6] = {true, false, false, false, false, false};

//midi control (not USB)
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);

//SD card file
File myFile;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  
  AudioMemory(20);
  sgtl5000_1.enable();
  sgtl5000_1.volume(1);
  AudioMemory_F32(16); //allocate Float32 audio data blocks
 
  //MIDI
  MIDI.begin();

  //gain control
  bigMix.gain(0,0.25);
  bigMix.gain(1,0.25);
  bigMix.gain(2,0.25);
  bigMix.gain(3,0.25);
  //compressor
  float knee_dBFS = -20.0f; 
  float comp_ratio = 1.0f;  
  float attack_sec = 0.0f;  
  float release_sec = 3.0f; 
  float fs_Hz = AUDIO_SAMPLE_RATE;
  compressor[0].setThresh_dBFS(knee_dBFS);       
  compressor[0].setCompressionRatio(comp_ratio); 
  compressor[0].setAttack_sec(attack_sec, fs_Hz);      
  compressor[0].setRelease_sec(release_sec, fs_Hz);

  compressor[1].setThresh_dBFS(knee_dBFS);       
  compressor[1].setCompressionRatio(comp_ratio); 
  compressor[1].setAttack_sec(attack_sec, fs_Hz);      
  compressor[1].setRelease_sec(release_sec, fs_Hz);

  compressor[2].setThresh_dBFS(knee_dBFS);       
  compressor[2].setCompressionRatio(comp_ratio); 
  compressor[2].setAttack_sec(attack_sec, fs_Hz);      
  compressor[2].setRelease_sec(release_sec, fs_Hz);

  compressor[3].setThresh_dBFS(knee_dBFS);       
  compressor[3].setCompressionRatio(comp_ratio); 
  compressor[3].setAttack_sec(attack_sec, fs_Hz);      
  compressor[3].setRelease_sec(release_sec, fs_Hz);

  compressor[4].setThresh_dBFS(knee_dBFS);       
  compressor[4].setCompressionRatio(comp_ratio); 
  compressor[4].setAttack_sec(attack_sec, fs_Hz);      
  compressor[4].setRelease_sec(release_sec, fs_Hz);        

  //voices
  operator1[0].begin(WAVEFORM_TRIANGLE);
  operator1[1].begin(WAVEFORM_TRIANGLE);
  operator1[2].begin(WAVEFORM_TRIANGLE);
  operator1[3].begin(WAVEFORM_TRIANGLE);
  operator2[0].begin(WAVEFORM_TRIANGLE);
  operator2[1].begin(WAVEFORM_TRIANGLE);
  operator2[2].begin(WAVEFORM_TRIANGLE);
  operator2[3].begin(WAVEFORM_TRIANGLE);
  operator3[0].begin(WAVEFORM_TRIANGLE);
  operator3[1].begin(WAVEFORM_TRIANGLE);
  operator3[2].begin(WAVEFORM_TRIANGLE);
  operator3[3].begin(WAVEFORM_TRIANGLE);
  operator4[0].begin(WAVEFORM_TRIANGLE);
  operator4[1].begin(WAVEFORM_TRIANGLE);
  operator4[2].begin(WAVEFORM_TRIANGLE);
  operator4[3].begin(WAVEFORM_TRIANGLE);
  operator5[0].begin(WAVEFORM_TRIANGLE);
  operator5[1].begin(WAVEFORM_TRIANGLE);
  operator5[2].begin(WAVEFORM_TRIANGLE);
  operator5[3].begin(WAVEFORM_TRIANGLE);
  operator6[0].begin(WAVEFORM_TRIANGLE);
  operator6[1].begin(WAVEFORM_TRIANGLE);
  operator6[2].begin(WAVEFORM_TRIANGLE);
  operator6[3].begin(WAVEFORM_TRIANGLE);
  
  //envelopes
  for(int i = 0; i < 4; i ++){
    envelope1[i].attack(0);
    envelope1[i].decay(0);
    envelope1[i].sustain(1);
    envelope1[i].release(500);
    envelope2[i].attack(0);
    envelope2[i].decay(0);
    envelope2[i].sustain(1);
    envelope2[i].release(500);
    envelope3[i].attack(0);
    envelope3[i].decay(0);
    envelope3[i].sustain(1);
    envelope3[i].release(500);
    envelope4[i].attack(0);
    envelope4[i].decay(0);
    envelope4[i].sustain(1);
    envelope4[i].release(500);
    envelope5[i].attack(0);
    envelope5[i].decay(0);
    envelope5[i].sustain(1);
    envelope5[i].release(500);
    envelope6[i].attack(0);
    envelope6[i].decay(0);
    envelope6[i].sustain(1);
    envelope6[i].release(500);

    //set base algorithm
    setAlgorithm(0);
  }

  //MIDI control USB
  usbMIDI.setHandleControlChange(myControlChange);
  usbMIDI.setHandleNoteOff(myNoteOff);
  usbMIDI.setHandleNoteOn(myNoteOn);
  usbMIDI.setHandlePitchChange(myPitchBend);

  //MIDI control 5-pin
  MIDI.setHandleControlChange(myControlChange);
  MIDI.setHandleNoteOff(myNoteOff);
  MIDI.setHandleNoteOn(myNoteOn);
  MIDI.setHandlePitchBend(myPitchBend);

  //SETUP!
  Serial.print("Initializing SD card...");
  if (!SD.begin(BUILTIN_SDCARD)) {
    Serial.println("initialization failed!");
    while (1);
    }
  Serial.println("initialization done.");
}

void setGain(){
  float divA = 1/(carrierCountA);
  
  for(int i = 0; i < 4; i ++){
    if(carriers[i]){
      mainMixer[0].gain(i-1,divA);
      mainMixer[1].gain(i-1,divA);
      mainMixer[2].gain(i-1,divA);
      mainMixer[3].gain(i-1,divA);
    }
  }
  if(carrierCountB != 0){
    float divB = 1/(carrierCountB);
    for(int i = 4; i < 6; i ++){
      if(carriers[i]){
        mainMixer2[0].gain(i-1,divB);
        mainMixer2[1].gain(i-1,divB);
        mainMixer2[2].gain(i-1,divB);
        mainMixer2[3].gain(i-1,divB);
      }
    }
  }
}

void myPitchBend(byte channel, int bend){
  float bendF = bend;
  bendF = bendF / 8192;
  bendFactor = pow(2, bendF);
  oscSet();
}
void oscSet() {
  for(int i = 0; i <4; i ++){
    operator1[i].frequency(noteFreqs[globalNote[i]]*octave[0] * bendFactor);
    operator2[i].frequency(noteFreqs[globalNote[i]]*octave[1] * bendFactor);
    operator3[i].frequency(noteFreqs[globalNote[i]]*octave[2] * bendFactor);
    operator4[i].frequency(noteFreqs[globalNote[i]]*octave[3] * bendFactor);
    operator5[i].frequency(noteFreqs[globalNote[i]]*octave[4] * bendFactor);
    operator6[i].frequency(noteFreqs[globalNote[i]]*octave[5] * bendFactor);
  }
}

void writePatch(){
    // open the file. note that only one file can be open at a time,
    // so you have to close this one before opening another.
    myFile = SD.open("patch.txt", FILE_WRITE);

    // if the file opened okay, write to it:
    if (myFile) {
      Serial.print("Writing to patch.txt...");
      myFile.println(currentAlgorithm);
      for(int i = 0; i < 6; i++){
        myFile.println(amplitude[i]);
        myFile.println(attack[i]);
        myFile.println(sustain[i]);
        myFile.println(decay[i]);
        myFile.println(release[i]);
        myFile.println(octave[i]);
      }
      myFile.println(feedback);
      myFile.close();
      Serial.println("done.");
    } else {
      // if the file didn't open, print an error:
      Serial.println("error opening test.txt");
    }

}

void readPatch(){
    char myData[10];
    // re-open the file for reading:
    myFile = SD.open("patch.txt");
    if (myFile) {
      // read from the file until there's nothing else in it:
      Serial.print("Reading patch.txt...");
      while (myFile.available()) {
        byte m = myFile.readBytesUntil('\n',myData,10);
        myData[m] = '\0';//insert null character
        currentAlgorithm = atoi(myData);
        setAlgorithm(currentAlgorithm);
        for(int i = 0; i < 6; i ++){
          m = myFile.readBytesUntil('\n',myData,10);
          myData[m] = '\0';//insert null character
          amplitude[i] = atof(myData);
          m = myFile.readBytesUntil('\n',myData,10);
          myData[m] = '\0';//insert null character
          attack[i] = atof(myData);
          m = myFile.readBytesUntil('\n',myData,10);
          myData[m] = '\0';//insert null character
          decay[i] = atof(myData);
          m = myFile.readBytesUntil('\n',myData,10);
          myData[m] = '\0';//insert null character
          sustain[i] = atof(myData);
          m = myFile.readBytesUntil('\n',myData,10);
          myData[m] = '\0';//insert null character
          release[i] = atof(myData);
          m = myFile.readBytesUntil('\n',myData,10);
          myData[m] = '\0';//insert null character
          octave[i] = atof(myData); 
          }
          m = myFile.readBytesUntil('\n',myData,10);
          myData[m] = '\0';//insert null character
          feedback = atof(myData);
        }
        Serial.println(" done!");
      // close the file:
      myFile.close();
      } else {
      // if the file didn't open, print an error:
      Serial.println("error opening patch.txt");
      }
}

void myNoteOn(byte channel, byte note, byte velocity) {
  for(int i = 0; i < 4; i ++){
    if(globalNote[i] == 0){
      globalVelocity = velocity;
      globalNote[i] = note;
      oscPlay(note,i);
      i = 4;
    }
  } 
}

void myNoteOff(byte channel, byte note, byte velocity) {
  for(int i = 0; i <4; i ++){
    if(globalNote[i] == note){
      globalNote[i] = 0;
      oscStop(i);
      i = 4;
    }
  }
}



void oscPlay(byte note, int i){
  
    operator1[i].frequency(noteFreqs[note]*octave[0]);
    operator2[i].frequency(noteFreqs[note]*octave[1]);
    operator3[i].frequency(noteFreqs[note]*octave[2]);
    operator4[i].frequency(noteFreqs[note]*octave[3]);
    operator5[i].frequency(noteFreqs[note]*octave[4]);
    operator6[i].frequency(noteFreqs[note]*octave[5]);
    float velo = (globalVelocity*DIV127);
    operator1[i].amplitude(velo*amplitude[0]);
    if(carriers[1]){
      operator2[i].amplitude(velo*amplitude[1]);
    }else{
      operator2[i].amplitude(amplitude[1]);
    }
    if(carriers[2]){
      operator3[i].amplitude(velo*amplitude[2]);
    }else{
      operator3[i].amplitude(amplitude[2]);
    }
    if(carriers[3]){
      operator4[i].amplitude(velo*amplitude[3]);
    }else{
      operator4[i].amplitude(amplitude[3]);
    }
    if(carriers[4]){
      operator5[i].amplitude(velo*amplitude[4]);
    }else{
      operator5[i].amplitude(amplitude[4]);
    }
    if(carriers[5]){
      operator6[i].amplitude(velo*amplitude[5]);
    }else{
      operator6[i].amplitude(amplitude[5]);
    }
  
    
    envelope1[i].noteOn();
    envelope2[i].noteOn();
    envelope3[i].noteOn();
    envelope4[i].noteOn();
    envelope5[i].noteOn();
    envelope6[i].noteOn();
  
}

void oscStop(int i){
  envelope1[i].noteOff();
  envelope2[i].noteOff(); 
  envelope3[i].noteOff();
  envelope4[i].noteOff();
  envelope5[i].noteOff();
  envelope6[i].noteOff();  
}

void myControlChange(byte channel, byte control, byte value){
  switch (control){
    case 100:
      attack[0] = ((float)value*DIV127)*11880;
      envelope1[0].attack(attack[0]);
      envelope1[1].attack(attack[0]);
      envelope1[2].attack(attack[0]);
      envelope1[3].attack(attack[0]);
      break;

    case 101:
      decay[0] = ((float)value*DIV127)*11880;
      envelope1[0].decay(decay[0]);
      envelope1[1].decay(decay[0]);
      envelope1[2].decay(decay[0]);
      envelope1[3].decay(decay[0]);
      break;

    case 102:
      sustain[0] = (float)value*DIV127;
      envelope1[0].sustain(sustain[0]);
      envelope1[1].sustain(sustain[0]);
      envelope1[2].sustain(sustain[0]);
      envelope1[3].sustain(sustain[0]);
      break;
    
    case 103:
      release[0] = ((float)value*DIV127)*11880;
      envelope1[0].release(release[0]);
      envelope1[1].release(release[0]);
      envelope1[2].release(release[0]);
      envelope1[3].release(release[0]);
      break;
    
    case 104:
      amplitude[1] = (float)value*DIV127;
      break;
    
    case 105:
      attack[1] = ((float)value*DIV127)*11880;
      envelope1[0].attack(attack[1]);
      envelope1[1].attack(attack[1]);
      envelope1[2].attack(attack[1]);
      envelope1[3].attack(attack[1]);
      break;

    case 106:
      decay[1] = ((float)value*DIV127)*11880;
      envelope1[0].decay(decay[1]);
      envelope1[1].decay(decay[1]);
      envelope1[2].decay(decay[1]);
      envelope1[3].decay(decay[1]);
      break;

    case 107:
      sustain[1] = (float)value*DIV127;
      envelope1[0].sustain(sustain[1]);
      envelope1[1].sustain(sustain[1]);
      envelope1[2].sustain(sustain[1]);
      envelope1[3].sustain(sustain[1]);
      break;
    
    case 108:
      release[1] = ((float)value*DIV127)*11880;
      envelope1[0].release(release[1]);
      envelope1[1].release(release[1]);
      envelope1[2].release(release[1]);
      envelope1[3].release(release[1]);
      break;
    
    case 109:
      amplitude[2] = (float)value*DIV127;
      break;
    
    case 110:
      attack[2] = ((float)value*DIV127)*11880;
      envelope1[0].attack(attack[2]);
      envelope1[1].attack(attack[2]);
      envelope1[2].attack(attack[2]);
      envelope1[3].attack(attack[2]);
      break;

    case 111:
      decay[2] = ((float)value*DIV127)*11880;
      envelope1[0].decay(decay[2]);
      envelope1[1].decay(decay[2]);
      envelope1[2].decay(decay[2]);
      envelope1[3].decay(decay[2]);
      break;

    case 112:
      sustain[2] = (float)value*DIV127;
      envelope1[0].sustain(sustain[2]);
      envelope1[1].sustain(sustain[2]);
      envelope1[2].sustain(sustain[2]);
      envelope1[3].sustain(sustain[2]);
      break;
    
    case 113:
      release[2] = ((float)value*DIV127)*11880;
      envelope1[0].release(release[2]);
      envelope1[1].release(release[2]);
      envelope1[2].release(release[2]);
      envelope1[3].release(release[2]);
      break;

    case 114:
      setAlgorithm(value);
      currentAlgorithm = value;
      break;
    

    case 31:
      amplitude[3] = (float)value*DIV127;
      break;
    
    case 116:
      attack[3] = ((float)value*DIV127)*11880;
      envelope1[0].attack(attack[3]);
      envelope1[1].attack(attack[3]);
      envelope1[2].attack(attack[3]);
      envelope1[3].attack(attack[3]);
      break;

    case 117:
      decay[3] = ((float)value*DIV127)*11880;
      envelope1[0].decay(decay[3]);
      envelope1[1].decay(decay[3]);
      envelope1[2].decay(decay[3]);
      envelope1[3].decay(decay[3]);
      break;

    case 118:
      sustain[3] = (float)value*DIV127;
      envelope1[0].sustain(sustain[3]);
      envelope1[1].sustain(sustain[3]);
      envelope1[2].sustain(sustain[3]);
      envelope1[3].sustain(sustain[3]);
      break;
    
    case 119:
      release[3] = ((float)value*DIV127)*11880;
      envelope1[0].release(release[3]);
      envelope1[1].release(release[3]);
      envelope1[2].release(release[3]);
      envelope1[3].release(release[3]);
      break;
    
    case 20:
      amplitude[4] = (float)value*DIV127;
      break;
    
    case 21:
      attack[4] = ((float)value*DIV127)*11880;
      envelope1[0].attack(attack[4]);
      envelope1[1].attack(attack[4]);
      envelope1[2].attack(attack[4]);
      envelope1[3].attack(attack[4]);
      break;

    case 22:
      decay[4] = ((float)value*DIV127)*11880;
      envelope1[0].decay(decay[4]);
      envelope1[1].decay(decay[4]);
      envelope1[2].decay(decay[4]);
      envelope1[3].decay(decay[4]);
      break;

    case 23:
      sustain[4] = (float)value*DIV127;
      envelope1[0].sustain(sustain[4]);
      envelope1[1].sustain(sustain[4]);
      envelope1[2].sustain(sustain[4]);
      envelope1[3].sustain(sustain[4]);
      break;
    
    case 24:
      release[4] = ((float)value*DIV127)*11880;
      envelope1[0].release(release[4]);
      envelope1[1].release(release[4]);
      envelope1[2].release(release[4]);
      envelope1[3].release(release[4]);
      break;
    
    case 25:
      amplitude[5] = (float)value*DIV127;
      break;
    
    case 26:
      attack[5] = ((float)value*DIV127)*11880;
      envelope1[0].attack(attack[5]);
      envelope1[1].attack(attack[5]);
      envelope1[2].attack(attack[5]);
      envelope1[3].attack(attack[5]);
      break;

    case 27:
      decay[5] = ((float)value*DIV127)*11880;
      envelope1[0].decay(decay[5]);
      envelope1[1].decay(decay[5]);
      envelope1[2].decay(decay[5]);
      envelope1[3].decay(decay[5]);
      break;

    case 28:
      sustain[5] = (float)value*DIV127;
      envelope1[0].sustain(sustain[5]);
      envelope1[1].sustain(sustain[5]);
      envelope1[2].sustain(sustain[5]);
      envelope1[3].sustain(sustain[5]);
      break;
    
    case 29:
      release[5] = ((float)value*DIV127)*11880;
      envelope1[0].release(release[5]);
      envelope1[1].release(release[5]);
      envelope1[2].release(release[5]);
      envelope1[3].release(release[5]);
      break;
    
    case 3:
      feedback = (float)value*DIV127;
      mixer6[0].gain(3,feedback);
      mixer6[1].gain(3,feedback);
      mixer6[2].gain(3,feedback);
      mixer6[3].gain(3,feedback);
      break;
    
    case 14:
      octave[1] = value +1;
      break;
    
    case 15:
      octave[2] = value+1;
    
    case 85:
      octave[3] = value +1;
    
    case 87:
      octave[4] = value +1;
    
    case 88:
      octave[5] = value +1;

    case 9:
      writePatch();
      break;
    
    case 86:
      readPatch();
      break;
    
  }
}

 void setAlgorithm(int i){
 
   //disconnect cables
   opToMainMix10.disconnect();
   opToMainMix11.disconnect();
   opToMainMix12.disconnect();
   opToMainMix13.disconnect();
   opToMainMix20.disconnect();
   opToMainMix21.disconnect();
   opToMainMix22.disconnect();
   opToMainMix23.disconnect();
   opToMainMix30.disconnect();
   opToMainMix31.disconnect();
   opToMainMix32.disconnect();
   opToMainMix33.disconnect();
   opToMainMix40.disconnect();
   opToMainMix41.disconnect();
   opToMainMix42.disconnect();
   opToMainMix43.disconnect();
   opToMainMix50.disconnect();
   opToMainMix51.disconnect();
   opToMainMix52.disconnect();
   opToMainMix53.disconnect();
   opToMainMix60.disconnect();
   opToMainMix61.disconnect();
   opToMainMix62.disconnect();
   opToMainMix63.disconnect();
   op2to10.disconnect();
   op2to11.disconnect();
   op2to12.disconnect();
   op2to13.disconnect();
   op3to10.disconnect();
   op3to11.disconnect();
   op3to11.disconnect();
   op3to11.disconnect();
   op3to20.disconnect();
   op3to21.disconnect();
   op3to22.disconnect();
   op3to23.disconnect();
   op4to10.disconnect();
   op4to11.disconnect();
   op4to12.disconnect();
   op4to13.disconnect();
   op4to20.disconnect();
   op4to21.disconnect();
   op4to22.disconnect();
   op4to23.disconnect();
   op4to30.disconnect();
   op4to31.disconnect();
   op4to32.disconnect();
   op4to33.disconnect();
   op5to20.disconnect();
   op5to21.disconnect();
   op5to22.disconnect();
   op5to23.disconnect();
   op5to30.disconnect();
   op5to31.disconnect();
   op5to32.disconnect();
   op5to33.disconnect();
   op5to40.disconnect();
   op5to41.disconnect();
   op5to42.disconnect();
   op5to43.disconnect();
   op6to30.disconnect();
   op6to31.disconnect();
   op6to32.disconnect();
   op6to33.disconnect();
   op6to40.disconnect();
   op6to41.disconnect();
   op6to42.disconnect();
   op6to43.disconnect();
   op6to50.disconnect();
   op6to51.disconnect();
   op6to52.disconnect();
   op6to53.disconnect();
   feedback0.disconnect();
   feedback1.disconnect(); 
   feedback2.disconnect(); 
   feedback3.disconnect();  

  //set to no carriers
  for(int i = 0; i < 6; i ++){
    carriers[i] = false;
  }


  //set chosen Algorithm
  switch (i){
    case 0:
    currentAlgorithm = 0; 
    carriers[0] = true;
    carriers[2] = true;
    carrierCountA = 2;
    carrierCountB = 0;
    opToMainMix10.connect();//1 out
    opToMainMix11.connect();
    opToMainMix12.connect();
    opToMainMix13.connect();
    opToMainMix30.connect();//3 out
    opToMainMix31.connect();
    opToMainMix32.connect();
    opToMainMix33.connect();
    op2to10.connect();//2 --> 1
    op2to11.connect();
    op2to12.connect();
    op2to13.connect();
    op4to30.connect();//4-->3
    op4to31.connect();
    op4to32.connect();
    op4to33.connect();
    op5to40.connect();//5-->4
    op5to41.connect();
    op5to42.connect();
    op5to43.connect();
    op6to50.connect();//6-->5
    op6to51.connect();
    op6to52.connect();
    op6to53.connect();
    feedback0.connect();//feedback
    feedback1.connect();
    feedback2.connect();
    feedback3.connect();
    break;

    case 1:
    currentAlgorithm = 1;
    carriers[0] = true;
    carriers[4] = true;
    carrierCountA = 1;
    carrierCountB = 1;
    opToMainMix10.connect();//1 out
    opToMainMix11.connect();
    opToMainMix12.connect();
    opToMainMix13.connect();
    opToMainMix50.connect();//5 out
    opToMainMix51.connect();
    opToMainMix52.connect();
    opToMainMix53.connect();
    op2to10.connect();//2-->1
    op2to11.connect();
    op2to12.connect();
    op2to13.connect();
    op3to20.connect();//3-->2
    op3to21.connect();
    op3to22.connect();
    op3to23.connect();
    op4to30.connect();//4-->3
    op4to31.connect();
    op4to32.connect();
    op4to33.connect();
    op6to50.connect();//6-->5
    op6to51.connect();
    op6to52.connect();
    op6to53.connect();
    feedback0.connect();//feedback
    feedback1.connect();
    feedback2.connect();
    feedback3.connect();
    break;

    case 2:
    currentAlgorithm = 2;
    carriers[0] = true;
    carriers[3] = true;
    carrierCountA = 2;
    carrierCountB = 0;
    opToMainMix10.connect();//1 out
    opToMainMix11.connect();
    opToMainMix12.connect();
    opToMainMix13.connect();
    opToMainMix40.connect();//4 out
    opToMainMix41.connect();
    opToMainMix42.connect();
    opToMainMix43.connect();
    op2to10.connect();//2-->1
    op2to11.connect();
    op2to12.connect();
    op2to13.connect();
    op3to20.connect();//3-->2
    op3to21.connect();
    op3to22.connect();
    op3to23.connect();
    op5to40.connect();//5-->4
    op5to41.connect();
    op5to42.connect();
    op5to43.connect();
    op6to50.connect();//6-->5
    op6to51.connect();
    op6to52.connect();
    op6to53.connect();
    feedback0.connect();//6-->6
    feedback1.connect();
    feedback2.connect();
    feedback3.connect();
    break;

    case 3:
    currentAlgorithm = 3;
    carriers[0] = true;
    carriers[2] = true;
    carriers[4] = true;
    carrierCountA = 2;
    carrierCountB = 1;
    opToMainMix10.connect();//1 out
    opToMainMix11.connect();
    opToMainMix12.connect();
    opToMainMix13.connect();
    opToMainMix30.connect();//3 out
    opToMainMix31.connect();
    opToMainMix32.connect();
    opToMainMix33.connect();
    opToMainMix50.connect();//5 out
    opToMainMix51.connect();
    opToMainMix52.connect();
    opToMainMix53.connect();
    op2to10.connect();//2-->1
    op2to11.connect();
    op2to12.connect();
    op2to13.connect();
    op4to30.connect();//4-->3
    op4to31.connect();
    op4to32.connect();
    op4to33.connect();
    op6to50.connect();//6-->5
    op6to51.connect();
    op6to52.connect();
    op6to53.connect();
    feedback0.connect();//6-->6
    feedback1.connect();
    feedback2.connect();
    feedback3.connect();
    break;

    case 4:
    currentAlgorithm = 4;
    carriers[0] = true;
    carriers[2] = true;
    carrierCountA = 2;
    carrierCountB = 0;
    opToMainMix10.connect();//1 out
    opToMainMix11.connect();
    opToMainMix12.connect();
    opToMainMix13.connect();
    opToMainMix30.connect();//3 out
    opToMainMix31.connect();
    opToMainMix32.connect();
    opToMainMix33.connect();
    op2to10.connect();//2-->1
    op2to11.connect();
    op2to12.connect();
    op2to13.connect();
    op4to30.connect();//4-->3
    op4to31.connect();
    op4to32.connect();
    op4to33.connect();
    op5to30.connect();//5-->3
    op5to31.connect();
    op5to32.connect();
    op5to33.connect();
    op6to50.connect();//6-->5
    op6to51.connect();
    op6to52.connect();
    op6to53.connect();
    feedback0.connect();//6-->6
    feedback1.connect();
    feedback2.connect();
    feedback3.connect();
    break;

    case 5:
    currentAlgorithm = 5;
    carriers[0] = true;
    carriers[2] = true;
    carrierCountA = 2;
    carrierCountB = 0;
    opToMainMix10.connect();//1 out
    opToMainMix11.connect();
    opToMainMix12.connect();
    opToMainMix13.connect();
    opToMainMix30.connect();//3 out
    opToMainMix31.connect();
    opToMainMix32.connect();
    opToMainMix33.connect();
    op6to30.connect();//6-->3
    op6to31.connect();
    op6to32.connect();
    op6to33.connect();
    feedback0.connect();//6-->6
    feedback1.connect();
    feedback2.connect();
    feedback3.connect();
    op2to10.connect();//2-->1
    op2to11.connect();
    op2to12.connect();
    op2to13.connect();
    op4to10.connect();//4-->1
    op4to11.connect();
    op4to12.connect();
    op4to13.connect();
    op5to40.connect();//5-->4
    op5to41.connect();
    op5to42.connect();
    op5to43.connect();
    break;  

    case 6:
    currentAlgorithm = 6;
    carriers[0] = true;
    carriers[1] = true;
    carrierCountA = 2;
    carrierCountB = 0;
    opToMainMix10.connect();//1 out
    opToMainMix11.connect();
    opToMainMix12.connect();
    opToMainMix13.connect();
    opToMainMix20.connect();//2 out
    opToMainMix21.connect();
    opToMainMix22.connect();
    opToMainMix23.connect();
    op5to20.connect();//5-->2
    op5to21.connect();
    op5to22.connect();
    op5to23.connect();
    op6to50.connect();//6-->5
    op6to51.connect();
    op6to52.connect();
    op6to53.connect();
    feedback0.connect();//6-->6
    feedback1.connect();
    feedback2.connect();
    feedback3.connect();
    op3to10.connect();//3-->1
    op3to11.connect();
    op3to12.connect();
    op3to13.connect();
    op4to10.connect();//4-->1
    op4to11.connect();
    op4to12.connect();
    op4to13.connect();
    break;    

    case 7:
    currentAlgorithm = 7;
    carriers[3] = true;
    carriers[0] = true;
    carrierCountA = 2;
    carrierCountB = 0;
    opToMainMix10.connect();//1 out
    opToMainMix11.connect();
    opToMainMix12.connect();
    opToMainMix13.connect();
    opToMainMix40.connect();//4 out
    opToMainMix41.connect();
    opToMainMix42.connect();
    opToMainMix43.connect();
    feedback0.connect();//6-->6
    feedback1.connect();
    feedback2.connect();
    feedback3.connect();
    op5to40.connect();//5-->4
    op5to41.connect();
    op5to42.connect();
    op5to43.connect();
    op2to10.connect();//2-->1
    op2to11.connect();
    op2to12.connect();
    op2to13.connect();
    op3to20.connect();//3-->2
    op3to21.connect();
    op3to22.connect();
    op3to23.connect();
    break;

    case 8:
    currentAlgorithm = 8;
    carriers[4] = true;
    carriers[0] = true;
    carrierCountA = 1;
    carrierCountB = 1;
    opToMainMix10.connect();//1 out
    opToMainMix11.connect();
    opToMainMix12.connect();
    opToMainMix13.connect();
    opToMainMix50.connect();//5 out
    opToMainMix51.connect();
    opToMainMix52.connect();
    opToMainMix53.connect();
    op6to50.connect();//6-->5
    op6to51.connect();
    op6to52.connect();
    op6to53.connect();
    feedback0.connect();//6-->6
    feedback1.connect();
    feedback2.connect();
    feedback3.connect();
    op2to10.connect();//2-->1
    op2to11.connect();
    op2to12.connect();
    op2to13.connect();
    op3to10.connect();//3-->1
    op3to11.connect();
    op3to12.connect();
    op3to13.connect();
    op4to10.connect();//4-->1
    op4to11.connect();
    op4to12.connect();
    op4to13.connect();
    break;

    case 9:
    currentAlgorithm = 9;
    carriers[0] = true;
    carriers[1] = true;
    carriers[2] = true;
    carriers[3] = true;
    carriers[4] = true;
    carriers[5] = true;
    carrierCountA = 4;
    carrierCountB = 2;
    opToMainMix10.connect();//1 out
    opToMainMix11.connect();
    opToMainMix12.connect();
    opToMainMix13.connect();
    opToMainMix20.connect();//2 out
    opToMainMix21.connect();
    opToMainMix22.connect();
    opToMainMix23.connect();
    opToMainMix30.connect();//3 out
    opToMainMix31.connect();
    opToMainMix32.connect();
    opToMainMix33.connect();
    opToMainMix40.connect();//4 out
    opToMainMix41.connect();
    opToMainMix42.connect();
    opToMainMix43.connect();
    opToMainMix50.connect();//5 out
    opToMainMix51.connect();
    opToMainMix52.connect();
    opToMainMix53.connect();
    opToMainMix60.connect();//6 out
    opToMainMix61.connect();
    opToMainMix62.connect();
    opToMainMix63.connect();
    feedback0.connect();//6-->6
    feedback1.connect();
    feedback2.connect();
    feedback3.connect();
    break;


  }
  setGain();
 }
 

void loop() {
  // put your main code here, to run repeatedly:
  
  usbMIDI.read();
  MIDI.read();
  

}

Thanks for any help :)
 
Hi liv


In you’re setgain, your setting i-1 - is that correct, looks like it should i
Code:
 void setGain(){
  float divA = 1/(carrierCountA);
  
  for(int i = 0; i < 4; i ++){
    if(carriers[i]){
      mainMixer[0].gain(i-1,divA);
      mainMixer[1].gain(i-1,divA);
      mainMixer[2].gain(i-1,divA);
      mainMixer[3].gain(i-1,divA);
    }
  }
  if(carrierCountB != 0){
    float divB = 1/(carrierCountB);
    for(int i = 4; i < 6; i ++){
      if(carriers[i]){
        mainMixer2[0].gain(i-1,divB);
        mainMixer2[1].gain(i-1,divB);
        mainMixer2[2].gain(i-1,divB);
        mainMixer2[3].gain(i-1,divB);
      }
    }
  }
}

Also, I find it useful to add in the analysePeak object at various points in the audio design (after mixers, on key inputs etc.) then set a function in your loop to print out the peak levels at a periodic intervals (every second or so) - that makes it easier to home in on where your gain staging is going wrong.

Cheers,Paul
 
In you’re setgain, your setting i-1 - is that correct, looks like it should i
Code:
 void setGain(){
  float divA = 1/(carrierCountA);
  
  for(int i = 0; i < 4; i ++){
    if(carriers[i]){
      mainMixer[0].gain(i-1,divA);
      mainMixer[1].gain(i-1,divA);
      mainMixer[2].gain(i-1,divA);
      mainMixer[3].gain(i-1,divA);
    }
  }
  if(carrierCountB != 0){
    float divB = 1/(carrierCountB);
    for(int [B][COLOR="#FF0000"]i = 4; i < 6; i ++[/COLOR][/B]){
      if(carriers[i]){
        [B][COLOR="#FF0000"]mainMixer2[/COLOR][/B][0].gain([B][COLOR="#FF0000"]i-1[/COLOR][/B],divB);
        mainMixer2[1].gain(i-1,divB);
        mainMixer2[2].gain(i-1,divB);
        mainMixer2[3].gain(i-1,divB);
      }
    }
  }
}
Even worse for mainMixer2 ... looks like you changed the design at some point and copy/pasta has left you only changing the gain of channel 0 (channel number is unsigned, and values >3 are ignored)
 
Even worse for mainMixer2 ... looks like you changed the design at some point and copy/pasta has left you only changing the gain of channel 0 (channel number is unsigned, and values >3 are ignored)

OH wow this is such a silly mistake. I'm going to fix some of these problems and see how it sounds. Thanks everyone for the help :eek:
 
So, it seems to be a problem with operator 3 specifically, the other algorithms that include carriers =/= 3 all work fine without any weird buzzy clippiness. So I will get to work looking for the culprit. Thanks again everyone!
 
Back
Top