If you would like this code and want me to share the folder where it includes user-defined files in the program, please email me at contact@djlita.com <3
#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 "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_ENABLED false
#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 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 };
float notesOn[127] = { 0.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;
float keyboardNotes[8] = { 38.02, 39.53, 40.96, 43.00, 45.04, 46.55, 47.98, 50.02 }; // HERE
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;
float delaySend = 0.0;
// 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 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 = 55; //a440
int keyboardOctave = 3;
//Convert any MIDI note number to it's frequency
float freqFromMidiNote(float note) {
return 440.0f * powf(2, (float (note) - 69.0f) / 12.0f); // efpitch/G3-55 // 55.0/12.0 with return 195.998f
}
//melody sequencemelodyNotes
int melodyNotes[32] = { 60, 62, 63, 72, 70, 65, 67, 70, 60, 62, 63, 72, 70, 65, 67, 70, 60, 62, 63, 72, 70, 65, 67, 70, 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 drumVolumes[8] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 };
float drumProbabilities[8] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 };
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;
double normalizedCutoff = 0.9; // used and then squared before scaling to get logarithmic curve
int cutoff = 10000;
float resonance = 0.7;
float globalGain = 4.0;
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;
unsigned long lastStepTime_previous = 0;
int currentStep = 0;
int currentStepMelody = 0;
int displayStep = 0;
int totalSteps = 8;
int totalStepsMelody = 32;
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>
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(150 * (128 / AUDIO_BLOCK_SAMPLES));
Serial.begin(9600);
if (MIDI_ENABLED) {
MIDI.begin(); // Initialize MIDI with Omni channel (responds to all MIDI channels)
}
display.begin();
neopixel.begin();
neopixel.clear();
neopixel.show();
// 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);
pinMode(31, INPUT);
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);
//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 updateMidiIn() {
int type, velocity, channel, d1, d2;
float note;
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();
switch (int(note)) {
case 24:
{
triggerSample(0);
}
break;
case 26:
{
triggerSample(1);
}
break;
case 28:
{
triggerSample(2);
}
break;
case 29:
{
triggerSample(3);
}
break;
case 31:
{
triggerSample(4);
}
break;
case 33:
{
triggerSample(5);
}
break;
case 35:
{
triggerSample(6);
}
break;
case 36:
{
triggerSample(7);
}
break;
default:
break;
}
if (velocity > 0) {
if (note > 36.0f) {
triggerNoteOn(note);
}
Serial.println(String("Note On: ch=") + channel + ", note=" + note + ", velocity=" + velocity);
} else {
if (note > 36.0f) {
triggerNoteOff(note);
}
Serial.println(String("Note Off: ch=") + channel + ", note=" + note);
}
break;
case midi::NoteOff:
note = MIDI.getData1();
if (note > 36.0f) {
triggerNoteOff(note);
}
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);
}
}
}
void triggerNoteOn(float note){
}
void triggerNoteOff(float note){
}
void loop() {
if (MIDI_ENABLED) {
updateMidiIn();
}
updateDisplay();
updateTempo();
updateVolume();
updateReverb();
updateDrumMix();
updateDrumProbabilities();
updateSequencer();
updateAdsrButton();
updateEnvelope();
updateTopRow();
updateSideButtons();
updateBottomRow();
updateDelay();
}
// MIDI -- sends over USB and Hardware port.
void sendMIDITrigger(float 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 (clearchangeflag == true) {
for (int i = 0; i < 32; i++) {
melodyNotes[i] = 0;
}
clearchangeflag = false;
} else {
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];
}
}
void startStop() {
if (playing) {
envelope1.noteOff();
playing = 0;
displayStep = -1;
} else {
currentStep = 0;
currentStepMelody = 0;
displayStep = 0;
lastStepTime = 0;
lastStepTime_previous = 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[currentStepMelody] != currentNote) {
melodyNotes[currentStepMelody] = currentNote;
//filterCutoffs[currentStep] = release;
} else {
melodyNotes[currentStepMelody] = 0;
}
}
}
lastMux1Vals[chan] = mux1Vals[chan];
}
}
void updateEnvelope() {
// static int counter_print = 0;
if (CurrentEncoderState == ADSR) {
int newPos1 = encoder1->getPosition();
if (newPos1 != lastPos1) {
int dir = (int)encoder1->getDirection();
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);
}
lastPos1 = newPos1;
}
if (CurrentEncoderState == ADSR) {
int newPos2 = encoder2->getPosition();
// Serial.println(newPos2);
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;
}
Serial.print("Decay: ");
Serial.println(decay);
}
lastPos2 = newPos2;
}
//apply 2 all encoders
if (CurrentEncoderState == ADSR) {
int newPos3 = encoder3->getPosition();
if (newPos3 != lastPos3) {
Serial.println("c");
int dir = (int)encoder3->getDirection();
if (dir == 1) {
normalizedCutoff += 0.02;
} else {
normalizedCutoff -= 0.02;
}
if (normalizedCutoff <= 0.02) {
normalizedCutoff = 0.02;
}
if (normalizedCutoff >= 0.9) {
normalizedCutoff = 0.9;
}
Serial.print("Normalized Cutoff: ");
Serial.println(normalizedCutoff);
}
lastPos3 = newPos3;
}
if (CurrentEncoderState == ADSR) {
int newPos4 = encoder4->getPosition();
if (newPos4 != lastPos4) {
Serial.println("r");
int dir = (int)encoder4->getDirection();
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);
}
lastPos4 = newPos4;
}
envelope1.attack(attack);
envelope1.hold(0);
envelope1.decay(decay);
envelope1.sustain(0);
envelope1.release(0);
cutoff = normalizedCutoff * normalizedCutoff * normalizedCutoff * 20000;
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
void updateDrumMix() {
if (CurrentEncoderState == Effects) {
static int pos = 0;
int newPos = encoder1->getPosition();
if (pos != newPos) { // ENCODER HAS CHANGED
int dir = (int)encoder1->getDirection();
drumVolumes[channel] += (float)(-1 * dir) / 50.0;
Serial.println("Drum volume changed");
if (drumVolumes[channel] > 2.0) {
drumVolumes[channel] = 2.0;
}
if (drumVolumes[channel] < 0.0) {
drumVolumes[channel] = 0.0;
}
//drumVolumes[channel] = newVolume;
//setting the mixer levels
mixer1.gain(0, 2.0 * drumVolumes[0] * globalGain); //daf aka kick
mixer1.gain(1, 1.0 * drumVolumes[1] * globalGain); //tabla low
mixer1.gain(2, 1.5 * drumVolumes[2] * globalGain); //tabla mid
mixer1.gain(3, 1.8 * drumVolumes[3] * globalGain); //tabla high
mixer2.gain(0, 0.5 * drumVolumes[4] * globalGain); // riq hit
mixer2.gain(1, 0.5 * drumVolumes[5] * globalGain); // riq shake
mixer2.gain(2, 0.5 * drumVolumes[6] * globalGain); //oud
mixer2.gain(3, 0.4 * drumVolumes[7] * globalGain); //chant
pos = newPos;
}
}
}
void updateDrumProbabilities() {
if (CurrentEncoderState == Effects) {
static int pos = 0;
int newPos = encoder2->getPosition();
if (pos != newPos) { // ENCODER HAS CHANGED
Serial.println("Drum probability changed");
int dir = (int)encoder2->getDirection();
drumProbabilities[channel] += (dir / 50.0);
if (drumProbabilities[channel] > 1.0) {
drumProbabilities[channel] = 1.0;
}
if (drumProbabilities[channel] < 0.0) {
drumProbabilities[channel] = 0.0;
}
pos = newPos;
}
}
}
// Reverb Zone
void updateReverb() {
if (CurrentEncoderState == Effects) {
static int pos = 0;
int newPos = encoder4->getPosition();
if (pos != newPos) { // ENCODER HAS CHANGED
Serial.println("Reverb changed");
int dir = (int)encoder4->getDirection();
reverbSends[channel] += (float)(dir) / 20.0;
if (reverbSends[channel] > 1.0) {
reverbSends[channel] = 1.0;
}
if (reverbSends[channel] < 0.0) {
reverbSends[channel] = 0.0;
}
//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() {
if (CurrentEncoderState == Effects) {
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.1;
} else {
Serial.println("dec");
delaySends[channel] -= 0.1;
}
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;
}
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;
}
}
bool checkProbability(float probability) {
float randomNum = (float)random(0, 100) / (float)100.0;
if (randomNum < probability) {
return true;
} else {
return false;
}
}
void updateSequencer() {
if (!playing) {
return;
}
if (MIDI_ENABLED) {
if (millis() > lastStepTime + (ms_per_step / 2)) {
for (int i = 0; i < 128; i++) {
if (notesOn[i] > 0) {
MIDI.sendNoteOff(i, 100, 1);
//delay(100);
notesOn[i] = 0;
//delay(100);
}
}
}
}
if (millis() > lastStepTime + ms_per_step) {
lastStepTime = millis();
//Playing back melody sequence with MIDI OUT
if (keyboardSequenceMute == 0 && melodyNotes[currentStepMelody] > 0) {
//Serial.println("hi");
triggerNoteOff(melodyNotes[currentStepMelody]); // going to eventually replace whole thing to playSDwave.play(filename)
triggerNoteOn(melodyNotes[currentStepMelody]); // going to eventually replace whole thing to playSDwave.play(filename)
// MIDI.sendNoteOff(melodyNotes[currentStep], 100, 1);
int lastNote = random(32, 100);
if (MIDI_ENABLED) {
MIDI.sendNoteOn(melodyNotes[currentStepMelody], 100, 1);
Serial.println(melodyNotes[currentStepMelody]);
notesOn[melodyNotes[currentStepMelody]] = 1;
}
}
if (kickNotes[currentStep] > 0) {
if (checkProbability(drumProbabilities[0])) {
triggerSample(0);
}
}
if (clapNotes[currentStep] > 0) {
if (checkProbability(drumProbabilities[1])) {
triggerSample(1);
}
}
if (openhihatNotes[currentStep] > 0) {
if (checkProbability(drumProbabilities[2])) {
triggerSample(2);
}
}
if (closedhihatNotes[currentStep] > 0) {
if (checkProbability(drumProbabilities[3])) {
triggerSample(3);
}
}
if (snareNotes[currentStep] > 0) {
if (checkProbability(drumProbabilities[4])) {
triggerSample(4);
}
}
if (cowbellNotes[currentStep] > 0) {
if (checkProbability(drumProbabilities[5])) {
triggerSample(5);
}
}
if (cymbalNotes[currentStep] > 0) {
if (checkProbability(drumProbabilities[6])) {
triggerSample(6);
}
}
if (tomNotes[currentStep] > 0) {
if (checkProbability(drumProbabilities[7])) {
triggerSample(7);
}
}
displayStep = currentStep;
currentStep++;
currentStepMelody++;
if (currentStep >= totalSteps) {
currentStep = 0;
}
if (currentStepMelody >= totalStepsMelody) {
currentStepMelody = 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(1);
display.setTextColor(WHITE);
display.print(bpm);
display.setTextSize(1);
display.println("BPM");
display.setTextSize(0.5);
display.print("Attack:");
display.println((float)attack / 1000.0);
display.print("DrumVol:");
display.println((float)drumVolumes[channel]);
display.print("Decay:");
display.print((float)decay / 1000.0);
display.print(" Prob:");
display.println();
display.print("CO:");
display.print((float)cutoff);
display.print(" Del:");
display.println((float)delaySends[channel]);
display.print("Res:");
display.print((float)resonance);
display.print(" Rev:");
display.println((float)reverbSends[channel]);
display.print("Synth ");
if (keyboardSequenceMute == 1) {
display.println("Off");
} else if (keyboardSequenceMute == 0) {
display.println("On");
}
//display.println(keyboardSequenceMute);
if (mutechangeflag == 1) {
display.println("Choose track to mute");
} else if (instrumentchangeflag == 1) {
display.println("Choose track to edit");
} else if (clearchangeflag == 1) {
display.println("Choose chan to clear");
} else {
display.print("Editing: ");
switch (channel) {
case 0:
display.print("Tabla Mid"); //kick
break;
case 1:
display.print("Tabla Low"); //clap
break;
case 2:
display.print("Tabla High"); //Open High
break;
case 3:
display.print("Riq Shake"); //Clsed HH
break;
case 4:
display.print("Riq Hit"); //snare
break;
case 5:
display.print("Oud"); //Cowbell
break;
case 6:
display.print("Daf"); //cymbal
break;
case 7:
display.print("Chant"); //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();
}