New Teensy 4.1 DIY Synthesizer

Rolfdegen

Well-known member
Hi there...

I am currently developing a new DIY synthesizer based on a
Teensy 4.0 Boards. The synthesizer will look similar to the small
Shruthi Synthesizer from Mutable Instruments. Compared to the Shruthi
this synth will be polyphonic, have a color TFT display
and other things like a 2Channel 16Bit DA-Converter, digital and
analog filters. The housing and board format is similar to the
Shruthi (see picture). That's why for the DIY Project I also created the
Name "Shruthi 2" selected.

20200919-154108.jpg


20200919-154130.jpg


I replaced the 2.2 inch TFT display with a smaller 1.8 inch
Display replaced. I think this fits better to the small
Shruthi format. The 2.2 inch display is a bit overloaded
looked like. Waveform displays and menu texts also fit like this
a small color display with a resolution of 128 x 160 pixels

I put the Teensy 4.0 board on the backside. What is still missing
is the 16Bit 2Ch. DA-converter PT8211. This is ordered. With the 4
Potis you control the parameter setting. The encoder is equipped with a
key function and controls the menu functions. There are 4
analog inputs for modulation. Midi sockets and 6 keys and 8 LEDs.

There will be the possibility to use the "Shruthi 2" with or without filter board
to operate. You then have the possibility to use the digital filters in the
Teensy to use.

Display test on Teensy: https://youtu.be/14eL3NDJccw

Greeting Rolf
 
Hallo

I have a problem with the playback of PWM sound and TFT display. I have no PWM sound on pin 10 + 12 when using the display driver.
The PWM sound works without display driver.

Code:
// Shruthi 2  with Teensy 4.0   (c) 21.09.2020

#define TFT_SCLK 13  // SCLK
#define TFT_MOSI 11  // MOSI
#define TFT_CS    6  // CS & DC can use pins 2, 6, 9, 10, 15, 20, 21, 22, 23
#define TFT_DC    9  //  but certain pairs must NOT be used: 2+10, 6+9, 20+23, 21+22
#define TFT_RST   8  // RST can use any pin
#define SD_CS     4  // CS for SD card, can use any pin

#include <Adafruit_GFX.h>
#include <ST7735_t3.h>
#include <SPI.h>
#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <SerialFlash.h>

#define RGB(r,g,b) (b<<11|g<<6|r)

AudioSynthWaveform       waveform1;      //xy=263,306
AudioFilterStateVariable filter1;        //xy=459,371
AudioMixer4              mixer1;         //xy=627,378
AudioOutputMQS           mqs1;           //xy=850,426
AudioConnection          patchCord1(waveform1, 0, filter1, 0);
AudioConnection          patchCord2(filter1, 0, mixer1, 0);
AudioConnection          patchCord3(filter1, 1, mixer1, 1);
AudioConnection          patchCord4(filter1, 2, mixer1, 2);
AudioConnection          patchCord5(mixer1, 0, mqs1, 0);
ST7735_t3 disp = ST7735_t3(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);


void setup() {
  Serial.begin(9600);
  
  // init 1.8" TFT
  disp.initR(INITR_BLACKTAB);
  disp.fillScreen(ST7735_BLACK);
  disp.setTextColor(ST7735_YELLOW, ST7735_BLACK);
  disp.setRotation(3);
  disp.setTextWrap(false);
  disp.setTextSize(2); 
  disp.setCursor(20,40);
  disp.print("SHRUTHI II");
  disp.setTextSize(0); 
  disp.setCursor(32,70);
  disp.print("www.tubeohm.com");
  
  // init PWM audio
  AudioMemory(20);
  analogReadResolution(8);
  analogReadAveraging(16);
  waveform1.begin(WAVEFORM_SAWTOOTH);
  waveform1.amplitude(0.85);
  waveform1.frequency(100);
  filter1.frequency(1000);
  filter1.octaveControl(1.0);   // freqency. Range is 0 to 7
  filter1.resonance(0);       //Q ranges from 0.7 to 5.0.
  mixer1.gain(0, 1);
  mixer1.gain(1, 0);
  mixer1.gain(2, 0);
  mixer1.gain(3, 0);
}

void loop() {
  
}
 
I think I found a solution. I swapped the Display connections MOSI and SCK to MOSI1 and SCK1 on teensy board.
 
OK.This is Pin function now:

#define TFT_SCLK 27 // SCK1
#define TFT_MOSI 26 // MOSI1
#define TFT_CS 6 // CS & DC can use pins 2, 6, 9, 10, 15, 20, 21, 22, 23
#define TFT_DC 9 // but certain pairs must NOT be used: 2+10, 6+9, 20+23, 21+22
#define TFT_RST 8 // RST can use any pin
 
Sounds and looks great, are you using some of the Shruthi codebase or are you using the audio lib? Cheers, Paul
 
I use the Audio Lib and later part of the Shruthi syntheses.

It's a Phoenix / Shruthi board without filters from tubeohm.com

Shruthi2.jpg
 
From today we will dance in several voices: cheer:

Teensy Synth
20201015_111551.jpg

Synth block
Synth-Block2 (1).jpg


The "Shruthi 2" now has 6 voices and plays polyphonically. I think you can expand that to 8 voices, since the processor load including the filter calculation is below 6%.
There is currently only one oscillator per voice. But later there will be 2 per vote. The oscillator functions are not yet integrated. This is my next step now.
The sound is still being worked on. There is still a lot to program. Let's do it ;-)

Video

My code (in worke)
Code:
//**************************************************  ***********************
// DIY Synth "Shruthi II" with Teensy 4.1 board and 16Bit Stereo DAC
//
// (c) Rolf Degen      Version 1.02  15.10.2020
//**************************************************  ***********************

#include <ST7735_t3.h>
#include <Audio.h>
#include <MIDI.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#define ENCODER_OPTIMIZE_INTERRUPTS
#include <Encoder.h>
#include <ResponsiveAnalogRead.h>



#define TFT_SCLK 27		// SCLK can also use pin 14
#define TFT_MOSI 26		// MOSI can also use pin 7
#define TFT_CS   25		// CS & DC can use pins 2, 6, 9, 10, 15, 20, 21, 22, 23
#define TFT_DC   24		//  but certain pairs must NOT be used: 2+10, 6+9, 20+23, 21+22
#define TFT_RST  9		// RST can use any pin
#define RGB(r,g,b) (b<<11|g<<6|r)
#define ST7735_BLACK   0x0000
#define ST7735_GRAY    0x8410
#define ST7735_WHITE   0xFFFF
#define ST7735_RED     0xF800
#define ST7735_ORANGE  0xFA60
#define ST7735_YELLOW  0xFFE0
#define ST7735_LIME    0x07FF
#define ST7735_GREEN   0x07E0
#define ST7735_CYAN    0x07FF
#define ST7735_AQUA    0x04FF
#define ST7735_BLUE    0x001F
#define ST7735_MAGENTA 0xF81F
#define ST7735_PINK    0xF8FF
#define Menu_Osc            0	// Menu pages
#define Menu_AmpEnv			1
#define Menu_FilterEnv		2
#define Menu_Filter			3
#define LowPass				0
#define BandPass			1
#define HighPass			2
#define pi		3.14159
#define NO_OF_VOICES        6

//------------------------------------------------------
// Global var
//------------------------------------------------------
const int ANALOG_PIN8 = A8;
unsigned long previousTime_cpu = 0;
unsigned long previousTime_pot = 0;
unsigned long previousTime_midi = 0;
unsigned long previousTime_ADC = 0;
const int interval_cpu = 200;           // poll interval CPU usage
const int interval_pot = 35;            // poll interval pots and keys
const int interval_ADC = 15;				// poll ADC
const int interval_midi = 1;            // poll interval midi data
const uint8_t channel = 1;
uint8_t note = 0;
byte velocity = 0;
float freq = 0;
int pitch_bnd = 1;
float bendf = 0;
float BendFactor = 1;
int pot_1 = 0;
int pot_2 = 0;
int pot_3 = 0;
int pot_4 = 0;
int pot_1_old = 0;
int pot_2_old = 0;
int pot_3_old = 0;
int pot_4_old = 0;
uint8_t Amp_env_delay = 0;
uint8_t Amp_env_att = 20;
uint8_t Amp_env_hold = 0;
uint8_t Amp_env_dcy = 30;
uint8_t Amp_env_sus = 40;
uint8_t Amp_env_rel = 50;
uint8_t Filter_env_delay = 0;
uint8_t Filter_env_att = 80;
uint8_t Filter_env_hold = 0;
uint8_t Filter_env_dcy = 70;
uint8_t Filter_env_sus = 70;
uint8_t Filter_env_rel = 60;
uint8_t Filter_cut = 64;
uint8_t Filter_res = 20;
uint8_t Filter_key = 50;
uint8_t Filter_typ = 0;
boolean pot_1_change = false;
boolean pot_2_change = false;
boolean pot_3_change = false;
boolean pot_4_change = false;
uint8_t Menu_page = 0;
float pot_div127 = 0.228;		// pot_value divider
int oldPosition  = -999;
uint8_t Osc_waveform = 0;

struct VoiceAndNote {
	int note;
	long timeOn;
	boolean voiceOn;
	uint8_t lampTimeOn;
};

struct VoiceAndNote voices[NO_OF_VOICES] = {
	{ -1, 0, false, 0},
	{ -1, 0, false, 0},
	{ -1, 0, false, 0},
	{ -1, 0, false, 0},
	{ -1, 0, false, 0},
	{ -1, 0, false, 0}
};

int voiceToReturn = -1;			// Voices allocation
long earliestTime = millis();	// Voices allocation



//**************************************************  ***********************
// Tabels
//**************************************************  ***********************

// Sine filter curv ------------------------------------------------------
const byte Filter_curve[385] PROGMEM = {
	1,      2,      2,      3,      2,      3,      3,      4,
	5,      4,      7,      5,      9,      7,     10,     11,
	11,     13,     13,     17,     16,     18,     21,     21,
	23,     25,     27,     28,     32,     31,     36,     36,
	39,     41,     43,     46,     48,     51,     53,     55,
	57,     62,     63,     65,     70,     70,     75,     76,
	81,     82,     85,     89,     92,     94,     97,    100,
	104,    107,    109,    112,    116,    119,    122,    124,
	129,    130,    135,    137,    140,    144,    147,    148,
	154,    155,    158,    163,    163,    169,    169,    174,
	177,    178,    182,    185,    187,    191,    192,    195,
	199,    200,    203,    205,    209,    210,    212,    216,
	216,    220,    221,    223,    226,    227,    230,    230,
	233,    235,    235,    239,    238,    241,    242,    243,
	245,    245,    246,    249,    247,    251,    249,    252,
	251,    252,    253,    253,    253,    254,    254,    254,
	253,    255,    254,    253,    253,    254,    252,    253,
	251,    251,    250,    250,    248,    248,    246,    246,
	245,    242,    243,    240,    239,    238,    236,    234,
	233,    231,    230,    226,    226,    224,    221,    219,
	217,    215,    212,    211,    208,    206,    202,    201,
	198,    196,    192,    190,    188,    184,    182,    179,
	177,    173,    170,    168,    164,    162,    158,    156,
	153,    149,    147,    143,    141,    136,    135,    131,
	128,    125,    122,    118,    116,    113,    109,    106,
	104,    101,     96,     95,     92,     88,     85,     83,
	80,     77,     74,     71,     69,     66,     63,     61,
	57,     56,     53,     50,     49,     45,     43,     42,
	38,     37,     35,     32,     31,     29,     26,     26,
	22,     22,     20,     19,     16,     16,     13,     14,
	11,     10,     10,      8,      8,      6,      6,      5,
	4,      5,      2,      3,      2,      2,      2,      3,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,		0,		0,		0,		0,		0,		0,		0,
	0,
};

// Potentiometer Power table
const int Pot_PowerTab[128] PROGMEM = {
	0,     0,     1,     2,     3,     4,     5,     6,
	7,     9,    12,    15,    19,    24,    29,    36,
	43,    50,    59,    68,    78,    89,   101,   114,
	128,   143,   159,   176,   194,   214,   234,   256,
	279,   303,   329,   355,   384,   413,   444,   476,
	510,   545,   582,   620,   660,   701,   744,   789,
	835,   882,   932,   983,  1036,  1091,  1147,  1206,
	1266,  1328,  1392,  1457,  1525,  1595,  1666,  1740,
	1815,  1893,  1973,  2055,  2138,  2224,  2313,  2403,
	2495,  2590,  2687,  2786,  2888,  2991,  3097,  3206,
	3317,  3430,  3545,  3663,  3784,  3907,  4032,  4160,
	4290,  4423,  4559,  4697,  4837,  4981,  5126,  5275,
	5426,  5580,  5737,  5896,  6059,  6224,  6391,  6562,
	6736,  6912,  7091,  7273,  7458,  7646,  7837,  8031,
	8228,  8428,  8630,  8836,  9045,  9257,  9473,  9691,
	9912, 10137, 10365, 10596, 10830, 11068, 11800, 11800,
};

// Filter Frequency
/*    
// DeepMind 6
const int FilterFrequency[256] PROGMEM = {
	50,		51,     52,     54,		55,     56,		58,		59,
	60,     62,		63,		65,		66,		68,		69,		71,
	73,		75,		76,		78,		80,		82,		84,		86,
	88,		90,		92,		94,		97,		99,		101,    104,
	106,	109,	111,    114,	116,	119,	122,	125,	
	128,	131,	134,	137,	141,	144,	147,	151,
	154,	158,	162,	166,	170,	174,	178,	182,
	186,	191,	195,	200,	205,	210,	215,	220,
	225,	230,	236,	241,	247,	253,	259,	265,
	271,	278,	284,	291,	298,	305,	313,	320,
	328,	335,	343,	351,	360,	368,	377,	386,
	395,	405,	414,	424,	434,	445,	455,	466,
	477,	488,	500,	512,	524,	537,	549,	562,
	576,	589,	603,	618,	632,	647,	663,	679,
	695,	711,	728,	746,	763,	781,	800,	819,
	838,	858,	879,	900,	921,	943,	965,	988,
	1012,	1036,	1060,	1086,	1112,	1138,	1165,	1193,
	1221,	1250,	1280,	1310,	1341,	1373,	1406,	1439,
	1474,	1509,	1544,	1581,	1619,	1657,	1697,	1737,
	
};
*/

// TSynth
const static int FilterFrequency[256] = {
	20,		20,		22,		23,		24,		26,		27,		28, 
	29,		31,		32,		33,		34,		35,		36,		38, 
	39,		40,		41,		43,		44,		46,		47,		49, 
	50,		52,		53,		55,		57,		59,		61,		63, 
	65,		68,		70,		73,		76,		78,		81,		84, 
	87,		91,		94,		98,		102,	106,	110,	114, 
	119,	123,	128,	133,	138,	144,	149,	155, 
	161,	167,	174,	181,	187,	195,	202,	210, 
	218,	226,	234,	243,	252,	261,	271,	281, 
	291,	301,	312,	323,	334,	346,	358,	370, 
	383,	395,	409,	422,	436,	451,	465,	480, 
	496,	512,	528,	544,	561,	578,	596,	614, 
	633,	652,	671,	691,	711,	732,	753,	774, 
	796,	818,	841,	865,	888,	913,	937,	962, 
	988,	1014,	1041,	1068,	1096,	1124,	1152,	1182, 
	1211,	1242,	1272,	1304,	1335,	1368,	1401,	1434, 
	1468,	1503,	1538,	1574,	1610,	1647,	1684,	1722, 
	1761,	1800,	1840,	1881,	1922,	1964,	2006,	2049, 
	2093,	2137,	2182,	2227,	2274,	2320,	2368,	2416, 
	2465,	2515,	2565,	2616,	2668,	2720,	2773,	2827, 
	2881,	2936,	2992,	3049,	3106,	3164,	3223,	3283, 
	3343,	3404,	3466,	3529,	3592,	3656,	3721,	3787, 
	3853,	3921,	3989,	4058,	4127,	4198,	4269,	4341, 
	4414,	4488,	4563,	4638,	4715,	4792,	4870,	4949, 
	5029,	5109,	5191,	5273,	5357,	5441,	5526,	5612, 
	5699,	5787,	5876,	5965,	6056,	6147,	6240,	6333, 
	6427,	6523,	6619,	6716,	6814,	6913,	7013,	7114, 
	7216,	7319,	7424,	7529,	7635,	7742,	7850,	7959, 
	8069,	8180,	8292,	8405,	8519,	8634,	8751,	8868, 
	8986,	9106,	9226,	9348,	9471,	9594,	9719,	9845, 
	9972,	10100,	10230,	10360,	10491,	10624,	10758,	10893, 
	11029,	11166,	11304,	11443,	11584,	11726,	12000,	12000
	};


// Waveform text
const char* const Waveform_text[] PROGMEM = {"SINE","SAW ","SQU ","TRI ","VTRI","ARB ","PULS","S&H "};



//------------------------------------------------------
// GUItool
//------------------------------------------------------
ST7735_t3 disp = ST7735_t3(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
Encoder myEnc(31, 30);
ResponsiveAnalogRead analog1(A0, true);
ResponsiveAnalogRead analog2(A2, true);
ResponsiveAnalogRead analog3(A3, true);
ResponsiveAnalogRead analog4(A8, true);

// GUItool: begin automatically generated code
AudioSynthWaveformDc     dc1;            //xy=393,162
AudioSynthWaveformDc     dc2;            //xy=387,383
AudioSynthWaveformDc     dc3;            //xy=385,590
AudioSynthWaveformDc     dc4;            //xy=382,789
AudioSynthWaveformDc     dc5;            //xy=380,959
AudioSynthWaveformDc     dc6;            //xy=376,1152
AudioSynthWaveform       waveform1;      //xy=399,92
AudioSynthWaveform       waveform2;      //xy=395,317
AudioSynthWaveform       waveform3;      //xy=394,528
AudioSynthWaveform       waveform4;      //xy=393,735
AudioSynthWaveform       waveform5;      //xy=389,909
AudioSynthWaveform       waveform6;      //xy=387,1093
AudioEffectEnvelope      envelope1_0;      //xy=1101,105
AudioEffectEnvelope      envelope2_0;      //xy=1104,331
AudioEffectEnvelope      envelope3_0;      //xy=1104,539
AudioEffectEnvelope      envelope4_0;     //xy=1106,745
AudioEffectEnvelope      envelope5_0;     //xy=1108,923
AudioEffectEnvelope      envelope6_0;     //xy=1110,1105
AudioEffectEnvelope      envelope1_1;      //xy=559,162
AudioEffectEnvelope      envelope2_1;      //xy=548,382
AudioEffectEnvelope      envelope3_1;      //xy=539,590
AudioEffectEnvelope      envelope4_1;      //xy=538,789
AudioEffectEnvelope      envelope5_1;      //xy=536,959
AudioEffectEnvelope      envelope6_1;      //xy=537,1152
AudioFilterStateVariable filter1;        //xy=723,99
AudioFilterStateVariable filter2;        //xy=718,325
AudioFilterStateVariable filter3;        //xy=712,533
AudioFilterStateVariable filter4;        //xy=709,739
AudioFilterStateVariable filter5;        //xy=711,917
AudioFilterStateVariable filter6;        //xy=713,1100
AudioMixer4              mixer1;         //xy=936,105
AudioMixer4              mixer2;         //xy=931,331
AudioMixer4              mixer3;         //xy=930,539
AudioMixer4              mixer4;         //xy=931,745
AudioMixer4              mixer5;         //xy=931,923
AudioMixer4              mixer6;         //xy=929,1106
AudioMixer4              mixer20;         //xy=1351,498
AudioMixer4              mixer21;         //xy=1351,942
AudioMixer4              mixer22;         //xy=1560,730
AudioOutputI2S           i2s1;           //xy=1745,728
AudioConnection          patchCord1(dc6, envelope6_1);
AudioConnection          patchCord2(dc5, envelope5_1);
AudioConnection          patchCord3(dc4, envelope4_1);
AudioConnection          patchCord4(dc3, envelope3_1);
AudioConnection          patchCord5(dc2, envelope2_1);
AudioConnection          patchCord6(waveform6, 0, filter6, 0);
AudioConnection          patchCord7(waveform5, 0, filter5, 0);
AudioConnection          patchCord8(dc1, envelope1_1);
AudioConnection          patchCord9(waveform4, 0, filter4, 0);
AudioConnection          patchCord10(waveform3, 0, filter3, 0);
AudioConnection          patchCord11(waveform2, 0, filter2, 0);
AudioConnection          patchCord12(waveform1, 0, filter1, 0);
AudioConnection          patchCord13(envelope5_1, 0, filter5, 1);
AudioConnection          patchCord14(envelope4_1, 0, filter4, 1);
AudioConnection          patchCord15(envelope3_1, 0, filter3, 1);
AudioConnection          patchCord16(envelope6_1, 0, filter6, 1);
AudioConnection          patchCord17(envelope2_1, 0, filter2, 1);
AudioConnection          patchCord18(envelope1_1, 0, filter1, 1);
AudioConnection          patchCord19(filter4, 0, mixer4, 0);
AudioConnection          patchCord20(filter4, 1, mixer4, 1);
AudioConnection          patchCord21(filter4, 2, mixer4, 2);
AudioConnection          patchCord22(filter3, 0, mixer3, 0);
AudioConnection          patchCord23(filter3, 1, mixer3, 1);
AudioConnection          patchCord24(filter3, 2, mixer3, 2);
AudioConnection          patchCord25(filter5, 0, mixer5, 0);
AudioConnection          patchCord26(filter5, 1, mixer5, 1);
AudioConnection          patchCord27(filter5, 2, mixer5, 2);
AudioConnection          patchCord28(filter6, 0, mixer6, 0);
AudioConnection          patchCord29(filter6, 1, mixer6, 1);
AudioConnection          patchCord30(filter6, 2, mixer6, 2);
AudioConnection          patchCord31(filter2, 0, mixer2, 0);
AudioConnection          patchCord32(filter2, 1, mixer2, 1);
AudioConnection          patchCord33(filter2, 2, mixer2, 2);
AudioConnection          patchCord34(filter1, 0, mixer1, 0);
AudioConnection          patchCord35(filter1, 1, mixer1, 1);
AudioConnection          patchCord36(filter1, 2, mixer1, 2);
AudioConnection          patchCord37(mixer3, envelope3_0);
AudioConnection          patchCord38(mixer2, envelope2_0);
AudioConnection          patchCord39(mixer6, envelope6_0);
AudioConnection          patchCord40(mixer4, envelope4_0);
AudioConnection          patchCord41(mixer5, envelope5_0);
AudioConnection          patchCord42(mixer1, envelope1_0);
AudioConnection          patchCord43(envelope1_0, 0, mixer20, 0);
AudioConnection          patchCord44(envelope2_0, 0, mixer20, 1);
AudioConnection          patchCord45(envelope3_0, 0, mixer20, 2);
AudioConnection          patchCord46(envelope4_0, 0, mixer20, 3);
AudioConnection          patchCord47(envelope5_0, 0, mixer21, 0);
AudioConnection          patchCord48(envelope6_0, 0, mixer21, 1);
AudioConnection          patchCord49(mixer20, 0, mixer22, 0);
AudioConnection          patchCord50(mixer21, 0, mixer22, 1);
AudioConnection          patchCord51(mixer22, 0, i2s1, 0);
AudioConnection          patchCord52(mixer22, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=1735,625
// GUItool: end automatically generated code


//**************************************************  ***********************
// draw Voice Lamps
//**************************************************  ***********************
void draw_Voice_Lamps(void)
{
	disp.drawLine(128, 1, 128, 16, ST7735_GRAY);
	disp.drawRect(133, 3, 7, 4, ST7735_RED);
	disp.drawRect(133 + 10, 3, 7, 4, ST7735_RED);
	disp.drawRect(133 + 10 + 10, 3, 7, 4, ST7735_RED);
	disp.drawRect(133, 11, 7, 4, ST7735_RED);
	disp.drawRect(133 + 10, 11, 7, 4, ST7735_RED);
	disp.drawRect(133 + 10 + 10, 11, 7, 4, ST7735_RED);
}

//**************************************************  ***********************
// Oscillator menu
//**************************************************  ***********************
void Osc_menu (void)
{
	disp.fillScreen(ST7735_BLACK);
	disp.drawLine(0, 20, 240, 20, ST7735_YELLOW);
	disp.setCursor(10, 5);
	disp.setTextSize(0);
	disp.print("OSC");
	disp.setTextColor(ST7735_WHITE);
	disp.setCursor(10, 105);
	disp.print("SHA");
	disp.setCursor(10 + 40, 105);
	disp.print("PRM");
	disp.setCursor(10 + 40 + 40, 105);
	disp.print("RNG");
	disp.setCursor(10 + 40 + 40 + 40, 105);
	disp.print("TUN");

	// draw pot values --------------------------
	disp.drawLine(4,116,30,116,ST7735_BLUE);
	disp.drawLine(4+40,116,30+40,116,ST7735_BLUE);
	disp.drawLine(4+40+40,116,30+40+40,116,ST7735_BLUE  );
	disp.drawLine(4+40+40+40,116,30+40+40+40,116,ST773  5_BLUE);
	
	// draw voice lamps --------------------------
	draw_Voice_Lamps();
	
	//draw_AMP_envLine();
	//pot_1 = Amp_env_att;
	//pot_2 = Amp_env_dcy;
	//pot_3 = Amp_env_sus;
	//pot_4 = Amp_env_rel;
	pot_1_change = true;
	pot_2_change = true;
	pot_3_change = true;
	pot_4_change = true;
	//set_AMP_envelope();
	refresh_pot_values();
}

//**************************************************  ***********************
// AMP envelope menu
//**************************************************  ***********************
void AMP_envelope_menu (void)
{
	disp.fillScreen(ST7735_BLACK);
	disp.drawLine(0, 20, 240, 20, ST7735_YELLOW);
	disp.setCursor(10, 5);
	disp.setTextSize(0);
	disp.print("AMP ENV");
	disp.setTextColor(ST7735_WHITE);
	disp.setCursor(10, 105);
	disp.print("ATK");
	disp.setCursor(10 + 40, 105);
	disp.print("DCY");
	disp.setCursor(10 + 40 + 40, 105);
	disp.print("SUS");
	disp.setCursor(10 + 40 + 40 + 40, 105);
	disp.print("REL");

	// draw pot values --------------------------
	disp.drawLine(4,116,30,116,ST7735_BLUE);
	disp.drawLine(4+40,116,30+40,116,ST7735_BLUE);
	disp.drawLine(4+40+40,116,30+40+40,116,ST7735_BLUE  );
	disp.drawLine(4+40+40+40,116,30+40+40+40,116,ST773  5_BLUE);
	
	// draw voice lamps --------------------------
	draw_Voice_Lamps();
	
	draw_AMP_envLine();
	pot_1 = Amp_env_att;
	pot_2 = Amp_env_dcy;
	pot_3 = Amp_env_sus;
	pot_4 = Amp_env_rel;
	pot_1_change = true;
	pot_2_change = true;
	pot_3_change = true;
	pot_4_change = true;
	set_AMP_envelope();
	refresh_pot_values();
}

//**************************************************  ***********************
// FILTER envelope menu
//**************************************************  ***********************
void Filter_envelope_menu (void)
{
	disp.fillScreen(ST7735_BLACK);
	disp.drawLine(0, 20, 240, 20, ST7735_YELLOW);
	disp.setCursor(10, 5);
	disp.setTextSize(0);
	disp.print("FILTER ENV");
	disp.setTextColor(ST7735_WHITE);
	disp.setCursor(10, 105);
	disp.print("ATK");
	disp.setCursor(10 + 40, 105);
	disp.print("DCY");
	disp.setCursor(10 + 40 + 40, 105);
	disp.print("SUS");
	disp.setCursor(10 + 40 + 40 + 40, 105);
	disp.print("REL");

	// draw pot values --------------------------
	disp.drawLine(4,116,30,116,ST7735_BLUE);
	disp.drawLine(4+40,116,30+40,116,ST7735_BLUE);
	disp.drawLine(4+40+40,116,30+40+40,116,ST7735_BLUE  );
	disp.drawLine(4+40+40+40,116,30+40+40+40,116,ST773  5_BLUE);
		
	// draw voice lamps --------------------------
	draw_Voice_Lamps();
	
	draw_Filter_envLine();
	pot_1 = Filter_env_att;
	pot_2 = Filter_env_dcy;
	pot_3 = Filter_env_sus;
	pot_4 = Filter_env_rel;
	pot_1_change = true;
	pot_2_change = true;
	pot_3_change = true;
	pot_4_change = true;
	set_Filter_envelope();
	refresh_pot_values();
}

//**************************************************  ***********************
// FILTER menu
//**************************************************  ***********************
void Filter_menu (void)
{
	disp.fillScreen(ST7735_BLACK);
	disp.drawLine(0, 20, 240, 20, ST7735_YELLOW);
	disp.setCursor(10, 5);
	disp.setTextSize(0);
	disp.print("FILTER");
	disp.setTextColor(ST7735_WHITE);
	disp.setCursor(10, 105);
	disp.print("FRQ");
	disp.setCursor(10 + 40, 105);
	disp.print("RES");
	disp.setCursor(10 + 40 + 40, 105);
	disp.print("KEY");
	disp.setCursor(6 + 40 + 40 + 40+4, 105);
	disp.print("MOD");

	// draw pot values --------------------------
	disp.drawLine(4,116,30,116,ST7735_BLUE);
	disp.drawLine(4+40,116,30+40,116,ST7735_BLUE);
	disp.drawLine(4+40+40,116,30+40+40,116,ST7735_BLUE  );
	disp.drawLine(4+40+40+40,116,30+40+40+40,116,ST773  5_BLUE);
		
	// draw voice lamps --------------------------
	draw_Voice_Lamps();
	
	// draw diagramm line
	disp.drawLine(19,45,19,45+41,ST7735_GRAY);
	disp.drawLine(19,45+41,19+115,45+41,ST7735_GRAY);
	disp.setTextColor(ST7735_GRAY);
	disp.setCursor(7, 46);
	disp.print("dB");
	disp.setCursor(110, 88);
	disp.print("f/Hz");
	
	draw_filter_curves(Filter_typ);
	pot_1 = Filter_cut;
	pot_2 = Filter_res;
	pot_3 = Filter_key;
	pot_4 = Filter_typ * 42; // pot_4 value
	set_Filter_typ();
	pot_1_change = true;
	pot_2_change = true;
	pot_3_change = true;
	pot_4_change = true;
	set_Filter_values();
	refresh_pot_values();
}

//**************************************************  ***********************
// draw_DCA envelope line
//**************************************************  ***********************
void draw_AMP_envLine(void)
{
	uint8_t xplot1 = Amp_env_att;
	uint8_t xplot1_decay = Amp_env_dcy;
	uint8_t yplot2_sustain = Amp_env_sus;
	uint8_t xplot3_release = Amp_env_rel;
	static uint8_t xplot1_temp = 10;
	static uint8_t yplot2_sustain_temp = 40;
	static uint8_t xplot1_decay_temp = 0;
	static uint8_t xplot3_release_temp = 0;
	
	// Attack line
	disp.drawLine(10,85,xplot1_temp,40,ST7735_BLACK);	// delete old line
	xplot1 = 10+(Amp_env_att / 4);
	disp.drawLine(10,85,xplot1,40,ST7735_RED);		// draw new line
	
	// Decay Line
	xplot1_decay = (Amp_env_dcy / 4);
	yplot2_sustain = 85 - ((Amp_env_sus * 85)/239);
	disp.drawLine(xplot1_temp,40,xplot1_temp + xplot1_decay_temp,yplot2_sustain_temp,ST7735_BLACK  );
	disp.drawLine(xplot1,40,xplot1 + xplot1_decay,yplot2_sustain,ST7735_RED);
	
	// Sustain Line
	disp.drawLine(xplot1_temp + xplot1_decay_temp,yplot2_sustain_temp,90,yplot2_su  stain_temp,ST7735_BLACK);
	disp.drawLine(xplot1 + xplot1_decay,yplot2_sustain,90,yplot2_sustain,ST77  35_RED);
	
	// Relaese line
	xplot3_release = (90 + ((Amp_env_rel * 25)/127));
	disp.drawLine(90,yplot2_sustain_temp,xplot3_releas  e_temp,85,ST7735_BLACK);
	disp.drawLine(90,yplot2_sustain,xplot3_release,85,  ST7735_RED);
	
	// draw little rectangle for ADSR points
	disp.fillRect(xplot1_temp - 2,39,5,5,ST7735_BLACK);
	disp.fillRect(xplot1 - 2,39,5,5,ST7735_BLUE);
	disp.fillRect(xplot1_temp + xplot1_decay_temp -2,yplot2_sustain_temp-1,5,5,ST7735_BLACK);
	disp.fillRect(xplot1 + xplot1_decay -2,yplot2_sustain-1,5,5,ST7735_BLUE);
	disp.fillRect(88,yplot2_sustain_temp-1,5,5,ST7735_BLACK);
	disp.fillRect(88,yplot2_sustain-1,5,5,ST7735_BLUE);
	
	
	// draw vertikal point-line for relaese
	for (uint8_t i = 40; i <= 85; i++){
		disp.drawPixel(90,i,ST7735_GRAY);
		i++;
		i++;
	}
	
	// save current lines for delete old lines
	xplot1_temp = xplot1;
	yplot2_sustain_temp = yplot2_sustain;
	xplot1_decay_temp = xplot1_decay;
	xplot3_release_temp = xplot3_release;

}

//##################################################  #######################
// draw Filter envelope line
//##################################################  #######################
void draw_Filter_envLine (void)
{
	uint8_t xplot1 = Filter_env_att;
	uint8_t yplot2_sustain = Filter_env_sus;
	uint8_t xplot1_decay = Filter_env_dcy;
	uint8_t xplot3_release = Filter_env_rel;
	static uint8_t xplot1_temp = 10;
	static uint8_t yplot2_sustain_temp = 40;
	static uint8_t xplot1_decay_temp = 0;
	static uint8_t xplot3_release_temp = 0;
	
	// Attack line
	disp.drawLine(10,85,xplot1_temp,40,ST7735_BLACK);	// delete old line
	xplot1 = 10+(Filter_env_att / 4);
	disp.drawLine(10,85,xplot1,40,ST7735_RED);		// draw new line
	
	// Decay Line
	xplot1_decay = (Filter_env_dcy / 4);
	yplot2_sustain = 85 - ((Filter_env_sus * 85)/239);
	disp.drawLine(xplot1_temp,40,xplot1_temp + xplot1_decay_temp,yplot2_sustain_temp,ST7735_BLACK  );
	disp.drawLine(xplot1,40,xplot1 + xplot1_decay,yplot2_sustain,ST7735_RED);
	
	// Sustain Line
	disp.drawLine(xplot1_temp + xplot1_decay_temp,yplot2_sustain_temp,90,yplot2_su  stain_temp,ST7735_BLACK);
	disp.drawLine(xplot1 + xplot1_decay,yplot2_sustain,90,yplot2_sustain,ST77  35_RED);
	
	// Relaese line
	xplot3_release = (90 + ((Filter_env_rel * 25)/127));
	disp.drawLine(90,yplot2_sustain_temp,xplot3_releas  e_temp,85,ST7735_BLACK);
	disp.drawLine(90,yplot2_sustain,xplot3_release,85,  ST7735_RED);
	
	// draw little rectangle for ADSR points
	disp.fillRect(xplot1_temp - 2,39,5,5,ST7735_BLACK);
	disp.fillRect(xplot1 - 2,39,5,5,ST7735_BLUE);
	disp.fillRect(xplot1_temp + xplot1_decay_temp -2,yplot2_sustain_temp-1,5,5,ST7735_BLACK);
	disp.fillRect(xplot1 + xplot1_decay -2,yplot2_sustain-1,5,5,ST7735_BLUE);
	disp.fillRect(88,yplot2_sustain_temp-1,5,5,ST7735_BLACK);
	disp.fillRect(88,yplot2_sustain-1,5,5,ST7735_BLUE);
	
	
	// draw vertikal point-line for relaese
	for (uint8_t i = 40; i <= 85; i++){
		disp.drawPixel(90,i,ST7735_GRAY);
		i++;
		i++;
	}
	
	// save current lines for delete old lines
	xplot1_temp = xplot1;
	yplot2_sustain_temp = yplot2_sustain;
	xplot1_decay_temp = xplot1_decay;
	xplot3_release_temp = xplot3_release;
	
}


//**************************************************  ***********************
// draw Filter curves on LCD
//**************************************************  ***********************
void draw_filter_curves (uint8_t filterTyp)
{
	// clear old curve
	disp.fillRect(20,48,114,38,ST7735_BLACK);
	
	// draw LowPass Filter curve -----------------------------------------
	if (filterTyp == LowPass){
		const uint8_t x_plot = 68;
		const uint8_t y_plot = 85;
		uint8_t pot_1_cut = Filter_cut;
		uint8_t pot_2_res = Filter_res;
		uint8_t x = 40;
		uint16_t r = 0;
		uint8_t y = 0;
		uint8_t y_ = 0;
		uint8_t i = 0;
		uint8_t i_ = 0;
		uint8_t q_typ = 12;			// Filter Q
		uint16_t resonance = 0;
				
		for (i = 0; i < 48; i++)
		{
			resonance = (Filter_curve[(i * 8)]);
			resonance = (((resonance >> 2) * pot_2_res) >> 7);
			r = (x + r - y) + resonance;
			y = r / q_typ;
			disp.drawLine((pot_1_cut / 2) + x_plot - i_,(y_plot - y_ / 2), (pot_1_cut / 2) + x_plot - i, (y_plot - y / 2),ST7735_RED);
			i_ = i;
			y_ = y;
		}
		disp.drawLine(20, (y_plot - y_ / 2), 20 + (pot_1_cut / 2), (y_plot - y_ / 2), ST7735_RED);
	}
	
	// draw BandPass Filter curve ----------------------------------------
	else if (filterTyp == BandPass){
		const uint8_t x_plot = 20;
		const uint8_t y_plot = 85;
		uint8_t pot_1_cut = Filter_cut;
		uint8_t pot_2_res = Filter_res;
		uint8_t x = 40;
		uint16_t r = 0;
		uint8_t y = 0;
		uint8_t y_ = 0;
		uint8_t i = 0;
		uint8_t i_ = 0;
		uint8_t q_typ = 12;			// Filter Q
		uint16_t resonance = 0;
		
		for (i = 0; i < 27; i++)
		{
			resonance = (Filter_curve[(i * 8)]);
			resonance = (((resonance >> 2) * pot_2_res) >> 7);
			r = (x + r - y) + resonance;
			y = r / q_typ;
			disp.drawLine((pot_1_cut / 2) + x_plot + i_,(y_plot - y_ / 2),(pot_1_cut / 2) + x_plot + i,(y_plot - y_ / 2),ST7735_RED);
			disp.drawLine((pot_1_cut / 2) + x_plot + 49 - i_,(y_plot - y_ / 2),(pot_1_cut / 2) + x_plot + 49 - i,(y_plot - y_ / 2),ST7735_RED);
			i_ = i;
			y_ = y;
		}
	}
	
	// draw HighPass Filter curve ----------------------------------------
	else if (filterTyp == HighPass){
		const uint8_t x_plot = 20;
		const uint8_t y_plot = 85;
		uint8_t pot_1_cut = Filter_cut;
		uint8_t pot_2_res = Filter_res;
		uint8_t x = 40;
		uint16_t r = 0;
		uint8_t y = 0;
		uint8_t y_ = 0;
		uint8_t i = 0;
		uint8_t i_ = 0;
		uint8_t q_typ = 12;			// Filter Q
		uint16_t resonance = 0;
		
		for (i = 0; i < 48; i++)
		{
			resonance = (Filter_curve[(i * 8)]);
			resonance = (((resonance >> 2) * pot_2_res) >> 7);
			r = (x + r - y) + resonance;
			y = r / q_typ;
			disp.drawLine((pot_1_cut / 2) + x_plot + i_,(y_plot - y_ / 2), (pot_1_cut / 2) + x_plot + i, (y_plot - y / 2),ST7735_RED);
			i_ = i;
			y_ = y;
		}
		disp.drawLine(68 + (pot_1 / 2), (y_plot - y_ / 2), 131, (y_plot - y_ / 2), ST7735_RED);
		
	}
}

//##################################################  #######################
// set Filter typ
//##################################################  #######################
void set_Filter_typ(void)
{
	if (pot_4 <= 39)						// set LowPass
	{
		mixer1.gain(0, 1.0);	// LP
		mixer1.gain(1, 0);		// BP
		mixer1.gain(2, 0);		// HP
		mixer1.gain(3, 0);		// --
		mixer2.gain(0, 1.0);	// LP
		mixer2.gain(1, 0);		// BP
		mixer2.gain(2, 0);		// HP
		mixer2.gain(3, 0);		// --
		mixer3.gain(0, 1.0);	// LP
		mixer3.gain(1, 0);		// BP
		mixer3.gain(2, 0);		// HP
		mixer3.gain(3, 0);		// --
		mixer4.gain(0, 1.0);	// LP
		mixer4.gain(1, 0);		// BP
		mixer4.gain(2, 0);		// HP
		mixer4.gain(3, 0);		// --
		mixer5.gain(0, 1.0);	// LP
		mixer5.gain(1, 0);		// BP
		mixer5.gain(2, 0);		// HP
		mixer5.gain(3, 0);		// --
		mixer6.gain(0, 1.0);	// LP
		mixer6.gain(1, 0);		// BP
		mixer6.gain(2, 0);		// HP
		mixer6.gain(3, 0);		// --
		disp.fillRect(134, 120, 17, 8, ST7735_BLACK);
		disp.setTextColor(ST7735_GRAY);
		disp.setCursor(134, 120);
		disp.print("LP");
		Filter_typ = LowPass;
	}
	else if (pot_4 >= 42 && pot_4 <= 79)	// set BandPass
	{
		mixer1.gain(0, 0);		// LP
		mixer1.gain(1, 2.0);	// BP
		mixer1.gain(2, 0);		// HP
		mixer1.gain(3, 0);		// --
		mixer2.gain(0, 0);		// LP
		mixer2.gain(1, 2.0);	// BP
		mixer2.gain(2, 0);		// HP
		mixer2.gain(3, 0);		// --
		mixer3.gain(0, 0);		// LP
		mixer3.gain(1, 2.0);	// BP
		mixer3.gain(2, 0);		// HP
		mixer3.gain(3, 0);		// --
		mixer4.gain(0, 0);		// LP
		mixer4.gain(1, 2.0);	// BP
		mixer4.gain(2, 0);		// HP
		mixer4.gain(3, 0);		// --
		mixer5.gain(0, 0);		// LP
		mixer5.gain(1, 2.0);	// BP
		mixer5.gain(2, 0);		// HP
		mixer5.gain(3, 0);		// --
		mixer6.gain(0, 0);		// LP
		mixer6.gain(1, 2.0);	// BP
		mixer6.gain(2, 0);		// HP
		mixer6.gain(3, 0);		// --
		disp.fillRect(134, 120, 17, 8, ST7735_BLACK);
		disp.setTextColor(ST7735_GRAY);
		disp.setCursor(134, 120);
		disp.print("BP");
		Filter_typ = BandPass;
	}
	else if (pot_4 >= 84 && pot_4 <= 127)	// set HighPass
	{
		mixer1.gain(0, 0);		// LP
		mixer1.gain(1, 0);		// BP
		mixer1.gain(2, 2.0);	// HP
		mixer1.gain(3, 0);		// --
		mixer2.gain(0, 0);		// LP
		mixer2.gain(1, 0);		// BP
		mixer2.gain(2, 2.0);	// HP
		mixer2.gain(3, 0);		// --
		mixer3.gain(0, 0);		// LP
		mixer3.gain(1, 0);		// BP
		mixer3.gain(2, 2.0);	// HP
		mixer3.gain(3, 0);		// --
		mixer4.gain(0, 0);		// LP
		mixer4.gain(1, 0);		// BP
		mixer4.gain(2, 2.0);	// HP
		mixer4.gain(3, 0);		// --
		mixer5.gain(0, 0);		// LP
		mixer5.gain(1, 0);		// BP
		mixer5.gain(2, 2.0);	// HP
		mixer5.gain(3, 0);		// --
		mixer6.gain(0, 0);		// LP
		mixer6.gain(1, 0);		// BP
		mixer6.gain(2, 2.0);	// HP
		mixer6.gain(3, 0);		// --
		disp.fillRect(134, 120, 17, 8, ST7735_BLACK);
		disp.setTextColor(ST7735_GRAY);
		disp.setCursor(134, 120);
		disp.print("HP");
		Filter_typ = HighPass;
	}	
}


//##################################################  #######################
// print CPU usage every 200ms
//##################################################  #######################
void print_CPU_usage (void)
{
	disp.fillRect(133, 25, 23, 8, ST7735_BLACK);
	disp.setCursor(133, 26);
	disp.setTextColor(ST7735_WHITE);
	disp.print(AudioProcessorUsage());
}

//**************************************************  ***********************
// read Potentiometers with averaging calculation
//**************************************************  ***********************
boolean read_pots (void)
{
	boolean pot_change = false;
	int adc_sum = 0;
	
	// read Potentiometer 1
	for (uint8_t i = 0; i < 16; i++){
		//analog1.update();				// averaging calculation
		adc_sum = adc_sum + ((analog1.getValue()) >> 3);
	}
	pot_1 = adc_sum / 16;
	if(pot_1_old  != pot_1){
		pot_1_old = pot_1;
		pot_1_change = true;
		pot_change = true;
	}
	
	// read Potentiometer 2
	adc_sum = 0;
	for (uint8_t i = 0; i < 16; i++){
		//analog2.update();
		adc_sum = adc_sum + ((analog2.getValue()) >> 3);
	}
	pot_2 = adc_sum / 16;
	if(pot_2_old  != pot_2){
		pot_2_old = pot_2;
		pot_2_change = true;
		pot_change = true;
	}
	
	// read Potentiometer 3
	adc_sum = 0;
	for (uint8_t i = 0; i < 16; i++){
		//analog3.update();
		adc_sum = adc_sum + ((analog3.getValue()) >> 3);
	}
	pot_3 = adc_sum / 16;
	if(pot_3_old  != pot_3){
		pot_3_old = pot_3;
		pot_3_change = true;
		pot_change = true;
	}
	
	// read Potentiometer 4
	adc_sum = 0;
	for (uint8_t i = 0; i < 16; i++){
		//analog4.update();
		adc_sum = adc_sum + ((analog4.getValue()) >> 3);
	}
	pot_4 = adc_sum / 16;
	if(pot_4_old  != pot_4){
		pot_4_old = pot_4;
		pot_4_change = true;
		pot_change = true;
	}
	
	boolean temp_flag = pot_change;
	pot_change = false;
	return temp_flag;
}

//**************************************************  ***********************
// draw Potentiometer values
//**************************************************  ***********************
void refresh_pot_values(void)
{
	uint8_t pot1_value = 0;
	uint8_t pot2_value = 0;
	uint8_t pot3_value = 0;
	uint8_t pot4_value = 0;
	
	if (pot_1_change == true)
	{
		pot1_value = pot_1;
		disp.fillRect(4, 114, 32, 4, ST7735_BLACK);
		disp.drawLine(4,116,32,116,ST7735_BLUE);
		disp.drawLine(4 + (pot_div127 * pot1_value),114,4 + (pot_div127 * pot1_value),117,ST7735_RED);
		pot_1_change = false;
	}
	
	if (pot_2_change == true)
	{
		pot2_value = pot_2;
		disp.fillRect(4+40, 114, 32, 4, ST7735_BLACK);
		disp.drawLine(4+40,116,32+40,116,ST7735_BLUE);
		disp.drawLine(4 + 40 + (pot_div127 * pot2_value),114,4 + 40 + (pot_div127 * pot2_value),117,ST7735_RED);
		pot_2_change = false;
	}
	
	if (pot_3_change == true)
	{
		pot3_value = pot_3;
		disp.fillRect(4+40+40, 114, 32, 4, ST7735_BLACK);
		disp.drawLine(4+40+40,116,32+40+40,116,ST7735_BLUE  );
		disp.drawLine(4 + 40 + 40+(pot_div127 * pot3_value),114,4 + 40 + 40+(pot_div127 * pot3_value),117,ST7735_RED);
		pot_3_change = false;
	}
	
	if (pot_4_change == true)
	{
		pot4_value = pot_4;
		disp.fillRect(4+40+40+40, 114, 32, 4, ST7735_BLACK);
		disp.drawLine(4+40+40+40,116,32+40+40+40,116,ST773  5_BLUE);
		disp.drawLine(4 + 40+40+40+(pot_div127 * pot4_value),114,4 + 40+40+40+(pot_div127 * pot4_value),117,ST7735_RED);
		pot_4_change = false;
	}
}

//**************************************************  ***********************
// read Encoder
//**************************************************  ***********************
boolean read_Encoder (void)
{
	int newPosition = (myEnc.read() >> 2);
	
	if (newPosition != oldPosition) {
		if (newPosition < 0) {
			newPosition = 0;
			oldPosition = 0;
			myEnc.write(0);			
		}
		
		else if (newPosition > 9){
			newPosition = 9;
			oldPosition = 9;
			myEnc.write(9 * 4);
		}
		oldPosition = newPosition;
		return true;
	}
	return false;
}

//**************************************************  ***********************
// set Voices Lamp off
//**************************************************  ***********************
void set_Voices_Lamp (void)
{
	if (voices[0].lampTimeOn == 1){
		disp.fillRect(133, 3, 7, 4, ST7735_BLACK);
		disp.drawRect(133, 3, 7, 4, ST7735_RED);	// Lamp1 off
		voices[0].lampTimeOn--;
	}
	else if (voices[0].lampTimeOn > 1){
		voices[0].lampTimeOn--;
	}
	
	if (voices[1].lampTimeOn == 1){
		disp.fillRect(133+10, 3, 7, 4, ST7735_BLACK);
		disp.drawRect(133+10, 3, 7, 4, ST7735_RED);	// Lamp2 off
		voices[1].lampTimeOn--;
	}
	else if (voices[1].lampTimeOn > 1){
		voices[1].lampTimeOn--;
	}
	
	if (voices[2].lampTimeOn == 1){
		disp.fillRect(133+20, 3, 7, 4, ST7735_BLACK);
		disp.drawRect(133+20, 3, 7, 4, ST7735_RED);	// Lamp3 off
		voices[2].lampTimeOn--;
	}
	else if (voices[2].lampTimeOn > 1){
		voices[2].lampTimeOn--;
	}
	
	if (voices[3].lampTimeOn == 1){
		disp.fillRect(133, 11, 7, 4, ST7735_BLACK);
		disp.drawRect(133, 11, 7, 4, ST7735_RED);	// Lamp4 off
		voices[3].lampTimeOn--;
	}
	else if (voices[3].lampTimeOn > 1){
		voices[3].lampTimeOn--;
	}
	
	if (voices[4].lampTimeOn == 1){
		disp.fillRect(133+10, 11, 7, 4, ST7735_BLACK);
		disp.drawRect(133+10, 11, 7, 4, ST7735_RED);	// Lamp5 off
		voices[4].lampTimeOn--;
	}
	else if (voices[4].lampTimeOn > 1){
		voices[4].lampTimeOn--;
	}
	
	if (voices[5].lampTimeOn == 1){
		disp.fillRect(133+20, 11, 7, 4, ST7735_BLACK);
		disp.drawRect(133+20, 11, 7, 4, ST7735_RED);	// Lamp6 off
		voices[5].lampTimeOn--;
	}
	else if (voices[5].lampTimeOn > 1){
		voices[5].lampTimeOn--;
	}	
}

//**************************************************  ***********************
// get Voice number
//**************************************************  ***********************
int getVoiceNo(int note)
{
	voiceToReturn = -1;      //Initialise
	earliestTime = millis(); //Initialise to now
	if (note == -1)
	{
		//NoteOn() - Get the oldest free voice (recent voices may be still on release stage)
		for (int i = 0; i < NO_OF_VOICES; i++)
		{
			if (voices[i].voiceOn == false)
			{
				if (voices[i].timeOn < earliestTime)
				{
					earliestTime = voices[i].timeOn;
					voiceToReturn = i;
				}
			}
		}
		if (voiceToReturn == -1)
		{
			//No free voices, need to steal oldest sounding voice
			earliestTime = millis(); //Reinitialise
			for (int i = 0; i < NO_OF_VOICES; i++)
			{
				if (voices[i].timeOn < earliestTime)
				{
					earliestTime = voices[i].timeOn;
					voiceToReturn = i;
				}
			}
		}
		return voiceToReturn + 1;
	}
	else
	{
		//NoteOff() - Get voice number from note
		for (int i = 0; i < NO_OF_VOICES; i++)
		{
			if (voices[i].note == note && voices[i].voiceOn)
			{
				return i + 1;
			}
		}
	}
	//Shouldn't get here, return voice 1
	return 1;
}

//**************************************************  ***********************
// set Voice on
//**************************************************  ***********************
void set_Voice_on(uint8_t note)
{
	float freq = 440.0 * powf(2.0, (float)(note - 69) * 0.08333333);
	
	switch(getVoiceNo(-1))
	{
		case 1:
			waveform1.frequency(freq * BendFactor);
			waveform1.phase(0);
			envelope1_0.noteOn();
			envelope1_1.noteOn();
			voices[0].note = note;
			voices[0].timeOn = millis();
			voices[0].voiceOn = true;
			disp.fillRect(133, 3, 7, 4, ST7735_RED);	// Lamp1 on
		break;
		
		case 2:
			waveform2.frequency(freq * BendFactor);
			waveform2.phase(0);
			envelope2_0.noteOn();
			envelope2_1.noteOn();
			voices[1].note = note;
			voices[1].timeOn = millis();
			voices[1].voiceOn = true;
			disp.fillRect(133+10, 3, 7, 4, ST7735_RED);	// Lamp2 on
		break;
		
		case 3:
			waveform3.frequency(freq * BendFactor);
			waveform3.phase(0);
			envelope3_0.noteOn();
			envelope3_1.noteOn();
			voices[2].note = note;
			voices[2].timeOn = millis();
			voices[2].voiceOn = true;
			disp.fillRect(133+20, 3, 7, 4, ST7735_RED);	// Lamp3 on
		break;
			
		case 4:
			waveform4.frequency(freq * BendFactor);
			waveform4.phase(0);
			envelope4_0.noteOn();
			envelope4_1.noteOn();
			voices[3].note = note;
			voices[3].timeOn = millis();
			voices[3].voiceOn = true;
			disp.fillRect(133, 11, 7, 4, ST7735_RED);	// Lamp4 on
		break;
		
		case 5:
			waveform5.frequency(freq * BendFactor);
			waveform5.phase(0);
			envelope5_0.noteOn();
			envelope5_1.noteOn();
			voices[4].note = note;
			voices[4].timeOn = millis();
			voices[4].voiceOn = true;
			disp.fillRect(133+10, 11, 7, 4, ST7735_RED);	// Lamp5 on
		break;
		
		case 6:
			waveform6.frequency(freq * BendFactor);
			waveform6.phase(0);
			envelope6_0.noteOn();
			envelope6_1.noteOn();
			voices[5].note = note;
			voices[5].timeOn = millis();
			voices[5].voiceOn = true;
			disp.fillRect(133+20, 11, 7, 4, ST7735_RED);	// Lamp6 on
		break;
	}
}

//**************************************************  ***********************
// set Voices off
//**************************************************  ***********************
void set_Voice_off(uint8_t note)
{
	switch (getVoiceNo(note))
	{
		case 1:
			envelope1_0.noteOff();	// AMP
			envelope1_1.noteOff();	// Filter
			voices[0].voiceOn = false;
			voices[0].lampTimeOn = 64;
		break;
		case 2:
			envelope2_0.noteOff();	// AMP
			envelope2_1.noteOff();	// Filter
			voices[1].voiceOn = false;
			voices[1].lampTimeOn = 64;;
		break;	
		case 3:
			envelope3_0.noteOff();	// AMP
			envelope3_1.noteOff();	// Filter
			voices[2].voiceOn = false;
			voices[2].lampTimeOn = 64;
		break;
		case 4:
			envelope4_0.noteOff();	// AMP
			envelope4_1.noteOff();	// Filter
			voices[3].voiceOn = false;
			voices[3].lampTimeOn = 64;
		break;
		case 5:
			envelope5_0.noteOff();	// AMP
			envelope5_1.noteOff();	// Filter
			voices[4].voiceOn = false;
			voices[4].lampTimeOn = 64;
		break;
		case 6:
			envelope6_0.noteOff();	// AMP
			envelope6_1.noteOff();	// Filter
			voices[5].voiceOn = false;
			voices[5].lampTimeOn = 64;
		break;
	}
}

//**************************************************  ***********************
// set AllNotesOff
//**************************************************  ***********************
void set_AllNotesOff(void)
{
	voices[0].voiceOn = false;
	voices[1].voiceOn = false;
	voices[2].voiceOn = false;
	voices[3].voiceOn = false;
	voices[4].voiceOn = false;
	voices[5].voiceOn = false;
	envelope1_0.noteOff();	// AMP
	envelope1_1.noteOff();	// Filter
	envelope2_0.noteOff();	// AMP
	envelope2_1.noteOff();	// Filter
	envelope3_0.noteOff();	// AMP
	envelope3_1.noteOff();	// Filter
	envelope5_0.noteOff();	// AMP
	envelope5_1.noteOff();	// Filter
	envelope6_0.noteOff();	// AMP
	envelope6_1.noteOff();	// Filter
}

//**************************************************  ***********************
// Midi handel  (every 1ms)
//**************************************************  ***********************
void midi_handel (void)
{
	if (MIDI.read()) { // look for a message
		switch (MIDI.getType()) { // get message type
			
			// note on ---------------------------------------------------
			case midi::NoteOn:
				note = MIDI.getData1();
				velocity = MIDI.getData2();
				set_Voice_on(note);
			break;
			
			// note off --------------------------------------------------
			case midi::NoteOff:
				note = MIDI.getData1();
				velocity = MIDI.getData2();
				set_Voice_off(note);
			break;
			
			// Contrl: PitchBend -----------------------------------------
			case midi::PitchBend:
			pitch_bnd = (MIDI.getData2() << 7) + MIDI.getData1();
			pitch_bnd = (pitch_bnd - 8192);
			bendf = pitch_bnd;
			bendf = bendf / 8192;
			bendf = bendf * 2;
			bendf = bendf / 12;
			BendFactor = pow(2, bendf);
			waveform1.frequency(freq * BendFactor);
			break;
			default:
			break;
		}
	}
}


//-------------------------------------------------------------------------
// set Osc values
//-------------------------------------------------------------------------
void set_OSC_values(void)
{
	uint8_t pot_temp = 0;
	
	if (pot_1_change == true){
		pot_temp = (pot_1 / 18);
		waveform1.begin(pot_temp);
		waveform2.begin(pot_temp);
		waveform3.begin(pot_temp);
		waveform4.begin(pot_temp);
		waveform5.begin(pot_temp);
		waveform6.begin(pot_temp);
		disp.setCursor(5,40);
		disp.fillRect(5,39,23,8,ST7735_BLACK);
		disp.setTextColor(ST7735_WHITE);
		disp.print(Waveform_text[pot_temp]);
		Osc_waveform = pot_1;
	}
	
	if (pot_2_change == true){
		
	}
	
	if (pot_3_change == true){
		
	}
	
	if (pot_4_change == true){
		
	}
}

//**************************************************  ***********************
// print pot_value
//**************************************************  ***********************
void print_potValue (int pot_temp, uint8_t x, uint8_t y)
{
	// sustain only in %
	if (x == 84) {
		disp.fillRect(x, y, 30, 8, ST7735_BLACK);
		disp.setTextColor(ST7735_GRAY);
		uint8_t value = ((float)0.79 * pot_temp);
		if (value < 10){
			disp.setCursor(x + 9, y);
			disp.print(value);
			disp.print("%");
		}
		else if (value < 100){
			disp.setCursor(x + 6, y);
			disp.print(value);
			disp.print("%");
		}
		else if (value >= 100){
			disp.setCursor(x + 2, y);
			disp.print(value);
			disp.print("%");
		}
	}

	// attack, decay and release
	else
	{
		disp.fillRect(x, y, 30, 8, ST7735_BLACK);
		disp.setTextColor(ST7735_GRAY);
		int value = pot_temp;
		if (value < 10) {
			disp.setCursor(x + 6, y);
			disp.print(value);
			disp.print("ms");
		}
		else if (value < 100) {
			disp.setCursor(x + 4,y);
			disp.print(value);
			disp.print("ms");
		}
		else if (value < 1000) {
			disp.setCursor(x, y);
			disp.print(value);
			disp.print("ms");
		}
		else if (value < 10000) {
			float val_sec = (float)value / 1000;
			disp.drawFloat(val_sec, 1, x, y);
			disp.setCursor(x + 24, y);
			disp.print("s");
		}
		else if (value >= 10000) {
			uint8_t val_sec = value / 1000;
			disp.setCursor(x + 6, y);
			disp.print(val_sec);
			disp.print("s");
		}
	}
	
	
}


//**************************************************  ***********************
// set AMP envelope(1)
///**************************************************  **********************
void set_AMP_envelope(void)
{
	float pot_temp = 0;
	
	// Delay
		/*
		envelope1_0.delay(0);
		envelope2_0.delay(0);
		envelope3_0.delay(0);
		envelope4_0.delay(0);
		envelope5_0.delay(0);
		envelope6_0.delay(0);
		*/
	
	// Attack
	if (pot_1_change == true){
		pot_temp = (Pot_PowerTab[pot_1]);
		envelope1_0.attack(pot_temp);
		envelope2_0.attack(pot_temp);
		envelope3_0.attack(pot_temp);
		envelope4_0.attack(pot_temp);
		envelope5_0.attack(pot_temp);
		envelope6_0.attack(pot_temp);
		Amp_env_att = pot_1;
		print_potValue(pot_temp,4,120);
		
	}
	
	// Hold
		/*
		envelope1_0.hold(0);
		envelope2_0.hold(0);
		envelope3_0.hold(0);
		envelope4_0.hold(0);
		envelope5_0.hold(0);
		envelope6_0.hold(0);
		*/
	
	// Decay
	if (pot_2_change == true){
		pot_temp = (Pot_PowerTab[pot_2]);
		envelope1_0.decay(pot_temp);
		envelope2_0.decay(pot_temp);
		envelope3_0.decay(pot_temp);
		envelope4_0.decay(pot_temp);
		envelope5_0.decay(pot_temp);
		envelope6_0.decay(pot_temp);
		Amp_env_dcy = pot_2;
		print_potValue(pot_temp, 4+40, 120);
	}
	
	// Sustain
	if (pot_3_change == true){
		if (pot_3 <= 2)
		{
			pot_3 = 0;
		}
		pot_temp = (0.008 * pot_3);
		envelope1_0.sustain(pot_temp);
		envelope2_0.sustain(pot_temp);
		envelope3_0.sustain(pot_temp);
		envelope4_0.sustain(pot_temp);
		envelope5_0.sustain(pot_temp);
		envelope6_0.sustain(pot_temp);
		Amp_env_sus = pot_3;
		print_potValue(pot_3, 4+40+40, 120);
	}
	
	// Release
	if (pot_4_change == true){
		pot_temp = (Pot_PowerTab[pot_4]);
		envelope1_0.release(pot_temp);
		envelope2_0.release(pot_temp);
		envelope3_0.release(pot_temp);
		envelope4_0.release(pot_temp);
		envelope5_0.release(pot_temp);
		envelope6_0.release(pot_temp);
		Amp_env_rel = pot_4;
		print_potValue(pot_temp, 4+40+40+40, 120);
		
	}
}

//-------------------------------------------------------------------------
// set Filter envelope(2)
//-------------------------------------------------------------------------
void set_Filter_envelope(void)
{
	float pot_temp = 0;
	
	// Delay
		/*
		envelope1_1.delay(0);
		envelope2_1.delay(0);
		envelope3_1.delay(0);
		envelope4_1.delay(0);
		envelope5_1.delay(0);
		envelope6_1.delay(0);
		*/
	
	// Attack	
	if (pot_1_change == true){
		pot_temp = (Pot_PowerTab[pot_1]);
		envelope1_1.attack(pot_temp);
		envelope2_1.attack(pot_temp);
		envelope3_1.attack(pot_temp);
		envelope4_1.attack(pot_temp);
		envelope5_1.attack(pot_temp);
		envelope6_1.attack(pot_temp);
		Filter_env_att = pot_1;
		print_potValue(pot_temp,4,120);
	}
	
	// Hold
		/*
		envelope1_1.hold(0);
		envelope2_1.hold(0);
		envelope3_1.hold(0);
		envelope4_1.hold(0);
		envelope5_1.hold(0);
		envelope6_1.hold(0);
		*/
	
	// Decay
	if (pot_2_change == true){
		pot_temp = (Pot_PowerTab[pot_2]);
		envelope1_1.decay(pot_temp);
		envelope2_1.decay(pot_temp);
		envelope3_1.decay(pot_temp);
		envelope4_1.decay(pot_temp);
		envelope5_1.decay(pot_temp);
		envelope6_1.decay(pot_temp);
		Filter_env_dcy = pot_2;
		print_potValue(pot_temp, 4+40, 120);
	}
	
	// Sustain
	if (pot_3_change == true){
		if (pot_3 <= 2)
		{
			pot_3 = 0;
		}
		pot_temp = (0.008 * pot_3);
		envelope1_1.sustain(pot_temp);
		envelope2_1.sustain(pot_temp);
		envelope3_1.sustain(pot_temp);
		envelope4_1.sustain(pot_temp);
		envelope5_1.sustain(pot_temp);
		envelope6_1.sustain(pot_temp);
		Filter_env_sus = pot_3;
		print_potValue(pot_3, 4+40+40, 120);
	}
	
	// Release
	if (pot_4_change == true){
		pot_temp = (Pot_PowerTab[pot_4]);
		envelope1_1.release(pot_temp);
		envelope2_1.release(pot_temp);
		envelope3_1.release(pot_temp);
		envelope4_1.release(pot_temp);
		envelope5_1.release(pot_temp);
		envelope6_1.release(pot_temp);
		Filter_env_rel = pot_4;
		print_potValue(pot_temp, 4+40+40+40, 120);
	}
}

//**************************************************  ***********************
// set Filter envelope(2)
//**************************************************  ***********************
void set_Filter_values(void)
{
	float pot_temp = 0;
	int pot_value = 0;
	
	// set frequency
	if (pot_1_change == true){
		for (uint8_t i = 0; i < 16; i++){
			analog1.update();
			pot_value = pot_value + ((analog1.getValue()) >> 2);
		}
		pot_value = pot_value / 16;
		pot_temp = (FilterFrequency[pot_value]);
		filter1.frequency(pot_temp);
		filter2.frequency(pot_temp);
		filter3.frequency(pot_temp);
		filter4.frequency(pot_temp);
		filter5.frequency(pot_temp);
		filter6.frequency(pot_temp);
		Filter_cut = pot_1;
		disp.fillRect(4, 120, 30, 8, ST7735_BLACK);
		disp.setTextColor(ST7735_GRAY);
		int value = pot_temp;
		if (value < 100){
			disp.setCursor(8, 120);
			disp.print(value);
			disp.print("Hz");
		}
		else if (value < 1000){
			disp.setCursor(4, 120);
			disp.print(value);
			disp.print("Hz");
		}
		else if (value < 10000){
			value = value / 1000;
			disp.setCursor(6, 120);
			disp.print(value);
			disp.print("KHz");
		}
		else if (value < 100000){
			value = value / 1000;
			disp.setCursor(4, 120);
			disp.print(value);
			disp.print("KHz");
		}
		
	}
	
	// set resonance
	if (pot_2_change == true){
		pot_temp = (0.039 * pot_2);
		filter1.resonance(pot_temp);
		filter2.resonance(pot_temp);
		filter3.resonance(pot_temp);
		filter4.resonance(pot_temp);
		filter5.resonance(pot_temp);
		filter6.resonance(pot_temp);
		Filter_res = pot_2;
		disp.fillRect(44, 120, 30, 8, ST7735_BLACK);
		disp.setTextColor(ST7735_GRAY);
		uint8_t value = ((float)0.79 * pot_2);
		if (value < 10){
			disp.setCursor(44 + 9, 120);
			disp.print(value);
			disp.print("%");
		}
		else if (value < 100){
			disp.setCursor(44 + 6, 120);
			disp.print(value);
			disp.print("%");
		}
		else if (value >= 100){
			disp.setCursor(44 + 2, 120);
			disp.print(value);
			disp.print("%");
		}	
	}
	
	// set KeyTracking
	if (pot_3_change == true){
		pot_value = 0;
		for (uint8_t i = 0; i < 16; i++){
			analog3.update();
			pot_value = pot_value + ((analog3.getValue()) >> 2);
		}
		pot_value = pot_value / 16;
		/*
		pot_temp = (0.055 * pot_3);
		filter1.octaveControl(pot_temp);
		filter2.octaveControl(pot_temp);
		filter3.octaveControl(pot_temp);
		filter4.octaveControl(pot_temp);
		filter5.octaveControl(pot_temp);
		filter6.octaveControl(pot_temp);
		*/
		Filter_key = pot_3;
		disp.fillRect(84, 120, 30, 8, ST7735_BLACK);
		disp.setTextColor(ST7735_GRAY);
		int value = (pot_value * 0.785) - 100;
		if (value == 0){
			disp.setCursor(84 + 12, 120);
			disp.print(value);
		}
		else if (value > -10 && value < 0){
			disp.setCursor(84 + 8, 120);
			disp.print(value);
		}
		else if (value > -100 && value < 0){
			disp.setCursor(84 + 6, 120);
			disp.print(value);
		}
		else if (value > 0 && value < 10){
			disp.setCursor(84 + 8, 120);
			disp.print("+");
			disp.print(value);
		}
		else if (value >= 10 && value < 100){
			disp.setCursor(84 + 6, 120);
			disp.print("+");
			disp.print(value);
		}
		
		
		
		
			
			//disp.print("+");
		
	}
	
	// set Filter Typ
	if (pot_4_change == true){
		set_Filter_typ();
	}
}

//**************************************************  ***********************
// init System
//**************************************************  ***********************
void setup() {
	// init 1.8" TFT ------------------------------------
	disp.initR(INITR_BLACKTAB);
	disp.fillScreen(ST7735_BLACK);
	disp.setTextColor(ST7735_YELLOW, ST7735_BLACK);
	disp.setRotation(3);
	disp.setTextWrap(false);
	disp.setTextSize(2);
	disp.setCursor(20, 40);
	disp.print("SHRUTHI II");
	disp.setTextSize(0);
	disp.setCursor(60, 70);
	disp.print("V 1.02");
	// init Audio and Waveform -------------------------------------------
	AudioMemory(48);
	sgtl5000_1.enable();
	sgtl5000_1.volume(0.9);
	sgtl5000_1.audioPostProcessorEnable();
	sgtl5000_1.enhanceBassEnable();
	sgtl5000_1.enhanceBass(0.85, 0.85, 0, 2);		// high Bass + HP-Filter
	waveform1.begin(0);   // SINE
	waveform2.begin(0);   // SINE
	waveform3.begin(0);   // SINE
	waveform4.begin(0);   // SINE
	waveform5.begin(0);   // SINE
	waveform6.begin(0);   // SINE
	waveform1.frequency(440);
	waveform2.frequency(440);
	waveform3.frequency(440);
	waveform4.frequency(440);
	waveform5.frequency(440);
	waveform6.frequency(440);
	waveform1.amplitude(0.5);
	waveform2.amplitude(0.5);
	waveform3.amplitude(0.5);
	waveform4.amplitude(0.5);
	waveform5.amplitude(0.5);
	waveform6.amplitude(0.5);
	// init Envelopes ---------------------------------------------------
	envelope1_0.delay(0);
	envelope2_0.delay(0);
	envelope3_0.delay(0);
	envelope4_0.delay(0);
	envelope5_0.delay(0);
	envelope6_0.delay(0);
	envelope1_0.attack(0);
	envelope2_0.attack(0);
	envelope3_0.attack(0);
	envelope4_0.attack(0);
	envelope5_0.attack(0);
	envelope6_0.attack(0);
	envelope1_0.hold(0);
	envelope2_0.hold(0);
	envelope3_0.hold(0);
	envelope4_0.hold(0);
	envelope5_0.hold(0);
	envelope6_0.hold(0);
	envelope1_0.decay(5);
	envelope2_0.decay(5);
	envelope3_0.decay(5);
	envelope4_0.decay(5);
	envelope5_0.decay(5);
	envelope6_0.decay(5);
	envelope1_0.sustain(0.7);
	envelope2_0.sustain(0.7);
	envelope3_0.sustain(0.7);
	envelope4_0.sustain(0.7);
	envelope5_0.sustain(0.7);
	envelope6_0.sustain(0.7);
	envelope1_0.release(50);
	envelope2_0.release(50);
	envelope3_0.release(50);
	envelope4_0.release(50);
	envelope5_0.release(50);
	envelope6_0.release(50);
	envelope1_1.delay(0);
	envelope2_1.delay(0);
	envelope3_1.delay(0);
	envelope4_1.delay(0);
	envelope5_1.delay(0);
	envelope6_1.delay(0);
	envelope1_1.attack(0);
	envelope2_1.attack(0);
	envelope3_1.attack(0);
	envelope4_1.attack(0);
	envelope5_1.attack(0);
	envelope6_1.attack(0);
	envelope1_1.hold(0);
	envelope2_1.hold(0);
	envelope3_1.hold(0);
	envelope4_1.hold(0);
	envelope5_1.hold(0);
	envelope6_1.hold(0);
	envelope1_1.decay(5);
	envelope2_1.decay(5);
	envelope3_1.decay(5);
	envelope4_1.decay(5);
	envelope5_1.decay(5);
	envelope6_1.decay(5);
	envelope1_1.sustain(0.7);
	envelope2_1.sustain(0.7);
	envelope3_1.sustain(0.7);
	envelope4_1.sustain(0.7);
	envelope5_1.sustain(0.7);
	envelope6_1.sustain(0.7);
	envelope1_1.release(50);
	envelope2_1.release(50);
	envelope3_1.release(50);
	envelope4_1.release(50);
	envelope5_1.release(50);
	envelope6_1.release(50);
	Amp_env_att = 0;
	Amp_env_dcy = 30;
	Amp_env_sus = 95;
	Amp_env_rel = 30;
	Filter_env_att = 0;
	Filter_env_dcy = 30;
	Filter_env_sus = 95;
	Filter_env_rel = 30;
	Filter_cut = 80;
	Filter_res = 30;
	Filter_key = 50;
	Filter_typ = 0;
	dc1.amplitude(1.0);
	dc2.amplitude(1.0);
	dc3.amplitude(1.0);
	dc4.amplitude(1.0);
	dc5.amplitude(1.0);
	dc6.amplitude(1.0);
	// Mixer 1-6 (Filter) ------------------------------------------------
	mixer1.gain(0, 1.0);	// LP
	mixer1.gain(1, 0);		// BP
	mixer1.gain(2, 0);		// HP
	mixer1.gain(3, 0);		// --
	mixer2.gain(0, 1.0);	// LP
	mixer2.gain(1, 0);		// BP
	mixer2.gain(2, 0);		// HP
	mixer2.gain(3, 0);		// --
	mixer3.gain(0, 1.0);	// LP
	mixer3.gain(1, 0);		// BP
	mixer3.gain(2, 0);		// HP
	mixer3.gain(3, 0);		// --
	mixer4.gain(0, 1.0);	// LP
	mixer4.gain(1, 0);		// BP
	mixer4.gain(2, 0);		// HP
	mixer4.gain(3, 0);		// --
	mixer5.gain(0, 1.0);	// LP
	mixer5.gain(1, 0);		// BP
	mixer5.gain(2, 0);		// HP
	mixer5.gain(3, 0);		// --
	mixer6.gain(0, 1.0);	// LP
	mixer6.gain(1, 0);		// BP
	mixer6.gain(2, 0);		// HP
	mixer6.gain(3, 0);		// --
	// Mixer AMP ---------------------------------------------------------
	mixer20.gain(0, 0.85);	// Osc1
	mixer20.gain(1, 0.85);	// Osc2
	mixer20.gain(2, 0.85);	// Osc3
	mixer20.gain(3, 0.85);	// Osc4
	mixer21.gain(0, 0.85);	// Osc5
	mixer21.gain(1, 0.85);	// Osc6
	mixer21.gain(2, 0);		// --
	mixer21.gain(3, 0);		// --
	mixer22.gain(0, 0.85);	// Sum1
	mixer22.gain(1, 0.85);	// Sum2
	mixer22.gain(2, 0);		// --
	mixer22.gain(3, 0);		// --
	// Filter ------------------------------------------------------------
	filter1.frequency(2000);
	filter2.frequency(2000);
	filter3.frequency(2000);
	filter4.frequency(2000);
	filter5.frequency(2000);
	filter6.frequency(2000);
	filter1.resonance(2.5);
	filter2.resonance(2.5);
	filter3.resonance(2.5);
	filter4.resonance(2.5);
	filter5.resonance(2.5);
	filter6.resonance(2.5);
	filter1.octaveControl(7.0);
	filter2.octaveControl(7.0);
	filter3.octaveControl(7.0);
	filter4.octaveControl(7.0);
	filter5.octaveControl(7.0);
	filter6.octaveControl(7.0);
	//--------------------------------------------------
	//init analog Inputs
	pinMode(14, INPUT_DISABLE);
	pinMode(16, INPUT_DISABLE);
	pinMode(17, INPUT_DISABLE);
	pinMode(22, INPUT_DISABLE);
	//analogReadResolution(12);
	//analogReadAveraging(16);
	//---------------------------------------------------
	// init Encoder
	//myEnc.begin(0, 0, 9); // will start at 20 and go from 0 to 40
	// --------------------------------------------------
	// init Midi and clear Note_buffers
	MIDI.begin(channel);
	set_AllNotesOff();
	//---------------------------------------------------
	// draw first menu site
	for (uint8_t i = 0; i <= 5; i++)
	{
		read_pots();
	}
	pot_1_change = false;
	pot_2_change = false;
	pot_3_change = false;
	pot_4_change = false;
	Osc_menu();
}


//**************************************************  ***********************
// Main loop
//**************************************************  ***********************
void loop() {
	unsigned long currentMillis = millis();
	
	// read Midi datas (every 1ms) --------------------------------------
	if (currentMillis - previousTime_midi >= interval_midi){
		midi_handel();
		set_Voices_Lamp();
		previousTime_midi = currentMillis;
	}
	
	// read ADC (every 15ms) --------------------------------------------
	if (currentMillis - previousTime_ADC >= interval_ADC){
		analog1.update();
		analog2.update();
		analog3.update();
		analog4.update();
		previousTime_ADC = currentMillis;
	}
	
	// read Encoder  and Potentiometers (every 25ms) --------------------
	if (currentMillis - previousTime_pot >= interval_pot){
		
		if(read_Encoder() == true){		// Encoder menu site
			Menu_page = oldPosition;
			if(Menu_page == Menu_Osc){
				Osc_menu();
			}
			else if(Menu_page == Menu_AmpEnv){
				AMP_envelope_menu();
			}
			else if(Menu_page == Menu_FilterEnv){
				Filter_envelope_menu();
			}
			else if(Menu_page == Menu_Filter){
				Filter_menu();
			}
		}
		
	// read Potentiometers
		if (read_pots() == true){
			if (Menu_page == Menu_Osc){
				set_OSC_values();
			}
			else if (Menu_page == Menu_AmpEnv){
				set_AMP_envelope();
				draw_AMP_envLine();
				refresh_pot_values();
			}
			else if (Menu_page == Menu_FilterEnv){
				set_Filter_envelope();
				draw_Filter_envLine();
				refresh_pot_values();
			}
			else if (Menu_page == Menu_Filter){
				set_Filter_values();
				draw_filter_curves(Filter_typ);
				refresh_pot_values();
			}
		}
	}
	
	// Measurement CPU usage (every 200ms) ------------------------------
	if (currentMillis - previousTime_cpu >= interval_cpu) {
		print_CPU_usage();
		previousTime_cpu = currentMillis;
	}
}




/*

// seriell print ----------------------------------------------------------

Serial.println();

*/

Greetings from germany :)
 
Last edited:
Hallo friends :)

I optimized the potentiometer request in the ADC setup settings.
This prevents the potentiometer values from jumping accidentally on the menu pages.

Envelope menu
20201017_164337.jpg

Code:
#include <ResponsiveAnalogRead.h>

//init ADC inputs fom Teensy in Setup function
	pinMode(14, INPUT_DISABLE);
	pinMode(16, INPUT_DISABLE);
	pinMode(17, INPUT_DISABLE);
	pinMode(22, INPUT_DISABLE);
        ResponsiveAnalogRead analog1(A0, true);
        ResponsiveAnalogRead analog2(A2, true);
        ResponsiveAnalogRead analog3(A3, true);
        ResponsiveAnalogRead analog4(A8, true);
	analog1.setActivityThreshold(16);
	analog2.setActivityThreshold(16);
	analog3.setActivityThreshold(16);
	analog4.setActivityThreshold(16);
	analog1.enableEdgeSnap();
	analog2.enableEdgeSnap();
	analog3.enableEdgeSnap();
	analog4.enableEdgeSnap();

//*************************************************************************
// read Potentiometers 
//*************************************************************************
boolean read_pots (void)
{
	boolean pot_change = false;
	
	// read Potentiometer 1
	if (analog1.hasChanged() == true){
		pot_1 = ((analog1.getValue())>> 3);
		pot_1_change = true;
		pot_change = true;
	}
	
	// read Potentiometer 2
	if (analog2.hasChanged() == true){
		pot_2 = ((analog2.getValue())>> 3);
		pot_2_change = true;
		pot_change = true;
	}
	
	// read Potentiometer 3
	if (analog3.hasChanged() == true){
		pot_3 = ((analog3.getValue())>> 3);
		pot_3_change = true;
		pot_change = true;
	}
	
	// read Potentiometer 4
	if (analog4.hasChanged() == true){
		pot_4 = ((analog4.getValue())>> 3);
		pot_4_change = true;
		pot_change = true;
	}
	
	boolean temp_flag = pot_change;
	pot_change = false;
	return temp_flag;
}

Greetings from germany. Rolf
 
Hello friends :)

Today I implemented the key tracking for the filter. The digital multimode filter has one
Control input with the designation octaveControl (). This can be used to control the filter corner frequency.
The signal for the filter envelope and for key tracking is sent to this control input via a mixer
connected (see SynthBlock). The filter cutoff frequency is set using the frequency () parameter
and the resonance via the parameter resonance ().

Filter description
Filter.jpg

SynthBlock
Shruthi2-Synth-Block.jpg
Big pic: https://i.ibb.co/pP9N6Ts/Shruthi2-Synth-Block.jpg

Greetings Rolf
 
Hallo

Here my Audio designe code

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

// GUItool: begin automatically generated code
AudioSynthWaveformDc     dc2;            //xy=297,292
AudioSynthWaveformDc     dc1;            //xy=299,157
AudioSynthWaveformDc     dc6;            //xy=298,900
AudioSynthWaveformDc     dc3;            //xy=300,428
AudioSynthWaveformDc     dc4;            //xy=300,564
AudioSynthWaveformDc     dc5;            //xy=300,757
AudioSynthWaveform       waveform2;      //xy=305,252
AudioSynthWaveform       waveform1;      //xy=307,116
AudioSynthWaveform       waveform6;      //xy=307,855
AudioSynthWaveform       waveform4;      //xy=309,521
AudioSynthWaveform       waveform3;      //xy=310,387
AudioSynthWaveform       waveform5;      //xy=310,714
AudioSynthWaveformDc     KeyTrak3;            //xy=438,469
AudioSynthWaveformDc     KeyTrak4;           //xy=440,607
AudioSynthWaveformDc     KeyTrak6;           //xy=439,946
AudioSynthWaveformDc     KeyTrak2;            //xy=443,335
AudioSynthWaveformDc     KeyTrak5;           //xy=442,803
AudioSynthWaveformDc     KeyTrak1;            //xy=454,198
AudioEffectEnvelope      envelope3_1;    //xy=454,428
AudioEffectEnvelope      envelope2_1;    //xy=457,292
AudioEffectEnvelope      envelope4_1;    //xy=456,564
AudioEffectEnvelope      envelope5_1;    //xy=456,757
AudioEffectEnvelope      envelope6_1;    //xy=459,900
AudioEffectEnvelope      envelope1_1;    //xy=465,157
AudioMixer4              mixEnvKey6;        //xy=631,919
AudioMixer4              mixEnvKey4;        //xy=633,583
AudioMixer4              mixEnvKey5;        //xy=633,777
AudioMixer4              mixEnvKey3;         //xy=638,447
AudioMixer4              mixEnvKey1;         //xy=641,177
AudioMixer4              mixEnvKey2;         //xy=641,311
AudioFilterStateVariable filter2;        //xy=806,258
AudioFilterStateVariable filter1;        //xy=809,120
AudioFilterStateVariable filter3;        //xy=809,394
AudioFilterStateVariable filter4;        //xy=809,528
AudioFilterStateVariable filter6;        //xy=812,863
AudioFilterStateVariable filter5;        //xy=814,720
AudioMixer4              mixer2;         //xy=1019,264
AudioMixer4              mixer1;         //xy=1022,126
AudioMixer4              mixer3;         //xy=1027,400
AudioMixer4              mixer6;         //xy=1028,869
AudioMixer4              mixer4;         //xy=1031,534
AudioMixer4              mixer5;         //xy=1034,726
AudioEffectEnvelope      envelope1_0;    //xy=1187,125
AudioEffectEnvelope      envelope2_0;    //xy=1192,264
AudioEffectEnvelope      envelope3_0;    //xy=1201,400
AudioEffectEnvelope      envelope4_0;    //xy=1206,534
AudioEffectEnvelope      envelope6_0;    //xy=1209,868
AudioEffectEnvelope      envelope5_0;    //xy=1211,726
AudioMixer4              mixer20;        //xy=1449,514
AudioMixer4              mixer21;        //xy=1454,745
AudioMixer4              mixer22;        //xy=1646,751
AudioOutputI2S           i2s1;           //xy=1831,749
AudioAnalyzePeak         peak1;          //xy=1831,798
AudioConnection          patchCord1(dc2, envelope2_1);
AudioConnection          patchCord2(dc1, envelope1_1);
AudioConnection          patchCord3(dc6, envelope6_1);
AudioConnection          patchCord4(dc3, envelope3_1);
AudioConnection          patchCord5(dc4, envelope4_1);
AudioConnection          patchCord6(dc5, envelope5_1);
AudioConnection          patchCord7(waveform2, 0, filter2, 0);
AudioConnection          patchCord8(waveform1, 0, filter1, 0);
AudioConnection          patchCord9(waveform6, 0, filter6, 0);
AudioConnection          patchCord10(waveform4, 0, filter4, 0);
AudioConnection          patchCord11(waveform3, 0, filter3, 0);
AudioConnection          patchCord12(waveform5, 0, filter5, 0);
AudioConnection          patchCord13(KeyTrak3, 0, mixEnvKey3, 1);
AudioConnection          patchCord14(KeyTrak4, 0, mixEnvKey4, 1);
AudioConnection          patchCord15(KeyTrak6, 0, mixEnvKey6, 1);
AudioConnection          patchCord16(KeyTrak2, 0, mixEnvKey2, 1);
AudioConnection          patchCord17(KeyTrak5, 0, mixEnvKey5, 1);
AudioConnection          patchCord18(KeyTrak1, 0, mixEnvKey1, 1);
AudioConnection          patchCord19(envelope3_1, 0, mixEnvKey3, 0);
AudioConnection          patchCord20(envelope2_1, 0, mixEnvKey2, 0);
AudioConnection          patchCord21(envelope4_1, 0, mixEnvKey4, 0);
AudioConnection          patchCord22(envelope5_1, 0, mixEnvKey5, 0);
AudioConnection          patchCord23(envelope6_1, 0, mixEnvKey6, 0);
AudioConnection          patchCord24(envelope1_1, 0, mixEnvKey1, 0);
AudioConnection          patchCord25(mixEnvKey6, 0, filter6, 1);
AudioConnection          patchCord26(mixEnvKey4, 0, filter4, 1);
AudioConnection          patchCord27(mixEnvKey5, 0, filter5, 1);
AudioConnection          patchCord28(mixEnvKey3, 0, filter3, 1);
AudioConnection          patchCord29(mixEnvKey1, 0, filter1, 1);
AudioConnection          patchCord30(mixEnvKey2, 0, filter2, 1);
AudioConnection          patchCord31(filter2, 0, mixer2, 0);
AudioConnection          patchCord32(filter2, 1, mixer2, 1);
AudioConnection          patchCord33(filter2, 2, mixer2, 2);
AudioConnection          patchCord34(filter1, 0, mixer1, 0);
AudioConnection          patchCord35(filter1, 1, mixer1, 1);
AudioConnection          patchCord36(filter1, 2, mixer1, 2);
AudioConnection          patchCord37(filter3, 0, mixer3, 0);
AudioConnection          patchCord38(filter3, 1, mixer3, 1);
AudioConnection          patchCord39(filter3, 2, mixer3, 2);
AudioConnection          patchCord40(filter4, 0, mixer4, 0);
AudioConnection          patchCord41(filter4, 1, mixer4, 1);
AudioConnection          patchCord42(filter4, 2, mixer4, 2);
AudioConnection          patchCord43(filter6, 0, mixer6, 0);
AudioConnection          patchCord44(filter6, 1, mixer6, 1);
AudioConnection          patchCord45(filter6, 2, mixer6, 2);
AudioConnection          patchCord46(filter5, 0, mixer5, 0);
AudioConnection          patchCord47(filter5, 1, mixer5, 1);
AudioConnection          patchCord48(filter5, 2, mixer5, 2);
AudioConnection          patchCord49(mixer2, envelope2_0);
AudioConnection          patchCord50(mixer1, envelope1_0);
AudioConnection          patchCord51(mixer3, envelope3_0);
AudioConnection          patchCord52(mixer6, envelope6_0);
AudioConnection          patchCord53(mixer4, envelope4_0);
AudioConnection          patchCord54(mixer5, envelope5_0);
AudioConnection          patchCord55(envelope1_0, 0, mixer20, 0);
AudioConnection          patchCord56(envelope2_0, 0, mixer20, 1);
AudioConnection          patchCord57(envelope3_0, 0, mixer20, 2);
AudioConnection          patchCord58(envelope4_0, 0, mixer20, 3);
AudioConnection          patchCord59(envelope6_0, 0, mixer21, 1);
AudioConnection          patchCord60(envelope5_0, 0, mixer21, 0);
AudioConnection          patchCord61(mixer20, 0, mixer22, 0);
AudioConnection          patchCord62(mixer21, 0, mixer22, 1);
AudioConnection          patchCord63(mixer22, 0, i2s1, 0);
AudioConnection          patchCord64(mixer22, 0, i2s1, 1);
AudioConnection          patchCord65(mixer22, peak1);
AudioControlSGTL5000     sgtl5000_1;     //xy=1828,698
// GUItool: end automatically generated code


Now I'm working on the wave oscillators and modulation.

Greetings Rolf
 
Hallo friends :)

I have a little problem with the resonance in the filter. I use an A State Variable (Chamberlin) filter with 12 dB / octave.
When I set the resonance to maximum level, the filter does not oscillate. I increased the Q value in the filter function from 5 to 15 but it doesn't oscillate.
Where is the problem :confused:

Code:
#ifndef filter_variable_h_
#define filter_variable_h_

#include "Arduino.h"
#include "AudioStream.h"

class AudioFilterStateVariable: public AudioStream
{
public:
	AudioFilterStateVariable() : AudioStream(2, inputQueueArray) {
		frequency(1000);
		octaveControl(1.0); // default values
		resonance(0.707);
		state_inputprev = 0;
		state_lowpass = 0;
		state_bandpass = 0;
	}
	void frequency(float freq) {
		if (freq < 20.0) freq = 20.0;
		else if (freq > AUDIO_SAMPLE_RATE_EXACT/2.5) freq = AUDIO_SAMPLE_RATE_EXACT/2.5;
		setting_fcenter = (freq * (3.141592654/(AUDIO_SAMPLE_RATE_EXACT*2.0)))
			* 2147483647.0;
		// TODO: should we use an approximation when freq is not a const,
		// so the sinf() function isn't linked?
		setting_fmult = sinf(freq * (3.141592654/(AUDIO_SAMPLE_RATE_EXACT*2.0)))
			* 2147483647.0;
	}
	void resonance(float q) {
		if (q < 0.7) q = 0.7;
		else if (q > 15.0) q = 15;
		// TODO: allow lower Q when frequency is lower
		setting_damp = (1.0 / q) * 1073741824.0;
	}
	void octaveControl(float n) {
		// filter's corner frequency is Fcenter * 2^(control * N)
		// where "control" ranges from -1.0 to +1.0
		// and "N" allows the frequency to change from 0 to 7 octaves
		if (n < 0.0) n = 0.0;
		else if (n > 6.9999) n = 6.9999;
		setting_octavemult = n * 4096.0;
	}
	virtual void update(void);
private:
	void update_fixed(const int16_t *in,
		int16_t *lp, int16_t *bp, int16_t *hp);
	void update_variable(const int16_t *in, const int16_t *ctl,
		int16_t *lp, int16_t *bp, int16_t *hp);
	int32_t setting_fcenter;
	int32_t setting_fmult;
	int32_t setting_octavemult;
	int32_t setting_damp;
	int32_t state_inputprev;
	int32_t state_lowpass;
	int32_t state_bandpass;
	audio_block_t *inputQueueArray[2];
};

#endif

Thanks for help. Greeting from germany. Rolf
 
It will take a little longer. I am currently developing the oscillator page.

This is my current synth block.

Synth-Block6voices.jpg

Greetings Rolf
 
No. I have tested the PT8211. The SGTL5000 makes a better sound and has Filter and bass boost built-in.
 
Hello. Very nice presets. It would be great if you made the code open source, so I can take the oscilloscope code, if and when you improve it. Presets #24 and #58 were designed to be held, by the way, not played staccato.
 
Back
Top