Issue changing to band limited waveforms

savt22

Member
Hi, I'm having a bit of a puzzling issue...

I'm having trouble creating a variable to switch between waveforms across all voices.

I'm working on an 8 voice polyphonic synth using the Teensy 4.0 with the audio board.

It works completely fine with any waveforms except the band limited waveforms... when I use the band limited waveforms, it almost sounds as though the oscillators are out of phase and distorted, and then after around 1 minute of use, the teensy 'crashes' - it produces a loud single pitch beep through the headphone out, then seems to reset.

If I avoid using band limited waveforms, the issue completely goes away. And if I simply manually set all oscillator waveforms within the case, rather than looping through a variable (i.e., waveformMod1.begin(WAVEFORM_BANDLIMIT_SAWTOOTH), I also don't have the issue.

I've snipped out a bit of code to show the gist of what I'm doing.

short osc1wave = WAVEFORM_SINE;
short osc2wave = WAVEFORM_SINE;

void loop() {

//osc1wave
waveformMod1.begin(osc1wave);
waveformMod3.begin(osc1wave);
waveformMod5.begin(osc1wave);
waveformMod7.begin(osc1wave);
waveformMod16.begin(osc1wave);
waveformMod9.begin(osc1wave);
waveformMod13.begin(osc1wave);
waveformMod12.begin(osc1wave);
//osc2wave
waveformMod2.begin(osc2wave);
waveformMod4.begin(osc2wave);
waveformMod6.begin(osc2wave);
waveformMod8.begin(osc2wave);
waveformMod15.begin(osc2wave);
waveformMod10.begin(osc2wave);
waveformMod14.begin(osc2wave);
waveformMod11.begin(osc2wave);
}

void myControlChange(byte channel, byte control, byte value) {
switch (control) {
//Switch between preset sounds based on a knob value range.
case 106:
switch (value) {
case 0 ... 31:
osc1wave = WAVEFORM_SINE;
osc2wave = WAVEFORM_SINE;
break;
case 32 ... 64:
osc1wave = WAVEFORM_BANDLIMIT_SAWTOOTH;
osc2wave = WAVEFORM_BANDLIMIT_SAWTOOTH;
break;
}
}
 
Helping to troubleshoot will be much more possible & predictable if you post your entire sketch. The snippet that you have posted leaves out too many details (e.g. how much audio memory did you allocate ??).

Mark J Culross
KD5RXT
 
Thanks - here is the full code. I'm absolutely not a code person, this is all quite new to me.

I just set out to create a small, 6 knob synth with some preset sounds I like, and knobs to get some variety, where in the future I can change around what the knobs do/different sounds. So there's things in there (like the filter envelopes) that I haven't used here but will use in a future version. At some point I want to change it from usb midi to hardware midi with the 6 knobs being pots rather than midi CC.

I did wonder about a memory issue - I ran into that problem when I first changed from mono to poly. How do I check max memory usage? I will have a search on here.

I did try arbitrarily increasing the memory. AudioMemory(80) works without issue if all instances of WAVEFORM_BANDLIMIT_SAWTOOTH are changed to WAVEFORM_SAWTOOTH, and the issue with WAVEFORM_BANDLIMIT_SAWTOOTH persists if I increase to 1000: AudioMemory(1000).

C++:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioAmplifier           amp18; //xy=167.5,1837.5
AudioAmplifier           amp19; //xy=167.5,2202.5
AudioAmplifier           amp20; //xy=178.5,2854.5
AudioAmplifier           amp1;           //xy=207.5000171661377,351.5000123977661
AudioAmplifier           amp8;           //xy=207.5000171661377,716.5000123977661
AudioAmplifier           amp21; //xy=200.5,2500.5
AudioAmplifier           amp12;          //xy=218.5000171661377,1368.500012397766
AudioAmplifier           amp9;           //xy=240.5000171661377,1014.5000123977661
AudioSynthWaveform       waveform5; //xy=247.5,2692.5
AudioSynthWaveform       waveform6; //xy=255.5,2349.5
AudioSynthWaveform       waveform7; //xy=263.5,2028.5
AudioSynthWaveform       waveform8; //xy=277.5,1554.5
AudioSynthWaveform       waveform4;      //xy=287.5000171661377,1206.500012397766
AudioSynthWaveform       waveform3;      //xy=295.5000171661377,863.5000123977661
AudioSynthWaveform       waveform2;      //xy=303.5000171661377,542.5000123977661
AudioSynthWaveform       waveform1;      //xy=317.5000171661377,68.50001239776611
AudioSynthWaveformModulated waveformMod9; //xy=365.5,2165.5
AudioSynthWaveformModulated waveformMod10; //xy=365.5,2203.5
AudioSynthWaveformModulated waveformMod11; //xy=363.5,2884.5
AudioSynthWaveformModulated waveformMod12; //xy=364.5,2839.5
AudioSynthWaveformModulated waveformMod13; //xy=369.5,2484.5
AudioSynthWaveformModulated waveformMod14; //xy=370.5,2523.5
AudioSynthWaveformModulated waveformMod15; //xy=375.5,1866.5
AudioSynthWaveformModulated waveformMod16; //xy=376.5,1817.5
AudioSynthKarplusStrong  string5; //xy=389.5,2239.5
AudioSynthNoisePink      pink5; //xy=392.5,2128.5
AudioEffectEnvelope      envelope13; //xy=390.5,2693.5
AudioSynthKarplusStrong  string6; //xy=390.5,2933.5
AudioSynthNoisePink      pink6; //xy=393.5,2789.5
AudioSynthKarplusStrong  string7; //xy=395.5,2563.5
AudioSynthKarplusStrong  string8; //xy=399.5,1916.5
AudioSynthWaveformModulated waveformMod3;   //xy=405.5000171661377,679.5000123977661
AudioSynthNoisePink      pink7; //xy=398.5,2442.5
AudioSynthWaveformModulated waveformMod4;   //xy=405.5000171661377,717.5000123977661
AudioEffectEnvelope      envelope14; //xy=399.5,2349.5
AudioSynthWaveformModulated waveformMod8;   //xy=403.5000171661377,1398.500012397766
AudioSynthWaveformModulated waveformMod7;   //xy=404.5000171661377,1353.500012397766
AudioSynthNoisePink      pink8; //xy=403.5,1776.5
AudioSynthWaveformModulated waveformMod5;   //xy=409.5000171661377,998.5000123977661
AudioSynthWaveformModulated waveformMod6;   //xy=410.5000171661377,1037.500012397766
AudioEffectEnvelope      envelope15; //xy=407.5,2028.5
AudioSynthWaveformModulated waveformMod2;   //xy=415.5000171661377,380.5000123977661
AudioSynthWaveformModulated waveformMod1;   //xy=416.5000171661377,331.5000123977661
AudioEffectEnvelope      envelope16; //xy=422.5,1554.5
AudioSynthKarplusStrong  string2;        //xy=429.5000171661377,753.5000123977661
AudioSynthNoisePink      pink2;          //xy=432.5000171661377,642.5000123977661
AudioEffectEnvelope      envelope10;     //xy=430.5000171661377,1207.500012397766
AudioSynthKarplusStrong  string4;        //xy=430.5000171661377,1447.500012397766
AudioSynthNoisePink      pink4;          //xy=433.5000171661377,1303.500012397766
AudioSynthKarplusStrong  string3;        //xy=435.5000171661377,1077.500012397766
AudioSynthKarplusStrong  string1;        //xy=439.5000171661377,430.5000123977661
AudioSynthNoisePink      pink3;          //xy=438.5000171661377,956.5000123977661
AudioEffectEnvelope      envelope5;      //xy=439.5000171661377,863.5000123977661
AudioSynthNoisePink      pink1;          //xy=443.5000171661377,290.5000123977661
AudioEffectEnvelope      envelope4;      //xy=447.5000171661377,542.5000123977661
AudioEffectEnvelope      envelope1;      //xy=462.5000171661377,68.50001239776611
AudioMixer4              mixer16; //xy=555.5,2850.5
AudioMixer4              mixer17; //xy=565.5,1813.5
AudioMixer4              mixer18; //xy=564.5,2210.5
AudioMixer4              mixer19; //xy=565.5,2572.5
AudioMixer4              mixer13;        //xy=595.5000171661377,1364.500012397766
AudioMixer4              mixer1;         //xy=605.5000171661377,327.5000123977661
AudioMixer4              mixer8;         //xy=604.5000171661377,724.5000123977661
AudioMixer4              mixer9;         //xy=605.5000171661377,1086.500012397766
AudioSynthWaveformDc     dc5; //xy=682.5,1553.5
AudioAmplifier           amp22; //xy=687.5,2852.5
AudioAmplifier           amp23; //xy=695.5,1809.5
AudioAmplifier           amp24; //xy=698.5,2573.5
AudioAmplifier           amp25; //xy=700.5,2212.5
AudioSynthWaveformDc     dc6; //xy=700.5,2348.5
AudioSynthWaveformDc     dc7; //xy=703.5,2024.5
AudioSynthWaveformDc     dc8; //xy=705.5,2695.5
AudioSynthWaveformDc     dc1;            //xy=722.5000171661377,67.50001239776611
AudioAmplifier           amp13;          //xy=727.5000171661377,1366.500012397766
AudioAmplifier           amp3;           //xy=735.5000171661377,323.5000123977661
AudioAmplifier           amp11;          //xy=738.5000171661377,1087.500012397766
AudioAmplifier           amp10;          //xy=740.5000171661377,726.5000123977661
AudioSynthWaveformDc     dc3;            //xy=740.5000171661377,862.5000123977661
AudioSynthWaveformDc     dc2;            //xy=743.5000171661377,538.5000123977661
AudioSynthWaveformDc     dc4;            //xy=745.5000171661377,1209.500012397766
AudioAmplifier           amp26; //xy=743.5,1742.5
AudioAmplifier           amp27; //xy=770.5,2160.5
AudioAmplifier           amp2;           //xy=783.5000171661377,256.5000123977661
AudioAmplifier           amp28; //xy=777.5,2472.5
AudioAmplifier           amp6;           //xy=810.5000171661377,674.5000123977661
AudioAmplifier           amp29; //xy=805.5,2814.5
AudioAmplifier           amp7;           //xy=817.5000171661377,986.5000123977661
AudioEffectEnvelope      envelope17; //xy=818.5,1553.5
AudioMixer4              mixer20; //xy=819.5,1674.5
AudioFilterStateVariable filter5; //xy=829.5,1812.5
AudioEffectEnvelope      envelope18; //xy=839.5,2025.5
AudioEffectEnvelope      envelope19; //xy=838.5,2347.5
AudioAmplifier           amp14;          //xy=845.5000171661377,1328.500012397766
AudioEffectEnvelope      envelope20; //xy=845.5,2695.5
AudioMixer4              mixer21; //xy=848.5,2098.5
AudioMixer4              mixer22; //xy=848.5,2414.5
AudioEffectEnvelope      envelope2;      //xy=858.5000171661377,67.50001239776611
AudioFilterStateVariable filter6; //xy=848.5,2872.5
AudioMixer4              mixer2;         //xy=859.5000171661377,188.5000123977661
AudioFilterStateVariable filter7; //xy=858.5,2560.5
AudioFilterStateVariable filter1;        //xy=869.5000171661377,326.5000123977661
AudioFilterStateVariable filter8; //xy=862.5,2212.5
AudioMixer4              mixer23; //xy=868.5,2760.5
AudioEffectEnvelope      envelope6;      //xy=879.5000171661377,539.5000123977661
AudioEffectEnvelope      envelope7;      //xy=878.5000171661377,861.5000123977661
AudioEffectEnvelope      envelope11;     //xy=885.5000171661377,1209.500012397766
AudioMixer4              mixer6;         //xy=888.5000171661377,612.5000123977661
AudioMixer4              mixer7;         //xy=888.5000171661377,928.5000123977661
AudioFilterStateVariable filter4;        //xy=888.5000171661377,1386.500012397766
AudioFilterStateVariable filter3;        //xy=898.5000171661377,1074.500012397766
AudioFilterStateVariable filter2;        //xy=902.5000171661377,726.5000123977661
AudioMixer4              mixer14;        //xy=908.5000171661377,1274.500012397766
AudioMixer4              mixer24; //xy=992.5,1812.5
AudioMixer4              mixer25; //xy=1007.5,2209.5
AudioMixer4              mixer26; //xy=1009.5,2557.5
AudioMixer4              mixer27; //xy=1009.5,2874.5
AudioMixer4              mixer3;         //xy=1032.5000171661377,326.5000123977661
AudioMixer4              mixer10;        //xy=1047.5000171661377,723.5000123977661
AudioMixer4              mixer11;        //xy=1049.5000171661377,1071.500012397766
AudioMixer4              mixer15;        //xy=1049.5000171661377,1388.500012397766
AudioEffectEnvelope      envelope21; //xy=1134.5,1812.5
AudioEffectEnvelope      envelope22; //xy=1137.5,2209.5
AudioEffectEnvelope      envelope23; //xy=1155.5,2872.5
AudioEffectEnvelope      envelope24; //xy=1163.5,2559.5
AudioEffectEnvelope      envelope3;      //xy=1174.5000171661377,326.5000123977661
AudioEffectEnvelope      envelope8;      //xy=1177.5000171661377,723.5000123977661
AudioEffectEnvelope      envelope12;     //xy=1195.5000171661377,1386.500012397766
AudioEffectEnvelope      envelope9;      //xy=1203.5000171661377,1073.500012397766
AudioMixer4              mixer28; //xy=1430,2045
AudioMixer4              mixer12;        //xy=1437.5000190734863,530.0000057220459
AudioAmplifier           amp17;          //xy=1814.5000190734863,299.00001859664917
AudioEffectFreeverbStereo freeverbs1;     //xy=1866.5000190734863,242.00001859664917
AudioMixer4              mixer100;        //xy=1916,1104.28564453125
AudioFilterLadder        ladder1;        //xy=2000.5000190734863,196.00001859664917
AudioFilterLadder        ladder2;        //xy=2004.5000190734863,308.00001859664917
AudioAmplifier           amp16;          //xy=2172.5000190734863,436.00001859664917
AudioAmplifier           amp15;          //xy=2174.5000190734863,394.00001859664917
AudioMixer4              mixer4;         //xy=2385.5000190734863,344.00001859664917
AudioMixer4              mixer5;         //xy=2387.5000190734863,415.00001859664917
AudioAmplifier           amp4;           //xy=2517.5000190734863,337.00001859664917
AudioAmplifier           amp5;           //xy=2518.5000190734863,419.00001859664917
AudioOutputI2S           i2s1;           //xy=2645.5000190734863,386.00001859664917
AudioConnection          patchCord1(amp18, 0, waveformMod16, 0);
AudioConnection          patchCord2(amp18, 0, waveformMod15, 0);
AudioConnection          patchCord3(amp19, 0, waveformMod9, 0);
AudioConnection          patchCord4(amp19, 0, waveformMod10, 0);
AudioConnection          patchCord5(amp20, 0, waveformMod12, 0);
AudioConnection          patchCord6(amp20, 0, waveformMod11, 0);
AudioConnection          patchCord7(amp1, 0, waveformMod1, 0);
AudioConnection          patchCord8(amp1, 0, waveformMod2, 0);
AudioConnection          patchCord9(amp8, 0, waveformMod3, 0);
AudioConnection          patchCord10(amp8, 0, waveformMod4, 0);
AudioConnection          patchCord11(amp21, 0, waveformMod13, 0);
AudioConnection          patchCord12(amp21, 0, waveformMod14, 0);
AudioConnection          patchCord13(amp12, 0, waveformMod7, 0);
AudioConnection          patchCord14(amp12, 0, waveformMod8, 0);
AudioConnection          patchCord15(amp9, 0, waveformMod5, 0);
AudioConnection          patchCord16(amp9, 0, waveformMod6, 0);
AudioConnection          patchCord17(waveform5, envelope13);
AudioConnection          patchCord18(waveform6, envelope14);
AudioConnection          patchCord19(waveform7, envelope15);
AudioConnection          patchCord20(waveform8, envelope16);
AudioConnection          patchCord21(waveform4, envelope10);
AudioConnection          patchCord22(waveform3, envelope5);
AudioConnection          patchCord23(waveform2, envelope4);
AudioConnection          patchCord24(waveform1, envelope1);
AudioConnection          patchCord25(waveformMod9, 0, mixer18, 1);
AudioConnection          patchCord26(waveformMod10, 0, mixer18, 2);
AudioConnection          patchCord27(waveformMod11, 0, mixer16, 2);
AudioConnection          patchCord28(waveformMod12, 0, mixer16, 1);
AudioConnection          patchCord29(waveformMod13, 0, mixer19, 1);
AudioConnection          patchCord30(waveformMod14, 0, mixer19, 2);
AudioConnection          patchCord31(waveformMod15, 0, mixer17, 2);
AudioConnection          patchCord32(waveformMod16, 0, mixer17, 1);
AudioConnection          patchCord33(string5, 0, mixer18, 3);
AudioConnection          patchCord34(pink5, 0, mixer18, 0);
AudioConnection          patchCord35(envelope13, amp20);
AudioConnection          patchCord36(envelope13, 0, mixer23, 1);
AudioConnection          patchCord37(string6, 0, mixer16, 3);
AudioConnection          patchCord38(pink6, 0, mixer16, 0);
AudioConnection          patchCord39(string7, 0, mixer19, 3);
AudioConnection          patchCord40(string8, 0, mixer17, 3);
AudioConnection          patchCord41(waveformMod3, 0, mixer8, 1);
AudioConnection          patchCord42(pink7, 0, mixer19, 0);
AudioConnection          patchCord43(waveformMod4, 0, mixer8, 2);
AudioConnection          patchCord44(envelope14, 0, mixer22, 1);
AudioConnection          patchCord45(envelope14, amp21);
AudioConnection          patchCord46(waveformMod8, 0, mixer13, 2);
AudioConnection          patchCord47(waveformMod7, 0, mixer13, 1);
AudioConnection          patchCord48(pink8, 0, mixer17, 0);
AudioConnection          patchCord49(waveformMod5, 0, mixer9, 1);
AudioConnection          patchCord50(waveformMod6, 0, mixer9, 2);
AudioConnection          patchCord51(envelope15, 0, mixer21, 1);
AudioConnection          patchCord52(envelope15, amp19);
AudioConnection          patchCord53(waveformMod2, 0, mixer1, 2);
AudioConnection          patchCord54(waveformMod1, 0, mixer1, 1);
AudioConnection          patchCord55(envelope16, amp18);
AudioConnection          patchCord56(envelope16, 0, mixer20, 1);
AudioConnection          patchCord57(string2, 0, mixer8, 3);
AudioConnection          patchCord58(pink2, 0, mixer8, 0);
AudioConnection          patchCord59(envelope10, amp12);
AudioConnection          patchCord60(envelope10, 0, mixer14, 1);
AudioConnection          patchCord61(string4, 0, mixer13, 3);
AudioConnection          patchCord62(pink4, 0, mixer13, 0);
AudioConnection          patchCord63(string3, 0, mixer9, 3);
AudioConnection          patchCord64(string1, 0, mixer1, 3);
AudioConnection          patchCord65(pink3, 0, mixer9, 0);
AudioConnection          patchCord66(envelope5, 0, mixer7, 1);
AudioConnection          patchCord67(envelope5, amp9);
AudioConnection          patchCord68(pink1, 0, mixer1, 0);
AudioConnection          patchCord69(envelope4, 0, mixer6, 1);
AudioConnection          patchCord70(envelope4, amp8);
AudioConnection          patchCord71(envelope1, amp1);
AudioConnection          patchCord72(envelope1, 0, mixer2, 1);
AudioConnection          patchCord73(mixer16, amp22);
AudioConnection          patchCord74(mixer17, amp23);
AudioConnection          patchCord75(mixer18, amp25);
AudioConnection          patchCord76(mixer19, amp24);
AudioConnection          patchCord77(mixer13, amp13);
AudioConnection          patchCord78(mixer1, amp3);
AudioConnection          patchCord79(mixer8, amp10);
AudioConnection          patchCord80(mixer9, amp11);
AudioConnection          patchCord81(dc5, envelope17);
AudioConnection          patchCord82(amp22, 0, filter6, 0);
AudioConnection          patchCord83(amp23, 0, filter5, 0);
AudioConnection          patchCord84(amp24, 0, filter7, 0);
AudioConnection          patchCord85(amp25, 0, filter8, 0);
AudioConnection          patchCord86(dc6, envelope19);
AudioConnection          patchCord87(dc7, envelope18);
AudioConnection          patchCord88(dc8, envelope20);
AudioConnection          patchCord89(dc1, envelope2);
AudioConnection          patchCord90(amp13, 0, filter4, 0);
AudioConnection          patchCord91(amp3, 0, filter1, 0);
AudioConnection          patchCord92(amp11, 0, filter3, 0);
AudioConnection          patchCord93(amp10, 0, filter2, 0);
AudioConnection          patchCord94(dc3, envelope7);
AudioConnection          patchCord95(dc2, envelope6);
AudioConnection          patchCord96(dc4, envelope11);
AudioConnection          patchCord97(amp26, 0, filter5, 1);
AudioConnection          patchCord98(amp27, 0, filter8, 1);
AudioConnection          patchCord99(amp2, 0, filter1, 1);
AudioConnection          patchCord100(amp28, 0, filter7, 1);
AudioConnection          patchCord101(amp6, 0, filter2, 1);
AudioConnection          patchCord102(amp29, 0, filter6, 1);
AudioConnection          patchCord103(amp7, 0, filter3, 1);
AudioConnection          patchCord104(envelope17, 0, mixer20, 0);
AudioConnection          patchCord105(mixer20, amp26);
AudioConnection          patchCord106(filter5, 0, mixer24, 0);
AudioConnection          patchCord107(filter5, 2, mixer24, 1);
AudioConnection          patchCord108(envelope18, 0, mixer21, 0);
AudioConnection          patchCord109(envelope19, 0, mixer22, 0);
AudioConnection          patchCord110(amp14, 0, filter4, 1);
AudioConnection          patchCord111(envelope20, 0, mixer23, 0);
AudioConnection          patchCord112(mixer21, amp27);
AudioConnection          patchCord113(mixer22, amp28);
AudioConnection          patchCord114(envelope2, 0, mixer2, 0);
AudioConnection          patchCord115(filter6, 0, mixer27, 0);
AudioConnection          patchCord116(filter6, 2, mixer27, 1);
AudioConnection          patchCord117(mixer2, amp2);
AudioConnection          patchCord118(filter7, 0, mixer26, 0);
AudioConnection          patchCord119(filter7, 2, mixer26, 1);
AudioConnection          patchCord120(filter1, 0, mixer3, 0);
AudioConnection          patchCord121(filter1, 2, mixer3, 1);
AudioConnection          patchCord122(filter8, 0, mixer25, 0);
AudioConnection          patchCord123(filter8, 2, mixer25, 1);
AudioConnection          patchCord124(mixer23, amp29);
AudioConnection          patchCord125(envelope6, 0, mixer6, 0);
AudioConnection          patchCord126(envelope7, 0, mixer7, 0);
AudioConnection          patchCord127(envelope11, 0, mixer14, 0);
AudioConnection          patchCord128(mixer6, amp6);
AudioConnection          patchCord129(mixer7, amp7);
AudioConnection          patchCord130(filter4, 0, mixer15, 0);
AudioConnection          patchCord131(filter4, 2, mixer15, 1);
AudioConnection          patchCord132(filter3, 0, mixer11, 0);
AudioConnection          patchCord133(filter3, 2, mixer11, 1);
AudioConnection          patchCord134(filter2, 0, mixer10, 0);
AudioConnection          patchCord135(filter2, 2, mixer10, 1);
AudioConnection          patchCord136(mixer14, amp14);
AudioConnection          patchCord137(mixer24, envelope21);
AudioConnection          patchCord138(mixer25, envelope22);
AudioConnection          patchCord139(mixer26, envelope24);
AudioConnection          patchCord140(mixer27, envelope23);
AudioConnection          patchCord141(mixer3, envelope3);
AudioConnection          patchCord142(mixer10, envelope8);
AudioConnection          patchCord143(mixer11, envelope9);
AudioConnection          patchCord144(mixer15, envelope12);
AudioConnection          patchCord145(envelope21, 0, mixer28, 0);
AudioConnection          patchCord146(envelope22, 0, mixer28, 1);
AudioConnection          patchCord147(envelope23, 0, mixer28, 3);
AudioConnection          patchCord148(envelope24, 0, mixer28, 2);
AudioConnection          patchCord149(envelope3, 0, mixer12, 0);
AudioConnection          patchCord150(envelope8, 0, mixer12, 1);
AudioConnection          patchCord151(envelope12, 0, mixer12, 3);
AudioConnection          patchCord152(envelope9, 0, mixer12, 2);
AudioConnection          patchCord153(mixer28, 0, mixer100, 1);
AudioConnection          patchCord154(mixer12, 0, mixer100, 0);
AudioConnection          patchCord155(amp17, freeverbs1);
AudioConnection          patchCord156(freeverbs1, 0, ladder1, 0);
AudioConnection          patchCord157(freeverbs1, 1, ladder2, 0);
AudioConnection          patchCord158(mixer100, amp17);
AudioConnection          patchCord159(mixer100, amp15);
AudioConnection          patchCord160(mixer100, amp16);
AudioConnection          patchCord161(ladder1, 0, mixer4, 0);
AudioConnection          patchCord162(ladder2, 0, mixer5, 0);
AudioConnection          patchCord163(amp16, 0, mixer5, 1);
AudioConnection          patchCord164(amp15, 0, mixer4, 1);
AudioConnection          patchCord165(mixer4, amp4);
AudioConnection          patchCord166(mixer5, amp5);
AudioConnection          patchCord167(amp4, 0, i2s1, 0);
AudioConnection          patchCord168(amp5, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=2655.833354949951,460.66670083999634
// GUItool: end automatically generated code

// to view the mapping on the PJRC Audio System Design Tool, copy and paste all code above this point into the "import" option.

// The file synth_karplusstrong.h in the audio library needs to be edited, with all 536 values changed to 1349 to allow karplus strong notes down to A0.

// The approach to polyphony was adapted from Mark J Culross's (KD5RXT) TeensyMIDIPolySynth, details of which are available here: https://forum.pjrc.com/index.php?threads/posted-teensymidipolysynth.60690/
#define MAX_POLY 8
#define LIMIT_POLY 8

// keep track of the maximum number of simultaneous notes active at any given time
int maximum_notes = 0;

// values from the "note on" messages
struct POLY_SPEC
{
   int channel;                    // MIDI channel
   int base_pitch;                 // pitch (before any octave shift)
   bool note_state;                // whether the note has been turned on or turned off
   unsigned long note_off_millis;  // the time when the note off began (to allow envelope to complete before deallocating this note)
};

// array to keep track of notes playing
POLY_SPEC poly_notes[MAX_POLY];

// the midi and note frequency allocation is adapted from the Notes and Volts Teensy Synth, who provide an excellent range of tutorials: https://www.youtube.com/watch?v=UJcZxyB5rVc&list=PL4_gPbvyebyHi4VRZEOG9RKOYq5Hre3a1

const float noteFreqs[128] = {8.176, 8.662, 9.177, 9.723, 10.301, 10.913, 11.562, 12.25, 12.978, 13.75, 14.568, 15.434, 16.352, 17.324, 18.354, 19.445, 20.602, 21.827, 23.125, 24.5, 25.957, 27.5, 29.135, 30.868, 32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55, 58.27, 61.735, 65.406, 69.296, 73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110, 116.541, 123.471, 130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220, 233.082, 246.942, 261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440, 466.164, 493.883, 523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880, 932.328, 987.767, 1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982, 1661.219, 1760, 1864.655, 1975.533, 2093.005, 2217.461, 2349.318, 2489.016, 2637.02, 2793.826, 2959.955, 3135.963, 3322.438, 3520, 3729.31, 3951.066, 4186.009, 4434.922, 4698.636, 4978.032, 5274.041, 5587.652, 5919.911, 6271.927, 6644.875, 7040, 7458.62, 7902.133, 8372.018, 8869.844, 9397.273, 9956.063, 10548.08, 11175.3, 11839.82, 12543.85};
int octave = -12;
const float DIV127 = (1.0 / 127.0);
float detuneFactor = 1;

// set-up variables, values the same as the first voice
//osc
short osc1wave = WAVEFORM_SINE;
short osc2wave = WAVEFORM_SINE;
short lfowave = WAVEFORM_SINE;
float pinknoisevol = 0;
float osc1vol = (20.0 * DIV127);
float osc2vol = (20.0 * DIV127);
float karplusvol = (20.0 * DIV127);
//lfo filter amplitude
float lfofilter = (20.0 * DIV127);
//lfo fm level
float lfofm = (0.1 * (2 * DIV127));
//lfo speed
float lfospeed = ((7 + 1) * ((7 + 1) * DIV127));
//lfo adsr
float lfoattack = (3000 * (0 * DIV127));
float lfodecay = (3000 * (127 * DIV127));
float lfosustain = (127 * DIV127);
float lforelease = (3000 * (0 * DIV127));
//adsr
float vcaattack = (3000 * (0 * DIV127));
float vcadecay = (3000 * (30 * DIV127));
float vcasustain = (127 * DIV127);
float vcarelease = (3000 * (38 * DIV127));
//filter
float filterfreq = ((10000 * (34 * DIV127)) + 100);
float filterres = ((4.3 * (0 * DIV127)) + 1.1);
//filter mix
float lowpassvol = ((0.8 * 127 * DIV127) - (0.8 * 98 * DIV127));
float highpassvol = (0.8 * 98 * DIV127);


void setup() {

  // Initial hardware and midi setup
  AudioMemory(80);
  usbMIDI.setHandleControlChange(myControlChange);
  usbMIDI.setHandleNoteOff(myNoteOff);
  usbMIDI.setHandleNoteOn(myNoteOn);
 
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.6);
  sgtl5000_1.audioPostProcessorEnable();
  sgtl5000_1.surroundSoundEnable();
  sgtl5000_1.surroundSound(7);
 
  //Start LFO waves

  waveform1.amplitude(0.75);
  waveform1.frequency(1.00);
  waveform1.pulseWidth(0.15);

  waveform2.amplitude(0.75);
  waveform2.frequency(1.00);
  waveform2.pulseWidth(0.15);

  waveform3.amplitude(0.75);
  waveform3.frequency(1.00);
  waveform3.pulseWidth(0.15);
 
  waveform4.amplitude(0.75);
  waveform4.frequency(1.00);
  waveform4.pulseWidth(0.15);

  waveform5.amplitude(0.75);
  waveform5.frequency(1.00);
  waveform5.pulseWidth(0.15);

  waveform6.amplitude(0.75);
  waveform6.frequency(1.00);
  waveform6.pulseWidth(0.15);

  waveform7.amplitude(0.75);
  waveform7.frequency(1.00);
  waveform7.pulseWidth(0.15);

  waveform8.amplitude(0.75);
  waveform8.frequency(1.00);
  waveform8.pulseWidth(0.15);
 

  //Start voice oscillators

  waveformMod1.amplitude(0.75);
  waveformMod1.frequency(123);

  waveformMod2.amplitude(0.75);
  waveformMod2.frequency(123);
 
  waveformMod3.amplitude(0.75);
  waveformMod3.frequency(123);

  waveformMod4.amplitude(0.75);
  waveformMod4.frequency(123);

  waveformMod5.amplitude(0.75);
  waveformMod5.frequency(123);

  waveformMod6.amplitude(0.75);
  waveformMod6.frequency(123);

  waveformMod7.amplitude(0.75);
  waveformMod7.frequency(123);

  waveformMod8.amplitude(0.75);
  waveformMod8.frequency(123);

  waveformMod16.amplitude(0.75);
  waveformMod16.frequency(123);

  waveformMod15.amplitude(0.75);
  waveformMod15.frequency(123);

  waveformMod9.amplitude(0.75);
  waveformMod9.frequency(123);

  waveformMod10.amplitude(0.75);
  waveformMod10.frequency(123);

  waveformMod13.amplitude(0.75);
  waveformMod13.frequency(123);

  waveformMod14.amplitude(0.75);
  waveformMod14.frequency(123);

  waveformMod12.amplitude(0.75);
  waveformMod12.frequency(123);

  waveformMod11.amplitude(0.75);
  waveformMod11.frequency(123);

  pink1.amplitude(0.75);
  pink2.amplitude(0.75);
  pink3.amplitude(0.75);
  pink4.amplitude(0.75);
  pink5.amplitude(0.75);
  pink6.amplitude(0.75);
  pink7.amplitude(0.75);
  pink8.amplitude(0.75);

  //Filter envelope isn't used here, so this switches off the filter envelope - change value to 1.0 if you intend to use the filter envelopes.
  dc1.amplitude(0.0);
  dc2.amplitude(0.0);
  dc3.amplitude(0.0);
  dc4.amplitude(0.0);
  dc5.amplitude(0.0);
  dc6.amplitude(0.0);
  dc7.amplitude(0.0);
  dc8.amplitude(0.0);

  //Filter envelope level
  amp2.gain(1.0);
  amp6.gain(1.0);
  amp7.gain(1.0);
  amp14.gain(1.0);
  amp26.gain(1.0);
  amp27.gain(1.0);
  amp28.gain(1.0);
  amp29.gain(1.0);

  //These mix combine the filter envelope signal and the LFO. Leave as is if using the filter envelope.
  mixer2.gain(0, 2);
  mixer6.gain(0, 2);
  mixer7.gain(0, 2);
  mixer14.gain(0, 2);
  mixer20.gain(0, 2);
  mixer21.gain(0, 2);
  mixer22.gain(0, 2);
  mixer23.gain(0, 2);

  //Attenuate the voice mixer outputs before the filter
  amp3.gain(0.5);
  amp10.gain(0.5);
  amp11.gain(0.5);
  amp13.gain(0.5);
  amp23.gain(0.5);
  amp25.gain(0.5);
  amp24.gain(0.5);
  amp22.gain(0.5);

  //filter octave controls - sets the extent of the effect of the envelope and LFO on opening the filter. 7 is max.
  filter1.octaveControl(7);
  filter2.octaveControl(7);
  filter3.octaveControl(7);
  filter4.octaveControl(7);
  filter5.octaveControl(7);
  filter6.octaveControl(7);
  filter7.octaveControl(7);
  filter8.octaveControl(7);
 
  //final output level -> 4 is left, 5 is right
  amp4.gain(2.5);
  amp5.gain(2.5);

  //Mix together high pass and low pass filter outputs
  mixer3.gain(0, 0.8);
  mixer3.gain(1, 0.0);
  mixer10.gain(0, 0.8);
  mixer10.gain(1, 0.0);
  mixer11.gain(0, 0.8);
  mixer11.gain(1, 0.0);
  mixer15.gain(0, 0.8);
  mixer15.gain(1, 0.0);
  mixer24.gain(0, 0.8);
  mixer24.gain(1, 0.0);
  mixer25.gain(0, 0.8);
  mixer25.gain(1, 0.0);
  mixer26.gain(0, 0.8);
  mixer26.gain(1, 0.0);
  mixer27.gain(0, 0.8);
  mixer27.gain(1, 0.0);

  //Mix stereo reverb output (0) with dry signal (1), 4 left 5 right
  mixer4.gain(0, 0.4);
  mixer4.gain(1, 0.08);

  mixer5.gain(0, 0.4);
  mixer5.gain(1, 0.08);

  //Set initial reverb settings - in my testing, increased dampening added noise to the end of the reverb tail
  freeverbs1.roomsize(1);
  freeverbs1.damping(0);
 
  //Amplify the signal prior to reverb
  amp17.gain(20 * 100 * DIV127);

  //Output mixer
  //voice1-4
  mixer12.gain(0, 0.08);
  mixer12.gain(1, 0.08);
  mixer12.gain(2, 0.08);
  mixer12.gain(3, 0.08);
  //voice5-8
  mixer28.gain(0, 0.08);
  mixer28.gain(1, 0.08);
  mixer28.gain(2, 0.08);
  mixer28.gain(3, 0.08);
  //mixdown
  mixer100.gain(0, 0.6);
  mixer100.gain(1, 0.6);

  //dry singal gain
  amp15.gain(8);
  amp16.gain(8);
 
  //reverb filter - this reduces high frequency noise and produces a low pass filtered reverb wet signal
  ladder1.frequency((10000 * (20 * DIV127)) + 100);
  ladder2.frequency((10000 * (20 * DIV127)) + 100);

  //detune
  detuneFactor = 1 - (0.05 * (2 * DIV127));
}

void loop() {
        usbMIDI.read();
     
        //listen for value changes

        //osc
        //lfowave
        waveform1.begin(lfowave);
        waveform2.begin(lfowave);
        waveform3.begin(lfowave);
        waveform4.begin(lfowave);
        waveform5.begin(lfowave);
        waveform6.begin(lfowave);
        waveform7.begin(lfowave);
        waveform8.begin(lfowave);
        //osc1wave
        waveformMod1.begin(osc1wave);
        waveformMod3.begin(osc1wave);
        waveformMod5.begin(osc1wave);
        waveformMod7.begin(osc1wave);
        waveformMod16.begin(osc1wave);
        waveformMod9.begin(osc1wave);
        waveformMod13.begin(osc1wave);
        waveformMod12.begin(osc1wave);
        //osc2wave
        waveformMod2.begin(osc2wave);
        waveformMod4.begin(osc2wave);
        waveformMod6.begin(osc2wave);
        waveformMod8.begin(osc2wave);
        waveformMod15.begin(osc2wave);
        waveformMod10.begin(osc2wave);
        waveformMod14.begin(osc2wave);
        waveformMod11.begin(osc2wave);
     
        //voicemix
        mixer1.gain(0, pinknoisevol);
        mixer1.gain(1, osc1vol);
        mixer1.gain(2, osc2vol);
        mixer1.gain(3, karplusvol);
        mixer8.gain(0, pinknoisevol);
        mixer8.gain(1, osc1vol);
        mixer8.gain(2, osc2vol);
        mixer8.gain(3, karplusvol);
        mixer9.gain(0, pinknoisevol);
        mixer9.gain(1, osc1vol);
        mixer9.gain(2, osc2vol);
        mixer9.gain(3, karplusvol);
        mixer13.gain(0, pinknoisevol);
        mixer13.gain(1, osc1vol);
        mixer13.gain(2, osc2vol);
        mixer13.gain(3, karplusvol);
        mixer16.gain(0, pinknoisevol);
        mixer16.gain(1, osc1vol);
        mixer16.gain(2, osc2vol);
        mixer16.gain(3, karplusvol);
        mixer18.gain(0, pinknoisevol);
        mixer18.gain(1, osc1vol);
        mixer18.gain(2, osc2vol);
        mixer18.gain(3, karplusvol);
        mixer19.gain(0, pinknoisevol);
        mixer19.gain(1, osc1vol);
        mixer19.gain(2, osc2vol);
        mixer19.gain(3, karplusvol);
        mixer17.gain(0, pinknoisevol);
        mixer17.gain(1, osc1vol);
        mixer17.gain(2, osc2vol);
        mixer17.gain(3, karplusvol);

        //lfo filter level
        mixer2.gain(1, lfofilter);
        mixer6.gain(1, lfofilter);
        mixer7.gain(1, lfofilter);
        mixer14.gain(1, lfofilter);
        mixer20.gain(1, lfofilter);
        mixer21.gain(1, lfofilter);
        mixer22.gain(1, lfofilter);
        mixer23.gain(1, lfofilter);
     
        //lfo fm level
        amp1.gain(lfofm);
        amp8.gain(lfofm);
        amp9.gain(lfofm);
        amp12.gain(lfofm);
        amp18.gain(lfofm);
        amp19.gain(lfofm);
        amp20.gain(lfofm);
        amp21.gain(lfofm);
   
        //lfo speed
        waveform1.frequency(lfospeed);
        waveform2.frequency(lfospeed);
        waveform3.frequency(lfospeed);
        waveform4.frequency(lfospeed);
        waveform5.frequency(lfospeed);
        waveform6.frequency(lfospeed);
        waveform7.frequency(lfospeed);
        waveform8.frequency(lfospeed);
     
        //lfoadsr
        envelope1.attack(lfoattack);
        envelope1.decay(lfodecay);
        envelope1.sustain(lfosustain);
        envelope1.release(lforelease);
        envelope4.attack(lfoattack);
        envelope4.decay(lfodecay);
        envelope4.sustain(lfosustain);
        envelope4.release(lforelease);
        envelope5.attack(lfoattack);
        envelope5.decay(lfodecay);
        envelope5.sustain(lfosustain);
        envelope5.release(lforelease);
        envelope10.attack(lfoattack);
        envelope10.decay(lfodecay);
        envelope10.sustain(lfosustain);
        envelope10.release(lforelease);
        envelope16.attack(lfoattack);
        envelope16.decay(lfodecay);
        envelope16.sustain(lfosustain);
        envelope16.release(lforelease);
        envelope15.attack(lfoattack);
        envelope15.decay(lfodecay);
        envelope15.sustain(lfosustain);
        envelope15.release(lforelease);
        envelope14.attack(lfoattack);
        envelope14.decay(lfodecay);
        envelope14.sustain(lfosustain);
        envelope14.release(lforelease);
        envelope13.attack(lfoattack);
        envelope13.decay(lfodecay);
        envelope13.sustain(lfosustain);
        envelope13.release(lforelease);
     
        //adsr
        envelope3.attack(vcaattack);
        envelope3.decay(vcadecay);
        envelope3.sustain(vcasustain);
        envelope3.release(vcarelease);
        envelope8.attack(vcaattack);
        envelope8.decay(vcadecay);
        envelope8.sustain(vcasustain);
        envelope8.release(vcarelease);
        envelope9.attack(vcaattack);
        envelope9.decay(vcadecay);
        envelope9.sustain(vcasustain);
        envelope9.release(vcarelease);
        envelope12.attack(vcaattack);
        envelope12.decay(vcadecay);
        envelope12.sustain(vcasustain);
        envelope12.release(vcarelease);
        envelope21.attack(vcaattack);
        envelope21.decay(vcadecay);
        envelope21.sustain(vcasustain);
        envelope21.release(vcarelease);
        envelope22.attack(vcaattack);
        envelope22.decay(vcadecay);
        envelope22.sustain(vcasustain);
        envelope22.release(vcarelease);
        envelope23.attack(vcaattack);
        envelope23.decay(vcadecay);
        envelope23.sustain(vcasustain);
        envelope23.release(vcarelease);
        envelope24.attack(vcaattack);
        envelope24.decay(vcadecay);
        envelope24.sustain(vcasustain);
        envelope24.release(vcarelease);
     
        //filter
        filter1.frequency(filterfreq);
        filter1.resonance(filterres);
        filter2.frequency(filterfreq);
        filter2.resonance(filterres);
        filter3.frequency(filterfreq);
        filter3.resonance(filterres);
        filter4.frequency(filterfreq);
        filter4.resonance(filterres);
        filter5.frequency(filterfreq);
        filter5.resonance(filterres);
        filter6.frequency(filterfreq);
        filter6.resonance(filterres);
        filter7.frequency(filterfreq);
        filter7.resonance(filterres);
        filter8.frequency(filterfreq);
        filter8.resonance(filterres);
   
        mixer3.gain(1, highpassvol);
        mixer3.gain(0, lowpassvol);
        mixer10.gain(1, highpassvol);
        mixer10.gain(0, lowpassvol);
        mixer11.gain(1, highpassvol);
        mixer11.gain(0, lowpassvol);
        mixer15.gain(1, highpassvol);
        mixer15.gain(0, lowpassvol);
        mixer24.gain(1, highpassvol);
        mixer24.gain(0, lowpassvol);
        mixer25.gain(1, highpassvol);
        mixer25.gain(0, lowpassvol);
        mixer26.gain(1, highpassvol);
        mixer26.gain(0, lowpassvol);
        mixer27.gain(1, highpassvol);
        mixer27.gain(0, lowpassvol);
}

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

      //polyphonic note allocation starts here
      int note_index = -1;

      for (int i = 0; i < LIMIT_POLY; i++)
      {
         //check for duplicate notes coming in, don't replay them
         if (((poly_notes[i].channel == 0) && (poly_notes[i].base_pitch == 0)) || ((poly_notes[i].channel == channel) && (poly_notes[i].base_pitch == note)))
         {
            note_index = i;
            break;
         }
      }

      //each case is what happens when you want to send a note to each voice channel - you need to turn the envelopes on and set the note pitch for each voice in turn.
      if (note_index != -1)
      {
         switch(note_index)
         {
            case 0:
            {
               envelope1.noteOn();
               envelope2.noteOn();
               envelope3.noteOn();
           
               waveformMod1.frequency(noteFreqs[note]);
               waveformMod2.frequency(noteFreqs[note - 12] * detuneFactor);

               waveformMod1.amplitude((float)(velocity) * DIV127);
               waveformMod2.amplitude((float)(velocity) * DIV127);
               pink1.amplitude((float)(velocity) * DIV127);

               delay(10);
               string1.noteOn(noteFreqs[note], (float)velocity * DIV127);

            }
            break;

            case 1:
            {
               envelope4.noteOn();
               envelope6.noteOn();
               envelope8.noteOn();
           
               waveformMod3.frequency(noteFreqs[note]);
               waveformMod4.frequency(noteFreqs[note - 12] * detuneFactor);

               waveformMod3.amplitude((float)(velocity) * DIV127);
               waveformMod4.amplitude((float)(velocity) * DIV127);
               pink2.amplitude((float)(velocity) * DIV127);

               delay(10);
               string2.noteOn(noteFreqs[note], (float)velocity * DIV127);


            }
            break;

            case 2:
            {
               envelope5.noteOn();
               envelope7.noteOn();
               envelope9.noteOn();

               waveformMod5.frequency(noteFreqs[note]);
               waveformMod6.frequency(noteFreqs[note - 12] * detuneFactor);
         
               waveformMod5.amplitude((float)(velocity) * DIV127);
               waveformMod6.amplitude((float)(velocity) * DIV127);
               pink3.amplitude((float)(velocity) * DIV127);

               delay(10);
               string3.noteOn(noteFreqs[note], (float)velocity * DIV127);
            }
            break;

            case 3:
            {    
               envelope10.noteOn();
               envelope11.noteOn();
               envelope12.noteOn();
                                   
               waveformMod7.frequency(noteFreqs[note]);
               waveformMod8.frequency(noteFreqs[note - 12] * detuneFactor);

               waveformMod7.amplitude((float)(velocity) * DIV127);
               waveformMod8.amplitude((float)(velocity) * DIV127);
               pink4.amplitude((float)(velocity) * DIV127);

               delay(10);
               string4.noteOn(noteFreqs[note], (float)velocity * DIV127);
            }
            break;

            case 4:
            {
               envelope16.noteOn();
               envelope17.noteOn();
               envelope21.noteOn();
           
               waveformMod16.frequency(noteFreqs[note]);
               waveformMod15.frequency(noteFreqs[note - 12] * detuneFactor);

               waveformMod16.amplitude((float)(velocity) * DIV127);
               waveformMod15.amplitude((float)(velocity) * DIV127);
               pink8.amplitude((float)(velocity) * DIV127);

               delay(10);
               string8.noteOn(noteFreqs[note], (float)velocity * DIV127);

            }
            break;

            case 5:
            {
               envelope15.noteOn();
               envelope18.noteOn();
               envelope22.noteOn();
           
               waveformMod9.frequency(noteFreqs[note]);
               waveformMod10.frequency(noteFreqs[note - 12] * detuneFactor);

               waveformMod9.amplitude((float)(velocity) * DIV127);
               waveformMod10.amplitude((float)(velocity) * DIV127);
               pink5.amplitude((float)(velocity) * DIV127);

               delay(10);
               string5.noteOn(noteFreqs[note], (float)velocity * DIV127);
            }
            break;

            case 6:
            {
               envelope14.noteOn();
               envelope19.noteOn();
               envelope24.noteOn();

               waveformMod13.frequency(noteFreqs[note]);
               waveformMod14.frequency(noteFreqs[note - 12] * detuneFactor);
         
               waveformMod13.amplitude((float)(velocity) * DIV127);
               waveformMod14.amplitude((float)(velocity) * DIV127);
               pink7.amplitude((float)(velocity) * DIV127);

               delay(10);
               string7.noteOn(noteFreqs[note], (float)velocity * DIV127);
            }
            break;

            case 7:
            {    
               envelope13.noteOn();
               envelope20.noteOn();
               envelope23.noteOn();
                                   
               waveformMod12.frequency(noteFreqs[note]);
               waveformMod11.frequency(noteFreqs[note - 12] * detuneFactor);

               waveformMod12.amplitude((float)(velocity) * DIV127);
               waveformMod11.amplitude((float)(velocity) * DIV127);
               pink6.amplitude((float)(velocity) * DIV127);

               delay(10);
               string6.noteOn(noteFreqs[note], (float)velocity * DIV127);
            }
            break;
         }
     
         poly_notes[note_index].channel = channel;
         poly_notes[note_index].base_pitch = note;
         poly_notes[note_index].note_state = true;
   
      }

   }

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

//this section mirrors the note on section above, but is for starting the release phase of the envelope when notes are released.
      int note_index = -1;

      for (int i = 0; i < LIMIT_POLY; i++)
      {
         if ((poly_notes[i].channel == channel) && (poly_notes[i].base_pitch == note))
         {
            note_index = i;
            break;
         }
      }

      if (note_index != -1)
      {
         poly_notes[note_index].note_state = false;
         poly_notes[note_index].note_off_millis = 0;

         {
            switch(note_index)
            {
               case 0:
               {

                  envelope1.noteOff();
                  envelope2.noteOff();
                  envelope3.noteOff();
                  string1.noteOff(0);
                                               
               }
               break;

               case 1:
               {
                  envelope4.noteOff();
                  envelope6.noteOff();
                  envelope8.noteOff();
                  string2.noteOff(0);
               }
               break;

               case 2:
               {
                  envelope5.noteOff();
                  envelope7.noteOff();
                  envelope9.noteOff();
                  string3.noteOff(0);
               
               }
               break;

               case 3:
               {
                  envelope10.noteOff();
                  envelope11.noteOff();
                  envelope12.noteOff();
                  string4.noteOff(0);
               }
               break;

               case 4:
               {
                  envelope16.noteOff();
                  envelope17.noteOff();
                  envelope21.noteOff();
                  string8.noteOff(0);                              
               }
               break;

               case 5:
               {
                  envelope15.noteOff();
                  envelope18.noteOff();
                  envelope22.noteOff();
                  string5.noteOff(0);
               }
               break;

               case 6:
               {
                  envelope14.noteOff();
                  envelope19.noteOff();
                  envelope24.noteOff();
                  string7.noteOff(0);              
               }
               break;

               case 7:
               {
                  envelope13.noteOff();
                  envelope20.noteOff();
                  envelope23.noteOff();
                  string6.noteOff(0);
               }
               break;
           
            }
            poly_notes[note_index].channel = 0;
            poly_notes[note_index].base_pitch = 0;
            poly_notes[note_index].note_state = false;
         }
      }


 }


void myControlChange(byte channel, byte control, byte value) {
  switch (control) {
    //Switch between preset sounds based on a knob value range.
    case 106:
      switch (value) {
       
        case 0 ... 31:
        //voice mix
        pinknoisevol = 0;
        osc1vol = (20.0 * DIV127);
        osc2vol = (20.0 * DIV127);
        karplusvol = (20.0 * DIV127);

        //lfo filter level
        lfofilter = (20.0 * DIV127);
     
        //lfo fm level
        lfofm = (0.1 * (2 * DIV127));
     
        //lfo speed
        lfospeed = ((7 + 1) * ((7 + 1) * DIV127));
     
        //detune
        detuneFactor = 1 - (0.05 * (2 * DIV127));
     
        //lfoadsr
        lfoattack = (3000 * (0 * DIV127));
        lfodecay = (3000 * (127 * DIV127));
        lfosustain = (127 * DIV127);
        lforelease = (3000 * (0 * DIV127));
     
        //adsr
        vcaattack = (3000 * (0 * DIV127));
        vcadecay = (3000 * (30 * DIV127));
        vcasustain = (127 * DIV127);
        vcarelease = (3000 * (38 * DIV127));
     
        //filter
        filterfreq = ((10000 * (34 * DIV127)) + 100);
        filterres = ((4.3 * (0 * DIV127)) + 1.1);
        lowpassvol = ((0.8 * 127 * DIV127) - (0.8 * 98 * DIV127));
        highpassvol = (0.8 * 98 * DIV127);
     
        //wf
        osc1wave = WAVEFORM_SINE;
        osc2wave = WAVEFORM_SINE;
        lfowave = WAVEFORM_SINE;
        break;
     
     
        case 32 ... 64:
        //voice mix
        pinknoisevol = 0;
        osc1vol = (70.0 * DIV127);
        osc2vol = (70.0 * DIV127);
        karplusvol = (18.0 * DIV127);

        //lfo filter level
        lfofilter = (12.0 * DIV127);
     
        //lfo fm level
        lfofm = (0.1 * (1 * DIV127));
     
        //lfo speed
        lfospeed = ((17 + 1) * ((17 + 1) * DIV127));
     
        //detune
        detuneFactor = 1 - (0.05 * (9 * DIV127));
        //lfoadsr
        lfoattack = (3000 * (10 * DIV127));
        lfodecay = (3000 * (22 * DIV127));
        lfosustain = (1 * DIV127);
        lforelease = (3000 * (0 * DIV127));
     
        //adsr
        vcaattack = (3000 * (10 * DIV127));
        vcadecay = (3000 * (22 * DIV127));
        vcasustain = (0 * DIV127);
        vcarelease = (3000 * (0 * DIV127));
     
        //filter
        filterfreq = ((10000 * (34 * DIV127)) + 100);
        filterres = ((4.3 * (20 * DIV127)) + 1.1);
        lowpassvol = ((0.8 * 127 * DIV127) - (0.8 * 98 * DIV127));
        highpassvol = (0.8 * 98 * DIV127);

        //wf
        osc1wave = WAVEFORM_BANDLIMIT_SAWTOOTH;
        osc2wave = WAVEFORM_BANDLIMIT_SAWTOOTH;
        lfowave = WAVEFORM_SINE;
        break;
     
        case 65 ... 96:
        //voice mix
        pinknoisevol = (5 * DIV127);
        osc1vol = (52.0 * DIV127);
        osc2vol = (8.0 * DIV127);
        karplusvol = (39.0 * DIV127);

        //lfo filter level
        lfofilter = (12.0 * DIV127);
     
        //lfo fm level
        lfofm = (0.1 * (2 * DIV127));
     
        //lfo speed
        lfospeed = ((54 + 1) * ((54 + 1) * DIV127));
     
        //detune
        detuneFactor = 1 - (0.05 * (36 * DIV127));
     
        //lfoadsr
        lfoattack = (3000 * (46 * DIV127));
        lfodecay = (3000 * (36 * DIV127));
        lfosustain = (1.0);
        lforelease = (3000 * (0 * DIV127));
     
        //adsr
        vcaattack = (3000 * (46 * DIV127));
        vcadecay = (3000 * (36 * DIV127));
        vcasustain = (127 * DIV127);
        vcarelease = (3000 * (1 * DIV127));
     
        //filter
        filterfreq = ((10000 * (48 * DIV127)) + 100);
        filterres = ((4.3 * (22 * DIV127)) + 1.1);
        lowpassvol = ((0.8 * 127 * DIV127) - (0.8 * 50 * DIV127));
        highpassvol = (0.8 * 50 * DIV127);
     
        //wf
        osc1wave = WAVEFORM_TRIANGLE_VARIABLE;
        osc2wave = WAVEFORM_BANDLIMIT_SAWTOOTH;
        lfowave = WAVEFORM_SAMPLE_HOLD;  
        break;

        case 97 ... 127:
        //voice mix
        pinknoisevol = (0 * DIV127);
        osc1vol = (48.0 * DIV127);
        osc2vol = (5.0 * DIV127);
        karplusvol = (60.0 * DIV127);

        //lfo filter level
        lfofilter = (12.0 * DIV127);
     
        //lfo fm level
        lfofm = (0.1 * (20 * DIV127));
     
        //lfo speed
        lfospeed = ((93 + 1) * ((93 + 1) * DIV127));
     
        //detune
        detuneFactor = 1 - (0.05 * (9 * DIV127));
     
        //lfoadsr
        lfoattack = (3000 * (0 * DIV127));
        lfodecay = (3000 * (9 * DIV127));
        lfosustain = (1 * DIV127);
        lforelease = (3000 * (0 * DIV127));
     
        //adsr
        vcaattack = (3000 * (0 * DIV127));
        vcadecay = (3000 * (5 * DIV127));
        vcasustain = (0 * DIV127);
        vcarelease = (3000 * (38 * DIV127));
     
        //filter
        filterfreq = ((10000 * (34 * DIV127)) + 100);
        filterres = ((4.3 * (0 * DIV127)) + 1.1);
        lowpassvol = ((0.8 * 127 * DIV127) - (0.8 * 50 * DIV127));
        highpassvol = (0.8 * 50 * DIV127);
     
        //wf
        osc1wave = WAVEFORM_TRIANGLE;
        osc2wave = WAVEFORM_SINE;
        lfowave = WAVEFORM_SQUARE;
        break;
      }
    break;

    case 107: // Dual attack knob - this controls the vca and lfo attack
      vcaattack = (3000 * (value * DIV127));
      lfoattack = (3000 * (value * DIV127));
      break;

    case 108:// Decay/sustain - this increase the vca decay, until it reaches the full value, at which stage sustain is set to full.
      vcadecay = (3000 * (value * DIV127));
      switch (value) {
        case 0 ... 126:
          vcasustain = (0.0);
        case 127:
          vcasustain = (1.0);
          break;
       }
    break;

    case 110: //LP/HP blend control
      highpassvol = (0.8 * value * DIV127);
      lowpassvol = ((0.8 * 127 * DIV127) - (0.8 * value * DIV127));
      break;

    case 111: //Sets the reverb level by changing amplification at different gain stages. Not very elegant but gave me the results I wanted. At the top end of the knob, the dry singal is attenuated until you reach a fully wet output.

      mixer4.gain(0, (0.4 * value * DIV127));
      mixer5.gain(0, (0.4 * value * DIV127));
   
      switch (value) {
         case 0 ... 119:
            mixer4.gain(1, 0.08);
            mixer5.gain(1, 0.08);
         case 120 ... 127:
            mixer4.gain(1, ((0.08 * 127 * DIV127) - (0.08 * value * DIV127)));
            mixer5.gain(1, ((0.08 * 127 * DIV127) - (0.08 * value * DIV127)));
      }
      break;
         
         
      switch (value) {
        case 0 ... 30:
            amp17.gain(10 * value * DIV127);
        case 31 ... 127:
            amp17.gain(10 * 100 * DIV127);
      }
      break;

    case 112: //volume control
      amp4.gain(5 * value * DIV127);
      amp5.gain(5 * value * DIV127);
      break;
     }
  }
 
Last edited:
There should be an example in the Teensyduino under Audio about CPU and memory usage (I am not at my PC right now to check the exact name).
 
I also think there is not enough audio buffer for 8 voices. I would try it at 64.


C:
FLASHMEM void setup()

{
    // init Hardware ------------------------------------------------------

    Serial.begin(19200);

    ....

    // init Audio buffer --------------------------------------------------

    AudioMemory(64); // Sample Blocks
...


I did it like this to select the waveforms.
C:
AudioSynthWaveformModulated waveformMod1[8];  //xy=503,170  Osc1

// Waveforms
const uint8_t waveform[] PROGMEM = {WAVEFORM_SINE, WAVEFORM_TRIANGLE,
WAVEFORM_SQUARE, WAVEFORM_PULSE, WAVEFORM_SAMPLE_HOLD, WAVEFORM_SAWTOOTH_REVERSE, WAVEFORM_TRIANGLE_VARIABLE,
WAVEFORM_BANDLIMIT_SAWTOOTH_REVERSE, WAVEFORM_BANDLIMIT_SAWTOOTH, WAVEFORM_BANDLIMIT_SQUARE, WAVEFORM_BANDLIMIT_PULSE
};

FLASHMEM void updateWaveform(int16_t selectWave)
{
    int16_t newWaveform;
  
    newWaveform = waveform[selectWave];
  
    for (uint8_t i = 0; i < 8; i++)
    {
        waveformMod1[i].begin(newWaveform);
    }
 
Last edited:
Don't do a waveform.begin() when you haven't changed the shape. The non-band-limited shapes don't appear to do much, but the band-limited ones have some initialisation code which you're repeatedly calling, probably very fast.

In general, I'd say don't repeatedly set any parameter which hasn't changed - even if it works now, you can't rely on a future library update not breaking your code...
 
Search for AudioMemoryUsageMax and AudioProcessorUsageMax for examples of logging memory and CPU usage.

Band limiting consumes more resources (quite a lot more) than the plain waveform generation, so be suspicious of running out of CPU, not just memory.
 
Hello,

Band limited waveforms requires more CPU. I don't know about memory. But for sure you must try larger buffer as Rolfdegen suggests. I am pretty sure it is going to make it.

You should also use pointers to a manipulate voices, so easier !!
Here is an example. Say you have 8 oscillators :

AudioSynthWaveform waveform5;
AudioSynthWaveform waveform6;
AudioSynthWaveform waveform7;
AudioSynthWaveform waveform8;
AudioSynthWaveform waveform4;
AudioSynthWaveform waveform3;
AudioSynthWaveform waveform2;
AudioSynthWaveform waveform1;

You can declare an array of pointers to manipulate your oscillators in a simpler way :

AudioSynthWaveformModulated *myOscillator[ ] = {&waveform1, &waveform2, &waveform3, &waveform4, &waveform5, &waveform6, &waveform7, &waveform8};

Then if you want to change the waveform (or any parameter) :

const byte polyphony = 8;

for (byte i = 0; i < polyphony; i++) {
myOscillator->begin(WAVEFORM_TRIAINGLE);
}

You can do the same with filters, effects, mixers... Note the use of "->" instead of " . "
Once you have declared all your arrays of pointers, it simplifies the code a lot.

And for your spe

Emmanuel
 
Thanks everyone for your replies.

Don't do a waveform.begin() when you haven't changed the shape. The non-band-limited shapes don't appear to do much, but the band-limited ones have some initialisation code which you're repeatedly calling, probably very fast.

In general, I'd say don't repeatedly set any parameter which hasn't changed - even if it works now, you can't rely on a future library update not breaking your code...

Thanks! This did the trick - I moved the code setting parameters out of the main loop and into the midi cc case bits, so parameters only get updated when the relevant midi cc is sent.

All working perfectly now!

Hello,

Band limited waveforms requires more CPU. I don't know about memory. But for sure you must try larger buffer as Rolfdegen suggests. I am pretty sure it is going to make it.

You should also use pointers to a manipulate voices, so easier !!
Here is an example. Say you have 8 oscillators :

AudioSynthWaveform waveform5;
AudioSynthWaveform waveform6;
AudioSynthWaveform waveform7;
AudioSynthWaveform waveform8;
AudioSynthWaveform waveform4;
AudioSynthWaveform waveform3;
AudioSynthWaveform waveform2;
AudioSynthWaveform waveform1;

You can declare an array of pointers to manipulate your oscillators in a simpler way :

AudioSynthWaveformModulated *myOscillator[ ] = {&waveform1, &waveform2, &waveform3, &waveform4, &waveform5, &waveform6, &waveform7, &waveform8};

Then if you want to change the waveform (or any parameter) :

const byte polyphony = 8;

for (byte i = 0; i < polyphony; i++) {
myOscillator->begin(WAVEFORM_TRIAINGLE);
}

You can do the same with filters, effects, mixers... Note the use of "->" instead of " . "
Once you have declared all your arrays of pointers, it simplifies the code a lot.

And for your spe

Emmanuel

This does look like it would be better, can I implement it in a switch statement so I can update with midi cc? I’ll have a look at implementing it.
 
Back
Top