#include <Arduino.h>
#include <cmath>
#include "Debugging.h"
// Pin Definitions for Channel 1
const int buttonPin1 = 34;
const int potPin1_1 = 12;
const int potPin1_2 = 13;
const int audioInPin1 = 36;
const int audioOutPin1 = 25;
// Pin Definitions for Channel 2
const int buttonPin2 = 35;
const int potPin2_1 = 14;
const int potPin2_2 = 27;
const int audioInPin2 = 39;
const int audioOutPin2 = 26;
// Variables for Channel 1
int buttonState1 = 0;
int lastButtonState1 = 0;
int effectIndex1 = 0;
int potValue1_1, potValue1_2;
int audioInValue1;
// Variables for Channel 2
int buttonState2 = 0;
int lastButtonState2 = 0;
int effectIndex2 = 0;
int potValue2_1, potValue2_2;
int audioInValue2;
// Delay and Reverb buffer
const int delayBufferSize = 1024;
int delayBuffer1[delayBufferSize];
int delayBuffer2[delayBufferSize];
int reverbBuffer1[delayBufferSize];
int reverbBuffer2[delayBufferSize];
int delayIndex = 0;
// List of Effects
enum Effects {Distortion, Delay, Overdrive, Crunch, Bright, TrueBypass};
Effects currentEffect1, currentEffect2;
// For debugging
String effectNames[] = {"Distortion", "Delay", "Overdrive", "Crunch", "Bright", "True Bypass"};
String paramNames[] = {"Gain, Threshold", "Delay Time, Delay Depth", "Drive, Tone", "Gain, Tone", "Wetness, Reverb", "N/A"};
// Debounce variables
unsigned long lastDebounceTime1 = 0;
unsigned long lastDebounceTime2 = 0;
const unsigned long debounceDelay = 50;
void setup() {
// Channel 1 Setup
pinMode(buttonPin1, INPUT_PULLUP);
pinMode(potPin1_1, INPUT);
pinMode(potPin1_2, INPUT);
pinMode(audioInPin1, INPUT);
// Channel 2 Setup
pinMode(buttonPin2, INPUT_PULLUP);
pinMode(potPin2_1, INPUT);
pinMode(potPin2_2, INPUT);
pinMode(audioInPin2, INPUT);
analogReadResolution(12); // Set ADC resolution to 12 bits
Serial.begin(115200); // Initialize Serial for debugging
}
void loop() {
// Debounce for Channel 1
int reading1 = digitalRead(buttonPin1);
if (reading1 != lastButtonState1) {
lastDebounceTime1 = millis();
}
if ((millis() - lastDebounceTime1) > debounceDelay) {
if (reading1 != buttonState1) {
buttonState1 = reading1;
if (buttonState1 == HIGH) {
effectIndex1 = (effectIndex1 + 1) % 6;
currentEffect1 = static_cast<Effects>(effectIndex1);
}
}
}
lastButtonState1 = reading1;
// Read pot values for Channel 1
potValue1_1 = analogRead(potPin1_1);
potValue1_2 = analogRead(potPin1_2);
// Read audio input for Channel 1
audioInValue1 = analogRead(audioInPin1);
// Apply effect for Channel 1
int processedAudio1 = applyEffect(audioInValue1, potValue1_1, potValue1_2, currentEffect1);
// Output processed audio for Channel 1
dacWrite(audioOutPin1, processedAudio1);
// Debounce for Channel 2
int reading2 = digitalRead(buttonPin2);
if (reading2 != lastButtonState2) {
lastDebounceTime2 = millis();
}
if ((millis() - lastDebounceTime2) > debounceDelay) {
if (reading2 != buttonState2) {
buttonState2 = reading2;
if (buttonState2 == HIGH) {
effectIndex2 = (effectIndex2 + 1) % 6;
currentEffect2 = static_cast<Effects>(effectIndex2);
}
}
}
lastButtonState2 = reading2;
// Read pot values for Channel 2
potValue2_1 = analogRead(potPin2_1);
potValue2_2 = analogRead(potPin2_2);
// Read audio input for Channel 2
audioInValue2 = analogRead(audioInPin2);
// Apply effect for Channel 2
int processedAudio2 = applyEffect(audioInValue2, potValue2_1, potValue2_2, currentEffect2);
// Output processed audio for Channel 2
dacWrite(audioOutPin2, processedAudio2);
}
int applyEffect(int audioIn, int param1, int param2, Effects effect) {
int audioOut = audioIn; // Default to no effect (True Bypass)
// Scaling potentiometer readings to [0, 1]
float p1 = (float)param1 / 4096.0;
float p2 = (float)param2 / 4096.0;
switch(effect) {
case Distortion:
audioOut = applyDistortion(audioIn, p1, p2);
break;
case Delay:
audioOut = applyDelay(audioIn, p1, p2, delayBuffer1);
break;
case Overdrive:
audioOut = applyOverdrive(audioIn, p1, p2);
break;
case Crunch:
audioOut = applyCrunch(audioIn, p1, p2);
break;
case Bright:
audioOut = applyBright(audioIn, p1, p2, reverbBuffer1);
break;
case TrueBypass:
audioOut = audioIn;
break;
}
return audioOut;
}
// Enhanced algorithms
// ... (Place the complete enhanced versions of applyBright, applyCrunch, applyDelay, applyDistortion, applyOverdrive here)
int applyBright(int sample, float wetness, float reverb, int *reverbBuffer) {
static float prevSample = 0;
float brightSample = wetness * (sample - prevSample) + (1 - wetness) * sample;
prevSample = sample;
// Reverb part
int reverbSample = reverbBuffer[(delayIndex - 2000 + delayBufferSize) % delayBufferSize];
int newReverbSample = sample + reverb * reverbSample;
reverbBuffer[delayIndex] = newReverbSample;
return int(brightSample * 1023.0 + newReverbSample);
}
int applyCrunch(int sample, float gain, float tone) {
float amplified = sample * gain;
float softClip = amplified / (1.0 + fabs(amplified));
static float prevSoftClip = 0;
float filteredSoftClip = tone * softClip + (1 - tone) * prevSoftClip;
prevSoftClip = filteredSoftClip;
return int(filteredSoftClip * 1023.0);
}
int applyDelay(int sample, float delayTime, float delayDepth, int *delayBuffer) {
int delaySampleIndex = (int)(delayTime * (delayBufferSize - 1));
int delayedSample = delayBuffer[(delayIndex - delaySampleIndex + delayBufferSize) % delayBufferSize];
delayBuffer[delayIndex] = sample;
delayIndex = (delayIndex + 1) % delayBufferSize;
int mixedSample = (1.0 - delayDepth) * sample + delayDepth * delayedSample;
return mixedSample;
}
int applyDistortion(int sample, float gain, float threshold) {
float amplified = sample * gain;
if (amplified > threshold * 1023.0) {
amplified = threshold * 1023.0;
} else if (amplified < -threshold * 1023.0) {
amplified = -threshold * 1023.0;
}
return int(amplified);
}
int applyOverdrive(int sample, float drive, float tone) {
float amplified = sample * drive;
float softClip = (2 / M_PI) * atan(amplified);
static float prevSoftClip = 0;
float filteredSoftClip = tone * softClip + (1 - tone) * prevSoftClip;
prevSoftClip = filteredSoftClip;
return int(filteredSoftClip * 1023.0);
}