This commit is contained in:
gauthiier
2018-12-01 12:57:32 +01:00
parent 5aa8489eee
commit dd0197fa42
23 changed files with 3954 additions and 0 deletions
@@ -0,0 +1,539 @@
//______________________/\\\\\__________________________/\\\______________________________/\\\__________________________________________________________
// ____________________/\\\///__________________________\/\\\_____________________________\/\\\__________________________________________________________
// ___________________/\\\______________________________\/\\\_____________________________\/\\\_____/\\\__/\\\_______________________________/\\\\\\\\___
// _____/\\\\\\\\__/\\\\\\\\\_______/\\\\\______________\/\\\____________/\\\\\___________\/\\\____\//\\\/\\\___/\\\\\\\\\\_____/\\\\\\\\___/\\\////\\\__
// ___/\\\//////__\////\\\//______/\\\///\\\____________\/\\\\\\\\\____/\\\///\\\____/\\\\\\\\\_____\//\\\\\___\/\\\//////____/\\\/////\\\_\//\\\\\\\\\__
// __/\\\____________\/\\\_______/\\\__\//\\\___________\/\\\////\\\__/\\\__\//\\\__/\\\////\\\______\//\\\____\/\\\\\\\\\\__/\\\\\\\\\\\___\///////\\\__
// _\//\\\___________\/\\\______\//\\\__/\\\____________\/\\\__\/\\\_\//\\\__/\\\__\/\\\__\/\\\___/\\_/\\\_____\////////\\\_\//\\///////__________\/\\\__
// __\///\\\\\\\\____\/\\\_______\///\\\\\/_____________\/\\\\\\\\\___\///\\\\\/___\//\\\\\\\/\\_\//\\\\/_______/\\\\\\\\\\__\//\\\\\\\\\\________\/\\\\_
// ____\////////_____\///__________\/////_______________\/////////______\/////______\///////\//___\////________\//////////____\//////////_________\////__
// CFO BODYSEQ sequencer, 3 button version, reworked interaction, http://www.vsionhairies.info/
#define MIDI_CHANNEL 1
#include <spi4teensy3.h>
#include <EEPROM.h>
#include "CFO_BODYSEQ.h"
const int seqLed [] = {3, 4, 5, 6, 7, 8, 9, 10};
int seqLedVal [] = {0, 0, 0, 0, 0, 0, 0, 0};
int _bpm = 120;
int s1;
const int statusLed1 = 13;
const int buttonPin [] = {11, 12, 2};
const int pot1 = A0, pot2 = A1;
const int bodySwitch [] = {A2, A3, A4, A5, A6, A7, A8, A9};
unsigned long lastPrint = millis();
boolean sequenceRunning = true;
float maxBodyReading = 0;
float maxBodyFadeout = 0.9999;
float averageNoise = 0;
int inputFreq = 10;
unsigned long lastInput = millis();
int seqStep = 0;
int seqLength = 7;
int seqNote[] = { -1, -1, 0, -1, 12, -1, -1, -1, -1, -1, 0, -1, 24, -1, -1, -1, -1, -1, 0, -1, 36, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, 0, -1, 12, -1, -1, -1, -1, -1, 0, -1, 24, -1, -1, -1, -1, -1, 0, -1, 36, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1};
int activeSeq = 0, seqStart = 0, seqEnd = 7;
unsigned long lastStep = millis();
int stepTime = 200, blinkTime = 50;
int baseNote = 36;
const int scale[3][7] = {
{0, 2, 4, 5, 7, 9, 11}, // major
{0, 2, 3, 5, 6, 7, 10}, // blues
{0, 3, 4, 7, 9, 10, -1} // rock
};
const int scaleLength = 24;
int activeScale [scaleLength];
int bodySwitchVal [] = {0, 0, 0, 0, 0, 0, 0, 0};
boolean bodySwitchesTouched = false;
int mode = 0;
int bank = 0, preset = 16;
boolean buttonState [] = {HIGH, HIGH, HIGH};
boolean buttonAction [] = {false, false, false};
int potVal1 = 0, potVal2 = 0;
boolean pot1Moved = false, pot2Moved = false, potsMoved = false;
int potNoise = 1;
boolean debug = true;
void setup() {
// We initialise the sound engine by calling Music.init() which outputs a tone
Music.init();
Music.enableEnvelope1();
Music.enableEnvelope2();
Music.getPreset(13);
Music.setEnv1Decay(36);
Music.setEnv1Sustain(0);
usbMIDI.setHandleNoteOff(OnNoteOff);
usbMIDI.setHandleNoteOn(OnNoteOn);
usbMIDI.setHandleControlChange(OnControlChange);
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
analogReadAveraging(32);
delay(1000);
Sequencer.init(120);
s1 = Sequencer.newSequence(NOTE_16, &sequenceCallback);
Sequencer.setInternalClock(true);
Sequencer.setInternal(s1, true);
Sequencer.setExternal(s1, true);
Sequencer.startSequence(s1);
checkBPM();
Serial.begin(9600);
Serial.println("hello");
pinMode(buttonPin[0], INPUT_PULLUP);
pinMode(buttonPin[1], INPUT_PULLUP);
pinMode(buttonPin[2], INPUT_PULLUP);
newActiveScale(scaleLength);
pinMode(statusLed1, OUTPUT);
for (int i = 0; i < 8; i++) {
pinMode(seqLed[i], OUTPUT);
}
startupAnimation();
sampleAverageNoise();
}
void loop() {
// check for incoming USB MIDI messages
usbMIDI.read();
Midi.checkSerialMidi();
// update sequencer
Sequencer.update();
// check user input
if (lastInput + inputFreq < millis()) {
// check user input
readPots();
readBodyswitches();
readButtons();
// general navigation
// button 0 pushed
if (buttonState[0] == LOW) {
noteInputFromBodyswitches();
}
// button 1 pushed
if (buttonState[1] == LOW) {
eraseNotesFromBodyswitches();
if (pot1Moved) {
// change sequencer speed
checkBPM();
potsMoved = false;
}
}
// button 2 pushed
if (buttonState[2] == LOW) {
changeSequenceBank();
activeSeq = bank;
if (pot2Moved) {
changePreset();
potsMoved = false;
}
if (pot1Moved) {
changeOctave();
potsMoved = false;
}
}
// button 0 and 2 pushed
if (buttonState[2] == LOW && buttonState[0] == LOW) {
int lowestSwitch = 0, highestSwitch = 0;
if (bodySwitchesTouched) {
for (int i = 0; i < 8; i++) {
if (bodySwitchVal[i] > 0) {
highestSwitch = i;
}
if (bodySwitchVal[7 - i] > 0) {
lowestSwitch = 7 - i;
}
}
seqStart = lowestSwitch;
seqEnd = highestSwitch;
}
}
lastInput = millis();
}
if (potsMoved) setCutoffFromPots();
updateLEDs();
}
void sampleAverageNoise() {
Serial.print("sampling average noise levels: ");
for (int i = 0; i < 8; i++) {
pinMode(seqLed[i], OUTPUT);
averageNoise += analogRead(bodySwitch[i]);
}
averageNoise = averageNoise / 8 + 3;
Serial.println(averageNoise);
}
void setCutoffFromPots() {
Music.setCutoff((analogRead(pot1)) * 64);
Music.setCutoffModAmount((analogRead(pot2)) * 64);
}
void updateLEDs() {
for (int i = 0; i < 8; i++) {
if (seqNote[activeSeq * 8 + i] != -1) {
// there is a note
digitalWrite(seqLed[i], HIGH);
}
else {
digitalWrite(seqLed[i], LOW);
}
}
// blink ON to show sequencer progression
if (lastStep + blinkTime < millis()) {
digitalWrite(seqLed[seqStep], HIGH);
}
// blink OFF to show sequencer progression
if (lastStep + stepTime - blinkTime/2 < millis()) {
digitalWrite(seqLed[seqStep], LOW);
}
}
void newActiveScale (int length) {
if (debug) Serial.println("lets make a new active scale");
int amountOfNotesInScale = 0;
for (int i = 0; i < 7; i++) {
if (scale[1][i] != -1) amountOfNotesInScale++;
}
for (int i = 0; i < length + 1; i++) {
int currentOctave = i / amountOfNotesInScale;
if (debug) Serial.print("octave ");
if (debug) Serial.print(currentOctave);
int currentNote = scale[1][i % amountOfNotesInScale];
if (debug) Serial.print("\tnote ");
if (debug) Serial.print(currentNote);
activeScale[i] = currentOctave * 12 + currentNote;
if (debug) Serial.print("\tthis yields ");
if (debug) Serial.println(activeScale[i]);
}
}
void eraseNotesFromBodyswitches() {
for (int i = 0; i < 8; i++) {
if (bodySwitchVal[i] > 0) {
seqNote[activeSeq * 8 + i] = -1;
}
}
//updateLEDs();
}
void noteInputFromBodyswitches() {
for (int i = 0; i < 8; i++) {
if (bodySwitchVal[i] > 0) {
if (debug) Serial.print(i);
if (debug) Serial.print(": ");
if (debug) Serial.print(bodySwitchVal[i]);
int note = map(bodySwitchVal[i], 0, 127, 0, scaleLength - 1);
if (debug) Serial.print("\tnote: ");
if (debug) Serial.print(note);
seqNote[activeSeq * 8 + i] = activeScale[note];
if (debug) Serial.print("\tseqNote: ");
if (debug) Serial.println(seqNote[activeSeq * 8 + i]);
}
}
//updateLEDs();
}
void readPots() {
int newPotVal1 = 1023 - analogRead(pot1);
int newPotVal2 = 1023 - analogRead(pot2);
potsMoved = false;
if ( (newPotVal1 < (potVal1 - potNoise)) || (newPotVal1 > (potVal1 + potNoise)) ) {
potVal1 = newPotVal1;
pot1Moved = true;
potsMoved = true;
}
else {
pot1Moved = false;
}
if ( (newPotVal2 < (potVal2 - potNoise)) || (newPotVal2 > (potVal2 + potNoise)) ) {
potVal2 = newPotVal2;
pot2Moved = true;
potsMoved = true;
}
else {
pot2Moved = false;
}
/*
if (potsMoved) {
if (debug) Serial.print("pot 1 ");
if (debug) Serial.println(potVal1);
if (debug) Serial.print("pot 2 ");
if (debug) Serial.println(potVal2);
}
*/
}
void changeOctave() {
// change from pot
int newOctave = map(analogRead(pot1), 0, 1023, -3, 4);
baseNote = 36 + newOctave * 12;
// display on LEDs which octave is active
for (int i = 0; i < 8; i++) {
if (newOctave + 3 == i) {
digitalWrite(seqLed[i], HIGH);
}
else {
digitalWrite(seqLed[i], LOW);
}
}
}
void changeSequenceBank() {
// select bank with body switches
int highest = -1, highestVal = averageNoise;
for (int i = 0; i < 8; i++) {
if (bodySwitchVal[i] > highestVal) {
highest = i;
highestVal = bodySwitchVal[i];
}
}
if (highest != -1) {
bank = highest;
if (debug) Serial.print("playing sequence bank: ");
if (debug) Serial.println(bank);
}
//updateLEDs();
}
void changePreset() {
int newPreset = map(analogRead(pot2), 0, 1023, 0, 31);
if (preset != newPreset) { // only do something if preset has changed
// NB! user preset 0-16 might be empty, resulting in crazy sounds!
if (debug) Serial.print("new preset ");
if (debug) Serial.println(newPreset);
preset = newPreset;
Music.getPreset(preset);
}
}
void sequenceCallback() {
// this is a callback function, called every time the sequencer steps
// calculate how many millis have passed since last step
unsigned long thisStep = millis();
stepTime = thisStep - lastStep;
lastStep = thisStep;
// and calculate sequencer blink time
blinkTime = max(stepTime >> 2, 100);
// updater sequencer notes
seqStep++;
if (seqStep > seqEnd) seqStep = seqStart;
int note = activeSeq * 8 + seqStep;
if (seqNote[note] != -1) {
Music.noteOn(baseNote + seqNote[note]);
}
//updateLEDs();
}
void updateSequence() {
if (lastStep + stepTime < millis()) {
seqStep++;
if (seqStep > seqEnd) seqStep = seqStart;
int note = activeSeq * 8 + seqStep;
if (seqNote[note] != -1) {
Music.noteOn(baseNote + seqNote[note]);
}
lastStep = millis();
}
//updateLEDs();
}
void readBodyswitches() {
bodySwitchesTouched = false;
for (int i = 0; i < 8; i++) {
int reading = constrain(analogRead (bodySwitch[i]), 0, 127);
maxBodyReading = max(maxBodyReading, reading);
if (reading > averageNoise) { // averageNoise is sampled on startup
int midiVal = map (reading, averageNoise, maxBodyReading, 0, 127);
bodySwitchVal[i] = constrain(midiVal, 0, 127);
bodySwitchesTouched = true;
}
else {
bodySwitchVal[i] = 0;
reading = 0;
}
seqLedVal[i] = reading * 2;
}
maxBodyReading = maxBodyReading * maxBodyFadeout;
}
void printFeedback() {
for (int i = 0; i < 8; i++) {
int reading = analogRead (bodySwitch[i]);
seqLedVal[i] = reading / 4;
Serial.print(i);
Serial.print(": ");
Serial.print(reading);
Serial.print("\t");
}
Serial.println();
int potVal1 = analogRead(pot1);
int potVal2 = analogRead(pot2);
Serial.print(potVal1);
Serial.print("\t");
Serial.print(potVal2);
Serial.println();
}
void startupAnimation() {
digitalWrite(statusLed1, HIGH);
for (int i = 0; i < 8; i++) {
digitalWrite(seqLed[i], HIGH);
delay(30);
}
for (int i = 0; i < 8; i++) {
digitalWrite(seqLed[i], LOW);
delay(30);
}
for (int i = 0; i < 8; i++) {
digitalWrite(seqLed[7 - i], HIGH);
delay(30);
}
for (int i = 0; i < 8; i++) {
digitalWrite(seqLed[7 - i], LOW);
delay(30);
}
digitalWrite(statusLed1, LOW);
delay(100);
}
void readButtons() {
// buttons are active low
for (int i = 0; i < 3; i++) {
if (digitalRead(buttonPin[i]) == HIGH) {
if (buttonState[i] == LOW) {
// button has just been released
buttonAction[i] = true;
if (debug) Serial.print("button ");
if (debug) Serial.print(i);
if (debug) Serial.println(" has just been released");
} else {
// button was already released, no action here
buttonAction[i] = false;
}
buttonState[i] = HIGH;
}
if (digitalRead(buttonPin[i]) == LOW) {
if (buttonState[i] == HIGH) {
// button has just been pushed
buttonAction[i] = true;
if (debug) Serial.print("button ");
if (debug) Serial.print(i);
if (debug) Serial.println(" has just been pushed");
buttonState[i] = LOW;
} else {
// button was already psuhed, no action here
buttonAction[i] = false;
}
}
}
}
//////////
// POTS //
//////////
void checkBPM() {
// >> is C for bitwise shift right.
if (debug) Serial.println("checkBPM");
int bpm = analogRead(A0) >> 2; // fast way of roughly dividing by 4
if (bpm != _bpm) {
_bpm = bpm;
if (debug) Serial.print("BPM set to ");
if (debug) Serial.println(_bpm);
Sequencer.setbpm(_bpm);
if (_bpm == 0) {
Midi.setMidiIn(false);
Midi.setMidiThru(false);
Midi.setMidiOut(false);
Midi.setMidiClockIn(true);
Midi.setMidiClockThru(true);
Midi.setMidiClockOut(false);
Sequencer.setInternalClock(false);
} else {
Midi.setMidiIn(false);
Midi.setMidiThru(false);
Midi.setMidiOut(false);
Midi.setMidiClockIn(false);
Midi.setMidiClockThru(false);
Midi.setMidiClockOut(true);
Sequencer.setInternalClock(true);
// Sequencer.sequencerContinue();
}
}
}