Hey everyone!
that took longer than intended. Excuses aside, here's the code I came up with:
class EnvelopeGenerator
{
//pins
byte triggerPin, attackPin, attackLengthPin, decayPin, decayLengthPin, sustainPin, releasePin, releaseLengthPin, outputPin;
//state variables
bool trigger = 0;
bool sustain = 0;
bool note_on = 0;
bool attack_length = 0;
bool decay_length = 0;
bool release_length = 0;
byte attack_state = 0;
byte decay_state = 0;
byte release_state = 0;
unsigned long last_time_of_attack_sample;
unsigned long last_time_of_decay_sample;
unsigned long last_time_of_release_sample;
int attack_sample_rate = 0;
int decay_sample_rate = 0;
int release_sample_rate = 0;
public:
EnvelopeGenerator(byte pin1, byte pin2, byte pin3, byte pin4, byte pin5, byte pin6, byte pin7, byte pin8, byte pin9)
{
triggerPin = pin1;
attackPin = pin2;
attackLengthPin = pin3;
decayPin = pin4;
decayLengthPin = pin5;
sustainPin = pin6;
releasePin = pin7;
releaseLengthPin = pin8;
outputPin = pin9;
}
int attack_time_map(int input) { //2ms per sample to 20ms per sample
return (input * attack_sample_rate);
}
int decay_time_map(int input) { //2ms per sample to 20ms per sample
return (input * decay_sample_rate);
}
int release_time_map(int input) { //2ms per sample to 20ms per sample
return (input * release_sample_rate);
}
void update_controls() {
attack_sample_rate = attack_time_map(analogRead(attackPin));
attack_length = digitalRead(attackLengthPin);
decay_sample_rate = decay_time_map(analogRead(decayPin));
decay_length = digitalRead(decayLengthPin);
sustain = map(analogRead(sustainPin), 0, 1023, 0, 255);
release_sample_rate = release_time_map(analogRead(releasePin));
release_length = digitalRead(releaseLengthPin);
}
void read_trigger() {
if (digitalRead(triggerPin) == true and trigger == false) {
trigger = true;
attack_state = 0;
note_on = true;
digitalWrite(13, HIGH);
}
else if (digitalRead(triggerPin) == false and trigger == true) {
trigger = false;
release_state = sustain;
note_on = false;
digitalWrite(13, LOW);
}
}
void loopFunc() {
//read trigger pin and set boolean variables depending on state
read_trigger();
if (note_on == true) {
analogWrite(outputPin, attack_state);
if (attack_state >= 255) {
decay_state = 255;
}
else ((micros() - last_time_of_attack_sample >= attack_sample_rate) and (attack_state < 255)); {
attack_state++;
if (attack_length = LOW) {
last_time_of_attack_sample = micros();
attack_sample_rate = 50;
}
else {
attack_sample_rate = 200;
last_time_of_attack_sample = micros();
}
}
}
else if ((decay_state >= 255) and note_on == true) {
analogWrite(outputPin, decay_state);
if ((micros() - last_time_of_decay_sample >= decay_sample_rate) and (decay_state > sustain)) {
decay_state--;
attack_state = 0;
if (decay_length == LOW) {
last_time_of_decay_sample = micros();
decay_sample_rate = 50;
}
else {
last_time_of_decay_sample = micros();
decay_sample_rate = 200;
}
}
}
else if ((sustain >= decay_state) and note_on == true) {
analogWrite(outputPin, sustain);
}
else {
analogWrite(outputPin, release_state);
if ((micros() - last_time_of_release_sample >= release_sample_rate)) {
release_state--;
sustain = 0;
if (release_length == LOW) {
last_time_of_release_sample = micros();
decay_sample_rate = 50;
}
else {
last_time_of_release_sample = micros();
decay_sample_rate = 200;
}
}
}
}
};
EnvelopeGenerator adsr1(2, A7, 3, A6, 4, A5, A4, 5, 6);
//EnvelopeGenerator adsr2(7, A3, 8, A2, 9, A1, A0, 10, 11);
unsigned long last_time_of_update;
int update_controls_delta = 15; //every 512ms update control parameters
void setup() {
Serial.begin(300);
}
void loop() {
//update control parameters periodically based on update_controls_delta variable
if (millis() - last_time_of_update >= update_controls_delta) {
adsr1.update_controls();
// adsr2.update_controls();
}
adsr1.loopFunc();
//adsr2.loopFunc();
}
I've got this uploaded to my Nano but I don't seem to have any control over the time parameter of each state (Attack, Decay, Sustain, Release)