//
// 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 ;
}
}
}