#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Adafruit_NeoPixel.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Bounce.h>
#include <EEPROM.h>
#include "mod-delay.h"
using namespace std;
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define PIN 8 //changed from last rev //pin3 on rev 2, pin 8 on rev 2.1 ->
#define NUMPIXELS 10 //changed from last rev
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
// GUItool: begin automatically generated code
AudioInputI2S i2s2; //xy=94,397
AudioSynthWaveform waveform1; //xy=95,302
AudioSynthWaveform waveform2; //xy=98,476
AudioSynthWaveformDc dc1; //xy=100,341
AudioAnalyzePeak peak1; //xy=251,372
AudioMixer4 inmix; //xy=251,424
AudioMixer4 mixer2; //xy=252,321
AudioMixer4 mixer3; //xy=252,495
AudioSynthWaveformDc dc2; //xy=265,256
AudioFilterBiquad biquad2; //xy=377,364
AudioSynthWaveform waveform4; //xy=423,464
AudioFilterStateVariable filter3; //xy=427,249
AudioEffectModDelay xdly2; //xy=501,399
AudioEffectModDelay xdly; //xy=503,327
AudioSynthWaveform waveform3; //xy=512,363
AudioAnalyzeNoteFrequency notefreq1; //xy=554,236
AudioEffectMultiply multiply1; //xy=646,352
AudioEffectMultiply multiply2; //xy=650,404
AudioMixer4 outmix; //xy=778,393
AudioSynthWaveform waveform5; //xy=869,493
AudioFilterBiquad biquad1; //xy=904,402
AudioMixer4 mixer1; //xy=1036,441
AudioAnalyzePeak peak2; //xy=1037,537
AudioSynthWaveformDc dc3; //xy=1038,497
AudioEffectMultiply multiply3; //xy=1160,471
AudioOutputI2S i2s1; //xy=1292,473
AudioConnection patchCord1(i2s2, 0, inmix, 0);
AudioConnection patchCord2(i2s2, 0, peak1, 0);
AudioConnection patchCord3(waveform1, 0, mixer2, 0);
AudioConnection patchCord4(waveform2, 0, mixer3, 0);
AudioConnection patchCord5(dc1, 0, mixer2, 1);
AudioConnection patchCord6(dc1, 0, mixer3, 1);
AudioConnection patchCord7(inmix, 0, mixer1, 1);
AudioConnection patchCord8(inmix, 0, filter3, 0);
AudioConnection patchCord9(inmix, biquad2);
AudioConnection patchCord10(mixer2, 0, xdly, 1);
AudioConnection patchCord11(mixer3, 0, xdly2, 1);
AudioConnection patchCord12(dc2, 0, filter3, 1);
AudioConnection patchCord13(biquad2, 0, xdly2, 0);
AudioConnection patchCord14(biquad2, 0, xdly, 0);
AudioConnection patchCord15(waveform4, 0, multiply2, 1);
AudioConnection patchCord16(filter3, 0, notefreq1, 0);
AudioConnection patchCord17(xdly2, 0, multiply2, 0);
AudioConnection patchCord18(xdly, 0, multiply1, 0);
AudioConnection patchCord19(waveform3, 0, multiply1, 1);
AudioConnection patchCord20(multiply1, 0, outmix, 0);
AudioConnection patchCord21(multiply2, 0, outmix, 1);
AudioConnection patchCord22(outmix, biquad1);
AudioConnection patchCord23(waveform5, peak2);
AudioConnection patchCord24(waveform5, 0, mixer1, 2);
AudioConnection patchCord25(biquad1, 0, mixer1, 0);
AudioConnection patchCord26(mixer1, 0, multiply3, 0);
AudioConnection patchCord27(dc3, 0, multiply3, 1);
AudioConnection patchCord28(multiply3, 0, i2s1, 0);
AudioConnection patchCord29(multiply3, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=579,550
// GUItool: end automatically generated code
// This is about max (97%!) for internal RAM
static const uint32_t LEN = 0x01500; //1500ok...
int16_t delaybuf[LEN];
int16_t delaybuf2[LEN];
uint32_t next;
int16_t ArbWave[256] = {0,0,0,0,7327,10362,12691,14654,16384,17947,19385,20724,21981,23170,24301,25381,26418,27415,28377,29308,30210,31086,31937,32767,32767,32767,
32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,31937,31086,30210,29308,28377,27415,26418,25381,24301,
23170,21981,20724,19385,17947,16384,14654,12691,10362,7327,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};
/***************/
//Pinout board rev1
int Pot1 = A6; // select the input pin for the potentiometer
int Pot2 = A3; // select the input pin for the potentiometer
int Pot3 = A2; // select the input pin for the potentiometer
int Pot4 = A1; // select the input pin for the potentiometer
int CV1 = A10;
int CV2 = A11;
int Tap1 = 2;
int Tap2 = 3;
int SW1 = A12;
int SW2 = A13;
//int ledPin2 = 4; // select the pin for the LED
//int ledPin3 = 5; // select the pin for the LED
int relayL = 4; // select the pin for the RelayL
int relayR = 5; // select the pin for the RelayR
//Variables for values
boolean Tap1Value = 0;
boolean Tap1ValueOld = 1;
boolean Tap2Value = 0;
float Pot1Value = 0; // variable to store the value coming from the sensor
float Pot2Value = 0; // variable to store the value coming from the sensor
float Pot3Value = 0; // variable to store the value coming from the sensor
float Pot4Value = 0; // variable to store the value coming from the sensor
int CV1Value = 0;
int CV2Value = 0;
int SW1Value = 0;
int SW2Value = 0;
float Pot1ValueOld = 0; // variable to store the previous value
float Pot2ValueOld = 0;
float Pot3ValueOld = 0;
float Pot4ValueOld = 0;
int SW1ValueOld = 0;
int SW2ValueOld = 0;
int CV1ValueOld = 0;
int CV2ValueOld = 0;
float margin = 0.01;
int InLevel = 0;
int OutLevel = 16;
int Tap1Timer = 0;
// Variables
int ledStateONOFF = LOW; // the current state of the output pin
int ledStateONOFF_old = LOW;
int buttonState0; // the current reading from the input pin
int lastButtonState0 = LOW; // the previous reading from the input pin
int ledStateBOOST = LOW; // the current state of the output pin
int ledStateBOOST_old = LOW;
int buttonState1; // the current reading from the input pin
int lastButtonState1 = LOW; // the previous reading from the input pin
unsigned long lastDebounceTime0 = 0; // the last time the output pin was toggled
unsigned long lastDebounceTime1 = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 20; // the debounce time; increase if the output flickers
const int myInput = AUDIO_INPUT_LINEIN;
int i,k;
float s_freq = 3;
float s_depth = 1;
long sum, sum_old;
long thresh = 0;
float freq_per = 0;
byte pd_state = 0;
const float sample_freq = 44100;
float Waveform_multi = 2.5;
uint32_t off =pixels.Color(0,0,0);
uint32_t blue =pixels.Color(0,0,50);
uint32_t red =pixels.Color(50,0,0);
uint32_t green =pixels.Color(0,40,0);
uint32_t yellow =pixels.Color(40,40,0);
uint32_t white =pixels.Color(30,30,30);
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;
}
Bounce OnOff = Bounce(Tap1, 30 );
Bounce BoostOnOff = Bounce(Tap2, 30);
elapsedMillis ClippingInterval; //timer that is used for peak reading
elapsedMillis HoldValue; //timer that is used for Volume Adjustment
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(100);
AudioMemory(100);
pixels.begin();
for (int i = 0;i<NUMPIXELS;i++){
pixels.setPixelColor(i,off);
}
pixels.show();
float fc = 300;
biquad1.setHighpass(0,5,0.7);
biquad1.setHighpass(1,5,0.7);
biquad1.setLowpass(2,fc,0.7);
biquad1.setLowpass(3,fc,0.7);
// biquad2.setHighpass(0,5,0.7);
// biquad2.setHighpass(1,5,0.7);
biquad2.setLowpass(0,fc,0.7);
biquad2.setLowpass(1,fc,0.7);
biquad2.setLowpass(2,fc,0.7);
biquad2.setLowpass(3,fc,0.7);
AudioNoInterrupts();
float mod_freq = 4;//4
waveform1.begin(1,mod_freq,WAVEFORM_ARBITRARY);
waveform1.arbitraryWaveform(DelayWave,50);
waveform2.phase(20);
waveform2.begin(1,mod_freq,WAVEFORM_ARBITRARY);
waveform2.arbitraryWaveform(DelayWave,50);
waveform2.phase(200);
waveform3.begin(1,mod_freq,WAVEFORM_ARBITRARY);
waveform3.arbitraryWaveform(ArbWave,50);
waveform3.phase(0);
waveform4.begin(1,mod_freq,WAVEFORM_ARBITRARY);
waveform4.arbitraryWaveform(ArbWave,50);
waveform4.phase(180);
notefreq1.begin(.8);
waveform5.begin(.5,20,WAVEFORM_TRIANGLE);
inmix.gain(0, 2);
//inmix.gain(1, 0.9);// set by knob
//inmix.gain(2, 0.02);
outmix.gain(0, 1.0);
outmix.gain(1, 1.0);
mixer1.gain(0,0.7);
mixer1.gain(1,0.7);
mixer1.gain(2,.3);
mixer1.gain(3,0);
mixer2.gain(0,1);
mixer2.gain(1, 0);
mixer3.gain(0,1);
mixer3.gain(1, 0);
filter3.frequency(300);
filter3.resonance(.7);
xdly.setbuf(LEN, delaybuf);
xdly2.setbuf(LEN, delaybuf2);
//sgtl5000_1.enable();
//sgtl5000_1.volume(0.5);
sgtl5000_1.enable(); // Enable the audio shield
//sgtl5000_1.inputSelect(myInput);
sgtl5000_1.volume(0.8);
sgtl5000_1.unmuteHeadphone();
sgtl5000_1.lineInLevel(EEPROM.read(0)); // stored input gain
sgtl5000_1.lineOutLevel(17); // 2,53Vp-p
sgtl5000_1.dacVolume (1);
AudioInterrupts();
pinMode(relayL, OUTPUT);
pinMode(relayR, OUTPUT);
pinMode(Tap1, INPUT);
pinMode(Tap2, INPUT);
sgtl5000_1.autoVolumeControl(0,0,0,-3.0,200,2000); //maxGain,response,hard limit,threshold,attack, decay
Serial.println("Setup complete.");
dc1.amplitude(0);
dc2.amplitude(0);
dc3.amplitude(1);
pixels.setPixelColor(0,red);
pixels.show();
}
void loop() {
// put your main code here, to run repeatedly:
OnOff.update(); //update the bounce
BoostOnOff.update();
int reading0 = digitalRead(Tap1);
int reading1 = digitalRead(Tap2);
// read the value from the sensor:
Pot1Value = analogRead(Pot1); //Sub
Pot2Value = analogRead(Pot2); //Tone
Pot3Value = analogRead(Pot3); //Mix
Pot4Value = analogRead(Pot4); //Master
Tap1Value = digitalRead(Tap1); //On off
Tap2Value = digitalRead(Tap2); //Sub only
SW1Value = analogRead(SW1); //Tone setting
SW2Value = analogRead(SW2); //Octave up
CV1Value = analogRead(CV1); //EXP1 input
CV2Value = analogRead(CV2); //EXP2 input
SW1Value = map(SW1Value, 0, 1023, 5, 0); //Tone
SW1Value = constrain(SW1Value, 1, 5);
SW2Value = map(SW2Value, 0, 1023, 5, 0);
SW2Value = constrain(SW2Value, 1, 5); //Octave up
//********************ON -OFF handling**********************
buttonState0 = OnOff.read();
if (lastButtonState0 != buttonState0){
if (buttonState0 == LOW) {
ledStateONOFF = !ledStateONOFF;
}
}
buttonState1 = BoostOnOff.read();
if (lastButtonState1 != buttonState1){
if (buttonState1 == LOW) {
ledStateBOOST = !ledStateBOOST;
}
}
// set the outputs:
if (ledStateONOFF != ledStateONOFF_old){
pixels.setPixelColor(2, pixels.Color(ledStateONOFF*30,(ledStateONOFF*30),ledStateONOFF*30)); // ONOFF bright white color.
digitalWrite(relayL, ledStateONOFF);
digitalWrite(relayR, ledStateONOFF);
ledStateONOFF_old = ledStateONOFF;
pixels.show(); // This sends the updated pixel color to the hardware.
}
if (ledStateBOOST != ledStateBOOST_old){
pixels.setPixelColor(1, pixels.Color(ledStateBOOST*30,(ledStateBOOST*30),ledStateBOOST*30)); // OCTAVE ONLY bright white color.
ledStateBOOST_old = ledStateBOOST;
pixels.show(); // This sends the updated pixel color to the hardware.
}
lastButtonState0 = buttonState0; //save readings to next round
lastButtonState1 = buttonState1;
/////////////////////////////////////////////////////
int margin = 12;
//Change tone controller/shape
if (SW1Value != SW1ValueOld){
if (SW1Value == 3)waveform5.begin(WAVEFORM_SQUARE);
else if (SW1Value == 5)waveform5.begin(WAVEFORM_TRIANGLE);
else waveform5.begin(WAVEFORM_SAWTOOTH);
Serial.println(" New wave: ");
Serial.println(SW1Value);
SW1ValueOld = SW1Value;
}
if (notefreq1.available()){
if (SW2Value == 1){
waveform5.frequency(notefreq1.read()* .5); //1 octave down
waveform5.amplitude(peak1.read());
}
else if (SW2Value == 5){
waveform5.frequency(notefreq1.read()* 2.5); //1.5 octave up
waveform5.amplitude(peak1.read());
}
else {
waveform5.frequency(notefreq1.read()* 2.); //1 octave up.
waveform5.amplitude(peak1.read());
}
}
if(!ledStateONOFF){ //OFF
//mixer1.gain(0,0);
//mixer1.gain(1,1);
// mixer1.gain(2, 0);
//mixer1.gain(3, 0);
}
else if(ledStateBOOST && ledStateONOFF){ //sub only
mixer1.gain(0,1);
mixer1.gain(1,0);
// mixer1.gain(2, 0);
mixer1.gain(3, 0);
}
else{ //On - mixed signals
mixer1.gain(0,(float)Pot3Value/0x3ff);
mixer1.gain(1,(1-(float)Pot3Value/0x3ff));
// mixer1.gain(2, 0);
mixer1.gain(3, 0);
}
if ((Pot1Value <= (Pot1ValueOld-margin)) || (Pot1Value >= (Pot1ValueOld+margin))) {
float note = (float)Pot1Value/0x3ff;
if (note > 0.85)note = 0.93;
else if ((note <= 0.85)&&(note > 0.5))note = 0.62;
else if ((note <= 0.5)&&(note > 0.32))note = 0.37;
else if ((note <= 0.32)&&(note > 0.0))note = 0.27;
AudioNoInterrupts();
waveform1.amplitude(note);//working values: 0.93 / 0.62 / 0.37 / 0.27
waveform2.amplitude(note);//working values: 0.93 / 0.62 / 0.37 / 0.27
AudioInterrupts();
Pot1ValueOld = Pot1Value;
Serial.print("Pot1:");
Serial.println(note);
}
if ((CV1Value <= (CV1ValueOld-margin)) || (CV1Value >= (CV1ValueOld+margin))) {
float note = mapfloat(CV1Value,0,190,0,1.0);
if (note > 0.85)note = 0.93;
// else if ((note <= 0.85)&&(note > 0.5))note = 0.62;
// else if ((note <= 0.5)&&(note > 0.32))note = 0.37;
// else if ((note <= 0.32)&&(note > 0.0))note = 0.27;
else if (note <= 0.1)note = 0.1;
//else note = 0.27;
Serial.print("CV1:");
Serial.println(note);
waveform1.amplitude(note);//working values: 0.93 / 0.62 / 0.37 / 0.27
waveform2.amplitude(note);//working values: 0.93 / 0.62 / 0.37 / 0.27
CV1ValueOld = CV1Value;
}
if ((Pot2Value <= (Pot2ValueOld-margin)) || (Pot2Value >= (Pot2ValueOld+margin))) {
Pot2ValueOld = Pot2Value;
if (Pot2Value > 990)Pot2Value = 1024;
mixer1.gain(2,1-(float)(Pot2Value/0x3ff));
Serial.print("Pot2:");
Serial.println(Pot2Value);
}
if ((CV2Value <= (CV2ValueOld-margin)) || (CV2Value >= (CV2ValueOld+margin))) {
float mixLevel = mapfloat(CV2Value,0,190,0,1.0);
mixer1.gain(2,mixLevel);
Serial.print("Cv2:");
Serial.println(mixLevel);
CV2ValueOld = CV2Value;
}
if ((Pot3Value <= (Pot3ValueOld-margin)) || (Pot3Value >= (Pot3ValueOld+margin))) {
mixer1.gain(0,(float)Pot3Value/0x3ff);
mixer1.gain(1,(1-(float)Pot3Value/0x3ff));
Serial.print("Pot3:");
Serial.println(Pot3Value);
Pot3ValueOld = Pot3Value;
}
if ((Pot4Value <= (Pot4ValueOld-margin)) || (Pot4Value >= (Pot4ValueOld+margin))) {
int outlevel = map(Pot4Value,0,1023,13,31);
sgtl5000_1.lineOutLevel(outlevel);
Serial.print("Pot4:");
Serial.println(Pot4Value);
Pot4ValueOld = Pot4Value;
}
//*******************INPUT/OUTPUT LEVEL ADJUST************************
if (!Tap1Value && (Tap1Value == Tap1ValueOld)){ //When Mode/tap is held down you can adjust the input gain of the input
Tap1Timer++;
delay(100);
if (Tap1Timer > 15){
InLevel = map(Pot4Value,0,1023,15,0);
sgtl5000_1.lineInLevel(InLevel);
pixels.setPixelColor(0, pixels.Color(InLevel*15,(InLevel*15),InLevel*0));
pixels.show(); // This sends the updated pixel color to the hardware.
digitalWrite(relayL, 1);
digitalWrite(relayR, 1);
ledStateONOFF = 1;
Pot4ValueOld = Pot4Value;
}
}
else if (Tap1Timer > 15){ //only write to EEPROM once
EEPROM.write(0, InLevel);
Serial.println(InLevel);
pixels.setPixelColor(0, red);
pixels.show(); // This sends the updated pixel color to the hardware.
Tap1Timer = 0;
}
else if (Tap1Value){
Tap1Timer = 0;
}
/*
if (SW1Value == 1){ //HP pos for Output level
if (!Tap1Value && (Tap1Value == Tap1ValueOld)){ //When Mode/tap is held down you can adjust the input gain of the input
// Serial.print("TIME");
Tap1Timer++;
if (Tap1Timer > 15){
outLevel = analogRead(Pot1);
outLevel = mapfloat(outLevel,0,1023,10,1);
delay(100);
//analogWrite(ledPin2, 255);
//display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(5, 10);
display.print("Output:");
display.print(outLevel);
display.display();
}
}
else if (Tap1Timer > 15){ //only write to EEPROM once
EEPROM.write(1, outLevel);
Tap1Timer = 0;
}
else if (Tap1Value){
// peak = peak1.read(); //read the signal output peak
if (peak == -1)(peak = 0);
//analogWrite(ledPin2, peak*100);
}
}
*/
/*
Serial.print(" Pot1: ");
Serial.print(Pot1Value);
Serial.print(" Pot2: ");
Serial.print(Pot2Value);
Serial.print(" Pot3: ");
Serial.print(Pot3Value);
Serial.print(" Pot4: ");
Serial.print(Pot4Value);
Serial.print(" SW1: ");
Serial.print(SW1Value);
Serial.print(" SW2: ");
Serial.print(SW2Value);
Serial.print(" CV1: ");
Serial.print(CV1Value);
Serial.print(" CV2: ");
Serial.println(CV2Value);
*/
SW2ValueOld = SW2Value;
Tap1ValueOld = Tap1Value;
if (ClippingInterval > 1000){
if (ledStateONOFF){
float peakLevel = peak1.readPeakToPeak();
if (peakLevel > 1) pixels.setPixelColor(2,red); //indicate high input level
else pixels.setPixelColor(2,white);
pixels.show(); // This sends the updated pixel color to the hardware.
ClippingInterval = 0;
}
}
/*
Serial.print("Diagnostics: ");
Serial.print(" max, buffs: ");
Serial.print(AudioProcessorUsageMax());
Serial.print(" ");
Serial.println(AudioMemoryUsageMax());
AudioProcessorUsageMaxReset();
xdly.inspect();
*/
}