// // Tone sequencer with gate and modulation outputs // // Author: P.J. Drongowski // Version: 1.1 // Date: 26 June 2016 // // Copyright (c) 2016 Paul J. Drongowski // Permission granted to redistribute and modify #include "ToneFreq.h" #include "ToneNote.h" // Define input pins int arInputPin = 0 ; int levelInputPin = 1 ; // Define output pins int gatePin = 1 ; int tonePin = 5 ; int modPin = 9 ; // Note control values int noteIndex = 0 ; int note = 0 ; int duration = 0 ; // Filter control values int attackDuration = 0 ; int releaseDuration = 0 ; int sustainDuration = 0 ; int sustainLevel = 64 ; int arIncrement = 0 ; int modValue = 0 ; // Define, declare and initialize the musical notes #define TEMPO (90) #define REST -1 #define SEQUENCE 18 #define START 15 int sequence[SEQUENCE][2] = { NOTE_As3, EIGHTH, REST, SIXTEENTH, NOTE_Gs4, SIXTEENTH, REST, EIGHTH, NOTE_As4, EIGHTH, REST, EIGHTH, NOTE_C4, EIGHTH, NOTE_Cs4, EIGHTH, NOTE_D4, EIGHTH, NOTE_Ds4, EIGHTH, REST, SIXTEENTH, NOTE_As4, SIXTEENTH, REST, EIGHTH, NOTE_Cs5, EIGHTH, REST, EIGHTH, NOTE_G3, EIGHTH, NOTE_Gs3, EIGHTH, NOTE_A3, EIGHTH } ; void pulseGatePin() { digitalWrite(gatePin, LOW) ; digitalWrite(gatePin, HIGH) ; delay(50) ; digitalWrite(gatePin, LOW) ; } // // Sample the analog inputs (sustain level and // attack/release time). Compute durations and the // attack/release increment (ramp value). // void computeModValues() { int arValue ; sustainLevel = analogRead(levelInputPin) >> 2 ; arValue = analogRead(arInputPin) >> 4 ; attackDuration = arValue ; sustainDuration = duration - (arValue << 1) ; releaseDuration = arValue ; arIncrement = sustainLevel / arValue ; modValue = 0 ; } void setup() { Serial.begin(9600) ; // Define pin modes pinMode(gatePin, OUTPUT) ; // Initialize pin values digitalWrite(gatePin, LOW) ; // Start playing the first note in the sequence // This note could be a pick-up! noteIndex = START ; note = sequence[noteIndex][0] ; duration = sequence[noteIndex][1] ; computeModValues() ; if (note != REST) { tone(tonePin, note) ; digitalWrite(gatePin, HIGH) ; } } void loop() { delay(1) ; duration-- ; if (duration <= 0) { // Current note has expired. noTone(tonePin) ; digitalWrite(gatePin, LOW) ; delay(1) ; // Find the next note to be played if (noteIndex >= (SEQUENCE-1)) { noteIndex = 0 ; } else { noteIndex += 1 ; } note = sequence[noteIndex][0] ; duration = sequence[noteIndex][1] ; computeModValues() ; // Start playing the next note if (note != REST) { tone(tonePin, note) ; digitalWrite(gatePin, HIGH) ; } } else { // Note continues. Adjust modulation value. analogWrite(modPin, modValue) ; if (attackDuration > 0) { attackDuration-- ; modValue += arIncrement ; } else if (sustainDuration > 0) { sustainDuration-- ; modValue = sustainLevel ; } else if (releaseDuration > 0) { releaseDuration-- ; modValue -= arIncrement ; } } }