#include <MozziGuts.h>
#include <Oscil.h>
#include <tables/sin8192_int8.h>
#include <tables/sin2048_int8.h>
#include <tables/saw8192_int8.h>
#include <tables/square_analogue512_int8.h>
#include <tables/square_no_alias_2048_int8.h>
#include <tables/triangle512_int8.h>
#include <mozzi_midi.h>
#include <LowPassFilter.h>
#include <ADSR.h>
#include <EventDelay.h>
#include "bitmaps.h"
unsigned int chosenOscillator;
int oscillatorType[] = { SIN8192_DATA, SAW8192_DATA, SQUARE_ANALOGUE512_DATA, TRIANGLE512_DATA, SQUARE_NO_ALIAS_2048_DATA };
//Different Oscillators
Oscil<8192, AUDIO_RATE> aOscil(SIN8192_DATA);
Oscil<2048, AUDIO_RATE> bOscil(SAW8192_DATA);
Oscil<2048, CONTROL_RATE> kVib(SIN2048_DATA);
//Envelope
ADSR<CONTROL_RATE, AUDIO_RATE> envelope;
//MIDI Notes
float NOTE_A = (int)mtof(57);
float NOTE_B = (int)mtof(59);
float NOTE_C = (int)mtof(60);
float NOTE_D = (int)mtof(62);
float NOTE_E = (int)mtof(64);
float NOTE_F = (int)mtof(65);
float NOTE_G = (int)mtof(67);
//Constants
#define CONTROL_RATE 128
const char LED_LIGHT = 13;
const char VIBRATO_KNOB = 0;
const char CUTOFF_KNOB = 1;
const char RESONANCE_KNOB = 2;
const char OSC_CHANGE = 3;
const char ATTACK_KNOB = 4;
const char RELEASE_LEVEL = 5;
const char BUTTON_1 = 2;
const char BUTTON_2 = 3;
const char BUTTON_3 = 4;
const char BUTTON_4 = 5;
const char BUTTON_5 = 6;
const char BUTTON_6 = 7;
const char BUTTON_7 = 8;
//Variables
LowPassFilter lpf;
unsigned int buttonPins[] = { BUTTON_1, BUTTON_2, BUTTON_3, BUTTON_4, BUTTON_5, BUTTON_6, BUTTON_7 };
unsigned int notes[] = { NOTE_A, NOTE_B, NOTE_C, NOTE_D, NOTE_E, NOTE_F, NOTE_G };
byte volume = 0;
unsigned int oscChange;
float addVibrato() {
// Instanstiates the vibrato knob
float vibratoKnob = mozziAnalogRead(VIBRATO_KNOB) / (float)5000;
float vibrato = vibratoKnob * kVib.next();
Serial.println(vibratoKnob);
return vibrato;
}
void setOscillator() {
oscChange = mozziAnalogRead(OSC_CHANGE) / 200;
chosenOscillator = oscChange;
aOscil.setTable(oscillatorType[chosenOscillator]);
}
void setADSR() {
unsigned int attack_knob = mozziAnalogRead(ATTACK_KNOB);
unsigned int release_knob = mozziAnalogRead(RELEASE_LEVEL);
byte attack_level = 100;
byte decay_level = 10;
envelope.setADLevels(attack_level, decay_level);
envelope.setTimes(attack_knob, 500, 10, release_knob);
}
void setCutoffFilter() {
unsigned int cutoff = mozziAnalogRead(CUTOFF_KNOB) / 6;
unsigned int resonance = mozziAnalogRead(RESONANCE_KNOB) / 8;
lpf.setCutoffFreqAndResonance(cutoff, resonance);
}
void playNote() {
bool buttonPressed = false;
// Checks the pressed button and plays the note associated with that button
for (int i = 0; i < sizeof(buttonPins) / sizeof(buttonPins[0]); i++) {
if (digitalRead(buttonPins[i]) == LOW) {
setADSR();
aOscil.setFreq(notes[i] + addVibrato());
envelope.noteOn();
buttonPressed = true;
digitalWrite(LED_LIGHT, HIGH);
break; // exit the loop if any button is pressed
}
}
if (!buttonPressed) {
envelope.noteOff();
digitalWrite(LED_LIGHT, LOW);
buttonPressed = false;
}
}
void setup() {
Serial.begin(115200);
kVib.setFreq(6.5f);
for (int i = 0; i < sizeof(buttonPins) / sizeof(buttonPins[0]); i++) {
pinMode(buttonPins[i], INPUT_PULLUP);
}
pinMode(LED_LIGHT, INPUT_PULLUP);
digitalWrite(LED_LIGHT, LOW);
startMozzi(CONTROL_RATE);
}
void updateControl() {
setOscillator();
setCutoffFilter();
envelope.update();
playNote();
}
AudioOutput_t updateAudio() {
int cutoffFilter = lpf.next(aOscil.next());
return MonoOutput::from16Bit((envelope.next() * cutoffFilter) * 2);
}
void loop() {
audioHook();
}