#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Multiplexer4067.h>
#include <Bounce.h>
#include <Adafruit_NeoPixel.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1325.h>
// WAV files converted to code by wav2sketch

#include "AudioSampleKickdrumteensywa.h"                // kick
#include "AudioSampleClap2009w.h"                       // clap
#include "AudioSampleBARNATON_GUARACHA_OPEN_CLASSIC.h"  // open hi-hat
#include "AudioSampleBARNATON_GUARACHA_CLOSED_METAL.h"  // closed hi-hat
#include "AudioSampleLonnysnaregood1wav.h"              // snare
#include "AudioSampleCowbelll.h"
#include "AudioSampleCymball.h"
#include "AudioSampleTom.h"

// If using software SPI, define CLK and MOSI
#define OLED_CLK 27
#define OLED_MOSI 11

// These are neede for both hardware & softare SPI
#define OLED_CS 38
#define OLED_RESET 10
#define OLED_DC 9
Adafruit_SSD1325 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
/* settings for our little animation later */
#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

#define LOGO16_GLCD_HEIGHT 16 
#define LOGO16_GLCD_WIDTH  16 

// Create the Audio components.  These should be created in the
// order data flows, inputs/sources -> processing -> outputs
// new GUI

const int multiplex1APin = 0;         // S0 pin // resuing these pins for the second multiplexer
const int multiplex1BPin = 1;         // S1 pin
const int multiplex1CPin = 2;  
const int multiplex1AnalogPin = 39;   // Analog input pin connected to the multiplexer

const int multiplex2APin = 4;         // S0 pin // resuing these pins for the second multiplexer
const int multiplex2BPin = 5;         // S1 pin
const int multiplex2CPin = 6;        // S2 pin
const int multiplex2AnalogPin = 24;  //6 Analog input pin connected to the second multiplexer

const int octaveButtonPin = 12;  

int keyboardState[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
int drumButtonsState[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
int keyboardNotes[8] = { 24, 26, 27, 29, 31, 32, 34, 36 };
int currentKeyPressed = -1;

typedef enum {
  DrumKeyModeInstrumentSelect,
  DrumKeyModeSequenceEdit,
  DrumKeyModeFreePlay
} DrumKeyMode;

typedef enum {
  LitaColorChannel0,
  LitaColorChannel1,
  LitaColorChannel2,
  LitaColorChannel3,
  LitaColorChannel4,
  LitaColorChannel5,
  LitaColorChannel6,
  LitaColorChannel7,
  LitaColorSequence,
  LitaColorMute

} LitaColor;

//GUItool: begin automatically generated code
// AudioPlayMemory playMem1;       //xy=487,140
// 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

// AudioPlayMemory playMem1;          //xy=122,180
// AudioPlayMemory playMem2;          //xy=120,223
// AudioPlayMemory playMem3;          //xy=120,270
// AudioPlayMemory playMem5;          //xy=120,359
// AudioPlayMemory playMem4;          //xy=121,315
// AudioPlayMemory playMem6;          //xy=121,403
// AudioPlayMemory playMem7;          //xy=122,450
// AudioPlayMemory playMem8;          //xy=125,499
// AudioSynthWaveform waveform1;      //xy=245,615
// AudioMixer4 mixer2;                //xy=317,376
// AudioMixer4 mixer1;                //xy=323,211
// AudioEffectEnvelope envelope1;     //xy=429,605
// AudioMixer4 mixer4;                //xy=484,273
// AudioFilterStateVariable filter1;  //xy=581,605
// AudioMixer4 mixer3;                //xy=723,287
// AudioEffectFreeverb freeverb1;     //xy=741,598
// AudioOutputI2S i2s1;               //xy=870,259
// AudioConnection patchCord1(playMem2, 0, mixer1, 1);
// AudioConnection patchCord2(playMem3, 0, mixer1, 2);
// AudioConnection patchCord3(playMem5, 0, mixer2, 0);
// AudioConnection patchCord4(playMem4, 0, mixer1, 3);
// AudioConnection patchCord5(playMem6, 0, mixer2, 1);
// AudioConnection patchCord6(playMem1, 0, mixer1, 0);
// AudioConnection patchCord7(playMem7, 0, mixer2, 2);
// AudioConnection patchCord8(playMem8, 0, mixer2, 3);
// AudioConnection patchCord9(waveform1, envelope1);
// AudioConnection patchCord10(mixer2, 0, mixer4, 1);
// AudioConnection patchCord11(mixer1, 0, mixer4, 0);
// AudioConnection patchCord12(envelope1, 0, filter1, 0);
// AudioConnection patchCord13(mixer4, 0, mixer3, 0);
// AudioConnection patchCord14(filter1, 0, freeverb1, 0);
// AudioConnection patchCord15(mixer3, 0, i2s1, 0);
// AudioConnection patchCord16(mixer3, 0, i2s1, 1);
// AudioConnection patchCord17(freeverb1, 0, mixer3, 2);
// AudioControlSGTL5000 sgtl5000_1;  //xy=485,89
// GUItool: end automatically generated code

// GUItool: begin automatically generated code
AudioSynthWaveform       pitchLFO;      //xy=114,646
AudioPlayMemory          playMem2;       //xy=120,223
AudioPlayMemory          playMem3;       //xy=120,270
AudioPlayMemory          playMem5;       //xy=120,359
AudioPlayMemory          playMem4;       //xy=121,315
AudioPlayMemory          playMem6;       //xy=121,403
AudioPlayMemory          playMem1;       //xy=122,180
AudioPlayMemory          playMem7;       //xy=122,450
AudioPlayMemory          playMem8;       //xy=125,499
AudioSynthWaveform       waveform1;      //xy=257,577
AudioSynthWaveformModulated waveformMod1;   //xy=274,652
AudioMixer4              mixer2;         //xy=317,376
AudioMixer4              mixer1;         //xy=323,211
AudioEffectEnvelope      envelope1;      //xy=429,605
AudioMixer4              mixer4;         //xy=484,273
AudioSynthWaveform       filterLFO;      //xy=510,684
AudioFilterStateVariable filter1;        //xy=581,605
AudioMixer4              mixer3;         //xy=723,287
AudioEffectFreeverb      freeverb1;      //xy=758,658
AudioOutputI2S           i2s1;           //xy=870,259
AudioConnection          patchCord1(pitchLFO, 0, waveformMod1, 0);
AudioConnection          patchCord2(playMem2, 0, mixer1, 1);
AudioConnection          patchCord3(playMem3, 0, mixer1, 2);
AudioConnection          patchCord4(playMem5, 0, mixer2, 0);
AudioConnection          patchCord5(playMem4, 0, mixer1, 3);
AudioConnection          patchCord6(playMem6, 0, mixer2, 1);
AudioConnection          patchCord7(playMem1, 0, mixer1, 0);
AudioConnection          patchCord8(playMem7, 0, mixer2, 2);
AudioConnection          patchCord9(playMem8, 0, mixer2, 3);
AudioConnection          patchCord10(waveformMod1, envelope1);
AudioConnection          patchCord11(mixer2, 0, mixer4, 1);
AudioConnection          patchCord12(mixer1, 0, mixer4, 0);
AudioConnection          patchCord13(envelope1, 0, filter1, 0);
AudioConnection          patchCord14(mixer4, 0, mixer3, 0);
AudioConnection          patchCord15(filterLFO, 0, filter1, 1);
AudioConnection          patchCord16(filter1, 0, freeverb1, 0);
AudioConnection          patchCord17(filter1, 0, mixer3, 1);
AudioConnection          patchCord18(mixer3, 0, i2s1, 0);
AudioConnection          patchCord19(mixer3, 0, i2s1, 1);
AudioConnection          patchCord20(freeverb1, 0, mixer3, 2);
AudioControlSGTL5000     sgtl5000_1;     //xy=485,89
// GUItool: end automatically generated code

// Create an object to control the audio shield.
AudioControlSGTL5000 audioShield;

// Bounce objects to read pushbuttons
// 5 ms debounce time
Bounce button0 = Bounce(25, 5);
Bounce button1 = Bounce(26, 5);
Bounce button2 = Bounce(22, 5);
Bounce button3 = Bounce(28, 5);
Bounce button4 = Bounce(29, 5);
Bounce button5 = Bounce(30, 5);
Bounce button6 = Bounce(31, 5);
Bounce button7 = Bounce(32, 5);

Bounce keyboardSequenceMuteButton = Bounce(34, 5);
Bounce clearDrumPartButton = Bounce(35, 5);
Bounce octaveButton = Bounce(octaveButtonPin, 5);

int bpm = 120;
int ms_per_step = 125;
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
int keyboardOctave = 3;

//Convert any MIDI note number to it's frequency
float freqFromMidiNote(int note) {
  return 440.0f * powf(2, (note - 69.0f) / 12.0f);
}

//melody sequencemelodyNotes
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, 0, 0, 0, 1, 0, 0, 0 };
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 mutes[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

int instrumentchangeflag = 0;

int channelselectbutton;
int lastchannelselectbutton = LOW;

int mutechangeflag = 0;

int channelmutebutton;
int lastchannelmutebutton = LOW;

int keyboardSequenceMute = 1;

int adsrButton;
int lastadsrButton;

int attack = 500;
int decay = 500;
float sustain = 0.5;
int release = 2000;

int velocity = 100;

int channel = 0;

int playing = 0;
int lastStartStopButtonState = LOW;

// int channel = 2;

unsigned long lastStepTime = 0;
int currentStep = 0;
int displayStep = 0;

int totalSteps = 8;

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;

Adafruit_NeoPixel neopixel = Adafruit_NeoPixel(8, 3, NEO_GRB);

void setup() {

  Serial.begin(9600);
  display.begin();

  neopixel.begin();
  neopixel.clear();
  neopixel.show();
  //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
  //AudioMemory(25);

  // put your setup code here, to run once:
  // pinMode(25, INPUT_PULLUP);
  // pinMode(26, INPUT_PULLUP);
  // pinMode(22, INPUT_PULLUP);
  // pinMode(28, INPUT_PULLUP);
  // pinMode(29, INPUT_PULLUP);
  // pinMode(30, INPUT_PULLUP);
  // pinMode(31, INPUT_PULLUP);
  // pinMode(32, INPUT_PULLUP);

  AudioMemory(10);

  // turn on the output
  audioShield.enable();
  audioShield.volume(0.8);

  // always need this for synth
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);

  waveformMod1.begin(0.8, 261, WAVEFORM_SINE);

  envelope1.noteOff();
  envelope1.attack(attack);
  envelope1.decay(decay);
  envelope1.sustain(sustain);
  envelope1.release(release);

  waveformMod1.frequency(440);
  waveformMod1.amplitude(1.0);

  waveformMod1.begin(1.0, 440, WAVEFORM_SINE);
  //current_waveform = WAVEFORM_TRIANGLE;
  waveformMod1.begin(current_waveform);

  pitchLFO.frequency(5);
  pitchLFO.amplitude(0.1);
  pitchLFO.begin(0.1, 5, WAVEFORM_SINE);
  pitchLFO.begin(current_waveform);

  filterLFO.frequency(1.0);
  filterLFO.amplitude(0.9);
  filterLFO.begin(0.9, 1.0, WAVEFORM_SINE);
  filterLFO.begin(current_waveform);

  //make pin 2 an input:
  pinMode(25, INPUT);
  pinMode(26, INPUT);
  pinMode(22, INPUT);
  pinMode(28, INPUT);
  pinMode(29, INPUT);
  pinMode(30, INPUT);
  pinMode(31, INPUT);
  pinMode(32, INPUT);
  pinMode(33, INPUT);  // START & STOP SEQUENCE
  pinMode(34, INPUT);  // MUTE KEYBOARD SEQUENCE SEQUENCE
  pinMode(35, INPUT);  // Clear drum part button
  pinMode(36, INPUT);  // Mute Button
  pinMode(37, INPUT);

  pinMode(40, INPUT);  // INSTRUMENT SELECT

  // Set the control pins (S0, S1, S2) as outputs
  pinMode(multiplex1APin, OUTPUT);
  pinMode(multiplex1BPin, OUTPUT);
  pinMode(multiplex1CPin, OUTPUT);
  // Set the control pins (S0, S1, S2) as outputs
  pinMode(multiplex2APin, OUTPUT);
  pinMode(multiplex2BPin, OUTPUT);
  pinMode(multiplex2CPin, OUTPUT);

  pinMode(multiplex1AnalogPin, INPUT);
  pinMode(multiplex2AnalogPin, INPUT);

  // Initialize the control pins
  digitalWrite(multiplex1APin, LOW);
  digitalWrite(multiplex1BPin, LOW);
  digitalWrite(multiplex1CPin, LOW);
  Serial.println("SETUP CompleteD");

    // Initialize the control pins
  digitalWrite(multiplex2APin, LOW);
  digitalWrite(multiplex2BPin, LOW);
  digitalWrite(multiplex2CPin, LOW);
  Serial.println("SETUP CompleteD");

  //setting the mixer levels
  mixer1.gain(0, 1.0);  //kick
  mixer1.gain(1, 0.3);  //clap
  mixer1.gain(2, 0.4);  //open hh
  mixer1.gain(3, 0.4);  //closed hh
  mixer2.gain(0, 0.3);  //snare
  mixer2.gain(1, 0.1);  //cowbell
  mixer2.gain(2, 0.3);  //ride
  mixer2.gain(3, 0.2);  //tom

  mixer3.gain(0, 2.0);  //drums
  mixer3.gain(1, 0.8);  //dry synth
  mixer3.gain(2, 0.2);  //synth reverb

  filter1.frequency(400);
  filter1.resonance(3);

}

void loop() {
  updateDisplay();

  updateTempo();
  updateLeds();
  updateSequencer();
  updatebuttonChannelMute();
  updatebuttonChannelSelect();
  updateAdsrButton();
  updateEnvelope();
  updateKeyboard();
  updateDrumButtons();

  // AudioNoInterrupts();
  // AudioInterrupts();

  /*
  //kick
  button0.update();  //
  if (button0.fallingEdge()) {
    playMem1.play(AudioSampleKickdrumteensywa);
  }
  // clap
  button1.update();
  if (button1.fallingEdge()) {
    playMem2.play(AudioSampleClap2009w);
  }
  //open hi-hat
  button2.update();
  if (button2.fallingEdge()) {
    playMem3.play(AudioSampleBarnaton_guaracha_open_classic);
  }
  // closed hi-hat
  button3.update();
  if (button3.fallingEdge()) {
    playMem4.play(AudioSampleBarnaton_guaracha_closed_metal);
  }
//snare
button4.update();
  if (button4.fallingEdge()) {
    playMem5.play(AudioSampleLonnysnaregood1wav);
  }
// cowbell
button5.update();
  if (button5.fallingEdge()) {
    playMem6.play(AudioSampleCowbelll);
}
//cymball
button6.update();
  if (button6.fallingEdge()) {
    playMem7.play(AudioSampleCymball);
}
// tom 
button7.update();
  if (button7.fallingEdge()) {
    playMem8.play(AudioSampleTom);
}
*/

  int startStopState = digitalRead(33);

  if (startStopState != lastStartStopButtonState) {

    if (startStopState == HIGH) {
      lastStartStopButtonState = HIGH;
      Serial.println("Start stop pressed");

      if (playing) {
        playing = 0;
        displayStep = -1;

      } else {
        currentStep = 0;
        displayStep = 0;
        lastStepTime = 0;
        playing = 1;
      }
    } else {
      lastStartStopButtonState = LOW;
    }

  } else {
  }

  keyboardSequenceMuteButton.update();
  if (keyboardSequenceMuteButton.fallingEdge()) {
    if (keyboardSequenceMute == 1) {
      keyboardSequenceMute = 0;
    } else {
      keyboardSequenceMute = 1;
      for (int i = 0; i < 8; i++) {
        triggerNoteOff(melodyNotes[currentStep]);  // going to eventually replace whole thing to playSDwave.play(filename)
      }
    }
  }

  clearDrumPartButton.update();
  if (clearDrumPartButton.fallingEdge()) {
    clearActiveDrumChannel();
  }

  octaveButton.update();
  if (octaveButton.fallingEdge()) {
    cycleOctave();
  }
}

void cycleOctave(){
  Serial.print("cycle octave ");
 Serial.println(keyboardOctave);

  keyboardOctave++;
  keyboardOctave %= 7;
}

void updateDrumButtons() {

  //for each channel (drum sound) update the sequence based on button pressess
  // for (int i = 0; i < 8; i++) {
  //   onButtonChangeNote(25 + i, i);
  // }

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

  for (int drumStep = 0; drumStep < 8; drumStep++) {
    // Select the channel using the control pins
    digitalWrite(multiplex2APin, (drumStep & 0x01) ? HIGH : LOW);
    digitalWrite(multiplex2BPin, (drumStep & 0x02) ? HIGH : LOW);
    digitalWrite(multiplex2CPin, (drumStep & 0x04) ? HIGH : LOW);

    buttonStates[drumStep] = digitalRead(multiplex2AnalogPin);

        //   check if the current button state is different than the last state:
    if (buttonStates[drumStep] != lastButtonStates[drumStep]) {

      Serial.print ("Button changed ");
      Serial.println (drumStep);

      // do stuff if it is different here
      if (buttonStates[drumStep] == LOW) {

        if (mutechangeflag == 1) {
          if (mutes[drumStep] == 0) {
            mutes[drumStep] = 1;
          } else {
            mutes[drumStep] = 0;
          }
          mutechangeflag = 0;
        } else if (instrumentchangeflag == 1) {
          channel = drumStep;
          triggerSample(channel);
          Serial.println(channel);
          instrumentchangeflag = 0;
        } else if (instrumentchangeflag == 0) {

          if (notesArray[drumStep] == 1) {
            notesArray[drumStep] = 0;
          } else if (notesArray[drumStep] == 0) {
            notesArray[drumStep] = 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.print("onbuttonchangenote Button was just pressed. ");
        Serial.println(drumStep);

      }
      // save button state for next comparison:
      lastButtonStates[drumStep] = buttonStates[drumStep];
    }
        delay(1);

  }  

}

void clearflags(){
  instrumentchangeflag = 0;
  mutechangeflag = 0;
}

void updateKeyboard() {

  static int counter = 0;
  for (int chan = 0; chan < 8; chan++) {

    // Select the channel using the control pins
    digitalWrite(multiplex1APin, (chan & 0x01) ? HIGH : LOW);
    digitalWrite(multiplex1BPin, (chan & 0x02) ? HIGH : LOW);
    digitalWrite(multiplex1CPin, (chan & 0x04) ? HIGH : LOW);

    // Read the analog value from the selected channel
    int sensorValue = digitalRead(multiplex1AnalogPin);

    int previousValue = keyboardState[chan];
    // int newValue = (int)(sensorValue > 500);
    int newValue = sensorValue;
    // rewrte this part
    if (previousValue != newValue) {

      if (newValue == 0) {
        triggerNoteOff(currentNote);
      }
      if (newValue == 1) {
        currentKeyPressed = chan;
        currentNote = keyboardNotes[currentKeyPressed] + (keyboardOctave * 12);
        triggerNoteOn(currentNote);

        if (melodyNotes[currentStep] != currentNote) {
          melodyNotes[currentStep] = currentNote;

        } else {
          melodyNotes[currentStep] = 0;
        }
        Serial.print("Chan trigger ");

        Serial.println(chan);

        Serial.print("Note is ");

        Serial.println(currentNote);
        // melodyNotes[sequenceCounter] = currentNote;
        // sequenceCounter++;
        // sequenceCounter %= 8;
        //Serial.println("hello");
      }

      keyboardState[chan] = 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);
    // }
    //Serial.println(" ");

    // Delay for a short time (optional)
    delay(1);
  }
  counter++;
}

void updateEnvelope() {

  static int counter_print = 0;

  attack = map(1024 - analogRead(A3), 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(A2), 0, 1023, 10, 1000);
  sustain = (float)(1024 - analogRead(A1)) / 1023.0;
  release = map(1024 - analogRead(A0), 0, 1023, 10, 1000);

  // this prints the value of the petentiometers for ADSR.
  // Serial.print(analogRead(A3));
  // Serial.print(" ");
  // Serial.print(analogRead(A2));
  // Serial.print(" ");
  // Serial.print(analogRead(A1));
  // Serial.print(" ");
  // Serial.print(analogRead(A0));
  // Serial.println(" ");

  // prints the ADSR value after mapping

  // 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) {
  waveformMod1.frequency(freqFromMidiNote(note));
  envelope1.noteOn();
}
void triggerNoteOff(int note) {
  envelope1.noteOff();
}

void updateAdsrButton() {

  lastadsrButton = adsrButton;
  adsrButton = digitalRead(37);
  // Serial.println(adsrButton);

  if (adsrButton != lastadsrButton) {
    if (adsrButton == HIGH) {
      current_waveform++;
      if (current_waveform == 4) {  // we are skipping over waveform arbituary
        current_waveform = 5;
      }
      current_waveform %= 13;
      waveformMod1.begin(current_waveform);
      Serial.println(current_waveform);

      // if(currentNote > 80){
      //   currentNote = 60;
      // }
      // currentNote+=2;

      // triggerNoteOn(currentNote);

      Serial.println("envelope start");
    }
    if (adsrButton == LOW) {
      Serial.println("envelope off");
      triggerNoteOff(currentNote);
    }
  }
}

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

  bpm = map(analogRead(A17), 0, 1023, 20, 360);

  //calculating milliseconds per step from BPM
  ms_per_step = (int)(60000.0 / (float)(bpm * 4));
}

void updatebuttonChannelSelect() {
  channelselectbutton = digitalRead(40);
  if (channelselectbutton != lastchannelselectbutton) {
    if (channelselectbutton == LOW) {
      instrumentchangeflag = !instrumentchangeflag;

//SWITCH OUT OF MUTE CHANGE MODE IF IT WAS SELECTED

      mutechangeflag = 0;

      Serial.println("instrument select");
    }
    lastchannelselectbutton = channelselectbutton;
  }
}

void updatebuttonChannelMute() {
  channelmutebutton = digitalRead(36);
  if (channelmutebutton != lastchannelmutebutton) {
    if (channelmutebutton == LOW) {

      if(mutechangeflag == 0){
        mutechangeflag = 1;
      }
      else{
        mutechangeflag = 0;
      }

//SWITCH OUT OF INSTRUMENT CHANGE MODE IF IT WAS SELECTED
      instrumentchangeflag = 0;

      Serial.println("mute select");
    }
    lastchannelmutebutton = channelmutebutton;
  }
}

// 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("Clap 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("Kick 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("Hi Hat 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("Closed hi hat 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];
  }
}

void clearActiveDrumChannel() {

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

  for (int i = 0; i < 8; i++) {
    notesArray[i] = 0;
  }
}

//
//Updates the sequence of selected channel when step button is pushed
void onButtonChangeNote(int pin, int step) {

}

void triggerSample(int channel) {

  if (mutes[channel] > 0) {
    return;
  }

  switch (channel) {
    case 0:
      playMem1.play(AudioSampleKickdrumteensywa);
      break;

    case 1:
      playMem2.play(AudioSampleClap2009w);
      break;

    case 2:
      playMem3.play(AudioSampleBarnaton_guaracha_open_classic);
      break;

    case 3:
      playMem4.play(AudioSampleBarnaton_guaracha_closed_metal);
      break;

    case 4:
      playMem5.play(AudioSampleLonnysnaregood1wav);
      break;

    case 5:
      playMem6.play(AudioSampleCowbelll);
      break;

    case 6:
      playMem7.play(AudioSampleCymball);
      break;

    case 7:
      playMem8.play(AudioSampleTom);
      break;
  }
}

void updateSequencer() {

  if (!playing) {
    return;
  }

  if (millis() > lastStepTime + ms_per_step) {

    lastStepTime = millis();

    //Playing back melody sequence
    if (keyboardSequenceMute == 0 && 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)
    }

    if (kickNotes[currentStep] > 0) {
      triggerSample(0);
    }
    if (clapNotes[currentStep] > 0) {
      triggerSample(1);
    }
    if (openhihatNotes[currentStep] > 0) {
      triggerSample(2);
    }
    if (closedhihatNotes[currentStep] > 0) {
      triggerSample(3);
    }
    if (snareNotes[currentStep] > 0) {
      triggerSample(4);
    }
    if (cowbellNotes[currentStep] > 0) {
      triggerSample(5);
    }
    if (cymbalNotes[currentStep] > 0) {
      triggerSample(6);
    }
    if (tomNotes[currentStep] > 0) {
      triggerSample(7);
    }

    displayStep = currentStep;
    currentStep++;
    if (currentStep >= totalSteps) {
      currentStep = 0;
    }
  }
}

void updateLed(int num, int on, LitaColor color) {

  int red = 0;
  int green = 0;
  int blue = 0;

  switch (color) {
    //pink
    case LitaColorChannel0:
      red = 255;
      green = 0;
      blue = 255;
      break;

    case LitaColorChannel1:
      //blue
      red = 0;
      green = 255;
      blue = 255;
      break;

    case LitaColorChannel2:
      //blue
      red = 64;
      green = 128;
      blue = 255;
      break;

    case LitaColorChannel3:

      //yellow
      red = 255;
      green = 128;
      blue = 255;
      break;

    //yellow
    case LitaColorChannel4:
      red = 128;
      green = 0;
      blue = 255;
      break;

    case LitaColorChannel5:
      red = 0;
      green = 255;
      blue = 64;
      break;

    case LitaColorChannel6:
      red = 64;
      green = 255;
      blue = 64;
      break;

    case LitaColorChannel7:
      red = 64;
      green = 255;
      blue = 64;
      break;

    case LitaColorSequence:
      red = 255;
      green = 255;
      blue = 0;
      break;

    case LitaColorMute:
      red = 255;
      green = 0;
      blue = 0;
      break;
  }

  //brightness of lights -- high number is darker
  int dimFactor = 128;

  neopixel.setPixelColor(num, 0, 0, 0);  //red
  neopixel.show();

  if (on) {
    neopixel.setPixelColor(num, red / dimFactor, green / dimFactor, blue / dimFactor);  //red
  } else {
    neopixel.setPixelColor(num, 0, 0, 0);  //red
  }
}

void updateLeds() {

  for (int i = 0; i < totalSteps; i++) {

    if (channel == 0) {
      if (kickNotes[i] == 1) {
        updateLed(i, 1, LitaColorChannel0);
      } else {
        updateLed(i, 0, LitaColorChannel0);
      }
    }

    if (channel == 1) {
      if (clapNotes[i] == 1) {
        updateLed(i, 1, LitaColorChannel1);
      } else {
        updateLed(i, 0, LitaColorChannel1);
      }
    }

    if (channel == 2) {
      if (openhihatNotes[i] == 1) {
        updateLed(i, 1, LitaColorChannel2);
      } else {
        updateLed(i, 0, LitaColorChannel2);
      }
    }

    if (channel == 3) {
      if (closedhihatNotes[i] == 1) {
        updateLed(i, 1, LitaColorChannel3);
      } else {
        updateLed(i, 0, LitaColorChannel3);
      }
    }

    if (channel == 4) {
      if (snareNotes[i] == 1) {
        updateLed(i, 1, LitaColorChannel4);
      } else {
        updateLed(i, 0, LitaColorChannel4);
      }
    }

    if (channel == 5) {
      if (cowbellNotes[i] == 1) {
        updateLed(i, 1, LitaColorChannel5);
      } else {
        updateLed(i, 0, LitaColorChannel5);
      }
    }

    if (channel == 6) {
      if (cymbalNotes[i] == 1) {
        updateLed(i, 1, LitaColorChannel6);
      } else {
        updateLed(i, 0, LitaColorChannel6);
      }
    }

    if (channel == 7) {
      if (tomNotes[i] == 1) {
        updateLed(i, 1, LitaColorChannel7);
      } else {
        updateLed(i, 0, LitaColorChannel7);
      }
    }

    // usbMIDI.sendNoteOn(note, velocity, channel);
  }

  if(displayStep >= 0){
  updateLed(displayStep, 1, LitaColorSequence);

  }

  for (int i = 0; i < 8; i++) {
    if (mutes[i] > 0) {
      updateLed(i, 1, LitaColorMute);
    }
  }

  neopixel.show();
}

void updateDisplay(){

  display.clearDisplay();   // clears the screen and buffer

  display.setRotation(2);
  display.clearDisplay();
  // text display tests
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  //display.setTextColor(BLACK, WHITE); // 'inverted' text
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.print(bpm);
  display.setTextSize(2);
  display.println("bpm");

  display.setTextSize(0.5);

 display.print("A:");
 display.println((float)attack/1000.0);
 display.print("D:");
 display.println((float)decay/1000.0);
 display.print("S:");
 display.println((float)sustain);
 display.print("R:");
 display.println((float)release/1000.0);

 if(mutechangeflag == 1){
  display.println("Choose track to mute");
 }
 else if(instrumentchangeflag == 1){
  display.println("Choose track to edit");
 }
else{

display.print("Editing: ");

 switch(channel){
  case 0:
    display.print("Kick");
    break;
  case 1:
    display.print("Clap");
    break;
  case 2:
    display.print("Open HH");
    break;
  case 3:
    display.print("Clsed HH");
    break;
  case 4:
    display.print("Snare");
    break;
  case 5:
    display.print("Cowbell");
    break;
  case 6:
    display.print("Cymbal");
    break;
  case 7:
    display.print("Tom");
    break;

 }

 
}

  display.setCursor(75,0);
  display.print("Oct:");
  display.println(keyboardOctave);

  display.setCursor(75,10);

  display.print("Wav:");

 switch(current_waveform){
  case 0:
    display.print("Sin");
    break;
  case 1:
    display.print("Saw");
    break;
  case 2:
    display.print("Sq");
    break;
  case 3:
    display.print("Tri");
    break;
  case 4:
    display.print("Arb");
    break;
  case 5:
    display.print("Pls");
    break;
  case 6:
    display.print("RSw");
    break;
  case 7:
    display.print("S&H");
    break;
  case 8:
    display.print("VTri");
    break;
  case 9:
    display.print("BSaw");
    break;
  case 10:
    display.print("BRSw");
    break;
  case 11:
    display.print("BSq");
    break;
  case 12:
    display.print("BPls");
    break;

 }
 display.println();
  display.display();
  

}