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

Thread: Polyphonic FM Synthesizer Clipping when >2 Voices

  1. #1

    Polyphonic FM Synthesizer Clipping when >2 Voices

    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). Click image for larger version. 

Name:	voice.png 
Views:	26 
Size:	61.1 KB 
ID:	30249 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

  2. #2
    Senior Member houtson's Avatar
    Join Date
    Aug 2015
    Location
    Scotland
    Posts
    249
    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

  3. #3
    Senior Member h4yn0nnym0u5e's Avatar
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    632
    Quote Originally Posted by houtson View Post
    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);
          }
        }
      }
    }
    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)

  4. #4
    Quote Originally Posted by h4yn0nnym0u5e View Post
    copy/pasta has left you only changing the gain of channel 0
    When your software is al dente.

  5. #5
    Senior Member h4yn0nnym0u5e's Avatar
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    632
    Quote Originally Posted by joepasquariello View Post
    When your software is al dente.
    It's a thing, apparently ... a fellow developer at work used the phrase to me, and it stuck: see https://en.wikipedia.org/wiki/Copypasta. Used here in the sense of "this code is just like the previous, so I'll make a copy and change just the relevant parts. Well, most of the relevant parts. Leaving an obscure bug..."

  6. #6
    Quote Originally Posted by h4yn0nnym0u5e View Post
    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

  7. #7
    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!

Posting Permissions

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