#define SCENE_INSTEAD_OF_VOLUME using namespace admux; // 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" #include "AudioSampleRivertoseakittablamid.h" #include "AudioSampleRivertoseakittablalow.h" #include "AudioSampleRivertoseakittablahigh.h" #in"> #define SCENE_INSTEAD_OF_VOLUME using namespace admux; // 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" #include "AudioSampleRivertoseakittablamid.h" #include "AudioSampleRivertoseakittablalow.h" #include "AudioSampleRivertoseakittablahigh.h" #in"> #define SCENE_INSTEAD_OF_VOLUME using namespace admux; // 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" #include "AudioSampleRivertoseakittablamid.h" #include "AudioSampleRivertoseakittablalow.h" #include "AudioSampleRivertoseakittablahigh.h" #in">
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>
#include <Adafruit_NeoPixel.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1325.h>
#include <RotaryEncoder.h>
#include <Mux.h>
#include "effect_tapedelay10tap.h"
#include <MIDI.h>

#define SCENE_INSTEAD_OF_VOLUME

using namespace admux;
// 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"

#include "AudioSampleRivertoseakittablamid.h"
#include "AudioSampleRivertoseakittablalow.h"
#include "AudioSampleRivertoseakittablahigh.h"
#include "AudioSampleRivertoseakitriqshake.h"
#include "AudioSampleRivertoseakitriqhit.h"
#include "AudioSampleRivertoseakitoud.h"
#include "AudioSampleRivertoseakitdaf.h"
#include "AudioSampleRivertoseakitchant.h"

//MIDI hardware connections
#define MIDI_OUT_PIN 29
#define MIDI_IN_PIN 28

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

#define rotaryVolumePinA 41
#define rotaryVolumePinB 32
RotaryEncoder *encoderVolume = nullptr;

#define rotaryTempoPinA 34
#define rotaryTempoPinB 33
RotaryEncoder *encoderTempo = nullptr;

#define rotary1PinA 16
#define rotary1PinB 17
RotaryEncoder *encoder1 = nullptr;

// #define rotary2PinA 14
// #define rotary2PinB 15
#define rotary2PinA 30
#define rotary2PinB 31
RotaryEncoder *encoder2 = nullptr;

#define rotary3PinA 25
#define rotary3PinB 26
RotaryEncoder *encoder3 = nullptr;

#define rotary4PinA 4
#define rotary4PinB 5
RotaryEncoder *encoder4 = nullptr;

#define DELAY_MAX_LEN 22050  // buffer for samples @44100 samples per second, 22050 = 0.5s
int16_t sample_delay_line[DELAY_MAX_LEN] = {};

const int muxA = 37;  // S0 pin // resuing these pins for the second multiplexer
const int muxB = 36;  // S1 pin
const int muxC = 35;  // S2 pin

const int mux1Common = 40;
const int mux2Common = 24;
const int mux3Common = 39;

Mux mux1(Pin(mux1Common, INPUT, PinType::Digital), Pinset(muxA, muxB, muxC));
Mux mux2(Pin(mux2Common, INPUT, PinType::Digital), Pinset(muxA, muxB, muxC));
Mux mux3(Pin(mux3Common, INPUT, PinType::Digital), Pinset(muxA, muxB, muxC));

int mux1Vals[8] = { 0 };
int lastMux1Vals[8] = { 0 };

int mux2Vals[8] = { 0 };
int lastMux2Vals[8] = { 0 };

int mux3Vals[8] = { 0 };
int lastMux3Vals[8] = { 0 };

int numMuxReads = 20;  // how many times to read mux in a row (to allow signal to propogate)

const int octaveButtonPin = 12;
int octaveButtonState = 1;

const int keyboardSequenceMuteButtonPin = 34;
int keyboardSequenceMuteButtonState = 1;

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

int previousSamples[10];
int previousSamplesIndex;

typedef enum {
  DrumKeyModeInstrumentSelect,
  DrumKeyModeSequenceEdit,
  DrumKeyModeFreePlay
} DrumKeyMode;

typedef enum {
  LitaColorChannel0,
  LitaColorChannel1,
  LitaColorChannel2,
  LitaColorChannel3,
  LitaColorChannel4,
  LitaColorChannel5,
  LitaColorChannel6,
  LitaColorChannel7,
  LitaColorSequence,
  LitaColorMute,
  StepActive
} LitaColor;

typedef enum{
  DrumMIDINote0 = 36,
  DrumMIDINote1 = 37,
  DrumMIDINote2 = 38,
  DrumMIDINote3 = 39,
  DrumMIDINote4 = 40,
  DrumMIDINote5 = 41,
  DrumMIDINote6 = 42,
  DrumMIDINote7 = 43
} DrumMIDINotes;

enum EncoderStates {
  ADSR,
  Effects
} CurrentEncoderState;

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

// GUItool: begin automatically generated code
AudioPlayMemory          playMem2;       //xy=204,701
AudioPlayMemory          playMem3;       //xy=204,748
AudioPlayMemory          playMem5;       //xy=204,837
AudioPlayMemory          playMem4;       //xy=205,793
AudioPlayMemory          playMem6;       //xy=205,881
AudioPlayMemory          playMem1;       //xy=206,658
AudioPlayMemory          playMem7;       //xy=206,928
AudioPlayMemory          playMem8;       //xy=209,977
AudioSynthWaveformModulated waveformMod1;   //xy=358,1130
AudioEffectEnvelope      envelope1;      //xy=513,1083
AudioMixer4              mixer1;         //xy=553,847
AudioMixer4              mixer2;         //xy=555,935
AudioFilterStateVariable filter1;        //xy=665,1083
AudioMixer4              delaysend1_4;   //xy=735,372
AudioMixer4              delaysend5_8;   //xy=735,454
AudioMixer4              reverbSend1to4; //xy=749,538
AudioMixer4              reverbSend5to8; //xy=749,606
AudioMixer4              mixer6;         //xy=923,348
AudioMixer4              mixer4;         //xy=934,558
AudioMixer4              mixer3;         //xy=1022,890
AudioEffectFreeverb      mainReverb;     //xy=1095,605
AudioEffectTapeDelay10tap         delay1;         //xy=1271.0000190734863,545.0000057220459
AudioMixer4              mixer7;         //xy=1494.0000190734863,901.0000152587891
AudioOutputI2S           i2s1;           //xy=1644.0000228881836,587.0000076293945
AudioConnection          patchCord1(playMem2, 0, mixer1, 1);
AudioConnection          patchCord2(playMem2, 0, reverbSend1to4, 1);
AudioConnection          patchCord3(playMem2, 0, delaysend1_4, 1);
AudioConnection          patchCord4(playMem3, 0, mixer1, 2);
AudioConnection          patchCord5(playMem3, 0, reverbSend1to4, 2);
AudioConnection          patchCord6(playMem3, 0, delaysend1_4, 2);
AudioConnection          patchCord7(playMem5, 0, mixer2, 0);
AudioConnection          patchCord8(playMem5, 0, reverbSend5to8, 0);
AudioConnection          patchCord9(playMem5, 0, delaysend5_8, 0);
AudioConnection          patchCord10(playMem4, 0, mixer1, 3);
AudioConnection          patchCord11(playMem4, 0, reverbSend1to4, 3);
AudioConnection          patchCord12(playMem4, 0, delaysend1_4, 3);
AudioConnection          patchCord13(playMem6, 0, mixer2, 1);
AudioConnection          patchCord14(playMem6, 0, reverbSend5to8, 1);
AudioConnection          patchCord15(playMem6, 0, delaysend5_8, 1);
AudioConnection          patchCord16(playMem1, 0, mixer1, 0);
AudioConnection          patchCord17(playMem1, 0, reverbSend1to4, 0);
AudioConnection          patchCord18(playMem1, 0, delaysend1_4, 0);
AudioConnection          patchCord19(playMem7, 0, mixer2, 2);
AudioConnection          patchCord20(playMem7, 0, reverbSend5to8, 2);
AudioConnection          patchCord21(playMem7, 0, delaysend5_8, 2);
AudioConnection          patchCord22(playMem8, 0, mixer2, 3);
AudioConnection          patchCord23(playMem8, 0, reverbSend5to8, 3);
AudioConnection          patchCord24(playMem8, 0, delaysend5_8, 3);
AudioConnection          patchCord25(waveformMod1, envelope1);
AudioConnection          patchCord26(envelope1, 0, filter1, 0);
AudioConnection          patchCord27(mixer1, 0, mixer3, 0);
AudioConnection          patchCord28(mixer2, 0, mixer3, 3);
AudioConnection          patchCord29(filter1, 0, mixer3, 1);
AudioConnection          patchCord30(delaysend1_4, 0, mixer6, 0);
AudioConnection          patchCord31(delaysend5_8, 0, mixer6, 1);
AudioConnection          patchCord32(reverbSend1to4, 0, mixer4, 0);
AudioConnection          patchCord33(reverbSend5to8, 0, mixer4, 1);
AudioConnection          patchCord34(mixer6, delay1);
AudioConnection          patchCord35(mixer4, mainReverb);
AudioConnection          patchCord36(mixer3, 0, mixer7, 0);
AudioConnection          patchCord37(mainReverb, 0, mixer3, 2);
AudioConnection          patchCord38(delay1, 0, mixer7, 1);
AudioConnection          patchCord39(delay1, 0, mixer6, 3);
AudioConnection          patchCord40(mixer7, 0, i2s1, 0);
AudioConnection          patchCord41(mixer7, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=1304,154
// GUItool: end automatically generated code

// 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 clearDrumPartButton = 0;// Bounce(35, 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 };    // corresponds to midi note c major scale
int filterCutoffs[8] = { 50, 50, 50, 50, 50, 50, 50, 50 };  // corresponds to midi note c major scale

//int melodyNotes[8] = { 48, 50, 52, 54, 56,58, 60, 62 };  // corresponds to midi note c major scale

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

int mutes[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

//int programMode = 0; // 0 is change beats; 1 is change effects

float reverbSends[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
float delaySends[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };

int whichReverbVoice = 0;

int instrumentchangeflag = 0;

int channelselectbutton;
int lastchannelselectbutton = LOW;

int mutechangeflag = 0;
int clearchangeflag = 0;

int channelmutebutton;
int lastchannelmutebutton = LOW;

int keyboardSequenceMute = 1;

int adsrButton;
int lastadsrButton;

#define defaultAttack 0
#define defaultDecay 100
#define defaultSustain 0.5
#define defaultRelease 20

int attack = defaultAttack;
int decay = defaultDecay;
float sustain = defaultSustain;
int release = defaultRelease;

int cutoff = 10000;
float resonance = 0.7;

int lastPos1 = 0;
int lastPos2 = 0;
int lastPos3 = 0;
int lastPos4 = 0;

int lastPosDelay = 0;

int velocity = 100;

int channel = 0;

int playing = 0;
int lastStartStopButtonState = LOW;

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

int totalSteps = 8;

int lastButtonState = LOW;  // state of the button last time you checked

int current_waveform = WAVEFORM_SINE;

//MIDI
// <https://www.pjrc.com/teensy/td_libs_MIDI.html>

#include <SoftwareSerial.h>
// SoftwareSerial mySerial = SoftwareSerial(28, 29);
// MIDI_CREATE_INSTANCE(SoftwareSerial, mySerial, MIDI);

MIDI_CREATE_INSTANCE(HardwareSerial, Serial7, MIDI);

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

void loadScene(int scene) {

  Serial.print("load scene ");
  Serial.println(scene);

  int numpatterns = 7;
  if (scene < 0) {
    while (scene < 0) {
      scene += numpatterns;
    }
  }
  scene = scene % numpatterns;

  switch (scene) {
    case 0:
      kickNotes[0] = 1;
      kickNotes[1] = 0;
      kickNotes[2] = 0;
      kickNotes[3] = 0;
      kickNotes[4] = 1;
      kickNotes[5] = 0;
      kickNotes[6] = 0;
      kickNotes[7] = 0;

      clapNotes[0] = 0;
      clapNotes[1] = 0;
      clapNotes[2] = 0;
      clapNotes[3] = 0;
      clapNotes[4] = 0;
      clapNotes[5] = 0;
      clapNotes[6] = 0;
      clapNotes[7] = 0;

      openhihatNotes[0] = 0;
      openhihatNotes[1] = 0;
      openhihatNotes[2] = 0;
      openhihatNotes[3] = 0;
      openhihatNotes[4] = 0;
      openhihatNotes[5] = 0;
      openhihatNotes[6] = 0;
      openhihatNotes[7] = 0;

      closedhihatNotes[0] = 0;
      closedhihatNotes[1] = 0;
      closedhihatNotes[2] = 0;
      closedhihatNotes[3] = 0;
      closedhihatNotes[4] = 0;
      closedhihatNotes[5] = 0;
      closedhihatNotes[6] = 0;
      closedhihatNotes[7] = 0;

      snareNotes[0] = 0;
      snareNotes[1] = 0;
      snareNotes[2] = 0;
      snareNotes[3] = 0;
      snareNotes[4] = 0;
      snareNotes[5] = 0;
      snareNotes[6] = 0;
      snareNotes[7] = 0;

      cowbellNotes[0] = 0;
      cowbellNotes[1] = 0;
      cowbellNotes[2] = 0;
      cowbellNotes[3] = 0;
      cowbellNotes[4] = 0;
      cowbellNotes[5] = 0;
      cowbellNotes[6] = 0;
      cowbellNotes[7] = 0;

      cymbalNotes[0] = 0;
      cymbalNotes[1] = 0;
      cymbalNotes[2] = 0;
      cymbalNotes[3] = 0;
      cymbalNotes[4] = 0;
      cymbalNotes[5] = 0;
      cymbalNotes[6] = 0;
      cymbalNotes[7] = 0;

      tomNotes[0] = 0;
      tomNotes[1] = 0;
      tomNotes[2] = 0;
      tomNotes[3] = 0;
      tomNotes[4] = 0;
      tomNotes[5] = 0;
      tomNotes[6] = 0;
      tomNotes[7] = 0;

      mutes[0] = 0;
      mutes[1] = 0;
      mutes[2] = 0;
      mutes[3] = 0;
      mutes[4] = 0;
      mutes[5] = 0;
      mutes[6] = 0;
      mutes[7] = 0;
      break;

    case 1:
      kickNotes[0] = 1;
      kickNotes[1] = 0;
      kickNotes[2] = 0;
      kickNotes[3] = 1;
      kickNotes[4] = 0;
      kickNotes[5] = 0;
      kickNotes[6] = 1;
      kickNotes[7] = 0;

      clapNotes[0] = 0;
      clapNotes[1] = 0;
      clapNotes[2] = 0;
      clapNotes[3] = 0;
      clapNotes[4] = 1;
      clapNotes[5] = 0;
      clapNotes[6] = 0;
      clapNotes[7] = 0;

      openhihatNotes[0] = 0;
      openhihatNotes[1] = 0;
      openhihatNotes[2] = 0;
      openhihatNotes[3] = 0;
      openhihatNotes[4] = 0;
      openhihatNotes[5] = 0;
      openhihatNotes[6] = 0;
      openhihatNotes[7] = 1;

      closedhihatNotes[0] = 0;
      closedhihatNotes[1] = 0;
      closedhihatNotes[2] = 0;
      closedhihatNotes[3] = 0;
      closedhihatNotes[4] = 0;
      closedhihatNotes[5] = 0;
      closedhihatNotes[6] = 0;
      closedhihatNotes[7] = 0;

      snareNotes[0] = 0;
      snareNotes[1] = 1;
      snareNotes[2] = 0;
      snareNotes[3] = 1;
      snareNotes[4] = 0;
      snareNotes[5] = 0;
      snareNotes[6] = 0;
      snareNotes[7] = 0;

      cowbellNotes[0] = 0;
      cowbellNotes[1] = 0;
      cowbellNotes[2] = 1;
      cowbellNotes[3] = 0;
      cowbellNotes[4] = 0;
      cowbellNotes[5] = 0;
      cowbellNotes[6] = 1;
      cowbellNotes[7] = 0;

      cymbalNotes[0] = 1;
      cymbalNotes[1] = 0;
      cymbalNotes[2] = 0;
      cymbalNotes[3] = 0;
      cymbalNotes[4] = 0;
      cymbalNotes[5] = 0;
      cymbalNotes[6] = 0;
      cymbalNotes[7] = 0;

      tomNotes[0] = 0;
      tomNotes[1] = 0;
      tomNotes[2] = 0;
      tomNotes[3] = 0;
      tomNotes[4] = 0;
      tomNotes[5] = 0;
      tomNotes[6] = 0;
      tomNotes[7] = 0;

      mutes[0] = 0;
      mutes[1] = 0;
      mutes[2] = 0;
      mutes[3] = 0;
      mutes[4] = 0;
      mutes[5] = 0;
      mutes[6] = 0;
      mutes[7] = 0;
      break;

    case 2:
      kickNotes[0] = 1;
      kickNotes[1] = 0;
      kickNotes[2] = 0;
      kickNotes[3] = 1;
      kickNotes[4] = 0;
      kickNotes[5] = 0;
      kickNotes[6] = 1;
      kickNotes[7] = 1;

      clapNotes[0] = 1;
      clapNotes[1] = 0;
      clapNotes[2] = 0;
      clapNotes[3] = 0;
      clapNotes[4] = 1;
      clapNotes[5] = 0;
      clapNotes[6] = 0;
      clapNotes[7] = 0;

      openhihatNotes[0] = 0;
      openhihatNotes[1] = 0;
      openhihatNotes[2] = 1;
      openhihatNotes[3] = 0;
      openhihatNotes[4] = 0;
      openhihatNotes[5] = 0;
      openhihatNotes[6] = 1;
      openhihatNotes[7] = 0;

      closedhihatNotes[0] = 1;
      closedhihatNotes[1] = 0;
      closedhihatNotes[2] = 0;
      closedhihatNotes[3] = 0;
      closedhihatNotes[4] = 1;
      closedhihatNotes[5] = 0;
      closedhihatNotes[6] = 0;
      closedhihatNotes[7] = 0;

      snareNotes[0] = 0;
      snareNotes[1] = 1;
      snareNotes[2] = 0;
      snareNotes[3] = 1;
      snareNotes[4] = 1;
      snareNotes[5] = 1;
      snareNotes[6] = 0;
      snareNotes[7] = 0;

      cowbellNotes[0] = 0;
      cowbellNotes[1] = 0;
      cowbellNotes[2] = 0;
      cowbellNotes[3] = 1;
      cowbellNotes[4] = 0;
      cowbellNotes[5] = 0;
      cowbellNotes[6] = 0;
      cowbellNotes[7] = 1;

      cymbalNotes[0] = 1;
      cymbalNotes[1] = 0;
      cymbalNotes[2] = 0;
      cymbalNotes[3] = 0;
      cymbalNotes[4] = 1;
      cymbalNotes[5] = 0;
      cymbalNotes[6] = 0;
      cymbalNotes[7] = 0;

      tomNotes[0] = 0;
      tomNotes[1] = 0;
      tomNotes[2] = 0;
      tomNotes[3] = 0;
      tomNotes[4] = 0;
      tomNotes[5] = 0;
      tomNotes[6] = 0;
      tomNotes[7] = 0;

      mutes[0] = 0;
      mutes[1] = 0;
      mutes[2] = 0;
      mutes[3] = 0;
      mutes[4] = 0;
      mutes[5] = 0;
      mutes[6] = 0;
      mutes[7] = 0;
      break;

    case 3:
      kickNotes[0] = 1;
      kickNotes[1] = 1;
      kickNotes[2] = 0;
      kickNotes[3] = 1;
      kickNotes[4] = 1;
      kickNotes[5] = 0;
      kickNotes[6] = 0;
      kickNotes[7] = 1;

      clapNotes[0] = 0;
      clapNotes[1] = 0;
      clapNotes[2] = 0;
      clapNotes[3] = 0;
      clapNotes[4] = 1;
      clapNotes[5] = 0;
      clapNotes[6] = 0;
      clapNotes[7] = 0;

      openhihatNotes[0] = 1;
      openhihatNotes[1] = 0;
      openhihatNotes[2] = 0;
      openhihatNotes[3] = 0;
      openhihatNotes[4] = 1;
      openhihatNotes[5] = 0;
      openhihatNotes[6] = 0;
      openhihatNotes[7] = 0;

      closedhihatNotes[0] = 1;
      closedhihatNotes[1] = 1;
      closedhihatNotes[2] = 1;
      closedhihatNotes[3] = 1;
      closedhihatNotes[4] = 1;
      closedhihatNotes[5] = 1;
      closedhihatNotes[6] = 1;
      closedhihatNotes[7] = 1;

      snareNotes[0] = 0;
      snareNotes[1] = 0;
      snareNotes[2] = 0;
      snareNotes[3] = 0;
      snareNotes[4] = 1;
      snareNotes[5] = 0;
      snareNotes[6] = 0;
      snareNotes[7] = 0;

      cowbellNotes[0] = 0;
      cowbellNotes[1] = 0;
      cowbellNotes[2] = 1;
      cowbellNotes[3] = 0;
      cowbellNotes[4] = 0;
      cowbellNotes[5] = 0;
      cowbellNotes[6] = 1;
      cowbellNotes[7] = 0;

      cymbalNotes[0] = 0;
      cymbalNotes[1] = 0;
      cymbalNotes[2] = 0;
      cymbalNotes[3] = 0;
      cymbalNotes[4] = 0;
      cymbalNotes[5] = 0;
      cymbalNotes[6] = 0;
      cymbalNotes[7] = 0;

      tomNotes[0] = 0;
      tomNotes[1] = 0;
      tomNotes[2] = 0;
      tomNotes[3] = 0;
      tomNotes[4] = 0;
      tomNotes[5] = 0;
      tomNotes[6] = 0;
      tomNotes[7] = 0;

      mutes[0] = 0;
      mutes[1] = 0;
      mutes[2] = 0;
      mutes[3] = 0;
      mutes[4] = 0;
      mutes[5] = 0;
      mutes[6] = 0;
      mutes[7] = 0;
      break;

    case 4:
      kickNotes[0] = 1;
      kickNotes[1] = 1;
      kickNotes[2] = 1;
      kickNotes[3] = 0;
      kickNotes[4] = 0;
      kickNotes[5] = 0;
      kickNotes[6] = 0;
      kickNotes[7] = 0;

      clapNotes[0] = 0;
      clapNotes[1] = 0;
      clapNotes[2] = 0;
      clapNotes[3] = 0;
      clapNotes[4] = 1;
      clapNotes[5] = 1;
      clapNotes[6] = 1;
      clapNotes[7] = 0;

      openhihatNotes[0] = 0;
      openhihatNotes[1] = 0;
      openhihatNotes[2] = 0;
      openhihatNotes[3] = 1;
      openhihatNotes[4] = 1;
      openhihatNotes[5] = 0;
      openhihatNotes[6] = 1;
      openhihatNotes[7] = 0;

      closedhihatNotes[0] = 0;
      closedhihatNotes[1] = 0;
      closedhihatNotes[2] = 1;
      closedhihatNotes[3] = 0;
      closedhihatNotes[4] = 0;
      closedhihatNotes[5] = 0;
      closedhihatNotes[6] = 1;
      closedhihatNotes[7] = 0;

      snareNotes[0] = 0;
      snareNotes[1] = 0;
      snareNotes[2] = 0;
      snareNotes[3] = 0;
      snareNotes[4] = 0;
      snareNotes[5] = 0;
      snareNotes[6] = 0;
      snareNotes[7] = 0;

      cowbellNotes[0] = 1;
      cowbellNotes[1] = 0;
      cowbellNotes[2] = 0;
      cowbellNotes[3] = 0;
      cowbellNotes[4] = 1;
      cowbellNotes[5] = 0;
      cowbellNotes[6] = 1;
      cowbellNotes[7] = 0;

      cymbalNotes[0] = 1;
      cymbalNotes[1] = 1;
      cymbalNotes[2] = 1;
      cymbalNotes[3] = 1;
      cymbalNotes[4] = 1;
      cymbalNotes[5] = 1;
      cymbalNotes[6] = 1;
      cymbalNotes[7] = 1;

      tomNotes[0] = 0;
      tomNotes[1] = 0;
      tomNotes[2] = 0;
      tomNotes[3] = 0;
      tomNotes[4] = 0;
      tomNotes[5] = 0;
      tomNotes[6] = 0;
      tomNotes[7] = 0;

      mutes[0] = 0;
      mutes[1] = 0;
      mutes[2] = 0;
      mutes[3] = 0;
      mutes[4] = 0;
      mutes[5] = 0;
      mutes[6] = 0;
      mutes[7] = 0;
      break;
      /////////////////////////////////////
    case 5:
      kickNotes[0] = 1;
      kickNotes[1] = 0;
      kickNotes[2] = 1;
      kickNotes[3] = 0;
      kickNotes[4] = 0;
      kickNotes[5] = 1;
      kickNotes[6] = 1;
      kickNotes[7] = 0;

      clapNotes[0] = 0;
      clapNotes[1] = 0;
      clapNotes[2] = 0;
      clapNotes[3] = 1;
      clapNotes[4] = 1;
      clapNotes[5] = 0;
      clapNotes[6] = 0;
      clapNotes[7] = 0;

      openhihatNotes[0] = 1;
      openhihatNotes[1] = 0;
      openhihatNotes[2] = 0;
      openhihatNotes[3] = 1;
      openhihatNotes[4] = 1;
      openhihatNotes[5] = 0;
      openhihatNotes[6] = 0;
      openhihatNotes[7] = 0;

      closedhihatNotes[0] = 1;
      closedhihatNotes[1] = 1;
      closedhihatNotes[2] = 1;
      closedhihatNotes[3] = 1;
      closedhihatNotes[4] = 1;
      closedhihatNotes[5] = 1;
      closedhihatNotes[6] = 1;
      closedhihatNotes[7] = 1;

      snareNotes[0] = 0;
      snareNotes[1] = 0;
      snareNotes[2] = 0;
      snareNotes[3] = 0;
      snareNotes[4] = 1;
      snareNotes[5] = 0;
      snareNotes[6] = 0;
      snareNotes[7] = 0;

      cowbellNotes[0] = 1;
      cowbellNotes[1] = 0;
      cowbellNotes[2] = 1;
      cowbellNotes[3] = 0;
      cowbellNotes[4] = 1;
      cowbellNotes[5] = 0;
      cowbellNotes[6] = 0;
      cowbellNotes[7] = 0;

      cymbalNotes[0] = 0;
      cymbalNotes[1] = 0;
      cymbalNotes[2] = 0;
      cymbalNotes[3] = 1;
      cymbalNotes[4] = 0;
      cymbalNotes[5] = 0;
      cymbalNotes[6] = 0;
      cymbalNotes[7] = 1;

      tomNotes[0] = 0;
      tomNotes[1] = 0;
      tomNotes[2] = 0;
      tomNotes[3] = 0;
      tomNotes[4] = 0;
      tomNotes[5] = 0;
      tomNotes[6] = 0;
      tomNotes[7] = 0;

      mutes[0] = 0;
      mutes[1] = 0;
      mutes[2] = 0;
      mutes[3] = 0;
      mutes[4] = 0;
      mutes[5] = 0;
      mutes[6] = 0;
      mutes[7] = 0;
      break;
      //////////////////////////////
      /////////////////////////////////////
    case 6:
      kickNotes[0] = 1;
      kickNotes[1] = 1;
      kickNotes[2] = 1;
      kickNotes[3] = 1;
      kickNotes[4] = 1;
      kickNotes[5] = 1;
      kickNotes[6] = 1;
      kickNotes[7] = 1;

      clapNotes[0] = 1;
      clapNotes[1] = 1;
      clapNotes[2] = 1;
      clapNotes[3] = 1;
      clapNotes[4] = 1;
      clapNotes[5] = 1;
      clapNotes[6] = 1;
      clapNotes[7] = 1;

      openhihatNotes[0] = 1;
      openhihatNotes[1] = 1;
      openhihatNotes[2] = 1;
      openhihatNotes[3] = 1;
      openhihatNotes[4] = 1;
      openhihatNotes[5] = 1;
      openhihatNotes[6] = 1;
      openhihatNotes[7] = 1;

      closedhihatNotes[0] = 1;
      closedhihatNotes[1] = 1;
      closedhihatNotes[2] = 1;
      closedhihatNotes[3] = 1;
      closedhihatNotes[4] = 1;
      closedhihatNotes[5] = 1;
      closedhihatNotes[6] = 1;
      closedhihatNotes[7] = 1;

      snareNotes[0] = 1;
      snareNotes[1] = 1;
      snareNotes[2] = 1;
      snareNotes[3] = 1;
      snareNotes[4] = 1;
      snareNotes[5] = 1;
      snareNotes[6] = 1;
      snareNotes[7] = 1;

      cowbellNotes[0] = 1;
      cowbellNotes[1] = 1;
      cowbellNotes[2] = 1;
      cowbellNotes[3] = 1;
      cowbellNotes[4] = 1;
      cowbellNotes[5] = 1;
      cowbellNotes[6] = 1;
      cowbellNotes[7] = 1;

      cymbalNotes[0] = 1;
      cymbalNotes[1] = 1;
      cymbalNotes[2] = 1;
      cymbalNotes[3] = 1;
      cymbalNotes[4] = 1;
      cymbalNotes[5] = 1;
      cymbalNotes[6] = 1;
      cymbalNotes[7] = 1;

      tomNotes[0] = 0;
      tomNotes[1] = 0;
      tomNotes[2] = 0;
      tomNotes[3] = 0;
      tomNotes[4] = 0;
      tomNotes[5] = 0;
      tomNotes[6] = 0;
      tomNotes[7] = 0;

      mutes[0] = 0;
      mutes[1] = 0;
      mutes[2] = 0;
      mutes[3] = 0;
      mutes[4] = 0;
      mutes[5] = 0;
      mutes[6] = 0;
      mutes[7] = 0;
      break;
      //////////////////////////////
  }
}
// This interrupt routine will be called on any change of one of the input signals
void checkPositionTempo() {
  //Serial.println("checkPosition tempo");
  encoderTempo->tick();  // just call tick() to check the state.
}

void checkPositionVolume() {
  //Serial.println("checkPosition volume");
  encoderVolume->tick();  // just call tick() to check the state.
}

void checkPositionRotary1() {
  //Serial.println("checkPosition rotary 1");
  encoder1->tick();  // just call tick() to check the state.
}

void checkPositionRotary2() {
  //Serial.println("checkPosition rotary 2");
  encoder2->tick();  // just call tick() to check the state.
}

void checkPositionRotary3() {
  //Serial.println("checkPosition rotary 3");
  encoder3->tick();  // just call tick() to check the state.
}

void checkPositionRotary4() {
  //Serial.println("checkPosition rotary 4");
  encoder4->tick();  // just call tick() to check the state.
}

void setup() {
 //AudioMemory(20);
  AudioMemory(150 * (128 / AUDIO_BLOCK_SAMPLES));
  Serial.begin(9600);
  Serial7.begin(31250);
  display.begin();

  neopixel.begin();
  neopixel.clear();
  neopixel.show();

//MIDI

  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

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

  //mainReverb.reverbTime(5.0);
  mainReverb.roomsize(0.97);
  mainReverb.damping(0.5);

  //delay
  delay1.begin(sample_delay_line, DELAY_MAX_LEN);
  delay1.delayfade(0, 500, 3.0);

  //make pin 2 an input:
  pinMode(16, INPUT);
  pinMode(17, INPUT);
  pinMode(25, INPUT);
  pinMode(26, INPUT);
  pinMode(22, INPUT);
  pinMode(28, INPUT);
  pinMode(29, INPUT);
  pinMode(30, INPUT_PULLUP);  // OCTAVE BUTTON
  pinMode(31, INPUT);         // MAGIC EFFECT BUTTON
  pinMode(32, INPUT);

  // Set up multiplexers
  pinMode(muxA, OUTPUT);
  pinMode(muxB, OUTPUT);
  pinMode(muxC, OUTPUT);

  pinMode(mux1Common, INPUT_PULLUP);
  pinMode(mux2Common, INPUT_PULLUP);
  pinMode(mux3Common, INPUT_PULLUP);

  float globalGain = 4.0;

  //setting the mixer levels
  mixer1.gain(0, 2.0 * globalGain);  //daf aka kick
  mixer1.gain(1, 1.0 * globalGain);  //tabla low
  mixer1.gain(2, 1.5 * globalGain);  //tabla mid
  mixer1.gain(3, 1.8 * globalGain);  //tabla high
  mixer2.gain(0, 0.5 * globalGain);  // riq hit
  mixer2.gain(1, 0.5 * globalGain);  // riq shake
  mixer2.gain(2, 0.5 * globalGain);  //oud
  mixer2.gain(3, 0.4 * globalGain);  //chant

  mixer3.gain(0, 2.0);                 //drums
  mixer3.gain(1, globalGain * 0.125);  //dry synth
  mixer3.gain(2, globalGain * 2);    //synth reverb
  mixer3.gain(3, 2.0);                 //drums pt 2

  mixer6.gain(2, 0.6);
  mixer6.gain(3, 0.6);
  mixer6.gain(0, 1);
  mixer6.gain(1, 1);

 mixer7.gain(1, 10);

delaysend1_4.gain(0,0);
delaysend1_4.gain(1,0);
delaysend1_4.gain(2,0);
delaysend1_4.gain(3,0);
delaysend5_8.gain(0,0);
delaysend5_8.gain(1,0);
delaysend5_8.gain(2,0);
delaysend5_8.gain(3,0);

  //setting the reverb send levels
  reverbSend1to4.gain(0, 0.0);  //kick
  reverbSend1to4.gain(1, 0.0);  //clap
  reverbSend1to4.gain(2, 0.0);  //open hh
  reverbSend1to4.gain(3, 0.0);  //closed hh
  reverbSend5to8.gain(0, 0.0);  //snare
  reverbSend5to8.gain(1, 0.0);  //cowbell
  reverbSend5to8.gain(2, 0.0);  //ride
  reverbSend5to8.gain(3, 0.0);  //tom

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

  encoderTempo = new RotaryEncoder(rotaryTempoPinA, rotaryTempoPinB, RotaryEncoder::LatchMode::TWO03);

  encoderVolume = new RotaryEncoder(rotaryVolumePinA, rotaryVolumePinB, RotaryEncoder::LatchMode::TWO03);
  encoderVolume->setPosition(-50);

  encoder1 = new RotaryEncoder(rotary1PinA, rotary1PinB, RotaryEncoder::LatchMode::TWO03);
  encoder2 = new RotaryEncoder(rotary2PinA, rotary2PinB, RotaryEncoder::LatchMode::TWO03);
  encoder3 = new RotaryEncoder(rotary3PinA, rotary3PinB, RotaryEncoder::LatchMode::TWO03);
  encoder4 = new RotaryEncoder(rotary4PinA, rotary4PinB, RotaryEncoder::LatchMode::TWO03);

  attachInterrupt(digitalPinToInterrupt(rotaryTempoPinA), checkPositionTempo, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotaryTempoPinB), checkPositionTempo, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotaryVolumePinA), checkPositionVolume, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotaryVolumePinB), checkPositionVolume, CHANGE);

  attachInterrupt(digitalPinToInterrupt(rotary1PinA), checkPositionRotary1, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotary1PinB), checkPositionRotary1, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotary2PinA), checkPositionRotary2, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotary2PinB), checkPositionRotary2, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotary3PinA), checkPositionRotary3, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotary3PinB), checkPositionRotary3, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotary4PinA), checkPositionRotary4, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotary4PinB), checkPositionRotary4, CHANGE);

  CurrentEncoderState = ADSR;

  Serial.println("Welcome to DRUM-U-LITA");
}

unsigned long t=0;
void loop() {
  updateDisplay();
  updateTempo();
  updateVolume();
  updateReverb();
  updateSequencer();
  updateAdsrButton();
  updateEnvelope();
  updateTopRow();
  updateSideButtons();
  updateBottomRow();
  updateDelay();

// // MIDI Output 

  int mnote;
  for (mnote=10; mnote <= 127; mnote++) {
    MIDI.sendNoteOn(mnote, 100, 1);
    delay(200);
    MIDI.sendNoteOff(mnote, 100, 1);
  }
  delay(2000);

 int type, note, velocity, channel, d1, d2;
  if (MIDI.read()) {                    // Is there a MIDI message incoming ?
    byte type = MIDI.getType();
    switch (type) {
      case midi::NoteOn:
        note = MIDI.getData1();
        velocity = MIDI.getData2();
        channel = MIDI.getChannel();
        if (velocity > 0) {
          Serial.println(String("Note On:  ch=") + channel + ", note=" + note + ", velocity=" + velocity);
        } else {
          Serial.println(String("Note Off: ch=") + channel + ", note=" + note);
        }
        break;
      case midi::NoteOff:
        note = MIDI.getData1();
        velocity = MIDI.getData2();
        channel = MIDI.getChannel();
        Serial.println(String("Note Off: ch=") + channel + ", note=" + note + ", velocity=" + velocity);
        break;
      default:
        d1 = MIDI.getData1();
        d2 = MIDI.getData2();
        Serial.println(String("Message, type=") + type + ", data = " + d1 + " " + d2);
    }
    t = millis();
  }
  if (millis() - t > 10000) {
    t += 10000;
    Serial.println("(inactivity)");
  }

  static int usage_counter = 0;
  static float usage = 0.0;
  usage = fmax(usage, AudioProcessorUsage());

  if (usage_counter % 50 == 0) {
    // Serial.print("Usage ");
    // Serial.print(usage);
    // Serial.print(" max ");
    // Serial.println(AudioProcessorUsageMax());
    // usage = 0.0;
    usage_counter = 0;

    if (!playing) {
      updateLeds();
    }
  }
  usage_counter++;
}

// MIDI -- sends over USB and Hardware port. 

void sendMIDITrigger(int note){

  // usbMIDI.sendNoteOn(note, 127, 1);
  // usbMIDI.sendNoteOff(note, 0, 1);

  MIDI.sendNoteOn(note, 127, 1);
  MIDI.sendNoteOff(note, 0, 1);
}

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

  keyboardOctave++;
  keyboardOctave %= 7;
}

void updateSideButtons() {

  for (int chan = 0; chan < 8; chan++) {
    mux2.channel(chan);  // set mux channel

    for (int i = 0; i < numMuxReads; i++) {  // reading same mux several times to allow address signal to propogate through, don't know why this mux is reacting slower than the others
      mux2Vals[chan] = mux2.read(chan);
    }

    if (mux2Vals[chan] != lastMux2Vals[chan]) {

      if (chan == 7) {

        //programMode = !mux2Vals[chan];
      }
      Serial.print("Mux 2 Pressed Channel:  ");
      Serial.print(chan);
      Serial.print(" ");
      Serial.println(mux2Vals[chan]);

      //Start / Stop button top left misc button
      if (chan == 5 && mux2Vals[chan] == HIGH) {
        startStop();
      }

      //Channel Select button top left misc button
      if (chan == 0 && mux2Vals[chan] == HIGH) {
        instrumentchangeflag = !instrumentchangeflag;
        mutechangeflag = 0;
        clearchangeflag = 0;
      }

      //Channel Select button top left misc button
      if (chan == 2 && mux2Vals[chan] == HIGH) {
        mutechangeflag = !mutechangeflag;
        instrumentchangeflag = 0;
        clearchangeflag = 0;
      }

      //Clear part button
      if (chan == 3 && mux2Vals[chan] == HIGH) {
        clearchangeflag = !clearchangeflag;
        instrumentchangeflag = 0;
        mutechangeflag = 0;
      }

      //Waveform select
      if (chan == 1 && mux2Vals[chan] == 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);
      }

      //Mute Keys button
      if (chan == 4 && mux2Vals[chan] == HIGH) {
        if (keyboardSequenceMute == 1) {
          keyboardSequenceMute = 0;
        } else {
          keyboardSequenceMute = 1;
          for (int i = 0; i < 8; i++) {
            triggerNoteOff(melodyNotes[i]);  // going to eventually replace whole thing to playSDwave.play(filename)
          }
        }
      }

      //Octave button
      if (chan == 6 && mux2Vals[chan] == HIGH) {
        cycleOctave();
      }

      //Encoder mode button
      if (chan == 7 && mux2Vals[chan] == HIGH) {
        if (CurrentEncoderState == ADSR) {
          CurrentEncoderState = Effects;
        } else if (CurrentEncoderState == Effects) {
          CurrentEncoderState = ADSR;
        }
      }
    }
    lastMux2Vals[chan] = mux2Vals[chan];
  }
  // Serial.println(" ");
}

void startStop() {

  if (playing) {
    envelope1.noteOff();
    playing = 0;
    displayStep = -1;

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

void updateTopRow() {
  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 chan = 0; chan < 8; chan++) {
    //hack for 12/8/2023 PCB
    // int drumStep = drumStepL - 1;
    // if (drumStep < 0) {
    //   drumStep += 8;
    // }

    mux3.channel(chan);

    for (int i = 0; i < numMuxReads; i++) {
      mux3Vals[chan] = mux3.read(chan);
    }

    //   check if the current button state is different than the last state:
    if (mux3Vals[chan] != lastMux3Vals[chan] /* && programMode==0*/) {
      Serial.print("Mux 3 Pressed Channel:  ");
      Serial.print(chan);
      Serial.print(" ");
      Serial.println(mux3Vals[chan]);

      // do stuff if it is different here
      if (mux3Vals[chan] == LOW) {

        if (mutechangeflag == 1) {
          if (mutes[chan] == 0) {
            mutes[chan] = 1;
          } else {
            mutes[chan] = 0;
          }
          mutechangeflag = 0;
        } else if (instrumentchangeflag == 1) {
          channel = chan;
          // triggerSample(channel);
          Serial.print("inst change: ");
          Serial.println(channel);
          instrumentchangeflag = 0;
        } else if (clearchangeflag == 1) {
          clearchangeflag = 0;
          channel = chan;
          clearActiveDrumChannel();
        } else {
          if (notesArray[chan] == 1) {
            notesArray[chan] = 0;
          } else if (notesArray[chan] == 0) {
            notesArray[chan] = 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]);
        }

        whichReverbVoice = chan;
      }
      // save button state for next comparison:
      lastMux3Vals[chan] = mux3Vals[chan];
    }
    // delay(1);
  }
}

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

void updateBottomRow() {
  for (int chan = 0; chan < 8; chan++) {
    mux1.channel(chan);

    for (int i = 0; i < numMuxReads; i++) {
      mux1Vals[chan] = mux1.read(chan);
    }

    // rewrte this part
    if (lastMux1Vals[chan] != mux1Vals[chan]) {
      Serial.print("Mux 1 Pressed Channel:  ");
      Serial.print(chan);
      Serial.print(" ");
      Serial.println(mux1Vals[chan]);

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

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

        } else {
          melodyNotes[currentStep] = 0;
        }
      }
    }
    lastMux1Vals[chan] = mux1Vals[chan];
  }
}

void updateEnvelope() {

  // static int counter_print = 0;

  int newPos1 = encoder1->getPosition();
  if (newPos1 != lastPos1) {
    int dir = (int)encoder1->getDirection();
    if (CurrentEncoderState == ADSR) {
      if (dir == 1) {
        attack = attack - 5;
      } else {
        attack = attack + 5;
      }

      if (attack <= 0) {
        attack = 0;
      }
      if (attack >= 1000) {
        attack = 1000;
      }
      Serial.print("attack: ");
      Serial.println(attack);
    } else if (CurrentEncoderState == Effects) {
      // modify your reverb or whatever effect you want here
    }
  }
  lastPos1 = newPos1;

  int newPos2 = encoder2->getPosition();
  if (newPos2 != lastPos2) {
    int dir = (int)encoder2->getDirection();
    if (dir == 1) {
      decay = decay + 5;
    } else {
      decay = decay - 5;
    }
    if (decay <= 0) {
      decay = 0;
    }

    if (decay >= 1000) {
      decay = 1000; 
    }
  }
  lastPos2 = newPos2;

  //apply 2 all encoders

  int newPos3 = encoder3->getPosition();
  if (newPos3 != lastPos3) {
    Serial.println("c");
    int dir = (int)encoder3->getDirection();
    if (CurrentEncoderState == ADSR) {
      if (dir == 1) {
        cutoff = cutoff + 100;
      } else {
        cutoff = cutoff - 100;
      }

      if (cutoff <= 20) {
        cutoff = 20;
      }
      if (cutoff >= 16000) {
        cutoff = 16000;
      }
      Serial.print("cutoff: ");
      Serial.println(cutoff);
    } else if (CurrentEncoderState == Effects) {
    }
  }
  lastPos3 = newPos3;

  int newPos4 = encoder4->getPosition();
  if (newPos4 != lastPos4) {
    Serial.println("r");
    int dir = (int)encoder4->getDirection();
    if (CurrentEncoderState == ADSR) {
      if (dir == 1) {
        resonance = resonance + 0.05;
      } else {
        resonance = resonance - 0.05;
      }
      if (resonance <= 0.7) {
        resonance = 0.7;
      }
      if (resonance >= 5) {
        resonance = 5;
      }
      Serial.print("res: ");
      Serial.println(resonance);
    }

    else if (CurrentEncoderState == Effects) {
    }
  }
  lastPos4 = newPos4;

  envelope1.attack(attack);
  envelope1.hold(0);
  envelope1.decay(decay);
  envelope1.sustain(0);
  envelope1.release(0);

  filter1.frequency(cutoff);
  filter1.resonance(resonance);
}

void triggerNoteOn(int note) {
  waveformMod1.frequency(freqFromMidiNote(note));
  envelope1.noteOn();
}
void triggerNoteOff(int note) {
  envelope1.noteOff();
}

void updateAdsrButton() {

  lastadsrButton = adsrButton;
  adsrButton = 0;  //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 updateVolume() {

  static int pos = 0;
  static int lastTime = millis();
  int delta_time = millis() - lastTime;
  if (delta_time > 100) {
    int newPos = encoderVolume->getPosition();
    if (pos != newPos) {

      Serial.print("pos:");
      Serial.print(newPos);
      Serial.print(" dir:");
      Serial.println((int)(encoderVolume->getDirection()));

      Serial.print("Millis - lasttime :");

      if (newPos > pos) {
        pos++;
      } else {
        pos--;
      }
      encoderVolume->setPosition(pos);

#ifdef SCENE_INSTEAD_OF_VOLUME
      loadScene(pos);
#else
      sgtl5000_1.volume(newVolume);

#endif

      lastTime = millis();

    }  // if
  } else {
    encoderVolume->setPosition(pos);
  }

  float newVolume = (float)(-1 * pos) / 100.0;
  if (newVolume > 1.0) {
    newVolume = 1.0;
  }
  if (newVolume < 0.0) {
    newVolume = 0.0;
  }
}

void updateTempo() {
  //tempo = map(analogRead(A17), 0, 1023, 50, 1000);

  static int pos = 0;
  static int lastTime = millis();

  if (millis() - lastTime > 100) {
    int newPos = encoderTempo->getPosition();
    if (pos != newPos) {
      lastTime = millis();
      Serial.print("pos:");
      Serial.print(newPos);
      Serial.print(" dir:");
      Serial.println((int)(encoderTempo->getDirection()));
      pos = newPos;
      encoderTempo->setPosition(pos);

    }  // if

    bpm = 120 + pos;
    if (bpm >= 360) {
      bpm = 360;
      pos = 240;
      encoderTempo->setPosition(pos);
    }
    if (bpm <= 5) {
      bpm = 5;
      pos = 5 - 120;
      encoderTempo->setPosition(pos);
    }

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

    delay1.delayfade(0, ms_per_step * 2, 3.0);

  } else {
    encoderTempo->setPosition(pos);
  }
}

//effects area

// Reverb Zone

void updateReverb() {
  static int pos = 0;
  int newPos = encoder2->getPosition();
  if (pos != newPos) {  // ENCODER HAS CHANGED

    float newReverb = (float)(pos) / 100.0;
    if (newReverb > 1.0) {
      newReverb = 1.0;
    }
    if (newReverb < 0.0) {
      newReverb = 0.0;
    }

    reverbSends[channel] = newReverb;

    //setting the reverb send levels
    reverbSend1to4.gain(0, reverbSends[0]);  //kick
    reverbSend1to4.gain(1, reverbSends[1]);  //clap
    reverbSend1to4.gain(2, reverbSends[2]);  //open hh
    reverbSend1to4.gain(3, reverbSends[3]);  //closed hh
    reverbSend5to8.gain(0, reverbSends[4]);  //snare
    reverbSend5to8.gain(1, reverbSends[5]);  //cowbell
    reverbSend5to8.gain(2, reverbSends[6]);  //ride
    reverbSend5to8.gain(3, reverbSends[7]);  //tom

    pos = newPos;
  }
}

// Delay Zone

void updateDelay() {
  int newPos = encoder3->getPosition();
  if (lastPosDelay != newPos) {
    int dir = (int)encoder3->getDirection();
    Serial.print(lastPosDelay);
    Serial.print(" ");
    Serial.print(newPos);
    if (newPos > lastPosDelay) {
      Serial.println("inc");
      delaySends[channel] += 0.05;
    } else {
      Serial.println("dec");
      delaySends[channel] -= 0.05;
    }

    if (delaySends[channel] <= 0) {
      delaySends[channel] = 0;
    }
    if (delaySends[channel] >= 1) {
      delaySends[channel] = 1;
    }
    lastPosDelay = newPos;
    Serial.println(delaySends[channel]);

    delaysend1_4.gain(0, delaySends[0]);
    delaysend1_4.gain(1, delaySends[1]);
    delaysend1_4.gain(2, delaySends[2]);
    delaysend1_4.gain(3, delaySends[3]);
    delaysend5_8.gain(0, delaySends[4]);
    delaysend5_8.gain(1, delaySends[5]);
    delaysend5_8.gain(2, delaySends[6]);
    delaysend5_8.gain(3, delaySends[7]);
  }
}

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

  ///////FIND ME

  switch (channel) {

    case 0:
      sendMIDITrigger(DrumMIDINote0);
      playMem1.play(AudioSampleRivertoseakitdaf);
      break;

    case 1:
      sendMIDITrigger(DrumMIDINote1);
      playMem2.play(AudioSampleRivertoseakittablalow);
      break;

    case 2:
      sendMIDITrigger(DrumMIDINote2);
      playMem3.play(AudioSampleRivertoseakittablamid);
      break;

    case 3:
      sendMIDITrigger(DrumMIDINote3);
      playMem4.play(AudioSampleRivertoseakittablahigh);
      break;

    case 4:
      sendMIDITrigger(DrumMIDINote4);
      playMem5.play(AudioSampleRivertoseakitriqhit);
      break;

    case 5:
      sendMIDITrigger(DrumMIDINote5);
      playMem6.play(AudioSampleRivertoseakitriqshake);
      break;

    case 6:
      sendMIDITrigger(DrumMIDINote6);
      playMem7.play(AudioSampleRivertoseakitoud);
      break;

    case 7:
      sendMIDITrigger(DrumMIDINote7);
      playMem8.play(AudioSampleRivertoseakitchant);
      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)

      // filter1.frequency(pow((float)filterCutoffs[currentStep], (float)2.0));
    }

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

    updateLeds();
  }
}

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

  int red = 0;
  int green = 0;
  int white = 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 = 240;
      break;

    case LitaColorMute:
      red = 155;
      green = 0;
      blue = 0;
      break;

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

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

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

void updateLeds() {

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

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

    // if (channel == 1) {
    if (clapNotes[i] == 1) {
      updateLed(i + 8, 1, StepActive);
    } else {
      updateLed(i + 8, 0, StepActive);
    }
    // }

    // if (channel == 2) {
    if (openhihatNotes[i] == 1) {
      updateLed(i + 16, 1, StepActive);
    } else {
      updateLed(i + 16, 0, StepActive);
    }
    //}

    // if (channel == 3) {
    if (closedhihatNotes[i] == 1) {
      updateLed(i + 24, 1, StepActive);
    } else {
      updateLed(i + 24, 0, StepActive);
    }
    //}

    //if (channel == 4) {
    if (snareNotes[i] == 1) {
      updateLed(i + 32, 1, StepActive);
    } else {
      updateLed(i + 32, 0, StepActive);
    }
    //}

    //if (channel == 5) {
    if (cowbellNotes[i] == 1) {
      updateLed(i + 40, 1, StepActive);
    } else {
      updateLed(i + 40, 0, StepActive);
    }
    //}

    //if (channel == 6) {
    if (cymbalNotes[i] == 1) {
      updateLed(i + 48, 1, StepActive);
    } else {
      updateLed(i + 48, 0, StepActive);
    }
    //}

    //if (channel == 7) {
    if (tomNotes[i] == 1) {
      updateLed(i + 56, 1, StepActive);
    } else {
      updateLed(i + 56, 0, StepActive);
    }
    //}

  }

  //Mutes
  for (int i = 0; i < 8; i++) {
    if (mutes[i] > 0) {
      updateLed(i * 8, 1, LitaColorMute);
      updateLed(i * 8 + 1, 1, LitaColorMute);
      updateLed(i * 8 + 2, 1, LitaColorMute);
      updateLed(i * 8 + 3, 1, LitaColorMute);
      updateLed(i * 8 + 4, 1, LitaColorMute);
      updateLed(i * 8 + 5, 1, LitaColorMute);
      updateLed(i * 8 + 6, 1, LitaColorMute);
      updateLed(i * 8 + 7, 1, LitaColorMute);
    }
  }

  //Vertical Bar
  int myDisplayStep = displayStep;
  if (displayStep >= 0) {
    while (myDisplayStep < 64) {
      updateLed(myDisplayStep, 1, LitaColorSequence);
      myDisplayStep += 8;
    }
  }

  neopixel.show();
}

void updateDisplay() {

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

  display.setRotation(0);
  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();
};