Synthetech
Active member
Ok so you may have seen my Seenthysizer...
https://forum.pjrc.com/threads/42266-Project-quot-Seenthysizer-quot
inside there you will find info about my ongoing quest to make a really cool Virtual Analog Synth using Teensy 3.5+
(again, here is a link to the Ctrlr app I use to interface/control the Seenthysizer
https://drive.google.com/file/d/0B_IDH8cQH_eNSDhXUkxzcEJTZDQ/view?usp=sharing
because of the Teensy USB interface /Windows bug mentioned elsewhere, you MUST HAVE THE Ctrlr App CLOSED when you start up the Seenthysizer.
So keep the Ctrlr app closed, load the code below into the Teensy 3.+, then start the Ctrlr App.
IF YOU MUST RESTART THE TEENSY, YOU MUST SHUT OFF THE APP FIRST! Otherwise strange things happen! Usually the USB inteface wont work.. then you have to shut it all down and begin again.)
I have busted my butt and brain trying to figure out how to make a good simulation of a MonoSynth for the past 2-3 weeks now..
I wanted to come on here and BEG and PLEAD for help, but I knew I had to keep trying to figure it out for myself.. to LEARN.
Well.. I did figure it out for the most part. It works, 80% of the time..
What's it suppose to do?
Well it's suppose to let you hold one note down, then you press another note..
The first note will shut off and the next note starts.. but wait! Don't let go of the first note!!
So you let go of the SECOND NOTE and then the FIRST NOTE retriggers!
You can do very fast "trills" using this "Mono Mode".
What sounds really cool is using three notes.. hold a middle note down and then alternate between a upper note and a lower note.
What does it do wrong?
Seems every now and then WHEN I AM PLAYING REALLY FAST with 3+ notes.. either my Array get's jacked up or the "currNote" gets set to "0" at the wrong time.
I tried to debug it with Serial.print's in the code, but I guess whatever is happening to "glitch" my method is happening in an area I'm not looking.
I have tried and tried to find a good example of code to use with the Teensy to make this "monosynth" happen.
I found methods for other things.. Java, C++ vst's, etc.
But nothing was even close to what I needed for the Seenthysizer!
So after a few weeks of lots of precious time spent on how NOT TO DO IT, the following code is the best I could come up with.
I am hoping someone who is much more experienced with coding methods can figure out what I may have done wrong or can do to improve the note assignments.
Here's the complete MonoSeenthysizer code-
The area where the notes are manipulated is here-
Hopefully one of you coding gurus can load this up, have a midi keyboard to test it with and by some miracle figure out how to make it not glitch.. ever!
*crossing fingers*.....
/Blaine
https://forum.pjrc.com/threads/42266-Project-quot-Seenthysizer-quot
inside there you will find info about my ongoing quest to make a really cool Virtual Analog Synth using Teensy 3.5+
(again, here is a link to the Ctrlr app I use to interface/control the Seenthysizer
https://drive.google.com/file/d/0B_IDH8cQH_eNSDhXUkxzcEJTZDQ/view?usp=sharing
because of the Teensy USB interface /Windows bug mentioned elsewhere, you MUST HAVE THE Ctrlr App CLOSED when you start up the Seenthysizer.
So keep the Ctrlr app closed, load the code below into the Teensy 3.+, then start the Ctrlr App.
IF YOU MUST RESTART THE TEENSY, YOU MUST SHUT OFF THE APP FIRST! Otherwise strange things happen! Usually the USB inteface wont work.. then you have to shut it all down and begin again.)
I have busted my butt and brain trying to figure out how to make a good simulation of a MonoSynth for the past 2-3 weeks now..
I wanted to come on here and BEG and PLEAD for help, but I knew I had to keep trying to figure it out for myself.. to LEARN.
Well.. I did figure it out for the most part. It works, 80% of the time..
What's it suppose to do?
Well it's suppose to let you hold one note down, then you press another note..
The first note will shut off and the next note starts.. but wait! Don't let go of the first note!!
So you let go of the SECOND NOTE and then the FIRST NOTE retriggers!
You can do very fast "trills" using this "Mono Mode".
What sounds really cool is using three notes.. hold a middle note down and then alternate between a upper note and a lower note.
What does it do wrong?
Seems every now and then WHEN I AM PLAYING REALLY FAST with 3+ notes.. either my Array get's jacked up or the "currNote" gets set to "0" at the wrong time.
I tried to debug it with Serial.print's in the code, but I guess whatever is happening to "glitch" my method is happening in an area I'm not looking.
I have tried and tried to find a good example of code to use with the Teensy to make this "monosynth" happen.
I found methods for other things.. Java, C++ vst's, etc.
But nothing was even close to what I needed for the Seenthysizer!
So after a few weeks of lots of precious time spent on how NOT TO DO IT, the following code is the best I could come up with.
I am hoping someone who is much more experienced with coding methods can figure out what I may have done wrong or can do to improve the note assignments.
Here's the complete MonoSeenthysizer code-
Code:
/*MonoLead_v1-9_beta
this is a modification of the Seenthysizer 2.8
it is using 7 voices for one note..
all voices are tuned to the same frequency and
then detuned apart from each other to fatten up
the sound tremendously!
Mono Mode with last note retrigger for trill effects!
This is an attempt to emulate the famous Roland JP-8000
"SUPERSAW" voice that is much sought after in the dance/trance
music scene.
--Enjoy-- More to come as I figure out more..
-Blaine Perkins
*/
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioSynthWaveformDc lfoenvelope; //xy=1526.1395568847656,1195.7141723632812
AudioSynthWaveform lfo; //xy=1614.1395568847656,1401.7141723632812
AudioMixer4 mixer1; //xy=1657.1395568847656,1256.7141723632812
AudioAnalyzePeak peak1; //xy=1886.1395568847656,1119.7141723632812
AudioSynthWaveform voice8b; //xy=2122.1395568847656,2170.7141723632812
AudioSynthNoiseWhite voice8n; //xy=2122.1395568847656,2205.7141723632812
AudioSynthWaveform voice8a; //xy=2124.1395568847656,2132.7141723632812
AudioSynthWaveform voice4a; //xy=2143.1395568847656,1154.7141723632812
AudioSynthWaveform voice4b; //xy=2144.1395568847656,1192.7141723632812
AudioSynthNoiseWhite voice4n; //xy=2144.1395568847656,1227.7141723632812
AudioSynthWaveform voice5b; //xy=2145.1395568847656,1448.7141723632812
AudioSynthNoiseWhite voice5n; //xy=2145.1395568847656,1483.7141723632812
AudioSynthWaveform voice5a; //xy=2150.1395568847656,1405.7141723632812
AudioSynthWaveform voice7b; //xy=2154.1395568847656,1939.7141723632812
AudioSynthNoiseWhite voice7n; //xy=2154.1395568847656,1974.7141723632812
AudioSynthWaveform voice6b; //xy=2157.1395568847656,1702.7141723632812
AudioSynthNoiseWhite voice6n; //xy=2157.1395568847656,1737.7141723632812
AudioSynthWaveform voice6a; //xy=2159.1395568847656,1664.7141723632812
AudioSynthWaveform voice7a; //xy=2159.1395568847656,1896.7141723632812
AudioSynthWaveform voice3b; //xy=2165.1395568847656,944.7141723632812
AudioSynthNoiseWhite voice3n; //xy=2165.1395568847656,979.7141723632812
AudioSynthWaveform voice3a; //xy=2170.1395568847656,901.7141723632812
AudioSynthWaveform voice1b; //xy=2195.1395568847656,478.71417236328125
AudioSynthNoiseWhite voice1n; //xy=2198.1395568847656,522.7141723632812
AudioSynthWaveform voice2b; //xy=2198.1395568847656,712.7141723632812
AudioSynthNoiseWhite voice2n; //xy=2198.1395568847656,747.7141723632812
AudioSynthWaveform voice1a; //xy=2200.1395568847656,435.71417236328125
AudioSynthWaveform voice2a; //xy=2200.1395568847656,674.7141723632812
AudioSynthWaveformDc voice8filterenv; //xy=2250.1395568847656,2316.7141723632812
AudioSynthWaveformDc voice8env; //xy=2264.1395568847656,2255.7141723632812
AudioMixer4 voice8mix; //xy=2267.1395568847656,2190.7141723632812
AudioSynthWaveformDc voice4filterenv; //xy=2272.1395568847656,1338.7141723632812
AudioSynthWaveformDc voice5filterenv; //xy=2273.1395568847656,1594.7141723632812
AudioSynthWaveformDc voice7filterenv; //xy=2282.1395568847656,2085.7141723632812
AudioSynthWaveformDc voice4env; //xy=2286.1395568847656,1277.7141723632812
AudioSynthWaveformDc voice6filterenv; //xy=2285.1395568847656,1848.7141723632812
AudioSynthWaveformDc voice5env; //xy=2287.1395568847656,1533.7141723632812
AudioMixer4 voice4mix; //xy=2289.1395568847656,1212.7141723632812
AudioMixer4 voice5mix; //xy=2290.1395568847656,1468.7141723632812
AudioSynthWaveformDc voice3filterenv; //xy=2293.1395568847656,1090.7141723632812
AudioSynthWaveformDc voice7env; //xy=2296.1395568847656,2024.7141723632812
AudioSynthWaveformDc voice6env; //xy=2299.1395568847656,1787.7141723632812
AudioMixer4 voice7mix; //xy=2299.1395568847656,1959.7141723632812
AudioMixer4 voice6mix; //xy=2302.1395568847656,1722.7141723632812
AudioSynthWaveformDc voice3env; //xy=2307.1395568847656,1029.7141723632812
AudioMixer4 voice3mix; //xy=2310.1395568847656,964.7141723632812
AudioSynthWaveformDc voice1filterenv; //xy=2324.1395568847656,614.7141723632812
AudioSynthWaveformDc voice2filterenv; //xy=2326.1395568847656,858.7141723632812
AudioMixer4 voice1mix; //xy=2340.1395568847656,498.71417236328125
AudioSynthWaveformDc voice2env; //xy=2340.1395568847656,797.7141723632812
AudioSynthWaveformDc voice1env; //xy=2341.1395568847656,563.7141723632812
AudioMixer4 voice2mix; //xy=2343.1395568847656,732.7141723632812
AudioEffectMultiply voice8multiply; //xy=2431.1395568847656,2228.7141723632812
AudioMixer4 voice8filtermodmixer; //xy=2441.1395568847656,2344.7141723632812
AudioEffectMultiply voice4multiply; //xy=2453.1395568847656,1250.7141723632812
AudioEffectMultiply voice5multiply; //xy=2454.1395568847656,1506.7141723632812
AudioMixer4 voice4filtermodmixer; //xy=2463.1395568847656,1366.7141723632812
AudioEffectMultiply voice7multiply; //xy=2463.1395568847656,1997.7141723632812
AudioEffectMultiply voice6multiply; //xy=2466.1395568847656,1760.7141723632812
AudioMixer4 voice5filtermodmixer; //xy=2471.1395568847656,1616.7141723632812
AudioEffectMultiply voice3multiply; //xy=2474.1395568847656,1002.7141723632812
AudioMixer4 voice6filtermodmixer; //xy=2476.1395568847656,1876.7141723632812
AudioMixer4 voice7filtermodmixer; //xy=2480.1395568847656,2107.7141723632812
AudioMixer4 voice3filtermodmixer; //xy=2491.1395568847656,1112.7141723632812
AudioEffectMultiply voice1multiply; //xy=2504.1395568847656,536.7141723632812
AudioEffectMultiply voice2multiply; //xy=2507.1395568847656,770.7141723632812
AudioMixer4 voice2filtermodmixer; //xy=2517.1395568847656,886.7141723632812
AudioMixer4 voice1filtermodmixer; //xy=2521.1395568847656,646.7141723632812
AudioFilterStateVariable voice8filter; //xy=2614.1395568847656,2251.7141723632812
AudioFilterStateVariable voice5filter; //xy=2634.1395568847656,1550.7141723632812
AudioFilterStateVariable voice4filter; //xy=2636.1395568847656,1273.7141723632812
AudioFilterStateVariable voice7filter; //xy=2643.1395568847656,2041.7141723632812
AudioFilterStateVariable voice6filter; //xy=2649.1395568847656,1783.7141723632812
AudioFilterStateVariable voice3filter; //xy=2654.1395568847656,1046.7141723632812
AudioFilterStateVariable voice2filter; //xy=2690.1395568847656,793.7141723632812
AudioFilterStateVariable voice1filter; //xy=2707.1395568847656,588.7141723632812
AudioMixer4 last4premix; //xy=3114.1395568847656,1523.7141723632812
AudioMixer4 first4premix; //xy=3115.1395568847656,1439.7141723632812
AudioMixer4 mainOutMixer; //xy=3519.4252014160156,1509.5711517333984
AudioFilterStateVariable delayFilter; //xy=3564.1395568847656,1633.7141723632812
AudioEffectDelay delay1; //xy=3693.1395568847656,1828.7141723632812
AudioOutputUSB usb1; //xy=3860.2857666015625,1450.28564453125
AudioOutputI2S i2s1; //xy=3861.1395568847656,1514.7141723632812
AudioConnection patchCord1(lfoenvelope, 0, mixer1, 0);
AudioConnection patchCord2(lfo, 0, voice1filtermodmixer, 1);
AudioConnection patchCord3(lfo, 0, voice2filtermodmixer, 1);
AudioConnection patchCord4(lfo, 0, voice3filtermodmixer, 1);
AudioConnection patchCord5(lfo, 0, voice4filtermodmixer, 1);
AudioConnection patchCord6(lfo, 0, voice5filtermodmixer, 1);
AudioConnection patchCord7(lfo, 0, voice6filtermodmixer, 1);
AudioConnection patchCord8(lfo, 0, voice7filtermodmixer, 1);
AudioConnection patchCord9(lfo, 0, voice8filtermodmixer, 1);
AudioConnection patchCord10(lfo, 0, mixer1, 1);
AudioConnection patchCord11(mixer1, peak1);
AudioConnection patchCord12(voice8b, 0, voice8mix, 1);
AudioConnection patchCord13(voice8n, 0, voice8mix, 2);
AudioConnection patchCord14(voice8a, 0, voice8mix, 0);
AudioConnection patchCord15(voice4a, 0, voice4mix, 0);
AudioConnection patchCord16(voice4b, 0, voice4mix, 1);
AudioConnection patchCord17(voice4n, 0, voice4mix, 2);
AudioConnection patchCord18(voice5b, 0, voice5mix, 1);
AudioConnection patchCord19(voice5n, 0, voice5mix, 2);
AudioConnection patchCord20(voice5a, 0, voice5mix, 0);
AudioConnection patchCord21(voice7b, 0, voice7mix, 1);
AudioConnection patchCord22(voice7n, 0, voice7mix, 2);
AudioConnection patchCord23(voice6b, 0, voice6mix, 1);
AudioConnection patchCord24(voice6n, 0, voice6mix, 2);
AudioConnection patchCord25(voice6a, 0, voice6mix, 0);
AudioConnection patchCord26(voice7a, 0, voice7mix, 0);
AudioConnection patchCord27(voice3b, 0, voice3mix, 1);
AudioConnection patchCord28(voice3n, 0, voice3mix, 2);
AudioConnection patchCord29(voice3a, 0, voice3mix, 0);
AudioConnection patchCord30(voice1b, 0, voice1mix, 1);
AudioConnection patchCord31(voice1n, 0, voice1mix, 2);
AudioConnection patchCord32(voice2b, 0, voice2mix, 1);
AudioConnection patchCord33(voice2n, 0, voice2mix, 3);
AudioConnection patchCord34(voice1a, 0, voice1mix, 0);
AudioConnection patchCord35(voice2a, 0, voice2mix, 0);
AudioConnection patchCord36(voice8filterenv, 0, voice8filtermodmixer, 0);
AudioConnection patchCord37(voice8env, 0, voice8multiply, 1);
AudioConnection patchCord38(voice8mix, 0, voice8multiply, 0);
AudioConnection patchCord39(voice4filterenv, 0, voice4filtermodmixer, 0);
AudioConnection patchCord40(voice5filterenv, 0, voice5filtermodmixer, 0);
AudioConnection patchCord41(voice7filterenv, 0, voice7filtermodmixer, 0);
AudioConnection patchCord42(voice4env, 0, voice4multiply, 1);
AudioConnection patchCord43(voice6filterenv, 0, voice6filtermodmixer, 0);
AudioConnection patchCord44(voice5env, 0, voice5multiply, 1);
AudioConnection patchCord45(voice4mix, 0, voice4multiply, 0);
AudioConnection patchCord46(voice5mix, 0, voice5multiply, 0);
AudioConnection patchCord47(voice3filterenv, 0, voice3filtermodmixer, 0);
AudioConnection patchCord48(voice7env, 0, voice7multiply, 1);
AudioConnection patchCord49(voice6env, 0, voice6multiply, 1);
AudioConnection patchCord50(voice7mix, 0, voice7multiply, 0);
AudioConnection patchCord51(voice6mix, 0, voice6multiply, 0);
AudioConnection patchCord52(voice3env, 0, voice3multiply, 1);
AudioConnection patchCord53(voice3mix, 0, voice3multiply, 0);
AudioConnection patchCord54(voice1filterenv, 0, voice1filtermodmixer, 0);
AudioConnection patchCord55(voice2filterenv, 0, voice2filtermodmixer, 0);
AudioConnection patchCord56(voice1mix, 0, voice1multiply, 0);
AudioConnection patchCord57(voice2env, 0, voice2multiply, 1);
AudioConnection patchCord58(voice1env, 0, voice1multiply, 1);
AudioConnection patchCord59(voice2mix, 0, voice2multiply, 0);
AudioConnection patchCord60(voice8multiply, 0, voice8filter, 0);
AudioConnection patchCord61(voice8filtermodmixer, 0, voice8filter, 1);
AudioConnection patchCord62(voice4multiply, 0, voice4filter, 0);
AudioConnection patchCord63(voice5multiply, 0, voice5filter, 0);
AudioConnection patchCord64(voice4filtermodmixer, 0, voice4filter, 1);
AudioConnection patchCord65(voice7multiply, 0, voice7filter, 0);
AudioConnection patchCord66(voice6multiply, 0, voice6filter, 0);
AudioConnection patchCord67(voice5filtermodmixer, 0, voice5filter, 1);
AudioConnection patchCord68(voice3multiply, 0, voice3filter, 0);
AudioConnection patchCord69(voice6filtermodmixer, 0, voice6filter, 1);
AudioConnection patchCord70(voice7filtermodmixer, 0, voice7filter, 1);
AudioConnection patchCord71(voice3filtermodmixer, 0, voice3filter, 1);
AudioConnection patchCord72(voice1multiply, 0, voice1filter, 0);
AudioConnection patchCord73(voice2multiply, 0, voice2filter, 0);
AudioConnection patchCord74(voice2filtermodmixer, 0, voice2filter, 1);
AudioConnection patchCord75(voice1filtermodmixer, 0, voice1filter, 1);
AudioConnection patchCord76(voice8filter, 0, last4premix, 3);
AudioConnection patchCord77(voice5filter, 0, last4premix, 0);
AudioConnection patchCord78(voice4filter, 0, first4premix, 3);
AudioConnection patchCord79(voice7filter, 0, last4premix, 2);
AudioConnection patchCord80(voice6filter, 0, last4premix, 1);
AudioConnection patchCord81(voice3filter, 0, first4premix, 2);
AudioConnection patchCord82(voice2filter, 0, first4premix, 1);
AudioConnection patchCord83(voice1filter, 0, first4premix, 0);
AudioConnection patchCord84(last4premix, 0, mainOutMixer, 1);
AudioConnection patchCord85(first4premix, 0, mainOutMixer, 0);
AudioConnection patchCord86(mainOutMixer, 0, i2s1, 0);
AudioConnection patchCord87(mainOutMixer, 0, i2s1, 1);
AudioConnection patchCord88(mainOutMixer, delay1);
AudioConnection patchCord89(mainOutMixer, 0, usb1, 1);
AudioConnection patchCord90(mainOutMixer, 0, usb1, 0);
AudioConnection patchCord91(delayFilter, 0, mainOutMixer, 3);
AudioConnection patchCord92(delay1, 0, delayFilter, 0);
AudioControlSGTL5000 sgtl5000_1; //xy=3598.1395568847656,1283.7141723632812
// GUItool: end automatically generated code
Bounce button0 = Bounce(0, 15);
//a table to store CC values coming in from the usbMIDI interface
//later any value can be recalled for each parameter
float CCvalues[128];
float prevCCvalues[128];
// array for the notes to be assigned to one of eight voices
int voice[4];
int noteFreq[1];
//vars for the state machine cases
const int noteOnWait = 0;
const int ATTACK = 1;
const int ATTACKwait = 2;
const int DECAY = 3;
const int SUSTAIN = 4;
const int RELEASE1 = 5;
//beginning cases for each voice state machines
int state0a = noteOnWait;
int state0b = noteOnWait;
int state0c = noteOnWait;
int state0d = noteOnWait;
int state0e = noteOnWait;
int state0f = noteOnWait;
int state0g = noteOnWait;
int state0h = noteOnWait;
int state0i = noteOnWait;
int state0j = noteOnWait;
int state0k = noteOnWait;
int state0l = noteOnWait;
int state0m = noteOnWait;
int state0n = noteOnWait;
int state0o = noteOnWait;
int state0p = noteOnWait;
//ADSR timing elements
unsigned long int attackMillisA[8];
unsigned long int attackMillisF[8];
//used to track how many voices are active
int noteCount = 0;
//used to track the current note
int currNote = 0;
//some of this from previous code may not be in use
float tempPulseWidth;
float tempPeak;
float tempRMS;
//synth
float mainVolume;
//not used at this time
//int tempLineOutLevel;
float vcoOneLevel;
float vcoTwoLevel;
float deTune;
float deTune1;
float deTune2;
float deTune3;
float deTune5;
float deTune6;
float deTune7;
int waveShapeOneIndex;
int waveShapeTwoIndex;
int lfoWaveShapeIndex;
short waveShapes[4] = {
WAVEFORM_SINE,
WAVEFORM_SAWTOOTH,
WAVEFORM_SQUARE,
WAVEFORM_PULSE,
};
bool voiceBPulse;
float tempDetuneMod;
float deTuneLfo;
//LFO WaveShapes
short lfoWaveShapes[5] = {
WAVEFORM_SINE,
WAVEFORM_SAWTOOTH,
WAVEFORM_SAWTOOTH_REVERSE,
WAVEFORM_SQUARE,
WAVEFORM_SAMPLE_HOLD,
};
//ADSR
int attackTime;
int decayTime;
float sustainLevel;
int releaseTime;
//Filter ADSR
int attackTimeFilter;
int decayTimeFilter;
float sustainLevelFilter;
int releaseTimeFilter;
//LFO ADSR -- not used at this time
// int attackTimeLFO;
// int decayTimeLFO;
// float sustainLevelLFO;
// int releaseTimeLFO;
//function to allocate a new MIDI Note On to the Note Stack array
//will kill current playing note and begin new note On if a prev. note is on
/*void killNotes()
{
currNote = 0;
state0a = noteOnWait;
voice1env.amplitude(0, 0);
state0b = noteOnWait;
voice1filterenv.amplitude(0, 0);
state0c = noteOnWait;
voice2env.amplitude(0, 0);
state0d = noteOnWait;
voice2filterenv.amplitude(0, 0);
state0e = noteOnWait;
voice3env.amplitude(0, 0);
state0f = noteOnWait;
voice3filterenv.amplitude(0, 0);
state0g = noteOnWait;
voice4env.amplitude(0, 0);
state0h = noteOnWait;
voice4filterenv.amplitude(0, 0);
state0i = noteOnWait;
voice5env.amplitude(0, 0);
state0j = noteOnWait;
voice5filterenv.amplitude(0, 0);
state0k = noteOnWait;
voice6env.amplitude(0, 0);
state0l = noteOnWait;
voice6filterenv.amplitude(0, 0);
state0m = noteOnWait;
voice7env.amplitude(0, 0);
state0n = noteOnWait;
voice7filterenv.amplitude(0, 0);
state0o = noteOnWait;
voice8env.amplitude(0, 0);
state0p = noteOnWait;
voice8filterenv.amplitude(0, 0);
}
*/
//MIDI routines
//triggered when usb port has data
void OnControlChange (byte Channel, byte control, byte value)
{
MIDIccData(control, value);
}
void OnNoteOn(byte channel, byte note, byte velocity)
{
MIDInoteOn(note, velocity);
}
void OnNoteOff(byte channel, byte note, byte velocity)
{
MIDInoteOff(note, velocity);
}
void MIDInoteOn(int note, int vel)
{
if (noteCount == 5) {
Serial.println("Voice Limit Exceeded!");
return;
}
if (!noteCount) {
voice [0] = note;
currNote = voice[0];
noteCount++;
Serial.print("1st Note # ");
Serial.println(currNote);
Serial.println("notecount= ");
Serial.println(noteCount);
return;
}
//Serial.println(i+1);
currNote=0;
for (int i = 0; i < 4; i++) {
if (!voice[i]) {
voice[i] = note;
currNote = voice[i];
noteCount++;
Serial.print("Replacement Note # ");
Serial.println(currNote);
Serial.print("Assigned to Voice # ");
Serial.println(i + 1);
Serial.println();
Serial.println("notecount= ");
Serial.println(noteCount);
break;
}
}
}
void MIDIccData(int CCnumber, float CCvalue)
{
//Serial.print("CC#= ");
//Serial.print(CCnumber);
//Serial.print(" Value= ");
//Serial.println(CCvalue);
//assign values to the CC lookup table
CCvalues[CCnumber] = {CCvalue};
}
//shuts notes off, removes them from note Stack and shifts the remainder notes
//towards bottom to keep all active notes down together in array
void MIDInoteOff(int note, int vel)
{
if (note == currNote && noteCount>1) {
currNote=0;
Serial.print("Trying to find note # ");
Serial.println(note);
for (int i = 0; i < 4; i++) {
Serial.print("searching voice- ");
Serial.println(i);
if (note == voice[i]) {
Serial.print("I FOUND IT! ");
voice[i] = 0;
currNote = voice[i - 1];
noteCount--;
Serial.print("Current note off # ");
Serial.println(note);
Serial.println("Shut Off Current Voice # ");
Serial.println(i + 1);
Serial.print("Current note ON # ");
Serial.println(currNote);
Serial.println();
Serial.println("notecount= ");
Serial.println(noteCount);
break;
}
}
return;
}
if (noteCount < 2) {
voice[0] = 0;
currNote = 0;
noteCount--;
if (noteCount < 0) {
noteCount = 0;
}
Serial.print("Last note off # ");
Serial.println(note);
Serial.println("Shut Off Voice # 1 ");
Serial.println();
Serial.println("notecount= ");
Serial.println(noteCount);
return;
//Serial.println(i+1);
}
if (noteCount > 1) {
for (int i = 0; i < 4; i++) {
if (voice[i] == note) {
voice[i] = 0;
Serial.print("Drop off note # ");
Serial.println(note);
Serial.print("Drop Off Voice # ");
Serial.println(i + 1);
for (int c = i + 1; c < 4; c++) {
voice[i] = voice[c];
i = i++;
}
voice[3] = 0;
noteCount--;
Serial.print("-note off # ");
Serial.println(note);
Serial.println();
Serial.println("notecount= ");
Serial.println(noteCount);
break;
}
}
}
}
//called to immediatly shut voices down when a new note is pressed down
//allows the new note to retrigger EG
//an exponential formula mapping function
float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
void setup() {
AudioMemory(320);
Serial.begin(9600);
sgtl5000_1.enable();
sgtl5000_1.volume(.7);
usbMIDI.setHandleNoteOff(OnNoteOff);
usbMIDI.setHandleNoteOn(OnNoteOn) ;
usbMIDI.setHandleControlChange(OnControlChange);
pinMode(0, INPUT_PULLUP);
//mix
first4premix.gain(0, .25);
first4premix.gain(1, .25);
first4premix.gain(2, .25);
first4premix.gain(3, .25);
last4premix.gain(0, .25);
last4premix.gain(1, .25);
last4premix.gain(2, .25);
last4premix.gain(3, .25);
//initiate values to CCvalues array for the default patch
CCvalues[7] = 119;
//CCvalues[32] = 15;
//CCvalues[33] = 8;
CCvalues[34] = 127;
CCvalues[35] = 5;
CCvalues[36] = 127;
CCvalues[40] = 32;
CCvalues[41] = 32;
//CCvalues[42] = 81;
//CCvalues[43] = 64;
CCvalues[44] = 83;
CCvalues[45] = 4;
//CCvalues[46] = 52;
//CCvalues[47] = 3;
CCvalues[49] = 127;
CCvalues[50] = 90;
CCvalues[71] = 43;
CCvalues[74] = 127;
CCvalues[94] = 17;
CCvalues[88] = 10;
CCvalues[89] = 10;
// initialize the oscillators
//Voice 1
//voice1a.begin(.3, 440, WAVEFORM_SQUARE);
voice1b.begin(.3, 440, WAVEFORM_SAWTOOTH);
//Voice 2
//voice2a.begin(.3, 440, WAVEFORM_SQUARE);
voice2b.begin(.3, 440, WAVEFORM_SAWTOOTH);
//Voice 3
//voice3a.begin(.3, 440, WAVEFORM_SQUARE);
voice3b.begin(.3, 440, WAVEFORM_SAWTOOTH);
//Voice 4
//voice4a.begin(.3, 440, WAVEFORM_SQUARE);
voice4b.begin(.3, 440, WAVEFORM_SAWTOOTH);
//Voice 5
//voice5a.begin(.3, 440, WAVEFORM_SQUARE);
voice5b.begin(.3, 440, WAVEFORM_SAWTOOTH);
//Voice 6
//voice6a.begin(.3, 440, WAVEFORM_SQUARE);
voice6b.begin(.3, 440, WAVEFORM_SAWTOOTH);
//Voice 7
//voice7a.begin(.3, 440, WAVEFORM_SQUARE);
voice7b.begin(.3, 440, WAVEFORM_SAWTOOTH);
//Voice 8
//voice8a.begin(.3, 440, WAVEFORM_SQUARE);
//voice8b.begin(.3, 440, WAVEFORM_SAWTOOTH);
delayFilter.frequency(3000);
delayFilter.resonance(1);
delay1.delay(0, 0);
mainOutMixer.gain(3, 0);
//LFO
lfo.begin(1, 3, WAVEFORM_SINE);
lfo.frequency(0);
voice1filtermodmixer.gain(1, 0);
voice2filtermodmixer.gain(1, 0);
voice3filtermodmixer.gain(1, 0);
voice4filtermodmixer.gain(1, 0);
voice5filtermodmixer.gain(1, 0);
voice6filtermodmixer.gain(1, 0);
voice7filtermodmixer.gain(1, 0);
voice8filtermodmixer.gain(1, 0);
deTune = 1;
mainOutMixer.gain(0, .5);
mainOutMixer.gain(1, .5);
//lfoenvelope.amplitude(1);
voiceBPulse = false;
}
void loop() {
usbMIDI.read();
button0.update();
//prints the values set in the CC lookup table
if (button0.fallingEdge()) {
for (int i = 0; i < 128; i++) {
if (CCvalues[i]) {
Serial.print("CC:");
Serial.print(i);
Serial.print(" is Value:");
Serial.print(CCvalues[i]);
Serial.println();
}
}
}
//Volume
mainVolume = CCvalues[7];
mainVolume = mainVolume / 127;
sgtl5000_1.volume(mainVolume);
//not used at this time
//tempLineOutLevel = CCvalues[7];
//tempLineOutLevel = map(tempLineOutLevel, 0, 127, 31, 13);
//sgtl5000_1.lineOutLevel(tempLineOutLevel);
//start of voice service for loop
//notes set to frequencies
for (int i = 0; i < 8; i++) {
if (i == 0) {
//voice1a.frequency(440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333));
voice1b.frequency((440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333))* deTune1);
}
if (i == 0) {
//voice2a.frequency(440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333));
voice2b.frequency((440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333))* deTune2);
}
if (i == 0) {
//voice3a.frequency(440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333));
voice3b.frequency((440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333))* deTune3);
}
if (i == 0) {
//voice4a.frequency(440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333));
voice4b.frequency(440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333));
}
if (i == 0) {
//voice5a.frequency(440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333));
voice5b.frequency((440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333))* deTune5);
}
if (i == 0) {
//voice6a.frequency(440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333));
voice6b.frequency((440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333))* deTune6);
}
if (i == 0) {
//voice7a.frequency(440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333));
voice7b.frequency((440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333))* deTune7);
}
if (i == 7) {
//voice8a.frequency(440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333));
//voice8b.frequency((440.0 * powf(2.0, (float)(currNote - 69) * 0.08333333))* deTune);
}
//sevice envelopes for voices
if (i == 0) {
switch (state0a) {
//service the Amp ADSR
case noteOnWait:
if (currNote) {
state0a = ATTACK;
}
break;
case ATTACK:
attackMillisA[i] = millis();
voice1env.amplitude(1, attackTime);
state0a = ATTACKwait;
if (!currNote) {
state0a = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisA[i] > attackTime) {
state0a = DECAY;
}
if (!currNote) {
state0a = RELEASE1;
}
break;
case DECAY:
voice1env.amplitude(sustainLevel, decayTime);
state0a = SUSTAIN;
if (!currNote) {
state0a = RELEASE1;
}
break;
case SUSTAIN:
if (!currNote) {
state0a = RELEASE1;
}
break;
case RELEASE1:
voice1env.amplitude(0, releaseTime);
state0a = noteOnWait;
break;
}
// service the Filter ADSR
switch (state0b) {
case noteOnWait:
if (currNote) {
state0b = ATTACK;
}
break;
case ATTACK:
attackMillisF[i] = millis();
voice1filterenv.amplitude(1, attackTimeFilter);
state0b = ATTACKwait;
if (!currNote) {
state0b = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisF[i] > attackTimeFilter) {
state0b = DECAY;
}
if (!currNote) {
state0b = RELEASE1;
}
break;
case DECAY:
voice1filterenv.amplitude(sustainLevelFilter, decayTimeFilter);
state0b = SUSTAIN;
if (!currNote) {
state0b = RELEASE1;
}
break;
case SUSTAIN:
if (!currNote) {
state0b = RELEASE1;
}
break;
case RELEASE1:
voice1filterenv.amplitude(0, releaseTimeFilter);
state0b = noteOnWait;
break;
}
}
if (i == 1) {
switch (state0c) {
//service the Amp ADSR
case noteOnWait:
if (currNote) {
state0c = ATTACK;
}
break;
case ATTACK:
attackMillisA[i] = millis();
voice2env.amplitude(1, attackTime);
state0c = ATTACKwait;
if (!currNote) {
state0c = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisA[i] > attackTime) {
state0c = DECAY;
}
if (!currNote) {
state0c = RELEASE1;
}
break;
case DECAY:
voice2env.amplitude(sustainLevel, decayTime);
state0c = SUSTAIN;
if (!currNote) {
state0c = RELEASE1;
}
break;
case SUSTAIN:
if (!currNote) {
state0c = RELEASE1;
}
break;
case RELEASE1:
voice2env.amplitude(0, releaseTime);
state0c = noteOnWait;
break;
}
// service the Filter ADSR
switch (state0d) {
case noteOnWait:
if (currNote) {
state0d = ATTACK;
}
break;
case ATTACK:
attackMillisF[i] = millis();
voice2filterenv.amplitude(1, attackTimeFilter);
state0d = ATTACKwait;
if (!currNote) {
state0d = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisF[i] > attackTimeFilter) {
state0d = DECAY;
}
if (!currNote) {
state0d = RELEASE1;
}
break;
case DECAY:
voice2filterenv.amplitude(sustainLevelFilter, decayTimeFilter);
state0d = SUSTAIN;
if (!currNote) {
state0d = RELEASE1;
}
break;
case SUSTAIN:
if (!currNote) {
state0d = RELEASE1;
}
break;
case RELEASE1:
voice2filterenv.amplitude(0, releaseTimeFilter);
state0d = noteOnWait;
break;
}
}
if (i == 2) {
switch (state0e) {
//service the Amp ADSR
case noteOnWait:
if (currNote) {
state0e = ATTACK;
}
break;
case ATTACK:
attackMillisA[i] = millis();
voice3env.amplitude(1, attackTime);
state0e = ATTACKwait;
if (!currNote) {
state0e = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisA[i] > attackTime) {
state0e = DECAY;
}
if (!currNote) {
state0e = RELEASE1;
}
break;
case DECAY:
voice3env.amplitude(sustainLevel, decayTime);
state0e = SUSTAIN;
if (!currNote) {
state0e = RELEASE1;
}
break;
case SUSTAIN:
if (!currNote) {
state0e = RELEASE1;
}
break;
case RELEASE1:
voice3env.amplitude(0, releaseTime);
state0e = noteOnWait;
break;
}
// service the Filter ADSR
switch (state0f) {
case noteOnWait:
if (currNote) {
state0f = ATTACK;
}
break;
case ATTACK:
attackMillisF[i] = millis();
voice3filterenv.amplitude(1, attackTimeFilter);
state0f = ATTACKwait;
if (!currNote) {
state0f = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisF[i] > attackTimeFilter) {
state0f = DECAY;
}
if (!currNote) {
state0f = RELEASE1;
}
break;
case DECAY:
voice3filterenv.amplitude(sustainLevelFilter, decayTimeFilter);
state0f = SUSTAIN;
if (!currNote) {
state0f = RELEASE1;
}
break;
case SUSTAIN:
if (!currNote) {
state0f = RELEASE1;
}
break;
case RELEASE1:
voice3filterenv.amplitude(0, releaseTimeFilter);
state0f = noteOnWait;
break;
}
}
if (i == 3) {
switch (state0g) {
//service the Amp ADSR
case noteOnWait:
if (currNote) {
state0g = ATTACK;
}
break;
case ATTACK:
attackMillisA[i] = millis();
voice4env.amplitude(1, attackTime);
state0g = ATTACKwait;
if (!currNote) {
state0g = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisA[i] > attackTime) {
state0g = DECAY;
}
if (!currNote) {
state0g = RELEASE1;
}
break;
case DECAY:
voice4env.amplitude(sustainLevel, decayTime);
state0g = SUSTAIN;
if (!currNote) {
state0g = RELEASE1;
}
break;
case SUSTAIN:
if (!currNote) {
state0g = RELEASE1;
}
break;
case RELEASE1:
voice4env.amplitude(0, releaseTime);
state0g = noteOnWait;
break;
}
// service the Filter ADSR
switch (state0h) {
case noteOnWait:
if (currNote) {
state0h = ATTACK;
}
break;
case ATTACK:
attackMillisF[i] = millis();
voice4filterenv.amplitude(1, attackTimeFilter);
state0h = ATTACKwait;
if (!currNote) {
state0h = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisF[i] > attackTimeFilter) {
state0h = DECAY;
}
if (!currNote) {
state0h = RELEASE1;
}
break;
case DECAY:
voice4filterenv.amplitude(sustainLevelFilter, decayTimeFilter);
state0h = SUSTAIN;
if (!currNote) {
state0h = RELEASE1;
}
break;
case SUSTAIN:
if (!currNote) {
state0h = RELEASE1;
}
break;
case RELEASE1:
voice4filterenv.amplitude(0, releaseTimeFilter);
state0h = noteOnWait;
break;
}
}
if (i == 4) {
switch (state0i) {
//service the Amp ADSR
case noteOnWait:
if (currNote) {
state0i = ATTACK;
}
break;
case ATTACK:
attackMillisA[i] = millis();
voice5env.amplitude(1, attackTime);
state0i = ATTACKwait;
if (!currNote) {
state0i = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisA[i] > attackTime) {
state0i = DECAY;
}
if (!currNote) {
state0i = RELEASE1;
}
break;
case DECAY:
voice5env.amplitude(sustainLevel, decayTime);
state0i = SUSTAIN;
if (!currNote) {
state0i = RELEASE1;
}
break;
case SUSTAIN:
if (!currNote) {
state0i = RELEASE1;
}
break;
case RELEASE1:
voice5env.amplitude(0, releaseTime);
state0i = noteOnWait;
break;
}
// service the Filter ADSR
switch (state0j) {
case noteOnWait:
if (currNote) {
state0j = ATTACK;
}
break;
case ATTACK:
attackMillisF[i] = millis();
voice5filterenv.amplitude(1, attackTimeFilter);
state0j = ATTACKwait;
if (!currNote) {
state0j = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisF[i] > attackTimeFilter) {
state0j = DECAY;
}
if (!currNote) {
state0j = RELEASE1;
}
break;
case DECAY:
voice5filterenv.amplitude(sustainLevelFilter, decayTimeFilter);
state0j = SUSTAIN;
if (!currNote) {
state0j = RELEASE1;
}
break;
case SUSTAIN:
if (!currNote) {
state0j = RELEASE1;
}
break;
case RELEASE1:
voice5filterenv.amplitude(0, releaseTimeFilter);
state0j = noteOnWait;
break;
}
}
if (i == 5) {
switch (state0k) {
//service the Amp ADSR
case noteOnWait:
if (currNote) {
state0k = ATTACK;
}
break;
case ATTACK:
attackMillisA[i] = millis();
voice6env.amplitude(1, attackTime);
state0k = ATTACKwait;
if (!currNote) {
state0k = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisA[i] > attackTime) {
state0k = DECAY;
}
if (!currNote) {
state0k = RELEASE1;
}
break;
case DECAY:
voice6env.amplitude(sustainLevel, decayTime);
state0k = SUSTAIN;
if (!currNote) {
state0k = RELEASE1;
}
break;
case SUSTAIN:
if (!currNote) {
state0k = RELEASE1;
}
break;
case RELEASE1:
voice6env.amplitude(0, releaseTime);
state0k = noteOnWait;
break;
}
// service the Filter ADSR
switch (state0l) {
case noteOnWait:
if (currNote) {
state0l = ATTACK;
}
break;
case ATTACK:
attackMillisF[i] = millis();
voice6filterenv.amplitude(1, attackTimeFilter);
state0l = ATTACKwait;
if (!currNote) {
state0l = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisF[i] > attackTimeFilter) {
state0l = DECAY;
}
if (!currNote) {
state0l = RELEASE1;
}
break;
case DECAY:
voice6filterenv.amplitude(sustainLevelFilter, decayTimeFilter);
state0l = SUSTAIN;
if (!currNote) {
state0l = RELEASE1;
}
break;
case SUSTAIN:
if (!currNote) {
state0l = RELEASE1;
}
break;
case RELEASE1:
voice6filterenv.amplitude(0, releaseTimeFilter);
state0l = noteOnWait;
break;
}
}
if (i == 6) {
switch (state0m) {
//service the Amp ADSR
case noteOnWait:
if (currNote) {
state0m = ATTACK;
}
break;
case ATTACK:
attackMillisA[i] = millis();
voice7env.amplitude(1, attackTime);
state0m = ATTACKwait;
if (!currNote) {
state0m = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisA[i] > attackTime) {
state0m = DECAY;
}
if (!currNote) {
state0m = RELEASE1;
}
break;
case DECAY:
voice7env.amplitude(sustainLevel, decayTime);
state0m = SUSTAIN;
if (!currNote) {
state0m = RELEASE1;
}
break;
case SUSTAIN:
if (!currNote) {
state0m = RELEASE1;
}
break;
case RELEASE1:
voice7env.amplitude(0, releaseTime);
state0m = noteOnWait;
break;
}
// service the Filter ADSR
switch (state0n) {
case noteOnWait:
if (currNote) {
state0n = ATTACK;
}
break;
case ATTACK:
attackMillisF[i] = millis();
voice7filterenv.amplitude(1, attackTimeFilter);
state0n = ATTACKwait;
if (!currNote) {
state0n = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisF[i] > attackTimeFilter) {
state0n = DECAY;
}
if (!currNote) {
state0n = RELEASE1;
}
break;
case DECAY:
voice7filterenv.amplitude(sustainLevelFilter, decayTimeFilter);
state0n = SUSTAIN;
if (!currNote) {
state0n = RELEASE1;
}
break;
case SUSTAIN:
if (!currNote) {
state0n = RELEASE1;
}
break;
case RELEASE1:
voice7filterenv.amplitude(0, releaseTimeFilter);
state0n = noteOnWait;
break;
}
}
/* if (i == 7) {
switch (state0o) {
//service the Amp ADSR
case noteOnWait:
if (voice[i]) {
state0o = ATTACK;
}
break;
case ATTACK:
attackMillisA[i] = millis();
voice8env.amplitude(1, attackTime);
state0o = ATTACKwait;
if (!voice[i]) {
state0o = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisA[i] > attackTime) {
state0o = DECAY;
}
if (!voice[i]) {
state0o = RELEASE1;
}
break;
case DECAY:
voice8env.amplitude(sustainLevel, decayTime);
state0o = SUSTAIN;
if (!voice[i]) {
state0o = RELEASE1;
}
break;
case SUSTAIN:
if (!voice[i]) {
state0o = RELEASE1;
}
break;
case RELEASE1:
voice8env.amplitude(0, releaseTime);
state0o = noteOnWait;
break;
}
// service the Filter ADSR
switch (state0p) {
case noteOnWait:
if (voice[i]) {
state0p = ATTACK;
}
break;
case ATTACK:
attackMillisF[i] = millis();
voice8filterenv.amplitude(1, attackTimeFilter);
state0p = ATTACKwait;
if (!voice[i]) {
state0p = RELEASE1;
}
break;
case ATTACKwait:
if (millis() - attackMillisF[i] > attackTimeFilter) {
state0p = DECAY;
}
if (!voice[i]) {
state0p = RELEASE1;
}
break;
case DECAY:
voice8filterenv.amplitude(sustainLevelFilter, decayTimeFilter);
state0p = SUSTAIN;
if (!voice[i]) {
state0p = RELEASE1;
}
break;
case SUSTAIN:
if (!voice[i]) {
state0p = RELEASE1;
}
break;
case RELEASE1:
voice8filterenv.amplitude(0, releaseTimeFilter);
state0p = noteOnWait;
break;
}
}
*/
}
//end of voice service for loop
//assign CC Values to Parameters
if (CCvalues[40] != prevCCvalues[40]) {
waveShapeOneIndex = CCvalues[40] / 31;
if (waveShapeOneIndex < 4) {
voice1a.begin(waveShapes[waveShapeOneIndex]);
voice2a.begin(waveShapes[waveShapeOneIndex]);
voice3a.begin(waveShapes[waveShapeOneIndex]);
voice4a.begin(waveShapes[waveShapeOneIndex]);
voice5a.begin(waveShapes[waveShapeOneIndex]);
voice6a.begin(waveShapes[waveShapeOneIndex]);
voice7a.begin(waveShapes[waveShapeOneIndex]);
voice8a.begin(waveShapes[waveShapeOneIndex]);
prevCCvalues[40] = CCvalues[40];
}
}
//vcoMixBalance
if (CCvalues[36] != prevCCvalues[36]) {
vcoOneLevel = (CCvalues[36]) / 127;
vcoTwoLevel = 1 - (CCvalues[36]) / 127;
voice1mix.gain(1, vcoOneLevel);
voice1mix.gain(0, vcoTwoLevel);
voice2mix.gain(1, vcoOneLevel);
voice2mix.gain(0, vcoTwoLevel);
voice3mix.gain(1, vcoOneLevel);
voice3mix.gain(0, vcoTwoLevel);
voice4mix.gain(1, vcoOneLevel);
voice4mix.gain(0, vcoTwoLevel);
voice5mix.gain(1, vcoOneLevel);
voice5mix.gain(0, vcoTwoLevel);
voice6mix.gain(1, vcoOneLevel);
voice6mix.gain(0, vcoTwoLevel);
voice7mix.gain(1, vcoOneLevel);
voice7mix.gain(0, vcoTwoLevel);
voice8mix.gain(1, vcoOneLevel);
voice8mix.gain(0, vcoTwoLevel);
prevCCvalues[36] = CCvalues[36];
}
if (CCvalues[41] != prevCCvalues[41]) {
waveShapeTwoIndex = CCvalues[41] / 31;
if (waveShapeTwoIndex < 4) {
if (waveShapeTwoIndex == 3) {
voiceBPulse = true;
} else {
voiceBPulse = false;
}
voice1b.begin(waveShapes[waveShapeTwoIndex]);
voice2b.begin(waveShapes[waveShapeTwoIndex]);
voice3b.begin(waveShapes[waveShapeTwoIndex]);
voice4b.begin(waveShapes[waveShapeTwoIndex]);
voice5b.begin(waveShapes[waveShapeTwoIndex]);
voice6b.begin(waveShapes[waveShapeTwoIndex]);
voice7b.begin(waveShapes[waveShapeTwoIndex]);
voice8b.begin(waveShapes[waveShapeTwoIndex]);
prevCCvalues[41] = CCvalues[41];
}
}
//0.94498843
//0.96855780
//0.99023822
//0.00995611
//0.03108269
//0.05372621
if (CCvalues[94] != prevCCvalues[94]) {
//deTune = CCvalues[94];
deTune1 = mapfloat(CCvalues[94], 0, 127, 1, .94498843);
deTune2 = mapfloat(CCvalues[94], 0, 127, 1, .96855780);
deTune3 = mapfloat(CCvalues[94], 0, 127, 1, .99023822);
deTune5 = mapfloat(CCvalues[94], 0, 127, 1, 1.00995611);
deTune6 = mapfloat(CCvalues[94], 0, 127, 1, 1.03108269);
deTune7 = mapfloat(CCvalues[94], 0, 127, 1, 1.05372621);
prevCCvalues[94] = CCvalues[94];
}
//LFO
if (CCvalues[47] != prevCCvalues[47]) {
lfo.frequency(CCvalues[47] / 13);
prevCCvalues[47] = CCvalues[47];
}
if (CCvalues[46] != prevCCvalues[46]) {
lfoWaveShapeIndex = CCvalues[46] / 25.4;
if (lfoWaveShapeIndex < 5) {
lfo.begin(lfoWaveShapes[lfoWaveShapeIndex]);
//Serial.println(lfoWaveShapeIndex);
prevCCvalues[46] = CCvalues[46];
}
}
//noise
if (CCvalues[48] != prevCCvalues[48]) {
voice1n.amplitude(CCvalues[48] / 384.8);
voice2n.amplitude(CCvalues[48] / 384.8);
voice3n.amplitude(CCvalues[48] / 384.8);
voice4n.amplitude(CCvalues[48] / 384.8);
voice5n.amplitude(CCvalues[48] / 384.8);
voice6n.amplitude(CCvalues[48] / 384.8);
voice7n.amplitude(CCvalues[48] / 384.8);
voice8n.amplitude(CCvalues[48] / 384.8);
prevCCvalues[48] = CCvalues[48];
}
//Filter
if (CCvalues[74] != prevCCvalues[74]) {
voice1filter.frequency(CCvalues[74] * 9.33);
voice2filter.frequency(CCvalues[74] * 9.33);
voice3filter.frequency(CCvalues[74] * 9.33);
voice4filter.frequency(CCvalues[74] * 9.33);
voice5filter.frequency(CCvalues[74] * 9.33);
voice6filter.frequency(CCvalues[74] * 9.33);
voice7filter.frequency(CCvalues[74] * 9.33);
voice8filter.frequency(CCvalues[74] * 9.33);
prevCCvalues[74] = CCvalues[74];
}
//resonance
if (CCvalues[71] != prevCCvalues[71]) {
if (CCvalues[71] < 5) {
CCvalues[71] = 5;
}
voice1filter.resonance((CCvalues[71] / 25.4) + .9);
voice2filter.resonance((CCvalues[71] / 25.4) + .9);
voice3filter.resonance((CCvalues[71] / 25.4) + .9);
voice4filter.resonance((CCvalues[71] / 25.4) + .9);
voice5filter.resonance((CCvalues[71] / 25.4) + .9);
voice6filter.resonance((CCvalues[71] / 25.4) + .9);
voice7filter.resonance((CCvalues[71] / 25.4) + .9);
voice8filter.resonance((CCvalues[71] / 25.4) + .9);
prevCCvalues[71] = CCvalues[71];
}
//filter octaveControl
voice1filter.octaveControl(3.5);
voice2filter.octaveControl(3.5);
voice3filter.octaveControl(3.5);
voice4filter.octaveControl(3.5);
voice5filter.octaveControl(3.5);
voice6filter.octaveControl(3.5);
voice7filter.octaveControl(3.5);
voice8filter.octaveControl(3.5);
//lfoModulation Depth
if (CCvalues[2] != prevCCvalues[2]) {
voice1filtermodmixer.gain(1, CCvalues[2] / 127);
voice2filtermodmixer.gain(1, CCvalues[2] / 127);
voice3filtermodmixer.gain(1, CCvalues[2] / 127);
voice4filtermodmixer.gain(1, CCvalues[2] / 127);
voice5filtermodmixer.gain(1, CCvalues[2] / 127);
voice6filtermodmixer.gain(1, CCvalues[2] / 127);
voice7filtermodmixer.gain(1, CCvalues[2] / 127);
voice8filtermodmixer.gain(1, CCvalues[2] / 127);
prevCCvalues[2] = CCvalues[2];
}
//envelope mod depth
if (CCvalues[49] != prevCCvalues[49]) {
voice1filtermodmixer.gain(0, CCvalues[49] / 127);
voice2filtermodmixer.gain(0, CCvalues[49] / 127);
voice3filtermodmixer.gain(0, CCvalues[49] / 127);
voice4filtermodmixer.gain(0, CCvalues[49] / 127);
voice5filtermodmixer.gain(0, CCvalues[49] / 127);
voice6filtermodmixer.gain(0, CCvalues[49] / 127);
voice7filtermodmixer.gain(0, CCvalues[49] / 127);
voice8filtermodmixer.gain(0, CCvalues[49] / 127);
prevCCvalues[49] = CCvalues[49];
}
//Delay
//time
if (CCvalues[88] != prevCCvalues[88]) {
delay1.delay(0, (CCvalues[88] * 8.05) / 2.4);
prevCCvalues[88] = CCvalues[88];
}
//feedback
if (CCvalues[89] != prevCCvalues[89]) {
mainOutMixer.gain(3, CCvalues[89] / 127);
prevCCvalues[89] = CCvalues[89];
}
//pulseWidth
if (CCvalues[50] != prevCCvalues[50]) {
tempPulseWidth = 1 - (CCvalues[50] / 127);
tempDetuneMod = CCvalues[50] / 254;
prevCCvalues[50] = CCvalues[50];
}
//attack Filter
if (CCvalues[42] != prevCCvalues[42]) {
attackTimeFilter = (CCvalues[42] * 12.05) * 2;
prevCCvalues[42] = CCvalues[42];
}
//attack Amp
if (CCvalues[32] != prevCCvalues[32]) {
attackTime = (CCvalues[32] * 8.05) * 2;
prevCCvalues[32] = CCvalues[32];
}
//decay Filter
if (CCvalues[43] != prevCCvalues[43]) {
decayTimeFilter = CCvalues[43] * 12.05;
prevCCvalues[43] = CCvalues[43];
}
//decay Amp
if (CCvalues[33] != prevCCvalues[33]) {
decayTime = CCvalues[33] * 8.05;
prevCCvalues[33] = CCvalues[33];
}
//sustain Filter
if (CCvalues[44] != prevCCvalues[44]) {
sustainLevelFilter = CCvalues[44] * 4.05;
sustainLevelFilter = mapfloat(sustainLevelFilter, 0, 127, -1, 1);
prevCCvalues[44] = CCvalues[44];
}
//sustain Amp
if (CCvalues[34] != prevCCvalues[34]) {
sustainLevel = CCvalues[34] / 127;
prevCCvalues[34] = CCvalues[34];
}
//release Filter
if (CCvalues[45] != prevCCvalues[45]) {
releaseTimeFilter = (CCvalues[45] * 8.05) * 2;
prevCCvalues[45] = CCvalues[45];
}
//Release Amp
if (CCvalues[35] != prevCCvalues[35]) {
releaseTime = (CCvalues[35] * 8.05) * 2;
prevCCvalues[35] = CCvalues[35];
}
//LFO Peak
if (peak1.available()) {
tempPeak = peak1.read();
}
voice1a.pulseWidth((tempPeak / 2) + tempPulseWidth);
voice2a.pulseWidth((tempPeak / 2) + tempPulseWidth);
voice3a.pulseWidth((tempPeak / 2) + tempPulseWidth);
voice4a.pulseWidth((tempPeak / 2) + tempPulseWidth);
voice5a.pulseWidth((tempPeak / 2) + tempPulseWidth);
voice6a.pulseWidth((tempPeak / 2) + tempPulseWidth);
voice7a.pulseWidth((tempPeak / 2) + tempPulseWidth);
voice8a.pulseWidth((tempPeak / 2) + tempPulseWidth);
if (voiceBPulse) {
voice1b.pulseWidth((tempPeak / 2) + tempPulseWidth);
voice2b.pulseWidth((tempPeak / 2) + tempPulseWidth);
voice3b.pulseWidth((tempPeak / 2) + tempPulseWidth);
voice4b.pulseWidth((tempPeak / 2) + tempPulseWidth);
voice5b.pulseWidth((tempPeak / 2) + tempPulseWidth);
voice6b.pulseWidth((tempPeak / 2) + tempPulseWidth);
voice7b.pulseWidth((tempPeak / 2) + tempPulseWidth);
voice8b.pulseWidth((tempPeak / 2) + tempPulseWidth);
} else {
deTuneLfo = ((tempPeak) * tempDetuneMod + 1);
//Serial.println(deTuneLfo);
}
//end loop
}
The area where the notes are manipulated is here-
Code:
void MIDInoteOn(int note, int vel)
{
if (noteCount == 5) {
Serial.println("Voice Limit Exceeded!");
return;
}
if (!noteCount) {
voice [0] = note;
currNote = voice[0];
noteCount++;
Serial.print("1st Note # ");
Serial.println(currNote);
Serial.println("notecount= ");
Serial.println(noteCount);
return;
}
//Serial.println(i+1);
currNote=0;
for (int i = 0; i < 4; i++) {
if (!voice[i]) {
voice[i] = note;
currNote = voice[i];
noteCount++;
Serial.print("Replacement Note # ");
Serial.println(currNote);
Serial.print("Assigned to Voice # ");
Serial.println(i + 1);
Serial.println();
Serial.println("notecount= ");
Serial.println(noteCount);
break;
}
}
}
void MIDIccData(int CCnumber, float CCvalue)
{
//Serial.print("CC#= ");
//Serial.print(CCnumber);
//Serial.print(" Value= ");
//Serial.println(CCvalue);
//assign values to the CC lookup table
CCvalues[CCnumber] = {CCvalue};
}
//shuts notes off, removes them from note Stack and shifts the remainder notes
//towards bottom to keep all active notes down together in array
void MIDInoteOff(int note, int vel)
{
if (note == currNote && noteCount>1) {
currNote=0;
Serial.print("Trying to find note # ");
Serial.println(note);
for (int i = 0; i < 4; i++) {
Serial.print("searching voice- ");
Serial.println(i);
if (note == voice[i]) {
Serial.print("I FOUND IT! ");
voice[i] = 0;
currNote = voice[i - 1];
noteCount--;
Serial.print("Current note off # ");
Serial.println(note);
Serial.println("Shut Off Current Voice # ");
Serial.println(i + 1);
Serial.print("Current note ON # ");
Serial.println(currNote);
Serial.println();
Serial.println("notecount= ");
Serial.println(noteCount);
break;
}
}
return;
}
if (noteCount < 2) {
voice[0] = 0;
currNote = 0;
noteCount--;
if (noteCount < 0) {
noteCount = 0;
}
Serial.print("Last note off # ");
Serial.println(note);
Serial.println("Shut Off Voice # 1 ");
Serial.println();
Serial.println("notecount= ");
Serial.println(noteCount);
return;
//Serial.println(i+1);
}
if (noteCount > 1) {
for (int i = 0; i < 4; i++) {
if (voice[i] == note) {
voice[i] = 0;
Serial.print("Drop off note # ");
Serial.println(note);
Serial.print("Drop Off Voice # ");
Serial.println(i + 1);
for (int c = i + 1; c < 4; c++) {
voice[i] = voice[c];
i = i++;
}
voice[3] = 0;
noteCount--;
Serial.print("-note off # ");
Serial.println(note);
Serial.println();
Serial.println("notecount= ");
Serial.println(noteCount);
break;
}
}
}
}
Hopefully one of you coding gurus can load this up, have a midi keyboard to test it with and by some miracle figure out how to make it not glitch.. ever!
*crossing fingers*.....
/Blaine
Last edited: