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).
Here, also is the entirety of my code:
Thanks for any help
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