halogravity
Well-known member
Hello everyone. I hope the below ramble makes sense.
I am coding a synth using your audio board and a Teensy 3.6. So far everything has worked flawlessly but I have hit a wall. My synth has 8 buttons that can be played on the actual unit, but I also am trying to add USB Host support so an external midi controller can be used as well. So far I have everything working great, reading the external midi device just fine, I am just burnt out on code and can't for the life of me figure out how to turn off envelopes in the order they are released.
I have two functions at the bottom of the main code ( myNoteOn, and myNoteOff ) that are turned on when a key is pressed and released on the midi controller. So far so good. But how do I keep track of which notes are played and then released, and set the waveform frequency and turn the envelope on and then off? I have 16 waveforms, 2 voices per key, 8 note polyphony is what I am trying to achieve. Forgive the rambling nature of this post I am code-fried atm...lol. Below I am posting the main code, and SynthArch (AudioTool code). Any help would be massively appreciated. Thanks so much!
MAIN CODE:
AudioTool Code:
I am coding a synth using your audio board and a Teensy 3.6. So far everything has worked flawlessly but I have hit a wall. My synth has 8 buttons that can be played on the actual unit, but I also am trying to add USB Host support so an external midi controller can be used as well. So far I have everything working great, reading the external midi device just fine, I am just burnt out on code and can't for the life of me figure out how to turn off envelopes in the order they are released.
I have two functions at the bottom of the main code ( myNoteOn, and myNoteOff ) that are turned on when a key is pressed and released on the midi controller. So far so good. But how do I keep track of which notes are played and then released, and set the waveform frequency and turn the envelope on and then off? I have 16 waveforms, 2 voices per key, 8 note polyphony is what I am trying to achieve. Forgive the rambling nature of this post I am code-fried atm...lol. Below I am posting the main code, and SynthArch (AudioTool code). Any help would be massively appreciated. Thanks so much!
MAIN CODE:
Code:
// PANDA SYNTH ALPHA
// aka SupaSynth aka Dirty Little Synth
// Coded by Chris Gardella
// 12/14/2018
// Last Edited 11/29/2019
//TODO:
// Add more interesting scales, at least a few major :)
// Add monochrome screen and rotary encoder
// Add multiplexer
// Add amp and speaker
// Rechargable Lithium battery UPDATE: Working on a 9v Battery!
// Add harware filter, delay, and looper, all low-fi
// Add https://electricdruid.net/adding-vintage-hiss-crackle-and-pop/ OR create a duplicate in Arduino code
// To that end, possible store wav files with hiss, crackle, and pop loops. long enough to not sound like loops. Maybe even jump around
// inside loops radnomly with granular module. Add SD Card integration.
// Add Noise Oscillator
// 5 Pin Midi In
// USBHost plug soldered to Teensy 3.6 DONE!
// USBMidi without PC ALMOST DONE!
// Velocity
// LFO
// Audio GUITool (synth architecture) code in seperate file
#include "SYNTHARCH.H"
#include <USBHost_t36.h>
USBHost myusb;
MIDIDevice midi1(myusb);
Bounce button0 = Bounce(25, 15);
Bounce button1 = Bounce(26, 15);
Bounce button2 = Bounce(27, 15);
Bounce button3 = Bounce(28, 15);
Bounce button4 = Bounce(29, 15);
Bounce button5 = Bounce(30, 15);
Bounce button6 = Bounce(31, 15);
Bounce button7 = Bounce(32, 15);
//8x8 array to store scales
float noteFrequencies[8][8] = {
//Am
{220.00, 246.94, 261.63, 293.66, 329.63, 349.23, 392.00, 440.00},
//C Hungarian Folk
{261.63, 277.18, 329.63, 349.23, 392.00, 415.30, 493.88, 523.25},
//Cm
{261.63, 293.66, 311.13, 349.23, 392.00, 415.30, 466.16, 523.25},
//Dm
{293.66, 329.63, 349.23, 392.00, 440.00, 466.16, 523.25, 587.33},
//Em
{329.63, 369.99, 392.00, 440.00, 493.88, 523.25, 587.33, 659.25},
//Fm
{349.23, 392.00, 415.30, 466.16, 523.25, 554.37, 622.25, 698.46},
//Gm
{392.00, 440.00, 466.16, 523.25, 587.33, 622.25, 698.46, 783.99},
//Chromatic
{220.00, 233.08, 246.94, 261.63, 277.18, 293.66, 311.13, 329.63},
};
// Define Variables
int NPROGS = 4;
int NPROGS2 = 4;
float mixgain = 0.4;
float attack = 500;
float decay = 500;
float sustain = 0.5;
float release = 1000;
float resonance = 3.8;
const byte BUFFER = 8; //Size of keyboard buffer
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};
byte globalNote = 0;
byte globalVelocity = 10;
int noteNum = 0;
float noteFlags[8];
int knob1 = 11880 * analogRead(A0) / 1023;
int knob2 = 11880 * analogRead(A1) / 1023;
int knob3 = analogRead(A2);
int scale = map(knob3, 0, 1024, 0, 7);
int knob4 = 11880 * analogRead(A3) / 1023;
int knobD = 256 * analogRead(A17) / 1023;
float knobR = 1.0 * analogRead(A18) / 1023;
float knobA = 1.0 * analogRead(A19) / 1023;
void setup() {
myusb.begin();
midi1.setHandleNoteOn(myNoteOn);
midi1.setHandleNoteOff(myNoteOff);
Serial.begin(9600);
// Full Synth requires some serious memory
AudioMemory(50);
sgtl5000_1.enable();
// Full volume is 1.0 which will damage speakers or ears in most cases :)
sgtl5000_1.volume(mixgain);
// Set keys pinmode
pinMode(25, INPUT_PULLUP);
pinMode(26, INPUT_PULLUP);
pinMode(27, INPUT_PULLUP);
pinMode(28, INPUT_PULLUP);
pinMode(29, INPUT_PULLUP);
pinMode(30, INPUT_PULLUP);
pinMode(31, INPUT_PULLUP);
pinMode(32, INPUT_PULLUP);
// Set all mixer volumes to the above declared value, mixgain
mixer1.gain(0, mixgain);
mixer1.gain(1, mixgain);
mixer1.gain(2, mixgain);
mixer1.gain(3, mixgain);
mixer2.gain(0, mixgain);
mixer2.gain(1, mixgain);
mixer2.gain(2, mixgain);
mixer2.gain(3, mixgain);
mixer3.gain(0, mixgain);
mixer3.gain(1, mixgain);
mixer3.gain(2, mixgain);
mixer3.gain(3, mixgain);
mixer4.gain(0, mixgain);
mixer4.gain(1, mixgain);
mixer4.gain(2, mixgain);
mixer4.gain(3, mixgain);
mixerFinal.gain(0, mixgain);
mixerFinal.gain(1, mixgain);
verbMix.gain(0, mixgain);
verbMix.gain(1, mixgain);
verbMix.gain(2, mixgain);
}
void loop() {
midi1.read();
AudioNoInterrupts();
int knob1 = 11880 * analogRead(A0) / 1023;
int knob2 = 11880 * analogRead(A1) / 1023;
int knob3 = analogRead(A2);
int scale = map(knob3, 0, 1024, 0, 7);
int knob4 = 11880 * analogRead(A3) / 1023;
int knobD = 256 * analogRead(A17) / 1023;
float knobR = 1.0 * analogRead(A18) / 1023;
float knobA = 1.0 * analogRead(A19) / 1023;
// Future Volume Knob
// float knobVol = 1.0 * analogRead(A20) / 1023;
// float mixgain = knobVol;
// Debug Code to view knob values
//Serial.println(knobR);
// Reverb! If statements to set mixer volume with freeverb to zero to approximate turning reverb off. 0.03 to allow for shitty pot jitter.
freeverbs1.roomsize(knobR);
freeverbs1.damping(knobA);
if (knobR > 0.03) {
verbMix.gain(1, mixgain);
verbMix.gain(2, mixgain - knobR);
}
if (knobR <= 0.03) {
verbMix.gain(0, 0);
verbMix.gain(1, 0);
}
uint8_t progs[NPROGS] = {
WAVEFORM_SINE,
WAVEFORM_SQUARE,
WAVEFORM_TRIANGLE,
WAVEFORM_SAWTOOTH,
};
int val = analogRead(A14);
int index = map(val, 0, 1024, 0, 3);
int myProg = progs[index];
// Pointer Array to begin waveforms Voice 1
const char prognum = myProg;
AudioSynthWaveformModulated *myWaveform[] = { &waveform1, &waveform2, &waveform3, &waveform4, &waveform5, &waveform6, &waveform7, &waveform8};
for (int i = 0; i < 8; i++) {
myWaveform[i]->begin(mixgain, noteFrequencies[scale][i], prognum);
}
uint8_t progs2[NPROGS2] = {
WAVEFORM_SINE,
WAVEFORM_SQUARE,
WAVEFORM_TRIANGLE,
WAVEFORM_SAWTOOTH,
};
int val2 = analogRead(A16);
int index2 = map(val2, 0, 1024, 0, 3);
int myProg2 = progs2[index2];
// Pointer Array to begin waveforms Voice 2
const char prognum2 = myProg2;
// Detune
int detune = knobD;
AudioSynthWaveformModulated *myWaveform2[] = { &waveform9, &waveform10, &waveform11, &waveform12, &waveform13, &waveform14, &waveform15, &waveform16};
for (int i = 0; i < 8; i++) {
myWaveform2[i]->begin(mixgain, noteFrequencies[scale][i] - detune, prognum2);
}
// Pointer Array to set the envelope value to knobs value
AudioEffectEnvelope *myEnvelope[] = { &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8, &envelope9, &envelope10, &envelope11, &envelope12, &envelope13, &envelope14, &envelope15, &envelope16 };
for (int i = 0; i < 16; i++) {
myEnvelope[i]->attack(knob1);
myEnvelope[i]->release(knob2);
}
// Pointer Array for filter settings
AudioFilterStateVariable *myfilter[] = { &filter1, &filter2, &filter3, &filter4, &filter5, &filter6, &filter7, &filter8, &filter9, &filter10, &filter11, &filter12, &filter13, &filter14, &filter15, &filter16 };
for (int i = 0; i < 16; i++) {
myfilter[i]->frequency(knob4);
//Resonace will be controlled by its own knob
myfilter[i]->resonance(resonance);
}
// Pointer Arrays to update buttons and trigger notes
AudioEffectEnvelope *myEnvelope2[] = { &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8, &envelope9, &envelope10, &envelope11, &envelope12, &envelope13, &envelope14, &envelope15, &envelope16 };
Bounce *mybutton2[] = { &button0, &button1, &button2, &button3, &button4, &button5, &button6, &button7};
for (int i = 0; i < 8; i++) {
mybutton2[i]->update();
if (mybutton2[i]->fallingEdge()) {
myEnvelope2[i]->noteOn();
myEnvelope2[i + 8]->noteOn();
}
if (mybutton2[i]->risingEdge()) {
myEnvelope2[i]->noteOff();
myEnvelope2[i + 8]->noteOff();
}
}
AudioInterrupts();
/*
// Below is the code to activate wave modulation at a fixed rate. TODO: Make rate Variable
modWave1.begin(0.6, 2, WAVEFORM_SINE);
modWave2.begin(0.6, 2, WAVEFORM_SINE);
*/
}
//---------NEED HELP BELOW---------------------------------------------------------------->
void myNoteOn(byte channel, byte note, byte velocity) {
if (noteNum <= 7) {
//const char prognum = myProg;
AudioSynthWaveformModulated *myWaveformUSB[] = { &waveform1, &waveform2, &waveform3, &waveform4, &waveform5, &waveform6, &waveform7, &waveform8};
myWaveformUSB[noteNum]->frequency(noteFreqs[note]);
AudioEffectEnvelope *myEnvelopeUSB[] = { &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8, &envelope9, &envelope10, &envelope11, &envelope12, &envelope13, &envelope14, &envelope15, &envelope16 };
myEnvelopeUSB[noteNum]->noteOn();
noteNum++;
}
}
void myNoteOff(byte channel, byte note, byte velocity) {
AudioEffectEnvelope *myEnvelopeUSB[] = { &envelope1, &envelope2, &envelope3, &envelope4, &envelope5, &envelope6, &envelope7, &envelope8, &envelope9, &envelope10, &envelope11, &envelope12, &envelope13, &envelope14, &envelope15, &envelope16 };
myEnvelopeUSB[noteNum]->noteOff();
noteNum--;
Serial.println(noteNum);
}
AudioTool Code:
Code:
#ifndef _SYNTHARCH_H
#define _SYNTHARCH_H
#include <Arduino.h>
#include <Bounce.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioSynthWaveform modWave1; //xy=62,158
AudioMixer4 mixer5; //xy=78,246
AudioSynthWaveformModulated waveform14; //xy=183,1372
AudioSynthWaveformModulated waveform16; //xy=186,1555
AudioSynthWaveformModulated waveform15; //xy=188,1473
AudioSynthWaveformModulated waveform12; //xy=195,1155
AudioSynthWaveformModulated waveform13; //xy=198,1242
AudioSynthWaveformModulated waveform9; //xy=200,872
AudioSynthWaveformModulated waveform10; //xy=201,964
AudioSynthWaveformModulated waveform11; //xy=201,1051
AudioSynthWaveformModulated waveform6; //xy=232,541
AudioSynthWaveformModulated waveform5; //xy=240,434
AudioSynthWaveformModulated waveform4; //xy=244,338
AudioSynthWaveformModulated waveform8; //xy=247,739
AudioSynthWaveformModulated waveform7; //xy=253,646.0000095367432
AudioSynthWaveformModulated waveform3; //xy=257,244
AudioSynthWaveformModulated waveform1; //xy=264,63
AudioSynthWaveformModulated waveform2; //xy=269,146
AudioFilterStateVariable filter12; //xy=345,1149
AudioFilterStateVariable filter13; //xy=353,1245
AudioFilterStateVariable filter10; //xy=355,959
AudioFilterStateVariable filter9; //xy=356,877
AudioFilterStateVariable filter16; //xy=358,1550
AudioFilterStateVariable filter14; //xy=361,1368
AudioFilterStateVariable filter11; //xy=366,1052
AudioFilterStateVariable filter15; //xy=365,1474
AudioFilterStateVariable filter4; //xy=391,343
AudioFilterStateVariable filter5; //xy=399,439
AudioFilterStateVariable filter1; //xy=401,73
AudioFilterStateVariable filter2; //xy=401,153
AudioFilterStateVariable filter8; //xy=404,744
AudioFilterStateVariable filter6; //xy=407,562
AudioFilterStateVariable filter3; //xy=412,246
AudioFilterStateVariable filter7; //xy=411,668
AudioEffectEnvelope envelope12; //xy=525,1136
AudioEffectEnvelope envelope13; //xy=533,1232
AudioEffectEnvelope envelope10; //xy=535,946
AudioEffectEnvelope envelope16; //xy=538,1537
AudioEffectEnvelope envelope9; //xy=542,880
AudioEffectEnvelope envelope14; //xy=541,1352
AudioEffectEnvelope envelope11; //xy=546,1039
AudioEffectEnvelope envelope15; //xy=545,1461
AudioEffectEnvelope envelope1; //xy=557,56
AudioEffectEnvelope envelope4; //xy=571,330
AudioEffectEnvelope envelope5; //xy=579,426
AudioEffectEnvelope envelope2; //xy=581,140
AudioEffectEnvelope envelope8; //xy=584,731
AudioEffectEnvelope envelope6; //xy=587,549
AudioEffectEnvelope envelope3; //xy=592,233
AudioEffectEnvelope envelope7; //xy=591,655
AudioMixer4 mixer1; //xy=797,715
AudioMixer4 mixer2; //xy=804,824
AudioMixer4 mixer3; //xy=806,965
AudioMixer4 mixer4; //xy=809,1107
AudioMixer4 mixerFinal; //xy=1006,888
AudioEffectFreeverbStereo freeverbs1; //xy=1164.199966430664,819.0000133514404
AudioMixer4 verbMix; //xy=1329.1999702453613,885.0000133514404
AudioOutputI2S i2s1; //xy=1459.9999713897705,880.0000133514404
AudioConnection patchCord1(modWave1, 0, mixer5, 0);
AudioConnection patchCord2(mixer5, 0, waveform1, 0);
AudioConnection patchCord3(mixer5, 0, waveform2, 0);
AudioConnection patchCord4(mixer5, 0, waveform3, 0);
AudioConnection patchCord5(mixer5, 0, waveform4, 0);
AudioConnection patchCord6(mixer5, 0, waveform5, 0);
AudioConnection patchCord7(mixer5, 0, waveform6, 0);
AudioConnection patchCord8(mixer5, 0, waveform7, 0);
AudioConnection patchCord9(mixer5, 0, waveform8, 0);
AudioConnection patchCord10(waveform14, 0, filter14, 0);
AudioConnection patchCord11(waveform16, 0, filter16, 0);
AudioConnection patchCord12(waveform15, 0, filter15, 0);
AudioConnection patchCord13(waveform12, 0, filter12, 0);
AudioConnection patchCord14(waveform13, 0, filter13, 0);
AudioConnection patchCord15(waveform9, 0, filter9, 0);
AudioConnection patchCord16(waveform9, 0, filter9, 1);
AudioConnection patchCord17(waveform10, 0, filter10, 0);
AudioConnection patchCord18(waveform11, 0, filter11, 0);
AudioConnection patchCord19(waveform6, 0, filter6, 0);
AudioConnection patchCord20(waveform5, 0, filter5, 0);
AudioConnection patchCord21(waveform4, 0, filter4, 0);
AudioConnection patchCord22(waveform8, 0, filter8, 0);
AudioConnection patchCord23(waveform7, 0, filter7, 0);
AudioConnection patchCord24(waveform3, 0, filter3, 0);
AudioConnection patchCord25(waveform1, 0, filter1, 0);
AudioConnection patchCord26(waveform1, 0, filter1, 1);
AudioConnection patchCord27(waveform2, 0, filter2, 0);
AudioConnection patchCord28(filter12, 0, envelope12, 0);
AudioConnection patchCord29(filter13, 0, envelope13, 0);
AudioConnection patchCord30(filter10, 0, envelope10, 0);
AudioConnection patchCord31(filter9, 0, envelope9, 0);
AudioConnection patchCord32(filter16, 0, envelope16, 0);
AudioConnection patchCord33(filter14, 0, envelope14, 0);
AudioConnection patchCord34(filter11, 0, envelope11, 0);
AudioConnection patchCord35(filter15, 0, envelope15, 0);
AudioConnection patchCord36(filter4, 0, envelope4, 0);
AudioConnection patchCord37(filter5, 0, envelope5, 0);
AudioConnection patchCord38(filter1, 0, envelope1, 0);
AudioConnection patchCord39(filter2, 0, envelope2, 0);
AudioConnection patchCord40(filter8, 0, envelope8, 0);
AudioConnection patchCord41(filter6, 0, envelope6, 0);
AudioConnection patchCord42(filter3, 0, envelope3, 0);
AudioConnection patchCord43(filter7, 0, envelope7, 0);
AudioConnection patchCord44(envelope12, 0, mixer3, 3);
AudioConnection patchCord45(envelope13, 0, mixer4, 0);
AudioConnection patchCord46(envelope10, 0, mixer3, 1);
AudioConnection patchCord47(envelope16, 0, mixer4, 3);
AudioConnection patchCord48(envelope9, 0, mixer3, 0);
AudioConnection patchCord49(envelope14, 0, mixer4, 1);
AudioConnection patchCord50(envelope11, 0, mixer3, 2);
AudioConnection patchCord51(envelope15, 0, mixer4, 2);
AudioConnection patchCord52(envelope1, 0, mixer1, 0);
AudioConnection patchCord53(envelope4, 0, mixer1, 3);
AudioConnection patchCord54(envelope5, 0, mixer2, 0);
AudioConnection patchCord55(envelope2, 0, mixer1, 1);
AudioConnection patchCord56(envelope8, 0, mixer2, 3);
AudioConnection patchCord57(envelope6, 0, mixer2, 1);
AudioConnection patchCord58(envelope3, 0, mixer1, 2);
AudioConnection patchCord59(envelope7, 0, mixer2, 2);
AudioConnection patchCord60(mixer1, 0, mixerFinal, 0);
AudioConnection patchCord61(mixer2, 0, mixerFinal, 1);
AudioConnection patchCord62(mixer3, 0, mixerFinal, 2);
AudioConnection patchCord63(mixer4, 0, mixerFinal, 3);
AudioConnection patchCord64(mixerFinal, freeverbs1);
AudioConnection patchCord65(mixerFinal, 0, verbMix, 2);
AudioConnection patchCord66(freeverbs1, 0, verbMix, 0);
AudioConnection patchCord67(freeverbs1, 1, verbMix, 1);
AudioConnection patchCord68(verbMix, 0, i2s1, 0);
AudioConnection patchCord69(verbMix, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=866,598
// GUItool: end automatically generated code
#endif // _SYNTHARCH_H