#include <Audio.h>
#include <movingAvg.h>
#include <Wire.h>
#include <SPI.h>
#include <SerialFlash.h>
#include <Bounce.h>
#include <Metro.h>
// GUItool: begin automatically generated code
AudioSynthWaveformSine sine1; //xy=167.9166717529297,448.3333435058594
AudioSynthWaveform waveform1; //xy=171.11111111111111,103.33333333333333
AudioSynthWaveformModulated waveformMod1; //xy=187.5,215
AudioEffectEnvelope envelope1; //xy=346.25,105
AudioEffectEnvelope envelope2; //xy=367.5,217.5
AudioEffectFreeverb freeverb1; //xy=411.25,388.75
AudioSynthWaveformPWM pwm1; //xy=413.75,486.25
AudioAmplifier amp3; //xy=458.75,445
AudioFilterLadder ladder1; //xy=517.5,117.5
AudioFilterStateVariable filter1; //xy=520,276.25
AudioEffectWaveFolder wavefolder1; //xy=587.5,491.25
AudioEffectFlange flange1; //xy=600,365
AudioEffectDigitalCombine combine1; //xy=625.0000610351562,226.25
AudioAmplifier amp4; //xy=687.5,116.25
AudioAmplifier amp5; //xy=687.5,151.25
AudioAmplifier amp6; //xy=728.75,185
AudioMixer4 mixer2; //xy=747.5,407.5
AudioAmplifier amp2; //xy=791.25,292.5
AudioMixer4 mixer1; //xy=856.25,160
AudioAmplifier amp1; //xy=938.75,318.75
AudioOutputI2S i2s1; //xy=1000,396.25
AudioConnection patchCord1(sine1, 0, waveformMod1, 0);
AudioConnection patchCord2(waveform1, envelope1);
AudioConnection patchCord3(waveformMod1, envelope2);
AudioConnection patchCord4(envelope1, 0, ladder1, 0);
AudioConnection patchCord5(envelope2, 0, combine1, 1);
AudioConnection patchCord6(envelope2, 0, filter1, 0);
AudioConnection patchCord7(envelope2, amp5);
AudioConnection patchCord8(freeverb1, 0, mixer2, 2);
AudioConnection patchCord9(pwm1, 0, wavefolder1, 1);
AudioConnection patchCord10(amp3, 0, wavefolder1, 0);
AudioConnection patchCord11(ladder1, 0, combine1, 0);
AudioConnection patchCord12(ladder1, amp4);
AudioConnection patchCord13(filter1, 0, amp3, 0);
AudioConnection patchCord14(filter1, 1, flange1, 0);
AudioConnection patchCord15(filter1, 2, freeverb1, 0);
AudioConnection patchCord16(wavefolder1, 0, mixer2, 0);
AudioConnection patchCord17(flange1, 0, mixer2, 1);
AudioConnection patchCord18(combine1, amp6);
AudioConnection patchCord19(amp4, 0, mixer1, 0);
AudioConnection patchCord20(amp5, 0, mixer1, 1);
AudioConnection patchCord21(amp6, 0, mixer1, 2);
AudioConnection patchCord22(mixer2, amp2);
AudioConnection patchCord23(amp2, 0, mixer1, 3);
AudioConnection patchCord24(mixer1, amp1);
AudioConnection patchCord25(amp1, 0, i2s1, 0);
AudioConnection patchCord26(amp1, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=925,478.75
// GUItool: end automatically generated code
#define FLANGE_DELAY_LENGTH (20*AUDIO_BLOCK_SAMPLES)
short delayline[FLANGE_DELAY_LENGTH];
int s_idx = FLANGE_DELAY_LENGTH/4;
int s_depth = FLANGE_DELAY_LENGTH/4;
float s_freq = .5;
float noteMap[128] = { 8.18, 8.66, 9.18, 9.72, 10.3, 10.91, 11.56, 12.25, 12.98, 13.75, 14.57, 15.43, 16.35, 17.32, 18.35, 19.45, 20.6, 21.83, 23.12, 24.5, 25.96, 27.5, 29.14, 30.87, 32.7, 34.65, 36.71, 38.89, 41.2, 43.65, 46.25, 49, 51.91, 55, 58.27, 61.74, 65.41, 69.3, 73.42, 77.78, 82.41, 87.31, 92.5, 98, 103.83, 110, 116.54, 123.47, 130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185, 196, 207.65, 220, 233.08, 246.94, 261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392, 415.3, 440, 466.16, 493.88, 523.25, 554.37, 587.33, 622.25, 659.26, 698.46, 739.99, 783.99, 830.61, 880, 932.33, 987.77, 1046.5, 1108.73, 1174.66, 1244.51, 1318.51, 1396.91, 1479.98, 1567.98, 1661.22, 1760, 1864.66, 1975.53, 2093, 2217.46, 2349.32, 2489.02, 2637.02, 2793.83, 2959.96, 3135.96, 3322.44, 3520, 3729.31, 3951.07, 4186.01, 4434.92, 4698.64, 4978.03, 5274.04, 5587.65, 5919.91, 6271.93, 6644.88, 7040, 7458.62, 7902.13, 8372.02, 8869.84, 9397.27, 9956.06, 10548.08, 11175.3, 11839.82, 12543.85 };
uint16_t knobs[15];
uint8_t I = 1;
uint8_t II = 3;
uint8_t III = 0;
uint8_t IV = 4;
uint8_t V = 2;
uint8_t VI = 6;
uint8_t VII = 5;
uint8_t VIII = 7;
uint8_t IX = 9;
uint8_t X = 8;
uint8_t XI = 12;
uint8_t XII = 10;
uint8_t XIII = 14;
uint8_t XIV = 13;
uint8_t XV = 11;
byte byteArray[32];
byte pot[7] = { A10, A11, A12, A14, A15, A16, A17 };
int potVal[7] = { 0, 0, 0, 0, 0, 0, 0 };
int potAvg[7] = { 0, 0, 0, 0, 0, 0, 0 };
int noteBuffer[2] = { 0, 0 };
int notes[128];
byte avgDepth = 10;
byte bufferIndex = 0;
movingAvg potAvg0(avgDepth);
movingAvg potAvg1(avgDepth);
movingAvg potAvg2(avgDepth);
movingAvg potAvg3(avgDepth);
movingAvg potAvg4(avgDepth);
movingAvg potAvg5(avgDepth);
movingAvg potAvg6(avgDepth);
bool knobMsg, noteMsg;
const int buttonPin = 36;
int envAttack = 8;
int envHold = 50;
int envDecay = 70;
float envSustain = 0.6;
int envRelease = 60;
Metro notePeriod = Metro(650);
Metro noteLength = Metro(200);
Metro blinkPeriod = Metro(400);
Metro blinkLength = Metro(400);
Metro logDelay = Metro(250);
unsigned long now;
unsigned long then;
int waveCurrent = 8;
int waveModCurrent = 8;
int octaveOffset = 0;
void setup() {
Wire1.begin(33);
Wire1.onReceive(onReceivePayload);
Serial.begin(31250);
potAvg0.begin();
potAvg1.begin();
potAvg2.begin();
potAvg3.begin();
potAvg4.begin();
potAvg5.begin();
potAvg6.begin();
pinMode(LED_BUILTIN, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
then = millis();
AudioMemory(10);
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);
//defaults
waveform1.frequency(440);
waveform1.amplitude(1.0);
waveform1.begin(WAVEFORM_TRIANGLE);
waveformMod1.frequency(440);
waveformMod1.amplitude(1.0);
waveformMod1.begin(WAVEFORM_TRIANGLE);
sine1.frequency(15.0);
sine1.amplitude(15.0);
envelope1.releaseNoteOn(10);
envelope2.releaseNoteOn(10);
flange1.begin(delayline,FLANGE_DELAY_LENGTH,s_idx,s_depth,s_freq);
mixer1.gain(0,1.0);
mixer1.gain(1,1.0);
mixer1.gain(2,1.0);
mixer1.gain(3,1.0);
}
void loop() {
bool buttonState = digitalRead(buttonPin);
readKnobs();
if (logDelay.check() == 1 && !buttonState) {
logKnobs();
}
setWaveform();
updateWaveformMod();
updateLfo();
setEnvelope();
updateLadder();
updateSplit();
updateCombine();
updateFlange();
updateReverb();
updateWavefolder();
updateMixers();
// testNotes();
blinkLed();
}
void setWaveform() {
int waveSelect = map(knobs[I], 0, 1023, 1, 8);
int previousWave = waveCurrent;
switch (waveSelect) {
case 1:
waveCurrent = WAVEFORM_SAWTOOTH;
break;
case 2:
waveCurrent = WAVEFORM_SAWTOOTH_REVERSE;
break;
case 3:
waveCurrent = WAVEFORM_SQUARE;
break;
case 4:
waveCurrent = WAVEFORM_TRIANGLE;
break;
case 5:
waveCurrent = WAVEFORM_TRIANGLE_VARIABLE;
break;
case 6:
waveCurrent = WAVEFORM_PULSE;
break;
case 7:
waveCurrent = WAVEFORM_SAMPLE_HOLD;
break;
case 8:
waveCurrent = WAVEFORM_SINE;
break;
}
if (previousWave != waveCurrent) {
AudioNoInterrupts();
waveform1.begin(waveCurrent);
AudioInterrupts();
}
};
void updateWaveformMod(){
int waveSelect = map(knobs[II], 0, 1023, 1, 8);
octaveOffset = map(knobs[VI], 0, 1023, -3, 3);
int previousModWave = waveModCurrent;
switch (waveSelect) {
case 1:
waveModCurrent = WAVEFORM_SAWTOOTH;
break;
case 2:
waveModCurrent = WAVEFORM_SAWTOOTH_REVERSE;
break;
case 3:
waveModCurrent = WAVEFORM_SQUARE;
break;
case 4:
waveModCurrent = WAVEFORM_TRIANGLE;
break;
case 5:
waveModCurrent = WAVEFORM_TRIANGLE_VARIABLE;
break;
case 6:
waveModCurrent = WAVEFORM_PULSE;
break;
case 7:
waveModCurrent = WAVEFORM_SAMPLE_HOLD;
break;
case 8:
waveModCurrent = WAVEFORM_SINE;
break;
}
if (previousModWave != waveModCurrent) {
AudioNoInterrupts();
waveformMod1.begin(waveModCurrent);
waveformMod1.frequencyModulation(2);
AudioInterrupts();
}
};
void updateLfo(){
AudioNoInterrupts();
if (knobs[III] > 2) {
float lfoRate = (knobs[III]/1023.0)*30.0;
sine1.frequency(lfoRate);
sine1.amplitude(1.0);
} else {
sine1.amplitude(0.0);
}
AudioInterrupts();
};
void setEnvelope(){
int envSelect = map(knobs[XI], 0, 1023, 1, 4);
switch (envSelect) {
case 1:
envAttack = 5;
envHold = 10;
envDecay = 50;
envSustain = 1;
envRelease = 5;
break;
case 2:
envAttack = 8;
envHold = 50;
envDecay = 70;
envSustain = 0.8;
envRelease = 60;
break;
case 3:
envAttack = 100;
envHold = 100;
envDecay = 150;
envSustain = 1;
envRelease = 200;
break;
case 4:
envAttack = 300;
envHold = 200;
envDecay = 70;
envSustain = 0.8;
envRelease = 400;
break;
}
AudioNoInterrupts();
envelope1.attack(envAttack);
envelope1.hold(envHold);
envelope1.decay(envDecay);
envelope1.sustain(envSustain);
envelope1.release(envRelease);
envelope2.attack(envAttack);
envelope2.hold(envHold);
envelope2.decay(envDecay);
envelope2.sustain(envSustain);
envelope2.release(envRelease);
AudioInterrupts();
};
void updateLadder(){
float ladFrequency = ((knobs[IV]/1023.0)*6000.0 + 20);
float ladResonance = (knobs[VIII]/1023.0);
AudioNoInterrupts();
ladder1.inputDrive(1.5);
ladder1.frequency(ladFrequency);
ladder1.resonance(ladResonance);
AudioInterrupts();
};
void updateSplit(){
float splitFrequency = (knobs[VII]/1023.0)*4000.0;
AudioNoInterrupts();
filter1.frequency(splitFrequency);
ladder1.resonance(0.705);
AudioInterrupts();
};
void updateCombine(){
int comSelect = map(knobs[IX], 0, 1023, 1, 5);
byte comMode = 0;
switch (comSelect) {
case 1:
comMode = 0;
break;
case 2:
comMode = 0;
break;
case 3:
comMode = 1;
break;
case 4:
comMode = 2;
break;
case 5:
comMode = 3;
break;
}
AudioNoInterrupts();
if (comSelect > 1) {
amp4.gain(0);
amp5.gain(0);
amp6.gain(1.0);
combine1.setCombineMode(comMode);
} else {
amp4.gain(1.0);
amp5.gain(1.0);
amp6.gain(0);
}
AudioInterrupts();
};
void updateFlange() {
float flangeMod = (knobs[X]/1023.0);
s_idx = ((flangeMod * 2)+2) * FLANGE_DELAY_LENGTH/4;
s_depth = ((flangeMod * 2)+2) * FLANGE_DELAY_LENGTH/4;
s_freq = .8;
AudioNoInterrupts();
flange1.voices(s_idx,s_depth,s_freq);
AudioInterrupts();
}
void updateReverb() {
float revTime = (knobs[V]/1023.0);
AudioNoInterrupts();
freeverb1.roomsize(revTime);
AudioInterrupts();
}
void updateWavefolder() {
float foldControl = (knobs[XIII]/1023.0);
AudioNoInterrupts();
amp3.gain(foldControl*5.0);
pwm1.amplitude(foldControl);
pwm1.frequency(150.0);
AudioInterrupts();
}
void updateMixers(){
float mainVolume = (knobs[XIV]/1023.0);
float fxVolume = (knobs[XV]/1023.0);
float mixFade = (knobs[XII]/1023.0);
float chWave, chWaveMod;
if (mixFade <= .5) {
chWave = 1.0;
chWaveMod = mixFade / .5;
} else {
chWave = 1.0 - ((mixFade - .5) / .5);
chWaveMod = 1.0;
}
// Serial.print("chWave: ");
// Serial.print(chWave);
// Serial.print(" chWaveMod: ");
// Serial.println(chWaveMod);
AudioNoInterrupts();
amp1.gain(mainVolume);
amp2.gain(fxVolume);
mixer1.gain(0,chWave);
mixer1.gain(1,chWaveMod);
AudioInterrupts();
};
void testNotes() {
if (notePeriod.check() == 1) {
AudioNoInterrupts();
if (envelope1.isActive()) {
envelope1.noteOff();
}
waveform1.frequency(random(100, 800));
envelope1.noteOn();
AudioInterrupts();
noteLength.check();
}
if (noteLength.check() == 1 && envelope1.isActive()) {
AudioNoInterrupts();
envelope1.noteOff();
AudioInterrupts();
}
}
void readKnobs() {
for (uint8_t i = 0; i < sizeof(potVal) / sizeof(potVal[0]); i++) {
potVal[i] = analogRead(pot[i]);
}
knobs[8] = potAvg0.reading(potVal[0]);
knobs[9] = potAvg1.reading(potVal[1]);
knobs[10] = potAvg2.reading(potVal[2]);
knobs[11] = potAvg3.reading(potVal[3]);
knobs[12] = potAvg4.reading(potVal[4]);
knobs[13] = potAvg5.reading(potVal[5]);
knobs[14] = potAvg6.reading(potVal[6]);
}
void onReceivePayload(int payloadSize) {
if (payloadSize > 0) {
for (int i = 0; i < payloadSize; i++) {
byteArray[bufferIndex] = Wire1.read();
bufferIndex++;
if (bufferIndex == payloadSize) {
bufferIndex = 0;
if (payloadSize == 16) {
for (uint8_t i = 0; i < 8; i++) {
knobs[i] = byteArray[i * 2] | byteArray[i * 2 + 1] << 8;
}
knobMsg = !knobMsg;
}
if (payloadSize == 4) {
for (uint8_t i = 0; i < 2; i++) {
noteBuffer[i] = byteArray[i * 2] | byteArray[i * 2 + 1] << 8;
}
handleMidiEvent(noteBuffer[0], noteBuffer[1]);
}
}
}
}
}
void logKnobs() {
Serial.print("I: ");
Serial.print(knobs[I]);
Serial.print(" II: ");
Serial.print(knobs[II]);
Serial.print(" III: ");
Serial.print(knobs[III]);
Serial.print(" IV: ");
Serial.print(knobs[IV]);
Serial.print(" V: ");
Serial.print(knobs[V]);
Serial.print(" VI: ");
Serial.print(knobs[VI]);
Serial.print(" VII: ");
Serial.print(knobs[VII]);
Serial.print(" VIII: ");
Serial.print(knobs[VIII]);
Serial.print(" IX: ");
Serial.print(knobs[IX]);
Serial.print(" X: ");
Serial.print(knobs[X]);
Serial.print(" XI: ");
Serial.print(knobs[XI]);
Serial.print(" XII: ");
Serial.print(knobs[XII]);
Serial.print(" XIII: ");
Serial.print(knobs[XIII]);
Serial.print(" XIV: ");
Serial.print(knobs[XIV]);
Serial.print(" XV: ");
Serial.print(knobs[XV]);
now = millis();
if (knobMsg) {
Serial.print(" receiving");
knobMsg = !knobMsg;
then = now;
} else if ((now - then) > 1000) {
Serial.print(" not receiving");
}
Serial.println();
}
void handleMidiEvent(int p, int v) {
// Serial.print("Note event: ");
if (v == 0) {
notes[p] = 0;
// Serial.print("noteOff ");
// Serial.print(p);
digitalWrite(LED_BUILTIN, LOW);
AudioNoInterrupts();
envelope1.noteOff();
envelope2.noteOff();
AudioInterrupts();
} else {
int offset = p + (octaveOffset * 12);
offset = constrain(offset, 0, 127);
float noteFrequency = noteMap[p];
float noteOffsetFrequency = noteMap[offset];
float noteVelocity = v / 127.0;
notes[p] = v;
// Serial.print("noteOn p-");
// Serial.print(p);
// Serial.print(" v-");
// Serial.print(noteVelocity);
// Serial.print(" frequency-");
// Serial.print(noteFrequency);
digitalWrite(LED_BUILTIN, HIGH);
AudioNoInterrupts();
if (envelope1.isActive()) {
envelope1.noteOff();
envelope2.noteOff();
}
waveform1.frequency(noteFrequency);
waveform1.amplitude(noteVelocity);
envelope1.noteOn();
waveformMod1.frequency(noteOffsetFrequency);
waveformMod1.amplitude(noteVelocity);
envelope2.noteOn();
AudioInterrupts();
}
// Serial.println();
}
void blinkLed() {
if (blinkPeriod.check() == 1) {
digitalWrite(LED_BUILTIN, HIGH);
} else if (blinkLength.check() == 1) {
digitalWrite(LED_BUILTIN, LOW);
}
}