#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Multiplexer4067.h>
// #include <Bounce.h>
const int multiplexAPin = 0; // S0 pin
const int multiplexBPin = 1; // S1 pin
const int multiplexCPin = 2; // S2 pin
const int multiplexAnalogPin = 39; // Analog input pin connected to the multiplexer
int keyboardState[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
int keyboardNotes[8] = { 48, 50, 51, 53, 55, 56, 58, 60 };
int currentKeyPressed = -1;
//GUItool: begin automatically generated code
AudioSynthWaveform waveform1; //xy=93,311
AudioEffectEnvelope envelope1; //xy=298,237
AudioOutputI2S i2s1; //xy=246,219
AudioMixer4 mixer1; //xy=253,323
AudioOutputAnalogStereo dacs1;
// AudioConnection patchCord1(waveform1, 0, i2s1, 0);
// AudioConnection patchCord2(waveform1, 0, dacs1, 0);
AudioConnection patchCord1(waveform1, envelope1);
AudioConnection patchCord2(envelope1, 0, i2s1, 0);
AudioConnection patchCord3(envelope1, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=504,172
// // GUItool: end automatically generated code
int tempo = 1000;
int tempoPotPin = A17;
//int synthNotes[8] = { 60, 62, 64, 65, 67, 69, 71, 72 };
//int drumNotes[8] = { 36, 39, 36, 39, 36, 39, 36, 39 };
//keep track of note for synth -- better to put this in a struct
int currentNote = 69;//a440
//Convert any MIDI note number to it's frequency
float freqFromMidiNote(int note){
return 440.0f * powf(2, (note - 69.0f) / 12.0f);
}
//melody sequence
int melodyNotes[8] = { 60, 62, 63, 72, 70, 65, 67, 70 };
//Drum sequence arrays
int kickNotes[8] = { 1, 0, 0, 0, 1, 0, 0, 0 };
int clapNotes[8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
int openhihatNotes[8] = { 0, 0, 1, 0, 0, 1, 0, 0 };
int closedhihatNotes[8] = { 0, 0, 0, 1, 0, 0, 0, 1 };
int snareNotes[8] = { 0, 0, 0, 0, 1, 0, 0, 0 };
int cowbellNotes[8] = { 1, 0, 0, 0, 0, 1, 0, 0 };
int cymbalNotes[8] = { 0, 0, 0, 1, 0, 0, 0, 1 };
int tomNotes[8] = { 0, 0, 1, 0, 0, 1, 0, 0 };
int instrumentchangeflag = 0;
int channelselectbutton;
int lastchannelselectbutton = LOW;
int adsrButton;
int lastadsrButton;
int attack = 500;
int decay = 500;
float sustain = 0.5;
int release = 2000;
int velocity = 100;
int channel = 0;
// int channel = 2;
unsigned long lastStepTime = 0;
int currentStep = 0;
int totalSteps = 8;
int ledPins[8] = { 5, 6, 38, 8, 9, 10, 11, 12 };
int buttonStates[8] = { LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW };
int lastButtonStates[8] = { LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW };
int lastButtonState = LOW; // state of the button last time you checked
//#include <MIDI.h>
//MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
int current_waveform = WAVEFORM_SINE;
void setup() {
//MIDI.begin(MIDI_CHANNEL_OMNI); // Initialize MIDI with Omni channel (responds to all MIDI channels)
//usbMIDI.sendNoteOn(note, velocity, channel); // Replace 'note', 'velocity', and 'channel' with your values
// Initialize serial communication
Serial.begin(9600);
AudioMemory(25);
// always need this for synth
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);
//waveform1.begin(0.8, 261, WAVEFORM_SINE);
envelope1.noteOff();
envelope1.attack(attack);
envelope1.decay(decay);
envelope1.sustain(sustain);
envelope1.release(release);
//setting the mixer levels
mixer1.gain(0, 1);
mixer1.gain(1, 1);
mixer1.gain(2, 1);
mixer1.gain(3, 1);
waveform1.frequency(440);
waveform1.amplitude(1.0);
waveform1.begin(1.0, 440, WAVEFORM_SINE);
//current_waveform = WAVEFORM_TRIANGLE;
//waveform1.begin(current_waveform);
//make pin 2 an input:
pinMode(25, INPUT);
pinMode(26, INPUT);
pinMode(27, INPUT);
pinMode(28, INPUT);
pinMode(29, INPUT);
pinMode(30, INPUT);
pinMode(31, INPUT);
pinMode(32, INPUT);
pinMode(37, INPUT);
pinMode(40, INPUT); // ON AND OFF BUTTON FOR INSTRUMENT SELECT
for (int i = 0; i < totalSteps; i++) {
pinMode(ledPins[i], OUTPUT);
}
// Set the control pins (S0, S1, S2) as outputs
pinMode(multiplexAPin, OUTPUT);
pinMode(multiplexBPin, OUTPUT);
pinMode(multiplexCPin, OUTPUT);
pinMode(multiplexAnalogPin, INPUT);
// Initialize the control pins
digitalWrite(multiplexAPin, LOW);
digitalWrite(multiplexBPin, LOW);
digitalWrite(multiplexCPin, LOW);
}
void loop() {
updateTempo();
updateSequencer();
updateLeds();
updatebuttonChannelSelect();
updateAdsrButton();
updateEnvelope();
updateKeyboard();
// AudioNoInterrupts();
// waveform1.frequency(4000);
// waveform1.phase(360);
// AudioInterrupts();
}
void updateKeyboard(){
static int sequenceCounter = 0;
static int counter = 0;
for (int channel = 0; channel < 8; channel++) {
// Select the channel using the control pins
digitalWrite(multiplexAPin, (channel & 0x01) ? HIGH : LOW);
digitalWrite(multiplexBPin, (channel & 0x02) ? HIGH : LOW);
digitalWrite(multiplexCPin, (channel & 0x04) ? HIGH : LOW);
// int channel = 0;
// digitalWrite(multiplexAPin, LOW);
// digitalWrite(multiplexBPin, LOW);
// digitalWrite(multiplexCPin, LOW);
// Read the analog value from the selected channel
int sensorValue = analogRead(multiplexAnalogPin);
int previousValue = keyboardState[channel];
int newValue = (int)(sensorValue > 500);
if(previousValue != newValue){
if(newValue == 0){
triggerNoteOff(currentNote);
}
if(newValue == 1){
currentKeyPressed = channel;
currentNote = keyboardNotes[currentKeyPressed];
triggerNoteOn(currentNote);
melodyNotes[sequenceCounter] = currentNote;
sequenceCounter++;
sequenceCounter %= 8;
}
}
keyboardState[channel] = newValue;
if(counter % 200 == 0){
// Print the channel and its value to the serial monitor
Serial.print("Channel ");
Serial.print(channel);
Serial.print(": ");
Serial.println(sensorValue);
}
// Delay for a short time (optional)
delay(1);
}
counter++;
}
void updateEnvelope() {
static int counter_print = 0;
attack = map(1024 - analogRead(A9), 0, 1023, 10, 1000); // first number is min input, second max input, third min output, fourth max output its always 0 fist then 1023
decay = map(1024 - analogRead(A8), 0, 1023, 10, 1000);
sustain = (float)(1024 - analogRead(A7)) / 1023.0;
release = map(1024 - analogRead(A6), 0, 1023, 10, 1000);
if(counter_print % 200 == 0){
Serial.print("envelope ");
Serial.print(attack);
Serial.print(" ");
Serial.print(decay);
Serial.print(" ");
Serial.print(sustain);
Serial.print(" ");
Serial.print(release);
Serial.println(" ");
counter_print = 0;
}
counter_print++;
envelope1.attack(attack);
envelope1.hold(0);
envelope1.decay(decay);
envelope1.sustain(sustain);
envelope1.release(release);
}
void triggerNoteOn(int note){
waveform1.frequency(freqFromMidiNote(note));
envelope1.noteOn();
}
void triggerNoteOff(int note){
envelope1.noteOff();
}
void updateAdsrButton() {
adsrButton = digitalRead(37);
if (adsrButton != lastadsrButton) {
if (adsrButton == HIGH) {
current_waveform++;
current_waveform %= 13;
waveform1.begin(current_waveform);
// if(currentNote > 80){
// currentNote = 60;
// }
// currentNote+=2;
// triggerNoteOn(currentNote);
// Serial.println("envelope start");
}
if (adsrButton == LOW) {
//Serial.println("envelope off");
//triggerNoteOff(currentNote);
}
}
lastadsrButton = adsrButton;
}
// void onNoteOn(int buttonNum) {
// Serial.println("button pressed");
// //envelope1.noteOn();
// }
// void onNoteOff(int buttonNum) {
// Serial.println("button released");
// //envelope1.noteOff();
//}
void updateTempo() {
tempo = map(analogRead(A17), 0, 1023, 50, 1000);
}
void updatebuttonChannelSelect() {
channelselectbutton = digitalRead(40);
if (channelselectbutton != lastchannelselectbutton) {
if (channelselectbutton == LOW)
{
instrumentchangeflag = 1;
Serial.println("instrument select");
}
lastchannelselectbutton = channelselectbutton;
}
}
// clap
void onButtonChangeclapNote(int pin, int step) {
buttonStates[step] = digitalRead(pin);
// check if the current button state is different than the last state:
if (buttonStates[step] != lastButtonStates[step]) {
// do stuff if it is different here
if (buttonStates[step] == LOW) {
// Serial.println(step);
//Serial.println(drumNotes[2]);
Serial.println("Button was just pressed.");
// if (drumNotes[step] == 0) {
// drumNotes[step] = 36;
// } else if (drumNotes[step] == 36) {
// drumNotes[step] = 39;
// } else if (drumNotes[step] == 39) {
// drumNotes[step] = 0;
// }
// clapNotes[step] = 1;
if (clapNotes[step] == 1) {
clapNotes[step] = 0;
} else if (clapNotes[step] == 0) {
clapNotes[step] = 1;
}
Serial.print(clapNotes[0]);
Serial.print(clapNotes[1]);
Serial.print(clapNotes[2]);
Serial.print(clapNotes[3]);
Serial.print(clapNotes[4]);
Serial.print(clapNotes[5]);
Serial.print(clapNotes[6]);
Serial.println(clapNotes[7]);
}
// save button state for next comparison:
lastButtonStates[step] = buttonStates[step];
}
}
// KICK PART FOR PATTERN
void onButtonChangekickNote(int pin, int step) {
buttonStates[step] = digitalRead(pin);
// check if the current button state is different than the last state:
if (buttonStates[step] != lastButtonStates[step]) {
// do stuff if it is different here
if (buttonStates[step] == LOW) {
// Serial.println(step);
//Serial.println(drumNotes[2]);
Serial.println("Button was just pressed.");
// if (drumNotes[step] == 0) {
// drumNotes[step] = 36;
// } else if (drumNotes[step] == 36) {
// drumNotes[step] = 39;
// } else if (drumNotes[step] == 39) {
// drumNotes[step] = 0;
// }
// clapNotes[step] = 1;
if (kickNotes[step] == 1) {
kickNotes[step] = 0;
} else if (kickNotes[step] == 0) {
kickNotes[step] = 1;
}
Serial.print(kickNotes[0]);
Serial.print(kickNotes[1]);
Serial.print(kickNotes[2]);
Serial.print(kickNotes[3]);
Serial.print(kickNotes[4]);
Serial.print(kickNotes[5]);
Serial.print(kickNotes[6]);
Serial.println(kickNotes[7]);
}
// save button state for next comparison:
lastButtonStates[step] = buttonStates[step];
}
}
//
// openhihatNotes PART FOR PATTERN
void onButtonChangeopenhihatNote(int pin, int step) {
buttonStates[step] = digitalRead(pin);
// check if the current button state is different than the last state:
if (buttonStates[step] != lastButtonStates[step]) {
// do stuff if it is different here
if (buttonStates[step] == LOW) {
Serial.println("Button was just pressed.");
if (openhihatNotes[step] == 1) {
openhihatNotes[step] = 0;
} else if (openhihatNotes[step] == 0) {
openhihatNotes[step] = 1;
}
Serial.print(openhihatNotes[0]);
Serial.print(openhihatNotes[1]);
Serial.print(openhihatNotes[2]);
Serial.print(openhihatNotes[3]);
Serial.print(openhihatNotes[4]);
Serial.print(openhihatNotes[5]);
Serial.print(openhihatNotes[6]);
Serial.println(openhihatNotes[7]);
}
// save button state for next comparison:
lastButtonStates[step] = buttonStates[step];
}
// delay(2);
}
// closedhihats
void onButtonChangeclosedhihatNote(int pin, int step) {
buttonStates[step] = digitalRead(pin);
// check if the current button state is different than the last state:
if (buttonStates[step] != lastButtonStates[step]) {
// do stuff if it is different here
if (buttonStates[step] == LOW) {
Serial.println("Button was just pressed.");
if (closedhihatNotes[step] == 1) {
closedhihatNotes[step] = 0;
} else if (closedhihatNotes[step] == 0) {
closedhihatNotes[step] = 1;
}
Serial.print(closedhihatNotes[0]);
Serial.print(closedhihatNotes[1]);
Serial.print(closedhihatNotes[2]);
Serial.print(closedhihatNotes[3]);
Serial.print(closedhihatNotes[4]);
Serial.print(closedhihatNotes[5]);
Serial.print(closedhihatNotes[6]);
Serial.println(closedhihatNotes[7]);
}
// save button state for next comparison:
lastButtonStates[step] = buttonStates[step];
}
}
// snare
void onButtonChangeNote(int pin, int step) {
int* notesArray = kickNotes;
// assign array based on channel
if (channel == 1) {
notesArray = clapNotes;
}
if (channel == 2) {
notesArray = openhihatNotes;
}
if (channel == 3) {
notesArray = closedhihatNotes;
}
if (channel == 4) {
notesArray = snareNotes;
}
if (channel == 5) {
notesArray = cowbellNotes;
}
if (channel == 6) {
notesArray = cymbalNotes;
}
if (channel == 7) {
notesArray = tomNotes;
}
buttonStates[step] = digitalRead(pin);
// check if the current button state is different than the last state:
if (buttonStates[step] != lastButtonStates[step]) {
// do stuff if it is different here
if (buttonStates[step] == LOW) {
if (instrumentchangeflag == 1) {
channel = step;
Serial.println(channel);
instrumentchangeflag = 0;
} else if (instrumentchangeflag == 0) {
if (notesArray[step] == 1) {
notesArray[step] = 0;
} else if (notesArray[step] == 0) {
notesArray[step] = 1;
}
Serial.print(notesArray[0]);
Serial.print(notesArray[1]);
Serial.print(notesArray[2]);
Serial.print(notesArray[3]);
Serial.print(notesArray[4]);
Serial.print(notesArray[5]);
Serial.print(notesArray[6]);
Serial.println(notesArray[7]);
}
Serial.println("Button was just pressed.");
}
// save button state for next comparison:
lastButtonStates[step] = buttonStates[step];
}
}
void updateSequencer() {
if (millis() > lastStepTime + tempo) {
lastStepTime = millis();
currentStep++;
if (currentStep >= totalSteps) {
currentStep = 0;
}
//Playing back melody sequence
// if (melodyNotes[currentStep] > 0) {
// triggerNoteOff(melodyNotes[currentStep]);// going to eventually replace whole thing to playSDwave.play(filename)
// triggerNoteOn(melodyNotes[currentStep]);// going to eventually replace whole thing to playSDwave.play(filename)
// }
int midiChannel = 1;
if (kickNotes[currentStep] > 0) {
usbMIDI.sendNoteOn(36, velocity, midiChannel); // going to eventually replace whole thing to playSDwave.play(filename)
}
if (clapNotes[currentStep] > 0) {
usbMIDI.sendNoteOn(39, velocity, midiChannel);
}
if (openhihatNotes[currentStep] > 0) {
usbMIDI.sendNoteOn(46, velocity, midiChannel);
}
if (closedhihatNotes[currentStep] > 0) {
usbMIDI.sendNoteOn(42, velocity, midiChannel);
}
if (snareNotes[currentStep] > 0) {
usbMIDI.sendNoteOn(38, velocity, midiChannel);
}
if (cowbellNotes[currentStep] > 0) {
usbMIDI.sendNoteOn(50, velocity, midiChannel);
}
if (cymbalNotes[currentStep] > 0) {
usbMIDI.sendNoteOn(49, velocity, midiChannel);
}
if (tomNotes[currentStep] > 0) {
usbMIDI.sendNoteOn(47, velocity, midiChannel);
}
}
// channel for different instruments
// kick
// should handle everything
// TODO: can we make this a loop?
onButtonChangeNote(25, 0);
onButtonChangeNote(26, 1);
onButtonChangeNote(27, 2);
onButtonChangeNote(28, 3);
onButtonChangeNote(29, 4);
onButtonChangeNote(30, 5);
onButtonChangeNote(31, 6);
onButtonChangeNote(32, 7);
// if (channel == 0 ) {
// onButtonChangekickNote (25, 0);
// onButtonChangekickNote (26, 1);
// onButtonChangekickNote (27, 2);
// onButtonChangekickNote (28, 3);
// onButtonChangekickNote (29, 4);
// onButtonChangekickNote (30, 5);
// onButtonChangekickNote (31, 6);
// onButtonChangekickNote (32, 7);
// }
// // clap
// else if (channel == 1) {
// onButtonChangeclapNote (25, 0);
// onButtonChangeclapNote (26, 1);
// onButtonChangeclapNote (27, 2);
// onButtonChangeclapNote (28, 3);
// onButtonChangeclapNote (29, 4);
// onButtonChangeclapNote (30, 5);
// onButtonChangeclapNote (31, 6);
// onButtonChangeclapNote (32, 7);
// }
// //openhihat
// else if (channel == 2) {
// onButtonChangeopenhihatNote (25, 0);
// onButtonChangeopenhihatNote (26, 1);
// onButtonChangeopenhihatNote (27, 2);
// onButtonChangeopenhihatNote (28, 3);
// onButtonChangeopenhihatNote (29, 4);
// onButtonChangeopenhihatNote (30, 5);
// onButtonChangeopenhihatNote (31, 6);
// onButtonChangeopenhihatNote (32, 7);
// }
// //closedhihat
// else if (channel == 3) {
// onButtonChangeclosedhihatNote (25, 0);
// onButtonChangeclosedhihatNote (26, 1);
// onButtonChangeclosedhihatNote (27, 2);
// onButtonChangeclosedhihatNote (28, 3);
// onButtonChangeclosedhihatNote (29, 4);
// onButtonChangeclosedhihatNote (30, 5);
// onButtonChangeclosedhihatNote (31, 6);
// onButtonChangeclosedhihatNote (32, 7);
// }
// else {
// //channel = 0;
// }
//else if (channel ==2){
// onButtonChangeclapNote (25, 0);
// onButtonChangeclapNote (26, 1);
// onButtonChangeclapNote (27, 2);
// onButtonChangeclapNote (28, 3);
// onButtonChangeclapNote (29, 4);
// onButtonChangeclapNote (30, 5);
// onButtonChangeclapNote (31, 6);
// onButtonChangeclapNote (32, 7);
//}
delay(10);
}
void updateLeds() {
for (int i = 0; i < totalSteps; i++) {
if (currentStep == i) {
digitalWrite(ledPins[i], HIGH);
} else {
digitalWrite(ledPins[i], LOW);
}
// usbMIDI.sendNoteOn(note, velocity, channel);
}
}