Skip to content

Commit 7294701

Browse files
author
katspaugh
committed
adsrduino and midi-cv
1 parent c06438f commit 7294701

File tree

7 files changed

+1169
-0
lines changed

7 files changed

+1169
-0
lines changed

ADSRduino/ADSRduino.ino

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// ADSRduino
2+
//
3+
// a simple ADSR for the Arduino
4+
// m0xpd
5+
// Feb 2017
6+
//
7+
// Modified by katspaugh in 2018 to use the Wire library
8+
//
9+
// see http://m0xpd.blogspot.co.uk/2017/02/signal-processing-on-arduino.html
10+
//
11+
// Uses a DAC microchip to produce CV
12+
// receives gate inputs on digital pin 2 (remember to protect e.g. with a 200R resistor and a 5V1 Zener diode)
13+
// and a loop mode input on digital pin 3 (pulling to 0V selects loop mode)
14+
//
15+
// Voltages between 0 and 5V (e.g. from potentiometers) on analog pins A0:A3 control Attack, Decay, Sustain & Release
16+
17+
#include <Wire.h>
18+
19+
// Pin definitions...
20+
const int gatePin = 2;
21+
22+
// Analog pins for the potentiometers
23+
const int pot0 = 6;
24+
const int pot1 = 0;
25+
const int pot2 = 7;
26+
const int pot3 = 1;
27+
28+
// Pins A4 (SDA), A5 (SCL) are reserved for the DAC
29+
const int DAC_vin = A3; // A2
30+
const int DAC_ground = A2; // A3
31+
const byte DAC_address = 0x60; // The I2C address can vary
32+
33+
float alpha = 0.7; // this is the pole location ('time constant') used for the first-order difference equation
34+
double alpha1 = 0.9; // initial value for attack
35+
double alpha2 = 0.9; // initial value for decay
36+
double alpha3 = 0.95; // initial value for release
37+
38+
float envelope = 0.0; // initialise the envelope
39+
float CV0 = 0.0; // result of reads from potentiometers (yes - it will only be an int, but helps with the casting!)
40+
float CV1 = 0.0;
41+
int CV2 = 0;
42+
float CV3 = 0.0;
43+
44+
int drive = 0;
45+
int sustain_Level = 0;
46+
int scan = 0;
47+
boolean note_active = false;
48+
boolean trigger = false;
49+
boolean decay = false;
50+
boolean release_done = true;
51+
52+
53+
void writeToDAC(int DC_Value) {
54+
Wire.beginTransmission(DAC_address);
55+
Wire.write(byte((DC_Value & 0x0f00) >> 8));
56+
Wire.write(byte(DC_Value & 0xff));
57+
Wire.endTransmission();
58+
}
59+
60+
void setup() {
61+
pinMode(gatePin, INPUT);
62+
63+
// Power up the DAC
64+
pinMode(DAC_vin, OUTPUT);
65+
pinMode(DAC_ground, OUTPUT);
66+
digitalWrite(DAC_vin, HIGH);
67+
digitalWrite(DAC_ground, LOW);
68+
69+
Wire.begin();
70+
71+
Serial.begin(9600);
72+
}
73+
74+
void loop() {
75+
boolean gate = digitalRead(gatePin); // read the gate input every time through the loop
76+
Serial.println(gate);
77+
update_params(scan); // scan only one of the other inputs each pass
78+
79+
boolean trigger = gate; // trigger an ADSR even if there's a gate OR if we're in loop mode
80+
while (trigger) {
81+
if (note_active == false) { // if a note isn't active and we're triggered, then start one!
82+
decay = false;
83+
drive = 4096; // drive toward full value
84+
alpha = alpha1; // set 'time constant' alpha1 for attack phase
85+
note_active = true; // set the note_active flag
86+
}
87+
if ((decay == false) && (envelope > 4000) && (drive == 4096)) { // if we've reached envelope >4000 with drive= 4096,
88+
// we must be at the end of attack phase
89+
// so switch to decay...
90+
decay = true; // set decay flag
91+
drive = sustain_Level; // drive toward sustain level
92+
alpha = alpha2; // and set 'time constant' alpha2 for decay phase
93+
}
94+
95+
envelope = ((1.0 - alpha) * drive + alpha * envelope); // implement difference equation: y(k) = (1 - alpha) * x(k) + alpha * y(k-1)
96+
writeToDAC(round(envelope)); // and output the envelope to the DAC
97+
98+
gate = digitalRead(gatePin); // read the gate pin (remember we're in the while loop)
99+
trigger = gate; // and re-evaluate the trigger function
100+
}
101+
102+
if (note_active == true) { // this is the start of the release phase
103+
drive = 0; // drive towards zero
104+
alpha = alpha3; // set 'time comnstant' alpha3 for release phase
105+
note_active = false; // turn off note_active flag
106+
release_done = false; // and set release_flag done false
107+
}
108+
109+
envelope = ((1.0 - alpha3) * drive + alpha3 * envelope); // implement the difference equation again (outside the while loop)
110+
writeToDAC(round(envelope)); // and output envelope
111+
gate = digitalRead(gatePin); // watch out for a new note
112+
scan += 1; // prepare to look at a new parameter input
113+
if (envelope < 4) { // is the release phase ended?
114+
release_done = true; // yes - so flag it
115+
}
116+
if (scan == 4) { // increment the scan pointer
117+
scan = 0;
118+
}
119+
}
120+
121+
// read the input parameters
122+
void update_params(int scan) {
123+
switch (scan) {
124+
case 0:
125+
CV0 = analogRead(pot0); // get the attack pole location
126+
alpha1 = 0.999 * cos((1023 - CV0) / 795);
127+
alpha1 = sqrt(alpha1);
128+
break;
129+
case 1:
130+
CV1 = analogRead(pot1); // get the release pole location
131+
alpha2 = 0.999 * cos((1023 - CV1) / 795);
132+
alpha2 = sqrt(alpha2);
133+
break;
134+
case 2:
135+
CV2 = analogRead(pot2); // get the (integer) sustain level
136+
sustain_Level = CV2 << 2;
137+
break;
138+
case 3:
139+
CV3 = analogRead(pot3); // get the release pole location (potentially closer to 1.0)
140+
alpha3 = 0.99999 * cos((1023 - CV3) / 795);
141+
alpha3 = sqrt(alpha3);
142+
break;
143+
}
144+
}

ADSRduino/README.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# ADSRduino
2+
This is a simple ADSR envelope generator for the Arduino
3+
4+
It is a hardware generator; it exists to generate a physical envelope voltage, which is output from an MCP4921 DAC converter
5+
(unlike code to generate soft signals to control software synths etc).
6+
7+
You can find some description at http://m0xpd.blogspot.co.uk/2017/02/signal-processing-on-arduino.html
8+
9+
## Modifications
10+
11+
@katspaugh modified this sketch to use the [Wire](https://www.arduino.cc/en/Reference/Wire) library
12+
for the communication with the DAC.

ADSRduino/Schematic.jpg

124 KB
Loading

0 commit comments

Comments
 (0)