examples
This commit is contained in:
parent
5aa8489eee
commit
85c52ea5c9
447
examples/CFO_BODYSEQ_2buttons/CFO_BODYSEQ_2buttons.ino
Executable file
447
examples/CFO_BODYSEQ_2buttons/CFO_BODYSEQ_2buttons.ino
Executable file
@ -0,0 +1,447 @@
|
|||||||
|
//______________________/\\\\\__________________________/\\\______________________________/\\\__________________________________________________________
|
||||||
|
// ____________________/\\\///__________________________\/\\\_____________________________\/\\\__________________________________________________________
|
||||||
|
// ___________________/\\\______________________________\/\\\_____________________________\/\\\_____/\\\__/\\\_______________________________/\\\\\\\\___
|
||||||
|
// _____/\\\\\\\\__/\\\\\\\\\_______/\\\\\______________\/\\\____________/\\\\\___________\/\\\____\//\\\/\\\___/\\\\\\\\\\_____/\\\\\\\\___/\\\////\\\__
|
||||||
|
// ___/\\\//////__\////\\\//______/\\\///\\\____________\/\\\\\\\\\____/\\\///\\\____/\\\\\\\\\_____\//\\\\\___\/\\\//////____/\\\/////\\\_\//\\\\\\\\\__
|
||||||
|
// __/\\\____________\/\\\_______/\\\__\//\\\___________\/\\\////\\\__/\\\__\//\\\__/\\\////\\\______\//\\\____\/\\\\\\\\\\__/\\\\\\\\\\\___\///////\\\__
|
||||||
|
// _\//\\\___________\/\\\______\//\\\__/\\\____________\/\\\__\/\\\_\//\\\__/\\\__\/\\\__\/\\\___/\\_/\\\_____\////////\\\_\//\\///////__________\/\\\__
|
||||||
|
// __\///\\\\\\\\____\/\\\_______\///\\\\\/_____________\/\\\\\\\\\___\///\\\\\/___\//\\\\\\\/\\_\//\\\\/_______/\\\\\\\\\\__\//\\\\\\\\\\________\/\\\\_
|
||||||
|
// ____\////////_____\///__________\/////_______________\/////////______\/////______\///////\//___\////________\//////////____\//////////_________\////__
|
||||||
|
// CFO BODYSEQ sequencer, 2 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 [] = {2,3,4,5,6,7,8,9};
|
||||||
|
int seqLedVal [] = {0,0,0,0,0,0,0,0};
|
||||||
|
|
||||||
|
const int statusLed1 = 10, statusLed2 = 11;
|
||||||
|
const int buttonPin [] = {12,13};
|
||||||
|
|
||||||
|
const int pot1 = A0, pot2 = A1;
|
||||||
|
const int bodySwitch [] = {A2,A3,A4,A5,A6,A7,A8,A9};
|
||||||
|
|
||||||
|
unsigned long lastPrint = millis();
|
||||||
|
|
||||||
|
boolean sequencerRunning = 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;
|
||||||
|
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 preset = 16;
|
||||||
|
|
||||||
|
boolean buttonState [] = {HIGH, HIGH};
|
||||||
|
boolean buttonAction [] = {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(16);
|
||||||
|
Music.setEnv1Decay(36);
|
||||||
|
Music.setEnv1Sustain(0);
|
||||||
|
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
|
||||||
|
analogReadAveraging(32);
|
||||||
|
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
delay(100);
|
||||||
|
|
||||||
|
Serial.println("hello");
|
||||||
|
|
||||||
|
pinMode(buttonPin[0], INPUT_PULLUP);
|
||||||
|
pinMode(buttonPin[1], INPUT_PULLUP);
|
||||||
|
|
||||||
|
newActiveScale(scaleLength);
|
||||||
|
|
||||||
|
pinMode(statusLed1,OUTPUT);
|
||||||
|
pinMode(statusLed2,OUTPUT);
|
||||||
|
for (int i = 0; i<8; i++) {
|
||||||
|
pinMode(seqLed[i], OUTPUT);
|
||||||
|
}
|
||||||
|
startupAnimation();
|
||||||
|
|
||||||
|
sampleAverageNoise();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// check for incoming USB MIDI messages
|
||||||
|
usbMIDI.read();
|
||||||
|
|
||||||
|
if (lastInput + inputFreq < millis()) {
|
||||||
|
|
||||||
|
// check user input
|
||||||
|
readPots();
|
||||||
|
readBodyswitches();
|
||||||
|
readButtons();
|
||||||
|
|
||||||
|
// general navigation
|
||||||
|
|
||||||
|
// button 0 pushed
|
||||||
|
if (buttonState[0] == LOW && buttonState[1] == HIGH) {
|
||||||
|
noteInputFromBodyswitches();
|
||||||
|
}
|
||||||
|
|
||||||
|
// button 1 pushed
|
||||||
|
if (buttonState[1] == LOW && buttonState[0] == HIGH) {
|
||||||
|
eraseNotesFromBodyswitches();
|
||||||
|
if (pot1Moved) {
|
||||||
|
// change sequencer speed
|
||||||
|
stepTime = map(analogRead(pot1),1023,0,1000,0);
|
||||||
|
potsMoved = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// both buttons pushed
|
||||||
|
if (buttonState[1] == LOW && buttonState[0] == LOW) {
|
||||||
|
changeMode();
|
||||||
|
activeSeq = mode;
|
||||||
|
if (pot2Moved) {
|
||||||
|
changePreset();
|
||||||
|
potsMoved = false;
|
||||||
|
}
|
||||||
|
if (pot1Moved) {
|
||||||
|
changeOctave();
|
||||||
|
potsMoved = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastInput = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sequencerRunning) updateSequence();
|
||||||
|
if (potsMoved) setCutoffFromPots();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sampleAverageNoise() {
|
||||||
|
Serial.print("sampling average noise levels: ");
|
||||||
|
|
||||||
|
for (int i = 0; i<8; i++) {
|
||||||
|
averageNoise += analogRead(bodySwitch[i]);
|
||||||
|
}
|
||||||
|
averageNoise = averageNoise/8 + 3;
|
||||||
|
Serial.println(averageNoise);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCutoffFromPots() {
|
||||||
|
Music.setCutoff((1023-analogRead(pot1))*64);
|
||||||
|
Music.setCutoffModAmount((1023-analogRead(pot2))*64);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLEDs() {
|
||||||
|
for (int i = 0; i<8; i++) {
|
||||||
|
if (seqNote[activeSeq*8+i] != -1) {
|
||||||
|
digitalWrite(seqLed[i], HIGH);
|
||||||
|
} else {
|
||||||
|
digitalWrite(seqLed[i], LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void newActiveScale (int length) {
|
||||||
|
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;
|
||||||
|
Serial.print("octave ");
|
||||||
|
Serial.print(currentOctave);
|
||||||
|
int currentNote = scale[1][i%amountOfNotesInScale];
|
||||||
|
Serial.print("\tnote ");
|
||||||
|
Serial.print(currentNote);
|
||||||
|
activeScale[i] = currentOctave*12+currentNote;
|
||||||
|
Serial.print("\tthis yields ");
|
||||||
|
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 = analogRead(pot1);
|
||||||
|
int newPotVal2 = 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) {
|
||||||
|
Serial.print("pot 1 ");
|
||||||
|
Serial.println(potVal1);
|
||||||
|
Serial.print("pot 2 ");
|
||||||
|
Serial.println(potVal2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeOctave() {
|
||||||
|
|
||||||
|
// change from pot
|
||||||
|
int newOctave = map(analogRead(pot1),1023,0,-3,4);
|
||||||
|
|
||||||
|
baseNote = 36 + newOctave*12;
|
||||||
|
|
||||||
|
for (int i = 0; i<8; i++) {
|
||||||
|
if (newOctave+3 == i) {
|
||||||
|
// SoftPWMSet(seqLed[i],255);
|
||||||
|
digitalWrite(seqLed[i],HIGH);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// SoftPWMSet(seqLed[i],0);
|
||||||
|
digitalWrite(seqLed[i],LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeMode() {
|
||||||
|
|
||||||
|
// select mode 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) {
|
||||||
|
mode = highest;
|
||||||
|
}
|
||||||
|
updateLEDs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void changePreset() {
|
||||||
|
int newPreset = map(analogRead(pot2),1023,0,63,0);
|
||||||
|
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 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();
|
||||||
|
|
||||||
|
int blinkTime = max(stepTime/5,100);
|
||||||
|
|
||||||
|
if (lastStep + blinkTime < millis()) {
|
||||||
|
digitalWrite(seqLed[seqStep], HIGH);
|
||||||
|
}
|
||||||
|
if (lastStep + stepTime - blinkTime < millis()) {
|
||||||
|
digitalWrite(seqLed[seqStep], LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 debugging purposes
|
||||||
|
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);
|
||||||
|
digitalWrite(statusLed2, 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);
|
||||||
|
digitalWrite(statusLed2, 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
465
examples/CFO_BODYSEQ_3buttons/CFO_BODYSEQ_3buttons.ino
Executable file
465
examples/CFO_BODYSEQ_3buttons/CFO_BODYSEQ_3buttons.ino
Executable file
@ -0,0 +1,465 @@
|
|||||||
|
//______________________/\\\\\__________________________/\\\______________________________/\\\__________________________________________________________
|
||||||
|
// ____________________/\\\///__________________________\/\\\_____________________________\/\\\__________________________________________________________
|
||||||
|
// ___________________/\\\______________________________\/\\\_____________________________\/\\\_____/\\\__/\\\_______________________________/\\\\\\\\___
|
||||||
|
// _____/\\\\\\\\__/\\\\\\\\\_______/\\\\\______________\/\\\____________/\\\\\___________\/\\\____\//\\\/\\\___/\\\\\\\\\\_____/\\\\\\\\___/\\\////\\\__
|
||||||
|
// ___/\\\//////__\////\\\//______/\\\///\\\____________\/\\\\\\\\\____/\\\///\\\____/\\\\\\\\\_____\//\\\\\___\/\\\//////____/\\\/////\\\_\//\\\\\\\\\__
|
||||||
|
// __/\\\____________\/\\\_______/\\\__\//\\\___________\/\\\////\\\__/\\\__\//\\\__/\\\////\\\______\//\\\____\/\\\\\\\\\\__/\\\\\\\\\\\___\///////\\\__
|
||||||
|
// _\//\\\___________\/\\\______\//\\\__/\\\____________\/\\\__\/\\\_\//\\\__/\\\__\/\\\__\/\\\___/\\_/\\\_____\////////\\\_\//\\///////__________\/\\\__
|
||||||
|
// __\///\\\\\\\\____\/\\\_______\///\\\\\/_____________\/\\\\\\\\\___\///\\\\\/___\//\\\\\\\/\\_\//\\\\/_______/\\\\\\\\\\__\//\\\\\\\\\\________\/\\\\_
|
||||||
|
// ____\////////_____\///__________\/////_______________\/////////______\/////______\///////\//___\////________\//////////____\//////////_________\////__
|
||||||
|
// 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};
|
||||||
|
|
||||||
|
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;
|
||||||
|
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 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.setSampler(true);
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.enableEnvelope2();
|
||||||
|
Music.getPreset(21);
|
||||||
|
Music.setEnv1Decay(36);
|
||||||
|
Music.setEnv1Sustain(0);
|
||||||
|
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
|
||||||
|
analogReadAveraging(32);
|
||||||
|
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
delay(100);
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
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
|
||||||
|
stepTime = map(analogRead(pot1),0,1023,1000,0);
|
||||||
|
potsMoved = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// button 2 pushed
|
||||||
|
if (buttonState[2] == LOW) {
|
||||||
|
changeMode();
|
||||||
|
activeSeq = mode;
|
||||||
|
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 (sequenceRunning) updateSequence();
|
||||||
|
if (potsMoved) setCutoffFromPots();
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
digitalWrite(seqLed[i], HIGH);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
digitalWrite(seqLed[i], LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void newActiveScale (int length) {
|
||||||
|
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;
|
||||||
|
Serial.print("octave ");
|
||||||
|
Serial.print(currentOctave);
|
||||||
|
int currentNote = scale[1][i%amountOfNotesInScale];
|
||||||
|
Serial.print("\tnote ");
|
||||||
|
Serial.print(currentNote);
|
||||||
|
activeScale[i] = currentOctave*12+currentNote;
|
||||||
|
Serial.print("\tthis yields ");
|
||||||
|
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) {
|
||||||
|
Serial.print("pot 1 ");
|
||||||
|
Serial.println(potVal1);
|
||||||
|
Serial.print("pot 2 ");
|
||||||
|
Serial.println(potVal2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeOctave() {
|
||||||
|
|
||||||
|
// change from pot
|
||||||
|
int newOctave = map(analogRead(pot1),0,1023,-3,4);
|
||||||
|
|
||||||
|
baseNote = 36 + newOctave*12;
|
||||||
|
|
||||||
|
for (int i = 0; i<8; i++) {
|
||||||
|
if (newOctave+3 == i) {
|
||||||
|
// SoftPWMSet(seqLed[i],255);
|
||||||
|
digitalWrite(seqLed[i],HIGH);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// SoftPWMSet(seqLed[i],0);
|
||||||
|
digitalWrite(seqLed[i],LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeMode() {
|
||||||
|
|
||||||
|
// select mode 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) {
|
||||||
|
mode = highest;
|
||||||
|
}
|
||||||
|
updateLEDs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void changePreset() {
|
||||||
|
int newPreset = map(analogRead(pot2),0,1023,63,0);
|
||||||
|
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 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();
|
||||||
|
|
||||||
|
int blinkTime = max(stepTime/5,100);
|
||||||
|
|
||||||
|
if (lastStep + blinkTime < millis()) {
|
||||||
|
digitalWrite(seqLed[seqStep], HIGH);
|
||||||
|
}
|
||||||
|
if (lastStep + stepTime - blinkTime < millis()) {
|
||||||
|
digitalWrite(seqLed[seqStep], LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
524
examples/CFO_BODYSEQ_3buttons_experimental/CFO_BODYSEQ_3buttons_experimental.ino
Executable file
524
examples/CFO_BODYSEQ_3buttons_experimental/CFO_BODYSEQ_3buttons_experimental.ino
Executable file
@ -0,0 +1,524 @@
|
|||||||
|
//______________________/\\\\\__________________________/\\\______________________________/\\\__________________________________________________________
|
||||||
|
// ____________________/\\\///__________________________\/\\\_____________________________\/\\\__________________________________________________________
|
||||||
|
// ___________________/\\\______________________________\/\\\_____________________________\/\\\_____/\\\__/\\\_______________________________/\\\\\\\\___
|
||||||
|
// _____/\\\\\\\\__/\\\\\\\\\_______/\\\\\______________\/\\\____________/\\\\\___________\/\\\____\//\\\/\\\___/\\\\\\\\\\_____/\\\\\\\\___/\\\////\\\__
|
||||||
|
// ___/\\\//////__\////\\\//______/\\\///\\\____________\/\\\\\\\\\____/\\\///\\\____/\\\\\\\\\_____\//\\\\\___\/\\\//////____/\\\/////\\\_\//\\\\\\\\\__
|
||||||
|
// __/\\\____________\/\\\_______/\\\__\//\\\___________\/\\\////\\\__/\\\__\//\\\__/\\\////\\\______\//\\\____\/\\\\\\\\\\__/\\\\\\\\\\\___\///////\\\__
|
||||||
|
// _\//\\\___________\/\\\______\//\\\__/\\\____________\/\\\__\/\\\_\//\\\__/\\\__\/\\\__\/\\\___/\\_/\\\_____\////////\\\_\//\\///////__________\/\\\__
|
||||||
|
// __\///\\\\\\\\____\/\\\_______\///\\\\\/_____________\/\\\\\\\\\___\///\\\\\/___\//\\\\\\\/\\_\//\\\\/_______/\\\\\\\\\\__\//\\\\\\\\\\________\/\\\\_
|
||||||
|
// ____\////////_____\///__________\/////_______________\/////////______\/////______\///////\//___\////________\//////////____\//////////_________\////__
|
||||||
|
// 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>
|
||||||
|
|
||||||
|
boolean playStep = false;
|
||||||
|
int ticksPerStep = 6;
|
||||||
|
|
||||||
|
const int seqLed [] = {3,4,5,6,7,8,9,10};
|
||||||
|
int seqLedVal [] = {0,0,0,0,0,0,0,0};
|
||||||
|
|
||||||
|
uint8_t ledValue = 0;
|
||||||
|
|
||||||
|
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 sequencerRunning = true;
|
||||||
|
|
||||||
|
float maxBodyReading = 0;
|
||||||
|
float maxBodyFadeout = 0.9999;
|
||||||
|
|
||||||
|
float averageNoise = 0;
|
||||||
|
|
||||||
|
int inputFreq = 10;
|
||||||
|
unsigned long lastInput = millis();
|
||||||
|
|
||||||
|
int seqStep = 0;
|
||||||
|
long seqTick = -1;
|
||||||
|
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;
|
||||||
|
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 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(16);
|
||||||
|
Music.setEnv1Decay(36);
|
||||||
|
Music.setEnv1Sustain(0);
|
||||||
|
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
|
||||||
|
analogReadAveraging(32);
|
||||||
|
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
delay(100);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
Music.setResonance(255);
|
||||||
|
|
||||||
|
startupAnimation();
|
||||||
|
sampleAverageNoise();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// check for incoming USB MIDI messages
|
||||||
|
usbMIDI.read();
|
||||||
|
Midi.checkSerialMidi();
|
||||||
|
if (sequencerRunning) updateSequence();
|
||||||
|
|
||||||
|
// MIDI_SERIAL.write(byte(0xB0 | (MIDI_CHANNEL-1 & 0x0F)));
|
||||||
|
// MIDI_SERIAL.write(0x7F & CFO_LIGHT_LED);
|
||||||
|
// MIDI_SERIAL.write(0x7F & ledValue++);
|
||||||
|
//
|
||||||
|
// if(ledValue > 15) ledValue = 0;
|
||||||
|
|
||||||
|
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
|
||||||
|
stepTime = map(analogRead(pot1),0,1023,1000,0);
|
||||||
|
potsMoved = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// button 2 pushed
|
||||||
|
if (buttonState[2] == LOW) {
|
||||||
|
changeMode();
|
||||||
|
activeSeq = mode;
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
digitalWrite(seqLed[i], HIGH);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
digitalWrite(seqLed[i], LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void newActiveScale (int length) {
|
||||||
|
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;
|
||||||
|
Serial.print("octave ");
|
||||||
|
Serial.print(currentOctave);
|
||||||
|
int currentNote = scale[1][i%amountOfNotesInScale];
|
||||||
|
Serial.print("\tnote ");
|
||||||
|
Serial.print(currentNote);
|
||||||
|
activeScale[i] = currentOctave*12+currentNote;
|
||||||
|
Serial.print("\tthis yields ");
|
||||||
|
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) {
|
||||||
|
Serial.print("pot 1 ");
|
||||||
|
Serial.println(potVal1);
|
||||||
|
Serial.print("pot 2 ");
|
||||||
|
Serial.println(potVal2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeOctave() {
|
||||||
|
|
||||||
|
// change from pot
|
||||||
|
int newOctave = map(analogRead(pot1),0,1023,-3,4);
|
||||||
|
|
||||||
|
baseNote = 36 + newOctave*12;
|
||||||
|
|
||||||
|
for (int i = 0; i<8; i++) {
|
||||||
|
if (newOctave+3 == i) {
|
||||||
|
// SoftPWMSet(seqLed[i],255);
|
||||||
|
digitalWrite(seqLed[i],HIGH);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// SoftPWMSet(seqLed[i],0);
|
||||||
|
digitalWrite(seqLed[i],LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeMode() {
|
||||||
|
|
||||||
|
// select mode 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) {
|
||||||
|
mode = highest;
|
||||||
|
}
|
||||||
|
updateLEDs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void changePreset() {
|
||||||
|
int newPreset = map(analogRead(pot2),0,1023,0,24);
|
||||||
|
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 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]);
|
||||||
|
// Midi.sendNoteOn(baseNote+seqNote[note], 127);
|
||||||
|
// }
|
||||||
|
// lastStep = millis();
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
if(playStep) playNote();
|
||||||
|
updateLEDs();
|
||||||
|
|
||||||
|
// int blinkTime = max(stepTime/5,100);
|
||||||
|
//
|
||||||
|
// if (lastStep + blinkTime < millis()) {
|
||||||
|
// digitalWrite(seqLed[seqStep], HIGH);
|
||||||
|
// }
|
||||||
|
// if (lastStep + stepTime - blinkTime < millis()) {
|
||||||
|
// digitalWrite(seqLed[seqStep], LOW);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RealTimeSystem(byte realtimebyte) {
|
||||||
|
if(realtimebyte == MIDI_CLOCK) {
|
||||||
|
seqTick++;
|
||||||
|
if(seqTick == ticksPerStep) {
|
||||||
|
seqTick = 0;
|
||||||
|
playStep = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(realtimebyte == MIDI_START) {
|
||||||
|
seqTick = 0;
|
||||||
|
seqStep = 0;
|
||||||
|
playStep = true;
|
||||||
|
digitalWrite(13, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(realtimebyte == MIDI_CONTINUE) {
|
||||||
|
playStep = true;
|
||||||
|
digitalWrite(13, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(realtimebyte == MIDI_STOP) {
|
||||||
|
Music.noteOff();
|
||||||
|
digitalWrite(13, LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void playNote() {
|
||||||
|
|
||||||
|
if (seqStep > seqEnd) seqStep = seqStart;
|
||||||
|
|
||||||
|
int note = activeSeq*8+seqStep;
|
||||||
|
|
||||||
|
if (seqNote[note] != -1) {
|
||||||
|
Music.noteOn(baseNote+seqNote[note]);
|
||||||
|
Midi.sendNoteOn(baseNote+seqNote[note], 127);
|
||||||
|
}
|
||||||
|
seqStep++;
|
||||||
|
playStep = false;
|
||||||
|
|
||||||
|
updateLEDs();
|
||||||
|
|
||||||
|
}
|
||||||
539
examples/CFO_BODYSEQ_3buttons_midi_synced/CFO_BODYSEQ_3buttons_midi_synced.ino
Executable file
539
examples/CFO_BODYSEQ_3buttons_midi_synced/CFO_BODYSEQ_3buttons_midi_synced.ino
Executable file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
#define MIDI_CHANNEL 1
|
||||||
|
|
||||||
|
#include <spi4teensy3.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include "CFO_BODYSEQ.h"
|
||||||
|
|
||||||
|
// sequence ID
|
||||||
|
int s1, s2;
|
||||||
|
int _bpm = 120;
|
||||||
|
|
||||||
|
// sequence step index
|
||||||
|
int indx1 = 0;
|
||||||
|
int indx2 = 0;
|
||||||
|
const int nbr_notes1 = 8; // try with 16 :)
|
||||||
|
const int nbr_steps2 = 8;
|
||||||
|
int notes1[] = {12, 24, 7, 12, 36, 12, 24, 15, 0, 12, 48, 36, 19, 24, 3, 36};
|
||||||
|
//int notes1[] = {36, 48, 31, 36, 60, 36, 48, 39, 24, 36, 72, 60, 43, 48, 27, 60};
|
||||||
|
int notes2[] = {0, 2, 3, 5, 6, 8, 10, 12};
|
||||||
|
int vels[] = {100, 72, 96, 64, 112, 88, 78, 96};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||||
|
Music.init();
|
||||||
|
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.enableEnvelope2();
|
||||||
|
Music.getPreset(13);
|
||||||
|
|
||||||
|
// These guys just have to be here...
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
|
||||||
|
Sequencer.init(_bpm);
|
||||||
|
|
||||||
|
s1 = Sequencer.newSequence(NOTE_16, 16, LOOP);
|
||||||
|
Sequencer.startSequence(s1);
|
||||||
|
Sequencer.insertNotes(s1, notes1, 16, 0);
|
||||||
|
Sequencer.insertNotes(s1, vels, 7, 8);
|
||||||
|
Sequencer.insertNotes(s1, vels, 3, 2);
|
||||||
|
Sequencer.setInternal(s1, true);
|
||||||
|
Sequencer.setExternal(s1, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Checking for incoming MIDI to use dashboard
|
||||||
|
Sequencer.update();
|
||||||
|
usbMIDI.read();
|
||||||
|
Midi.checkSerialMidi();
|
||||||
|
checkBPM();
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkBPM() {
|
||||||
|
// int bpm = analogRead(A0)>>2;
|
||||||
|
int bpm = 124;
|
||||||
|
if(bpm != _bpm) {
|
||||||
|
_bpm = bpm;
|
||||||
|
Serial.println(_bpm);
|
||||||
|
Sequencer.setbpm(_bpm);
|
||||||
|
if(_bpm == 0) {
|
||||||
|
Midi.setMidiIn(false);
|
||||||
|
Midi.setMidiThru(true);
|
||||||
|
Midi.setMidiOut(false);
|
||||||
|
Midi.setMidiClockIn(true);
|
||||||
|
Midi.setMidiClockThru(true);
|
||||||
|
Midi.setMidiClockOut(false);
|
||||||
|
Sequencer.setInternalClock(false);
|
||||||
|
} else {
|
||||||
|
Midi.setMidiIn(false);
|
||||||
|
Midi.setMidiThru(false);
|
||||||
|
Midi.setMidiOut(true);
|
||||||
|
Midi.setMidiClockIn(false);
|
||||||
|
Midi.setMidiClockThru(false);
|
||||||
|
Midi.setMidiClockOut(true);
|
||||||
|
Sequencer.setInternalClock(true);
|
||||||
|
// Sequencer.sequencerContinue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
234
examples/CFO_BODYSEQ_O/CFO_BODYSEQ_O.ino
Executable file
234
examples/CFO_BODYSEQ_O/CFO_BODYSEQ_O.ino
Executable file
@ -0,0 +1,234 @@
|
|||||||
|
//______________________/\\\\\__________________________/\\\______________________________/\\\__________________________________________________________
|
||||||
|
// ____________________/\\\///__________________________\/\\\_____________________________\/\\\__________________________________________________________
|
||||||
|
// ___________________/\\\______________________________\/\\\_____________________________\/\\\_____/\\\__/\\\_______________________________/\\\\\\\\___
|
||||||
|
// _____/\\\\\\\\__/\\\\\\\\\_______/\\\\\______________\/\\\____________/\\\\\___________\/\\\____\//\\\/\\\___/\\\\\\\\\\_____/\\\\\\\\___/\\\////\\\__
|
||||||
|
// ___/\\\//////__\////\\\//______/\\\///\\\____________\/\\\\\\\\\____/\\\///\\\____/\\\\\\\\\_____\//\\\\\___\/\\\//////____/\\\/////\\\_\//\\\\\\\\\__
|
||||||
|
// __/\\\____________\/\\\_______/\\\__\//\\\___________\/\\\////\\\__/\\\__\//\\\__/\\\////\\\______\//\\\____\/\\\\\\\\\\__/\\\\\\\\\\\___\///////\\\__
|
||||||
|
// _\//\\\___________\/\\\______\//\\\__/\\\____________\/\\\__\/\\\_\//\\\__/\\\__\/\\\__\/\\\___/\\_/\\\_____\////////\\\_\//\\///////__________\/\\\__
|
||||||
|
// __\///\\\\\\\\____\/\\\_______\///\\\\\/_____________\/\\\\\\\\\___\///\\\\\/___\//\\\\\\\/\\_\//\\\\/_______/\\\\\\\\\\__\//\\\\\\\\\\________\/\\\\_
|
||||||
|
// ____\////////_____\///__________\/////_______________\/////////______\/////______\///////\//___\////________\//////////____\//////////_________\////__
|
||||||
|
// 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>
|
||||||
|
|
||||||
|
#define NUM_TRACKS 8
|
||||||
|
#define NUM_STEPS 8
|
||||||
|
#define NUM_LEDS 8
|
||||||
|
|
||||||
|
int mode;
|
||||||
|
|
||||||
|
int track[8];
|
||||||
|
int debounceTime = 40;
|
||||||
|
|
||||||
|
int _bpm;
|
||||||
|
|
||||||
|
const int scale[] = {0, 2, 3, 5, 7, 8, 10, 12};
|
||||||
|
//const int octave[] = {-24, -12, 0, 12, 24};
|
||||||
|
int rootNote = 36;
|
||||||
|
|
||||||
|
int trackPlaying = 0 ;
|
||||||
|
int trackSelected = 0;
|
||||||
|
int stepSelected = 0;
|
||||||
|
int noteSelected = 0;
|
||||||
|
int oct = 0;
|
||||||
|
|
||||||
|
int notes[64];
|
||||||
|
int octave[64];
|
||||||
|
int noteValues[8];
|
||||||
|
|
||||||
|
int leds;
|
||||||
|
int note;
|
||||||
|
|
||||||
|
//int var = 0;
|
||||||
|
//const int pot1 = A0, pot2 = A1;
|
||||||
|
|
||||||
|
// old stuff
|
||||||
|
const int seqLed[] = {3,4,5,6,7,8,9,10};
|
||||||
|
const int statusLed1 = 13;
|
||||||
|
//boolean debug = true;
|
||||||
|
|
||||||
|
|
||||||
|
/////////////
|
||||||
|
// BUTTONS //
|
||||||
|
/////////////
|
||||||
|
#define NUM_BUTTONS 8
|
||||||
|
const int buttonPin [] = {11,12,2};
|
||||||
|
int buttonIndex = 0;
|
||||||
|
int buttonRead = 0;
|
||||||
|
int buttonChange = 0;
|
||||||
|
int buttonState[] = {0, 0, 0};
|
||||||
|
unsigned long buttonNow = 0;
|
||||||
|
unsigned long buttonTime[] = {0, 0, 0};
|
||||||
|
int machineState = 0;
|
||||||
|
|
||||||
|
//////////
|
||||||
|
// KEYS //
|
||||||
|
//////////
|
||||||
|
#define NUM_KEYS 8
|
||||||
|
#define KEY_THRESHOLD 15
|
||||||
|
const int keyPin[] = {A2,A3,A4,A5,A6,A7,A8,A9};
|
||||||
|
int keyIndex = 0;
|
||||||
|
int keyRead = 0;
|
||||||
|
int keyValue = 0;
|
||||||
|
int keyChange = 0;
|
||||||
|
int keyState[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
unsigned long keyNow = 0;
|
||||||
|
unsigned long keyTime[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
int keys;
|
||||||
|
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Music.init();
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.enableEnvelope2();
|
||||||
|
Music.getPreset(21);
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
analogReadAveraging(32);
|
||||||
|
delay(2000);
|
||||||
|
Sequencer.init(120);
|
||||||
|
setupSequences();
|
||||||
|
initInterface();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
Sequencer.update();
|
||||||
|
usbMIDI.read();
|
||||||
|
Midi.checkSerialMidi();
|
||||||
|
readButtons();
|
||||||
|
readKeys();
|
||||||
|
checkBPM();
|
||||||
|
Music.setCutoffModAmount((analogRead(A1))*64);
|
||||||
|
|
||||||
|
// if(buttonChange || keyChange) {
|
||||||
|
switch(machineState) {
|
||||||
|
case 0:
|
||||||
|
playTrack();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
selectNote();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
selectStep();
|
||||||
|
break;
|
||||||
|
case 3: // nothing
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
selectTrack();
|
||||||
|
break;
|
||||||
|
case 5: // nothing
|
||||||
|
break;
|
||||||
|
case 6: // nothing
|
||||||
|
break;
|
||||||
|
case 7: // nothing
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
updateLEDs();
|
||||||
|
// buttonChange = 0;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void playTrack() {
|
||||||
|
if(keyChange) {
|
||||||
|
Serial.println("PLAY TRACK");
|
||||||
|
// code here
|
||||||
|
keyChange = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void selectNote() {
|
||||||
|
noteSelected = notes[stepSelected + 8 * trackSelected];
|
||||||
|
oct = octave[stepSelected + 8 * trackSelected];
|
||||||
|
if(keyChange) {
|
||||||
|
for(int i = 0; i < NUM_KEYS-1; i++) {
|
||||||
|
if(keys & (1 << i)) noteSelected = i;
|
||||||
|
notes[stepSelected + 8 * trackSelected] = noteSelected;
|
||||||
|
}
|
||||||
|
if(keys & (1 << 7)) {
|
||||||
|
oct ^= 1;
|
||||||
|
octave[stepSelected + 8 * trackSelected] = oct;
|
||||||
|
}
|
||||||
|
for(int i = 0; i < NUM_STEPS; i++) {
|
||||||
|
noteValues[i] = rootNote + scale[notes[8 * trackSelected + i]] + octave[i + 8 * trackSelected] * 12;
|
||||||
|
Sequencer.insertNotes(track[trackSelected], noteValues, 8, 0);
|
||||||
|
}
|
||||||
|
keyChange = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void selectStep() {
|
||||||
|
if(keyChange) {
|
||||||
|
Serial.println("SELECT STEP");
|
||||||
|
for(int i = 0; i < NUM_KEYS; i++) {
|
||||||
|
// code here
|
||||||
|
if(keys & (1 << i)) {
|
||||||
|
stepSelected = i;
|
||||||
|
Serial.print("Step selected: ");
|
||||||
|
Serial.println(stepSelected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keyChange = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void selectTrack() {
|
||||||
|
// if(keys > 0) {
|
||||||
|
if(keyChange) {
|
||||||
|
Serial.println("SELECT TRACK");
|
||||||
|
for(int i = 0; i < NUM_KEYS; i++) {
|
||||||
|
// Serial.print("Rechecking sequence on position ");
|
||||||
|
// Serial.print(i);
|
||||||
|
// Serial.print(". It is set to sequence index ");
|
||||||
|
// Serial.println(track[i]);
|
||||||
|
Sequencer.setInternal(track[i], false);
|
||||||
|
if(keys & (1 << i)) {
|
||||||
|
trackSelected = i;
|
||||||
|
Serial.print("trackSelected shows ");
|
||||||
|
Serial.print(trackSelected);
|
||||||
|
Serial.print(" - Track selected: ");
|
||||||
|
Serial.println(track[trackSelected]);
|
||||||
|
}
|
||||||
|
Sequencer.setInternal(track[trackSelected], true);
|
||||||
|
}
|
||||||
|
keyChange = 0;
|
||||||
|
}
|
||||||
|
// code here
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setupSequences() {
|
||||||
|
for(int i = 0; i < NUM_TRACKS; i++) {
|
||||||
|
for(int j = 0; j < NUM_STEPS; j++) {
|
||||||
|
notes[8*i + j] = j;
|
||||||
|
}
|
||||||
|
track[i] = Sequencer.newSequence(NOTE_16, 8, LOOP);
|
||||||
|
Serial.print("Track created for sequence ");
|
||||||
|
Serial.print(track[i]);
|
||||||
|
Serial.print(" on position ");
|
||||||
|
Serial.println(i);
|
||||||
|
Sequencer.startSequence(track[i]);
|
||||||
|
for(int j = 0; j < NUM_STEPS; j++) {
|
||||||
|
noteValues[j] = rootNote + scale[notes[8 * i + j]] + octave[8 * i + j] * 12;
|
||||||
|
}
|
||||||
|
Sequencer.insertNotes(track[i], noteValues, 8, 0);
|
||||||
|
Sequencer.setInternal(track[i], true);
|
||||||
|
Sequencer.setExternal(track[i], false);
|
||||||
|
Serial.print("Internal set to ");
|
||||||
|
Serial.println(Sequencer.getInternal(track[i]));
|
||||||
|
}
|
||||||
|
for(int i = 0; i < NUM_TRACKS; i++) {
|
||||||
|
Serial.print("Rechecking sequence on position ");
|
||||||
|
Serial.print(i);
|
||||||
|
Serial.print(" - set to sequence index ");
|
||||||
|
Serial.println(track[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
157
examples/CFO_BODYSEQ_O/interface.ino
Executable file
157
examples/CFO_BODYSEQ_O/interface.ino
Executable file
@ -0,0 +1,157 @@
|
|||||||
|
/////////////
|
||||||
|
// BUTTONS //
|
||||||
|
/////////////
|
||||||
|
void readButtons() {
|
||||||
|
// buttons are active low
|
||||||
|
for(int i = 0; i < NUM_BUTTONS; i++) {
|
||||||
|
// int i = buttonIndex++;
|
||||||
|
// if(buttonIndex >= NUM_BUTTONS) buttonIndex = 0;
|
||||||
|
buttonNow = millis();
|
||||||
|
if((buttonNow - buttonTime[i]) > debounceTime) {
|
||||||
|
buttonRead = digitalRead(buttonPin[i]);
|
||||||
|
if(buttonRead != buttonState[i]) {
|
||||||
|
buttonState[i] = buttonRead;
|
||||||
|
buttonChange |= 1<<i;
|
||||||
|
buttonTime[i] = buttonNow;
|
||||||
|
machineState = 7 - buttonState[0] - buttonState[1] * 2 - buttonState[2] * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////
|
||||||
|
// KEYS //
|
||||||
|
//////////
|
||||||
|
void readKeys() {
|
||||||
|
for (int i = 0; i < NUM_KEYS; i++) {
|
||||||
|
// int i = keyIndex++;
|
||||||
|
// if(keyIndex >= NUM_KEYS) keyIndex = 0;
|
||||||
|
keyNow = millis();
|
||||||
|
if((keyNow - keyTime[i]) > debounceTime) {
|
||||||
|
keyRead = analogRead(keyPin[i]);
|
||||||
|
// if(i==4) Serial.println(keyRead);
|
||||||
|
if(keyRead > KEY_THRESHOLD) {
|
||||||
|
keyValue = 1;
|
||||||
|
} else {
|
||||||
|
keyValue = 0;
|
||||||
|
}
|
||||||
|
// keyValue = (keyRead > KEY_THRESHOLD) ? 1 : 0 ;
|
||||||
|
if(keyValue != keyState[i]) {
|
||||||
|
keyState[i] = keyValue;
|
||||||
|
keyChange |= 1<<i;
|
||||||
|
keyTime[i] = keyNow;
|
||||||
|
}
|
||||||
|
if(keyState[i]) {
|
||||||
|
keys |= 1<<i;
|
||||||
|
} else {
|
||||||
|
keys &= ~(1<<i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////
|
||||||
|
// POTS //
|
||||||
|
//////////
|
||||||
|
void checkBPM() {
|
||||||
|
int bpm = analogRead(A0)>>2;
|
||||||
|
if(bpm != _bpm) {
|
||||||
|
_bpm = bpm;
|
||||||
|
Serial.print("BPM set to ");
|
||||||
|
Serial.println(_bpm);
|
||||||
|
Sequencer.setbpm(_bpm);
|
||||||
|
if(_bpm == 0) {
|
||||||
|
Midi.setMidiIn(true);
|
||||||
|
Midi.setMidiThru(true);
|
||||||
|
Midi.setMidiOut(true);
|
||||||
|
Midi.setMidiClockIn(true);
|
||||||
|
Midi.setMidiClockThru(true);
|
||||||
|
Midi.setMidiClockOut(true);
|
||||||
|
Sequencer.setInternalClock(false);
|
||||||
|
} else {
|
||||||
|
Midi.setMidiIn(false);
|
||||||
|
Midi.setMidiThru(false);
|
||||||
|
Midi.setMidiOut(false);
|
||||||
|
Midi.setMidiClockIn(false);
|
||||||
|
Midi.setMidiClockThru(false);
|
||||||
|
Midi.setMidiClockOut(false);
|
||||||
|
Sequencer.setInternalClock(true);
|
||||||
|
// Sequencer.sequencerContinue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void initInterface() {
|
||||||
|
pinMode(buttonPin[0], INPUT_PULLUP);
|
||||||
|
pinMode(buttonPin[1], INPUT_PULLUP);
|
||||||
|
pinMode(buttonPin[2], INPUT_PULLUP);
|
||||||
|
pinMode(statusLed1,OUTPUT);
|
||||||
|
for (int i = 0; i<8; i++) {
|
||||||
|
pinMode(seqLed[i], OUTPUT);
|
||||||
|
}
|
||||||
|
startupAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void updateLEDs() {
|
||||||
|
switch(machineState) {
|
||||||
|
case 0:
|
||||||
|
leds = 0 | (1 << trackSelected);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
leds = 0 | (1 << noteSelected);
|
||||||
|
leds = leds | (octave[stepSelected + 8 * trackSelected] << 7);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
leds = 0 | (1 << stepSelected);
|
||||||
|
break;
|
||||||
|
case 3: // nothing
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
leds = 0 | (1 << trackSelected);
|
||||||
|
break;
|
||||||
|
case 5: // nothing
|
||||||
|
break;
|
||||||
|
case 6: // nothing
|
||||||
|
break;
|
||||||
|
case 7: // nothing
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (int i = 0; i<8; i++) {
|
||||||
|
digitalWrite(seqLed[i], leds & (1 << i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
110
examples/CFO_BODYSEQ_P/CFO_BODYSEQ_P.ino
Executable file
110
examples/CFO_BODYSEQ_P/CFO_BODYSEQ_P.ino
Executable file
@ -0,0 +1,110 @@
|
|||||||
|
#define MIDI_CHANNEL 1
|
||||||
|
|
||||||
|
#include <spi4teensy3.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <CFO_BODYSEQ.h>
|
||||||
|
|
||||||
|
// sequence ID
|
||||||
|
int s1, s2;
|
||||||
|
int _bpm, _eend, _beegin;
|
||||||
|
|
||||||
|
// sequence step index
|
||||||
|
int indx1 = 0;
|
||||||
|
int indx2 = 0;
|
||||||
|
const int nbr_notes1 = 8; // try with 16 :)
|
||||||
|
const int nbr_steps2 = 8;
|
||||||
|
//int notes1[] = {12, 24, 7, 12, 36, 12, 24, 15, 0, 12, 48, 36, 19, 24, 3, 36};
|
||||||
|
int notes1[] = {36, 48, 31, 36, 60, 36, 48, 39, 24, 36, 72, 60, 43, 48, 27, 60};
|
||||||
|
int notes2[] = {0, 2, 3, 5, 6, 8, 10, 12};
|
||||||
|
int vels[] = {100, 72, 96, 64, 112, 88, 78, 96};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||||
|
Music.init();
|
||||||
|
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.enableEnvelope2();
|
||||||
|
Music.getPreset(13);
|
||||||
|
|
||||||
|
// These guys just have to be here...
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
|
||||||
|
analogReadAveraging(32);
|
||||||
|
|
||||||
|
Sequencer.init(120);
|
||||||
|
|
||||||
|
// s1 = Sequencer.newSequence(NOTE_16, 16, LOOP, !REVERSE); // overloaded function
|
||||||
|
s1 = Sequencer.newSequence(NOTE_16, 16, LOOP);
|
||||||
|
Sequencer.startSequence(s1);
|
||||||
|
Sequencer.insertNotes(s1, notes1, 16, 0);
|
||||||
|
// Sequencer.insertNotes(s1, vels, 7, 8);
|
||||||
|
// Sequencer.insertNotes(s1, vels, 3, 2);
|
||||||
|
Sequencer.setInternal(s1, true);
|
||||||
|
Sequencer.setExternal(s1, false);
|
||||||
|
Midi.setMidiIn(true);
|
||||||
|
Midi.setMidiThru(true);
|
||||||
|
Midi.setMidiOut(true);
|
||||||
|
Midi.setMidiClockIn(true);
|
||||||
|
Midi.setMidiClockThru(true);
|
||||||
|
Midi.setMidiClockOut(true);
|
||||||
|
Sequencer.setInternalClock(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Checking for incoming MIDI to use dashboard
|
||||||
|
Sequencer.update();
|
||||||
|
usbMIDI.read();
|
||||||
|
Midi.checkSerialMidi();
|
||||||
|
// checkBPM();
|
||||||
|
// checkBeegin();
|
||||||
|
// checkEend();
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkBPM() {
|
||||||
|
int bpm = analogRead(A0)>>2;
|
||||||
|
if(bpm != _bpm) {
|
||||||
|
_bpm = bpm;
|
||||||
|
Serial.println(_bpm);
|
||||||
|
Sequencer.setbpm(_bpm);
|
||||||
|
if(_bpm == 0) {
|
||||||
|
Midi.setMidiIn(true);
|
||||||
|
Midi.setMidiThru(true);
|
||||||
|
Midi.setMidiOut(true);
|
||||||
|
Midi.setMidiClockIn(true);
|
||||||
|
Midi.setMidiClockThru(true);
|
||||||
|
Midi.setMidiClockOut(true);
|
||||||
|
Sequencer.setInternalClock(false);
|
||||||
|
} else {
|
||||||
|
Midi.setMidiIn(false);
|
||||||
|
Midi.setMidiThru(false);
|
||||||
|
Midi.setMidiOut(false);
|
||||||
|
Midi.setMidiClockIn(false);
|
||||||
|
Midi.setMidiClockThru(false);
|
||||||
|
Midi.setMidiClockOut(false);
|
||||||
|
Sequencer.setInternalClock(true);
|
||||||
|
// Sequencer.sequencerContinue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void checkBeegin() {
|
||||||
|
int beegin = analogRead(A0)>>6;
|
||||||
|
if(beegin != _beegin) {
|
||||||
|
_beegin = beegin;
|
||||||
|
Sequencer.setBegin(s1, _beegin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkEend() {
|
||||||
|
int eend = analogRead(A1)>>6;
|
||||||
|
if(eend != _eend) {
|
||||||
|
_eend = eend;
|
||||||
|
Sequencer.setEnd(s1, _eend);
|
||||||
|
}
|
||||||
|
}
|
||||||
103
examples/CFO_BODYSEQ_Q/CFO_BODYSEQ_Q.ino
Executable file
103
examples/CFO_BODYSEQ_Q/CFO_BODYSEQ_Q.ino
Executable file
@ -0,0 +1,103 @@
|
|||||||
|
#define MIDI_CHANNEL 1
|
||||||
|
|
||||||
|
#include <spi4teensy3.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <CFO_BODYSEQ.h>
|
||||||
|
|
||||||
|
// sequence ID
|
||||||
|
int s1, s2;
|
||||||
|
int _bpm, _eend, _beegin;
|
||||||
|
|
||||||
|
// sequence step index
|
||||||
|
int indx1 = 0;
|
||||||
|
int indx2 = 0;
|
||||||
|
const int nbr_notes1 = 8; // try with 16 :)
|
||||||
|
const int nbr_steps2 = 8;
|
||||||
|
//int notes1[] = {12, 24, 7, 12, 36, 12, 24, 15, 0, 12, 48, 36, 19, 24, 3, 36};
|
||||||
|
int notes1[] = {36, 48, 31, 36, 60, 36, 48, 39, 24, 36, 72, 60, 43, 48, 27, 60};
|
||||||
|
int notes2[] = {0, 2, 3, 5, 6, 8, 10, 12};
|
||||||
|
int vels[] = {100, 72, 96, 64, 112, 88, 78, 96};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||||
|
Music.init();
|
||||||
|
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.enableEnvelope2();
|
||||||
|
Music.getPreset(21);
|
||||||
|
|
||||||
|
// These guys just have to be here...
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
|
||||||
|
analogReadAveraging(32);
|
||||||
|
|
||||||
|
Sequencer.init(120);
|
||||||
|
|
||||||
|
// s1 = Sequencer.newSequence(NOTE_16, 16, LOOP, !REVERSE); // overloaded function
|
||||||
|
s1 = Sequencer.newSequence(NOTE_16, 16, LOOP);
|
||||||
|
Sequencer.startSequence(s1);
|
||||||
|
Sequencer.insertNotes(s1, notes1, 16, 0);
|
||||||
|
Sequencer.insertNotes(s1, vels, 7, 8);
|
||||||
|
Sequencer.insertNotes(s1, vels, 3, 2);
|
||||||
|
Sequencer.setInternal(s1, true);
|
||||||
|
Sequencer.setExternal(s1, false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Checking for incoming MIDI to use dashboard
|
||||||
|
Sequencer.update();
|
||||||
|
usbMIDI.read();
|
||||||
|
Midi.checkSerialMidi();
|
||||||
|
checkBPM();
|
||||||
|
// checkBeegin();
|
||||||
|
checkEend();
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkBPM() {
|
||||||
|
int bpm = analogRead(A0)>>2;
|
||||||
|
if(bpm != _bpm) {
|
||||||
|
_bpm = bpm;
|
||||||
|
Serial.println(_bpm);
|
||||||
|
Sequencer.setbpm(_bpm);
|
||||||
|
if(_bpm == 0) {
|
||||||
|
Midi.setMidiIn(true);
|
||||||
|
Midi.setMidiThru(true);
|
||||||
|
Midi.setMidiOut(true);
|
||||||
|
Midi.setMidiClockIn(true);
|
||||||
|
Midi.setMidiClockThru(true);
|
||||||
|
Midi.setMidiClockOut(true);
|
||||||
|
Sequencer.setInternalClock(false);
|
||||||
|
} else {
|
||||||
|
Midi.setMidiIn(false);
|
||||||
|
Midi.setMidiThru(false);
|
||||||
|
Midi.setMidiOut(false);
|
||||||
|
Midi.setMidiClockIn(false);
|
||||||
|
Midi.setMidiClockThru(false);
|
||||||
|
Midi.setMidiClockOut(false);
|
||||||
|
Sequencer.setInternalClock(true);
|
||||||
|
// Sequencer.sequencerContinue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void checkBeegin() {
|
||||||
|
int beegin = analogRead(A0)>>6;
|
||||||
|
if(beegin != _beegin) {
|
||||||
|
_beegin = beegin;
|
||||||
|
Sequencer.setBegin(s1, _beegin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkEend() {
|
||||||
|
int eend = analogRead(A1)>>6;
|
||||||
|
if(eend != _eend) {
|
||||||
|
_eend = eend;
|
||||||
|
Sequencer.setEnd(s1, _eend);
|
||||||
|
}
|
||||||
|
}
|
||||||
286
examples/CFO_BODYSEQ_SAMPLER/CFO_BODYSEQ_SAMPLER.ino
Executable file
286
examples/CFO_BODYSEQ_SAMPLER/CFO_BODYSEQ_SAMPLER.ino
Executable file
@ -0,0 +1,286 @@
|
|||||||
|
//______________________/\\\\\__________________________/\\\______________________________/\\\__________________________________________________________
|
||||||
|
// ____________________/\\\///__________________________\/\\\_____________________________\/\\\__________________________________________________________
|
||||||
|
// ___________________/\\\______________________________\/\\\_____________________________\/\\\_____/\\\__/\\\_______________________________/\\\\\\\\___
|
||||||
|
// _____/\\\\\\\\__/\\\\\\\\\_______/\\\\\______________\/\\\____________/\\\\\___________\/\\\____\//\\\/\\\___/\\\\\\\\\\_____/\\\\\\\\___/\\\////\\\__
|
||||||
|
// ___/\\\//////__\////\\\//______/\\\///\\\____________\/\\\\\\\\\____/\\\///\\\____/\\\\\\\\\_____\//\\\\\___\/\\\//////____/\\\/////\\\_\//\\\\\\\\\__
|
||||||
|
// __/\\\____________\/\\\_______/\\\__\//\\\___________\/\\\////\\\__/\\\__\//\\\__/\\\////\\\______\//\\\____\/\\\\\\\\\\__/\\\\\\\\\\\___\///////\\\__
|
||||||
|
// _\//\\\___________\/\\\______\//\\\__/\\\____________\/\\\__\/\\\_\//\\\__/\\\__\/\\\__\/\\\___/\\_/\\\_____\////////\\\_\//\\///////__________\/\\\__
|
||||||
|
// __\///\\\\\\\\____\/\\\_______\///\\\\\/_____________\/\\\\\\\\\___\///\\\\\/___\//\\\\\\\/\\_\//\\\\/_______/\\\\\\\\\\__\//\\\\\\\\\\________\/\\\\_
|
||||||
|
// ____\////////_____\///__________\/////_______________\/////////______\/////______\///////\//___\////________\//////////____\//////////_________\////__
|
||||||
|
// 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>
|
||||||
|
|
||||||
|
#define NUM_TRACKS 8
|
||||||
|
#define NUM_STEPS 8
|
||||||
|
#define NUM_SAMPLES 8
|
||||||
|
#define NUM_LEDS 8
|
||||||
|
|
||||||
|
int mode;
|
||||||
|
unsigned long debounceTime = 100;
|
||||||
|
unsigned long debounceTimeDefault = 100;
|
||||||
|
unsigned long debounceTimeLong = 500;
|
||||||
|
|
||||||
|
int _bpm;
|
||||||
|
|
||||||
|
int trackPlaying = 0 ;
|
||||||
|
int trackSelected = 0;
|
||||||
|
int sampleSelected = 0;
|
||||||
|
int stepSelected = 0;
|
||||||
|
int trackChained = -1;
|
||||||
|
|
||||||
|
int s1;
|
||||||
|
int indx = 0;
|
||||||
|
int indxLED;
|
||||||
|
uint8_t sample[NUM_TRACKS][NUM_SAMPLES][NUM_STEPS];
|
||||||
|
|
||||||
|
int leds;
|
||||||
|
int chainedLedState = 0;
|
||||||
|
unsigned long ledNow;
|
||||||
|
unsigned long ledTime = 0;
|
||||||
|
unsigned long ledPulse = 100;
|
||||||
|
|
||||||
|
bool inStartupMode = true;
|
||||||
|
|
||||||
|
|
||||||
|
// old stuff
|
||||||
|
const int seqLed[] = {3,4,5,6,7,8,9,10};
|
||||||
|
const int statusLed1 = 13;
|
||||||
|
//boolean debug = true;
|
||||||
|
|
||||||
|
/////////////
|
||||||
|
// BUTTONS //
|
||||||
|
/////////////
|
||||||
|
#define NUM_BUTTONS 3
|
||||||
|
const int buttonPin [] = {11,12,2};
|
||||||
|
int buttonIndex = 0;
|
||||||
|
int buttonRead = 0;
|
||||||
|
int buttonChange = 0;
|
||||||
|
int buttonState[] = {0, 0, 0};
|
||||||
|
unsigned long buttonNow = 0;
|
||||||
|
unsigned long buttonTime[] = {0, 0, 0};
|
||||||
|
int machineState = 0;
|
||||||
|
|
||||||
|
//////////
|
||||||
|
// KEYS //
|
||||||
|
//////////
|
||||||
|
#define NUM_KEYS 8
|
||||||
|
#define KEY_THRESHOLD 15
|
||||||
|
const int keyPin[] = {A2,A3,A4,A5,A6,A7,A8,A9};
|
||||||
|
int keyIndex = 0;
|
||||||
|
int keyRead = 0;
|
||||||
|
int keyValue = 0;
|
||||||
|
int keyChange = 0;
|
||||||
|
int keyState[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
unsigned long keyNow = 0;
|
||||||
|
unsigned long keyTime[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
int keys;
|
||||||
|
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Music.init();
|
||||||
|
Music.setSampler(true);
|
||||||
|
Music.setSynth(false);
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
analogReadAveraging(32);
|
||||||
|
Sequencer.init(120);
|
||||||
|
// Sequencer.setInternalClock(true);
|
||||||
|
s1 = Sequencer.newSequence(NOTE_16, &s1cb);
|
||||||
|
// resetMemory();
|
||||||
|
loadSequences();
|
||||||
|
initInterface();
|
||||||
|
Sequencer.startSequence(s1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
Sequencer.update();
|
||||||
|
usbMIDI.read();
|
||||||
|
Midi.checkSerialMidi();
|
||||||
|
readButtons();
|
||||||
|
readKeys();
|
||||||
|
checkBPM();
|
||||||
|
checkBitcrush();
|
||||||
|
|
||||||
|
switch(machineState) {
|
||||||
|
case 0:
|
||||||
|
playTrack();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
selectStep();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
selectSample();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
selectTrack();
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
selectTrack();
|
||||||
|
break;
|
||||||
|
case 5: // nothing
|
||||||
|
chainTrack();
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
copyTrack();
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
clearTrack();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
updateLEDs();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void playTrack() {
|
||||||
|
if(keyChange && keys) {
|
||||||
|
Serial.println("PLAY TRACK");
|
||||||
|
for(int i = 0; i < NUM_KEYS; i++) {
|
||||||
|
if(keys & (1 << i)) {
|
||||||
|
if(trackPlaying == i) trackChained = -1;
|
||||||
|
if(trackChained < 0) trackPlaying = i;
|
||||||
|
else trackChained = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keyChange = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void selectStep() {
|
||||||
|
if(keyChange) {
|
||||||
|
Serial.println("SELECT STEP");
|
||||||
|
for(int k = 0; k < NUM_KEYS; k++) {
|
||||||
|
if(keys & (1 << k)) {
|
||||||
|
stepSelected = k;
|
||||||
|
int j = sampleSelected;
|
||||||
|
int i = trackSelected;
|
||||||
|
sample[i][j][k] ^= 1;
|
||||||
|
EEPROM.write(k + NUM_SAMPLES * (j + i * NUM_TRACKS), sample[i][j][k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keyChange = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void selectSample() {
|
||||||
|
if(keyChange) {
|
||||||
|
Serial.println("SELECT SAMPLE");
|
||||||
|
for(int i = 0; i < NUM_KEYS; i++) {
|
||||||
|
if(keys & (1 << i)) {
|
||||||
|
sampleSelected = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keyChange = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void selectTrack() {
|
||||||
|
if(keyChange) {
|
||||||
|
Serial.println("SELECT TRACK");
|
||||||
|
for(int i = 0; i < NUM_KEYS; i++) {
|
||||||
|
if(keys & (1 << i)) {
|
||||||
|
trackSelected = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keyChange = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void chainTrack() {
|
||||||
|
if(keyChange) {
|
||||||
|
Serial.println("SELECT TRACK");
|
||||||
|
for(int i = 0; i < NUM_KEYS; i++) {
|
||||||
|
if(keys & (1 << i)) {
|
||||||
|
if(i == trackChained) trackChained = -1;
|
||||||
|
else trackChained = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keyChange = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyTrack() {
|
||||||
|
if(keyChange) {
|
||||||
|
debounceTime = debounceTimeLong;
|
||||||
|
Serial.println("COPY TRACK");
|
||||||
|
for(int i = 0; i < NUM_KEYS; i++) {
|
||||||
|
if(keys & (1 << i)) {
|
||||||
|
for(int j=0; j<NUM_SAMPLES; j++) {
|
||||||
|
for(int k=0; k<NUM_STEPS; k++) {
|
||||||
|
sample[i][j][k] = sample[trackSelected][j][k];
|
||||||
|
EEPROM.write(k + NUM_SAMPLES * (j + i * NUM_TRACKS), sample[i][j][k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keyChange = 0;
|
||||||
|
debounceTime = debounceTimeDefault;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearTrack() {
|
||||||
|
if(keyChange) {
|
||||||
|
Serial.println("CLEAR TRACK");
|
||||||
|
for(int i = 0; i < NUM_KEYS; i++) {
|
||||||
|
if(keys & (1 << i)) {
|
||||||
|
for(int j=0; j<NUM_SAMPLES; j++) {
|
||||||
|
for(int k=0; k<NUM_STEPS; k++) {
|
||||||
|
sample[i][j][k] = 0;
|
||||||
|
EEPROM.write(k + NUM_SAMPLES * (j + i * NUM_TRACKS), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keyChange = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void resetMemory() {
|
||||||
|
for(int i=0; i<NUM_TRACKS; i++) {
|
||||||
|
for(int j=0; j<NUM_SAMPLES; j++) {
|
||||||
|
for(int k=0; k<NUM_STEPS; k++) {
|
||||||
|
EEPROM.write(k + NUM_SAMPLES * (j + i * NUM_TRACKS), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadSequences() {
|
||||||
|
for(int i=0; i<NUM_TRACKS; i++) {
|
||||||
|
for(int j=0; j<NUM_SAMPLES; j++) {
|
||||||
|
for(int k=0; k<NUM_STEPS; k++) {
|
||||||
|
sample[i][j][k] = EEPROM.read(k + NUM_SAMPLES * (j + i * NUM_TRACKS));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void s1cb() {
|
||||||
|
indxLED = indx;
|
||||||
|
for(int i=0; i<NUM_SAMPLES; i++) {
|
||||||
|
if(sample[trackPlaying][i][indx]) Music.noteOnSample(i);
|
||||||
|
}
|
||||||
|
indx++;
|
||||||
|
if(indx >= NUM_STEPS) {
|
||||||
|
indx = 0;
|
||||||
|
if(trackChained < 0);
|
||||||
|
else {
|
||||||
|
int t = trackPlaying;
|
||||||
|
trackPlaying = trackChained;
|
||||||
|
trackChained = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
201
examples/CFO_BODYSEQ_SAMPLER/interface.ino
Executable file
201
examples/CFO_BODYSEQ_SAMPLER/interface.ino
Executable file
@ -0,0 +1,201 @@
|
|||||||
|
/////////////
|
||||||
|
// BUTTONS //
|
||||||
|
/////////////
|
||||||
|
void readButtons() {
|
||||||
|
// buttons are active low
|
||||||
|
for(int i = 0; i < NUM_BUTTONS; i++) {
|
||||||
|
// int i = buttonIndex++;
|
||||||
|
// if(buttonIndex >= NUM_BUTTONS) buttonIndex = 0;
|
||||||
|
buttonNow = millis();
|
||||||
|
if((buttonNow - buttonTime[i]) > debounceTime) {
|
||||||
|
buttonRead = digitalRead(buttonPin[i]);
|
||||||
|
if(buttonRead != buttonState[i]) {
|
||||||
|
buttonState[i] = buttonRead;
|
||||||
|
buttonChange |= 1<<i;
|
||||||
|
buttonTime[i] = buttonNow;
|
||||||
|
machineState = 7 - buttonState[0] - buttonState[1] * 2 - buttonState[2] * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////
|
||||||
|
// KEYS //
|
||||||
|
//////////
|
||||||
|
void readKeys() {
|
||||||
|
int keyr = 0;
|
||||||
|
int keyv = 0;
|
||||||
|
for (int i = 0; i < NUM_KEYS; i++) {
|
||||||
|
keyNow = millis();
|
||||||
|
if((keyNow - keyTime[i]) > debounceTime) {
|
||||||
|
keyRead = analogRead(keyPin[i]);
|
||||||
|
if(keyRead > KEY_THRESHOLD) {
|
||||||
|
keyValue = 1;
|
||||||
|
} else {
|
||||||
|
keyValue = 0;
|
||||||
|
}
|
||||||
|
if(i == 0) {
|
||||||
|
keyr = keyRead;
|
||||||
|
keyv = keyValue;
|
||||||
|
}
|
||||||
|
// keyValue = (keyRead > KEY_THRESHOLD) ? 1 : 0 ;
|
||||||
|
if(keyState[i] != keyValue) {
|
||||||
|
keyState[i] = keyValue;
|
||||||
|
keyChange |= 1<<i;
|
||||||
|
keyTime[i] = keyNow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < NUM_KEYS; i++) {
|
||||||
|
if(keyState[i] == 1) {
|
||||||
|
keys |= (1<<i);
|
||||||
|
} else if(keyState[i] == 0) {
|
||||||
|
keys &= ~(1<<i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Serial.printf("keyTime[0]=%10ld, keyr=%i, keyv=%i - keyState is %i%i%i%i%i%i%i%i, keys is %X \n", keyTime[0], keyr, keyv, keyState[0], keyState[1], keyState[2], keyState[3], keyState[4], keyState[5], keyState[6], keyState[7], keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////
|
||||||
|
// POTS //
|
||||||
|
//////////
|
||||||
|
void checkBPM() {
|
||||||
|
int bpm = analogRead(A0)>>2;
|
||||||
|
if(bpm != _bpm) {
|
||||||
|
_bpm = bpm;
|
||||||
|
Serial.print("BPM set to ");
|
||||||
|
Serial.println(_bpm);
|
||||||
|
Sequencer.setbpm(_bpm);
|
||||||
|
if(_bpm == 0) {
|
||||||
|
Midi.setMidiIn(true);
|
||||||
|
Midi.setMidiThru(true);
|
||||||
|
Midi.setMidiOut(true);
|
||||||
|
Midi.setMidiClockIn(true);
|
||||||
|
Midi.setMidiClockThru(true);
|
||||||
|
Midi.setMidiClockOut(true);
|
||||||
|
Sequencer.setInternalClock(false);
|
||||||
|
} else {
|
||||||
|
Midi.setMidiIn(false);
|
||||||
|
Midi.setMidiThru(false);
|
||||||
|
Midi.setMidiOut(false);
|
||||||
|
Midi.setMidiClockIn(false);
|
||||||
|
Midi.setMidiClockThru(false);
|
||||||
|
Midi.setMidiClockOut(false);
|
||||||
|
Sequencer.setInternalClock(true);
|
||||||
|
// Sequencer.sequencerContinue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkBitcrush() {
|
||||||
|
int bc = (1024 - analogRead(A1)) >> 7;
|
||||||
|
Music.setBitcrush(bc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void initInterface() {
|
||||||
|
pinMode(buttonPin[0], INPUT_PULLUP);
|
||||||
|
pinMode(buttonPin[1], INPUT_PULLUP);
|
||||||
|
pinMode(buttonPin[2], INPUT_PULLUP);
|
||||||
|
pinMode(statusLed1,OUTPUT);
|
||||||
|
for (int i = 0; i<8; i++) {
|
||||||
|
pinMode(seqLed[i], OUTPUT);
|
||||||
|
}
|
||||||
|
startupAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void updateLEDs() {
|
||||||
|
ledNow = millis();
|
||||||
|
int t = trackSelected;
|
||||||
|
int s = sampleSelected;
|
||||||
|
leds = 0;
|
||||||
|
switch(machineState) {
|
||||||
|
case 0: // PLAY TRACK
|
||||||
|
leds |= (1 << trackPlaying);
|
||||||
|
if(trackChained >= 0) {
|
||||||
|
if((ledNow - ledTime) > ledPulse) {
|
||||||
|
chainedLedState ^= 1;
|
||||||
|
ledTime = ledNow;
|
||||||
|
}
|
||||||
|
leds |= (chainedLedState << trackChained);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1: // SELECT STEP
|
||||||
|
// leds = 0;
|
||||||
|
for(int i=0; i<NUM_STEPS; i++) {
|
||||||
|
leds |= (sample[t][s][i] << i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: // SELECT SAMPLE
|
||||||
|
leds |= (1 << sampleSelected);
|
||||||
|
break;
|
||||||
|
case 3: // SELECT TRACK
|
||||||
|
leds |= (1 << trackSelected);
|
||||||
|
break;
|
||||||
|
case 4: // SELECT TRACK
|
||||||
|
leds |= (1 << trackSelected);
|
||||||
|
break;
|
||||||
|
case 5: // CHAIN TRACKS PLAYING
|
||||||
|
leds |= (1 << trackPlaying);
|
||||||
|
if(trackChained >= 0) {
|
||||||
|
if((ledNow - ledTime) > ledPulse) {
|
||||||
|
chainedLedState ^= 1;
|
||||||
|
ledTime = ledNow;
|
||||||
|
}
|
||||||
|
leds |= (chainedLedState << trackChained);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 6: // COPY TRACK
|
||||||
|
leds |= (1 << trackSelected);
|
||||||
|
break;
|
||||||
|
case 7: // CLEAR TRACK
|
||||||
|
for(int i=0; i<NUM_KEYS; i++) {
|
||||||
|
for(int j=0; j<NUM_SAMPLES; j++) {
|
||||||
|
for(int k=0; k<NUM_STEPS; k++) {
|
||||||
|
leds |= (sample[i][j][k] << i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i<8; i++) {
|
||||||
|
leds |= (1 << indxLED);
|
||||||
|
digitalWrite(seqLed[i], leds & (1 << i));
|
||||||
|
// leds ^= (1 << indxLED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
53
examples/CFO_PROTOSEQ/CFO_PROTOSEQ.ino
Executable file
53
examples/CFO_PROTOSEQ/CFO_PROTOSEQ.ino
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
#define MIDI_CHANNEL 1
|
||||||
|
|
||||||
|
#include <spi4teensy3.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <CFO_PROTOSEQ.h>
|
||||||
|
|
||||||
|
// sequence ID
|
||||||
|
int s1;
|
||||||
|
|
||||||
|
//int notes1[] = {12, 24, 7, 12, 36, 12, 24, 15, 0, 12, 48, 36, 19, 24, 3, 36};
|
||||||
|
int notes1[] = {36, 48, 31, 36, 60, 36, 48, 39, 24, 36, 72, 60, 43, 48, 27, 60};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||||
|
Music.init();
|
||||||
|
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.enableEnvelope2();
|
||||||
|
Music.getPreset(13);
|
||||||
|
|
||||||
|
// These guys just have to be here...
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
|
||||||
|
analogReadAveraging(32);
|
||||||
|
|
||||||
|
Sequencer.init(140);
|
||||||
|
|
||||||
|
s1 = Sequencer.newSequence(NOTE_16, 16, LOOP);
|
||||||
|
Sequencer.startSequence(s1);
|
||||||
|
Sequencer.insertNotes(s1, notes1, 16, 0);
|
||||||
|
Sequencer.setInternal(s1, true);
|
||||||
|
Sequencer.setExternal(s1, false);
|
||||||
|
|
||||||
|
Midi.setMidiIn(false);
|
||||||
|
Midi.setMidiThru(false);
|
||||||
|
Midi.setMidiOut(false);
|
||||||
|
Midi.setMidiClockIn(false);
|
||||||
|
Midi.setMidiClockThru(false);
|
||||||
|
Midi.setMidiClockOut(false);
|
||||||
|
Sequencer.setInternalClock(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
Sequencer.update();
|
||||||
|
usbMIDI.read();
|
||||||
|
Midi.checkSerialMidi();
|
||||||
|
}
|
||||||
|
|
||||||
58
examples/CFO_PROTOSEQ_KLOCKMEISTER/CFO_PROTOSEQ_KLOCKMEISTER.ino
Executable file
58
examples/CFO_PROTOSEQ_KLOCKMEISTER/CFO_PROTOSEQ_KLOCKMEISTER.ino
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
#define MIDI_CHANNEL 1
|
||||||
|
|
||||||
|
#include <spi4teensy3.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <CFO_PROTOSEQ.h>
|
||||||
|
|
||||||
|
// sequence ID
|
||||||
|
int s1;
|
||||||
|
|
||||||
|
//int notes1[] = {12, 24, 7, 12, 36, 12, 24, 15, 0, 12, 48, 36, 19, 24, 3, 36};
|
||||||
|
int notes1[] = {36, 48, 31, 36, 60, 36, 48, 39, 24, 36, 72, 60, 43, 48, 27, 60};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||||
|
Music.init();
|
||||||
|
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.enableEnvelope2();
|
||||||
|
Music.getPreset(13);
|
||||||
|
|
||||||
|
// These guys just have to be here...
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
|
||||||
|
analogReadAveraging(32);
|
||||||
|
|
||||||
|
Sequencer.init(140);
|
||||||
|
|
||||||
|
s1 = Sequencer.newSequence(NOTE_16, 16, LOOP);
|
||||||
|
Sequencer.insertNotes(s1, notes1, 16, 0);
|
||||||
|
Sequencer.setInternal(s1, true);
|
||||||
|
Sequencer.setExternal(s1, false);
|
||||||
|
Sequencer.startSequence(s1);
|
||||||
|
|
||||||
|
Midi.setMidiIn(false);
|
||||||
|
Midi.setMidiThru(false);
|
||||||
|
Midi.setMidiOut(false);
|
||||||
|
Midi.setMidiClockIn(false);
|
||||||
|
Midi.setMidiClockThru(false);
|
||||||
|
Midi.setMidiClockOut(true);
|
||||||
|
Sequencer.setInternalClock(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Serial.print("loop - ");
|
||||||
|
// Serial.println(micros());
|
||||||
|
Sequencer.update();
|
||||||
|
// Serial.println("Sequencer.update()");
|
||||||
|
usbMIDI.read();
|
||||||
|
// Serial.println("usbMIDI.read()");
|
||||||
|
Midi.checkSerialMidi();
|
||||||
|
// Serial.println("Midi.checkSerialMidi()");
|
||||||
|
}
|
||||||
|
|
||||||
53
examples/CFO_PROTOSEQ_SLAVE/CFO_PROTOSEQ_SLAVE.ino
Executable file
53
examples/CFO_PROTOSEQ_SLAVE/CFO_PROTOSEQ_SLAVE.ino
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
#define MIDI_CHANNEL 2
|
||||||
|
|
||||||
|
#include <spi4teensy3.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <CFO_PROTOSEQ.h>
|
||||||
|
|
||||||
|
// sequence ID
|
||||||
|
int s1;
|
||||||
|
|
||||||
|
//int notes1[] = {12, 24, 7, 12, 36, 12, 24, 15, 0, 12, 48, 36, 19, 24, 3, 36};
|
||||||
|
int notes1[] = {36, 48, 31, 36, 60, 36, 48, 39, 24, 36, 72, 60, 43, 48, 27, 60};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||||
|
Music.init();
|
||||||
|
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.enableEnvelope2();
|
||||||
|
Music.getPreset(13);
|
||||||
|
|
||||||
|
// These guys just have to be here...
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
|
||||||
|
analogReadAveraging(32);
|
||||||
|
|
||||||
|
Sequencer.init(140);
|
||||||
|
|
||||||
|
s1 = Sequencer.newSequence(NOTE_16, 16, LOOP);
|
||||||
|
Sequencer.startSequence(s1);
|
||||||
|
Sequencer.insertNotes(s1, notes1, 16, 0);
|
||||||
|
Sequencer.setInternal(s1, true);
|
||||||
|
Sequencer.setExternal(s1, false);
|
||||||
|
|
||||||
|
Midi.setMidiIn(false);
|
||||||
|
Midi.setMidiThru(false);
|
||||||
|
Midi.setMidiOut(false);
|
||||||
|
Midi.setMidiClockIn(true);
|
||||||
|
Midi.setMidiClockThru(true);
|
||||||
|
Midi.setMidiClockOut(false);
|
||||||
|
Sequencer.setInternalClock(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
Sequencer.update();
|
||||||
|
usbMIDI.read();
|
||||||
|
Midi.checkSerialMidi();
|
||||||
|
}
|
||||||
|
|
||||||
66
examples/Music/Init_midi/Init_midi.ino
Executable file
66
examples/Music/Init_midi/Init_midi.ino
Executable file
@ -0,0 +1,66 @@
|
|||||||
|
#define MIDI_CHANNEL 1
|
||||||
|
|
||||||
|
#include <spi4teensy3.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <CFO_BODYSEQ.h>
|
||||||
|
|
||||||
|
const int pot1 = A0, pot2 = A1;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||||
|
Music.init();
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.enableEnvelope2();
|
||||||
|
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
Music.getPreset(16);
|
||||||
|
Music.setEnv1Decay(36);
|
||||||
|
Music.setEnv1Sustain(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
usbMIDI.read();
|
||||||
|
updateSequence();
|
||||||
|
Music.setCutoff((1023-analogRead(pot1))*64);
|
||||||
|
Music.setCutoffModAmount((1023-analogRead(pot2))*64);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean noteIsOn = false;
|
||||||
|
int n = 0;
|
||||||
|
int dir = 1;
|
||||||
|
int rootNote = 36;
|
||||||
|
//int note[] = {0,0,0,0,0,0,0,0,0};
|
||||||
|
int note[] = {0,12,3,19,15,9,5,24,7};
|
||||||
|
|
||||||
|
long time = 0;
|
||||||
|
long lastTime = 0;
|
||||||
|
long timeDelay = 60;
|
||||||
|
|
||||||
|
void updateSequence() {
|
||||||
|
// This short routine loops note over and over again
|
||||||
|
time = millis();
|
||||||
|
if(time - lastTime > timeDelay) {
|
||||||
|
if(!noteIsOn) {
|
||||||
|
Music.noteOn(rootNote+note[n]);
|
||||||
|
noteIsOn = true;
|
||||||
|
n = n + dir;
|
||||||
|
if(n > 7)
|
||||||
|
{
|
||||||
|
dir = -1;
|
||||||
|
}
|
||||||
|
else if(n < 1)
|
||||||
|
{
|
||||||
|
dir = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Music.noteOff();
|
||||||
|
noteIsOn = false;
|
||||||
|
}
|
||||||
|
lastTime = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
1
examples/Music/Music_tutorial_files.txt
Executable file
1
examples/Music/Music_tutorial_files.txt
Executable file
@ -0,0 +1 @@
|
|||||||
|
Put Music Tutorial sketches in this folder
|
||||||
60
examples/Music/_6_noteOn_noteOff/_6_noteOn_noteOff.ino
Executable file
60
examples/Music/_6_noteOn_noteOff/_6_noteOn_noteOff.ino
Executable file
@ -0,0 +1,60 @@
|
|||||||
|
#include <spi4teensy3.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <CFO_BODYSEQ.h>
|
||||||
|
|
||||||
|
boolean noteIsOn = false;
|
||||||
|
int n = 0;
|
||||||
|
int dir = 1;
|
||||||
|
int rootNote = 36;
|
||||||
|
int note[] = {0,12,3,19,15,9,5,24,7};
|
||||||
|
|
||||||
|
long time = 0;
|
||||||
|
long lastTime = 0;
|
||||||
|
long timeDelay = 60;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||||
|
Music.init();
|
||||||
|
|
||||||
|
// Choosing the square wave oscillator.
|
||||||
|
Music.setWaveform(SAW);
|
||||||
|
|
||||||
|
// Detuning the three oscillators slightly to create movement in the sound.
|
||||||
|
Music.setDetune(0.005);
|
||||||
|
|
||||||
|
// enabling the envelope lets us define an gain envelope for the synth
|
||||||
|
// without having to specify it in our loop() or physics code.
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.setEnv1Attack(8);
|
||||||
|
Music.setEnv1Decay(90);
|
||||||
|
Music.setEnv1Sustain(48);
|
||||||
|
Music.setEnv1Release(64);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// This short routine loops note over and over again
|
||||||
|
time = millis();
|
||||||
|
if(time - lastTime > timeDelay) {
|
||||||
|
if(!noteIsOn) {
|
||||||
|
Music.noteOn(rootNote+note[n]);
|
||||||
|
noteIsOn = true;
|
||||||
|
n = n + dir;
|
||||||
|
if(n > 7)
|
||||||
|
{
|
||||||
|
dir = -1;
|
||||||
|
}
|
||||||
|
else if(n < 1)
|
||||||
|
{
|
||||||
|
dir = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Music.noteOff();
|
||||||
|
noteIsOn = false;
|
||||||
|
}
|
||||||
|
lastTime = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
84
examples/sampler/sampler.ino
Executable file
84
examples/sampler/sampler.ino
Executable file
@ -0,0 +1,84 @@
|
|||||||
|
#define MIDI_CHANNEL 1
|
||||||
|
|
||||||
|
#include <spi4teensy3.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <CFO_BODYSEQ.h>
|
||||||
|
|
||||||
|
// sequence ID
|
||||||
|
int s1;
|
||||||
|
|
||||||
|
// sequence step index
|
||||||
|
int indx1 = 0;
|
||||||
|
|
||||||
|
const int nbr_notes1 = 16;
|
||||||
|
|
||||||
|
int BD[] = {1,0,0,1, 0,0,1,0, 0,0,1,0, 0,0,0,0};
|
||||||
|
int SN[] = {0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0};
|
||||||
|
int RS[] = {0,0,1,0, 0,1,0,0, 0,0,1,0, 0,1,0,0};
|
||||||
|
int CP[] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1};
|
||||||
|
int HH[] = {1,0,1,0, 1,1,0,1, 0,1,0,1, 0,1,0,1};
|
||||||
|
int OH[] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,0};
|
||||||
|
int CL[] = {0,1,0,0, 0,0,1,0, 0,0,0,1, 0,1,1,0};
|
||||||
|
int CB[] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
|
||||||
|
|
||||||
|
|
||||||
|
//int BD[] = {1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1};
|
||||||
|
//int SN[] = {1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1};
|
||||||
|
//int RS[] = {1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1};
|
||||||
|
//int CP[] = {1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1};
|
||||||
|
//int HH[] = {1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1};
|
||||||
|
//int OH[] = {1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1};
|
||||||
|
//int CL[] = {1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1};
|
||||||
|
//int CB[] = {1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||||
|
Music.init();
|
||||||
|
Music.setSampler(true);
|
||||||
|
Music.setSynth(false);
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.enableEnvelope2();
|
||||||
|
|
||||||
|
// These guys just have to be here...
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
|
||||||
|
// this is the sequencer code
|
||||||
|
Sequencer.init(120);
|
||||||
|
Sequencer.setInternalClock(true);
|
||||||
|
|
||||||
|
//Sequencer.newSequence(SUBDIV, CALLBACK);
|
||||||
|
s1 = Sequencer.newSequence(NOTE_16, &s1cb);
|
||||||
|
// Sequencer.setInternal(s1, true);
|
||||||
|
// Sequencer.setExternal(s1, false);
|
||||||
|
|
||||||
|
// start sequences
|
||||||
|
Sequencer.startSequence(s1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// Checking for incoming MIDI to use dashboard
|
||||||
|
usbMIDI.read();
|
||||||
|
Sequencer.update();
|
||||||
|
Midi.checkSerialMidi();
|
||||||
|
}
|
||||||
|
|
||||||
|
// callback function for the step sequencer
|
||||||
|
|
||||||
|
void s1cb() {
|
||||||
|
if(BD[indx1]) Music.noteOnSample(0);
|
||||||
|
if(SN[indx1]) Music.noteOnSample(1);
|
||||||
|
if(RS[indx1]) Music.noteOnSample(2);
|
||||||
|
if(CP[indx1]) Music.noteOnSample(3);
|
||||||
|
if(HH[indx1]) Music.noteOnSample(4);
|
||||||
|
if(OH[indx1]) Music.noteOnSample(5);
|
||||||
|
if(CL[indx1]) Music.noteOnSample(6);
|
||||||
|
if(CB[indx1]) Music.noteOnSample(7);
|
||||||
|
|
||||||
|
indx1++;
|
||||||
|
if(indx1 >= nbr_notes1) indx1 = 0;
|
||||||
|
}
|
||||||
131
examples/sampler_and_sequenced_audio/sampler_and_sequenced_audio.ino
Executable file
131
examples/sampler_and_sequenced_audio/sampler_and_sequenced_audio.ino
Executable file
@ -0,0 +1,131 @@
|
|||||||
|
#define MIDI_CHANNEL 1
|
||||||
|
|
||||||
|
#include <spi4teensy3.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <CFO_BODYSEQ.h>
|
||||||
|
|
||||||
|
// sequence ID
|
||||||
|
int s1, s2, s3, s4;
|
||||||
|
|
||||||
|
// sequence step index
|
||||||
|
int indx1 = 0;
|
||||||
|
int indx2 = 0;
|
||||||
|
int indx3 = 0;
|
||||||
|
int indx4 = 0;
|
||||||
|
|
||||||
|
const int nbr_notes1 = 16;
|
||||||
|
const int nbr_steps2 = 8;
|
||||||
|
const int nbr_notes3 = 8;
|
||||||
|
|
||||||
|
const int notes1[] = {12, 24, 7, 12, 36, 12, 24, 15, 0, 12, 48, 36, 19, 24, 3, 36};
|
||||||
|
const int midiCC[] = {8, 8, 11, 21, 21, 11, 21, 31, 8};
|
||||||
|
const int midiValue[] = {0, 80, 68, 68, 68, 72, 72, 72, 0};
|
||||||
|
|
||||||
|
int BD[] = {1, 0, 0, 1, 0, 0, 1, 0};
|
||||||
|
int SN[] = {0, 0, 0, 0, 1, 0, 0, 0};
|
||||||
|
int RS[] = {0, 1, 0, 1, 0, 0, 1, 0};
|
||||||
|
int CP[] = {0, 0, 0, 0, 1, 0, 0, 0};
|
||||||
|
int HH[] = {1, 0, 1, 1, 0, 1, 0, 0};
|
||||||
|
int OH[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
int CL[] = {0, 0, 1, 0, 0, 1, 0, 0};
|
||||||
|
int CB[] = {0, 0, 0, 0, 0, 0, 0, 1};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||||
|
Music.init();
|
||||||
|
Music.setSampler(true);
|
||||||
|
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.enableEnvelope2();
|
||||||
|
|
||||||
|
// Loading a preset from EEPROM
|
||||||
|
Music.getPreset(21);
|
||||||
|
|
||||||
|
// These guys just have to be here...
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
|
||||||
|
// this is the sequencer code
|
||||||
|
Sequencer.init(120);
|
||||||
|
// Midi.setMidiIn(false);
|
||||||
|
// Midi.setMidiThru(false);
|
||||||
|
// Midi.setMidiOut(false);
|
||||||
|
// Midi.setMidiClockIn(false);
|
||||||
|
// Midi.setMidiClockThru(false);
|
||||||
|
// Midi.setMidiClockOut(true);
|
||||||
|
Sequencer.setInternalClock(true);
|
||||||
|
|
||||||
|
//Sequencer.newSequence(SUBDIV, CALLBACK);
|
||||||
|
// create new sequences and IDs
|
||||||
|
s1 = Sequencer.newSequence(NOTE_16, &s1cb);
|
||||||
|
s2 = Sequencer.newSequence(NOTE_32, &s2cb);
|
||||||
|
s3 = Sequencer.newSequence(NOTE_8, &s3cb);
|
||||||
|
s4 = Sequencer.newSequence(NOTE_16, &s4cb);
|
||||||
|
Sequencer.setInternal(s1, true);
|
||||||
|
Sequencer.setExternal(s1, false);
|
||||||
|
Sequencer.setInternal(s2, true);
|
||||||
|
Sequencer.setExternal(s2, false);
|
||||||
|
Sequencer.setInternal(s3, true);
|
||||||
|
Sequencer.setExternal(s3, false);
|
||||||
|
Sequencer.setInternal(s4, true);
|
||||||
|
Sequencer.setExternal(s4, false);
|
||||||
|
|
||||||
|
// start sequences
|
||||||
|
Sequencer.startSequence(s1);
|
||||||
|
Sequencer.startSequence(s2);
|
||||||
|
Sequencer.startSequence(s3); // start s4 instead of s3
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// Checking for incoming MIDI to use dashboard
|
||||||
|
usbMIDI.read();
|
||||||
|
Sequencer.update();
|
||||||
|
Midi.checkSerialMidi();
|
||||||
|
}
|
||||||
|
|
||||||
|
// callback function for the step sequencers
|
||||||
|
|
||||||
|
void s1cb() {
|
||||||
|
Music.noteOn(notes1[indx1++] + 24, 127);
|
||||||
|
if(indx1 >= nbr_notes1) indx1 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void s2cb() {
|
||||||
|
Midi.controller(MIDI_CHANNEL - 1, midiCC[indx2], midiValue[indx2]);
|
||||||
|
indx2++;
|
||||||
|
if(indx2 >= nbr_steps2) indx2 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void s3cb() {
|
||||||
|
if(BD[indx3]) Music.noteOnSample(0);
|
||||||
|
if(SN[indx3]) Music.noteOnSample(1);
|
||||||
|
if(RS[indx3]) Music.noteOnSample(2);
|
||||||
|
if(CP[indx3]) Music.noteOnSample(3);
|
||||||
|
if(HH[indx3]) Music.noteOnSample(4);
|
||||||
|
if(OH[indx3]) Music.noteOnSample(5);
|
||||||
|
if(CL[indx3]) Music.noteOnSample(6);
|
||||||
|
if(CB[indx3]) Music.noteOnSample(7);
|
||||||
|
|
||||||
|
indx3++;
|
||||||
|
if(indx3 >= nbr_notes3) indx3 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void s4cb() {
|
||||||
|
if(BD[indx3]) Music.noteOnSample(0);
|
||||||
|
if(SN[indx3]) Music.noteOnSample(1);
|
||||||
|
if(RS[indx3]) Music.noteOnSample(2);
|
||||||
|
if(CP[indx1]) Music.noteOnSample(3);
|
||||||
|
if(HH[indx4++]) Music.noteOnSample(4);
|
||||||
|
if(OH[indx3]) Music.noteOnSample(5);
|
||||||
|
if(CL[indx4]) Music.noteOnSample(6);
|
||||||
|
if(CB[indx3++]) Music.noteOnSample(7);
|
||||||
|
|
||||||
|
indx3++;
|
||||||
|
if(indx3 >= nbr_notes3) indx3 = 0;
|
||||||
|
if(indx2 >= nbr_notes1) indx4 = 0;
|
||||||
|
}
|
||||||
60
examples/sequenced_audio/sequenced_audio.ino
Executable file
60
examples/sequenced_audio/sequenced_audio.ino
Executable file
@ -0,0 +1,60 @@
|
|||||||
|
#define MIDI_CHANNEL 1
|
||||||
|
|
||||||
|
#include <spi4teensy3.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <CFO_BODYSEQ.h>
|
||||||
|
|
||||||
|
// sequence ID
|
||||||
|
int s1;
|
||||||
|
// sequence step index
|
||||||
|
int indx1 = 0;
|
||||||
|
const int nbr_notes1 = 16;
|
||||||
|
const int notes1[] = {12, 24, 7, 12, 36, 12, 24, 15, 0, 12, 48, 36, 19, 24, 3, 36};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||||
|
Music.init();
|
||||||
|
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.enableEnvelope2();
|
||||||
|
Music.getPreset(13);
|
||||||
|
|
||||||
|
// These guys just have to be here...
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
|
||||||
|
// this is the sequencer code
|
||||||
|
Sequencer.init(140);
|
||||||
|
// Midi.setMidiIn(false);
|
||||||
|
// Midi.setMidiThru(false);
|
||||||
|
// Midi.setMidiOut(false);
|
||||||
|
// Midi.setMidiClockIn(false);
|
||||||
|
// Midi.setMidiClockThru(false);
|
||||||
|
// Midi.setMidiClockOut(true);
|
||||||
|
Sequencer.setInternalClock(true);
|
||||||
|
|
||||||
|
s1 = Sequencer.newSequence(NOTE_16, &s1cb);
|
||||||
|
Sequencer.setInternal(s1, true);
|
||||||
|
Sequencer.setExternal(s1, false);
|
||||||
|
Sequencer.startSequence(s1);
|
||||||
|
|
||||||
|
// Loading a preset from EEPROM
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// Checking for incoming MIDI to use dashboard
|
||||||
|
usbMIDI.read();
|
||||||
|
Sequencer.update();
|
||||||
|
Midi.checkSerialMidi();
|
||||||
|
}
|
||||||
|
|
||||||
|
// callback function for the step sequencer
|
||||||
|
|
||||||
|
void s1cb() {
|
||||||
|
Music.noteOn(notes1[indx1++] + 24, 127);
|
||||||
|
if(indx1 >= nbr_notes1) indx1 = 0;
|
||||||
|
}
|
||||||
79
examples/sequenced_audio2/sequenced_audio2.ino
Executable file
79
examples/sequenced_audio2/sequenced_audio2.ino
Executable file
@ -0,0 +1,79 @@
|
|||||||
|
#define MIDI_CHANNEL 1
|
||||||
|
|
||||||
|
#include <spi4teensy3.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <CFO_BODYSEQ.h>
|
||||||
|
|
||||||
|
// sequence ID
|
||||||
|
int s1, s2;
|
||||||
|
// sequence step index
|
||||||
|
int indx1 = 0;
|
||||||
|
int indx2 = 0;
|
||||||
|
const int nbr_notes1 = 16;
|
||||||
|
const int nbr_steps2 = 8;
|
||||||
|
const int notes1[] = {12, 24, 7, 12, 36, 12, 24, 15, 0, 12, 48, 36, 19, 24, 3, 36};
|
||||||
|
const int midiCC[] = {8, 8, 11, 21, 21, 11, 21, 31, 8};
|
||||||
|
const int midiValue[] = {0, 80, 68, 68, 68, 72, 72, 72, 0};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||||
|
Music.init();
|
||||||
|
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.enableEnvelope2();
|
||||||
|
|
||||||
|
// Loading a preset from EEPROM
|
||||||
|
Music.getPreset(13);
|
||||||
|
|
||||||
|
// These guys just have to be here...
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
|
||||||
|
// this is the sequencer code
|
||||||
|
Sequencer.init(120);
|
||||||
|
// Midi.setMidiIn(false);
|
||||||
|
// Midi.setMidiThru(false);
|
||||||
|
// Midi.setMidiOut(false);
|
||||||
|
// Midi.setMidiClockIn(false);
|
||||||
|
// Midi.setMidiClockThru(false);
|
||||||
|
// Midi.setMidiClockOut(true);
|
||||||
|
Sequencer.setInternalClock(true);
|
||||||
|
|
||||||
|
//Sequencer.newSequence(CALLBACK, SUBDIV);
|
||||||
|
// create new sequence and ID (s1)
|
||||||
|
s1 = Sequencer.newSequence(NOTE_16, &s1cb);
|
||||||
|
s2 = Sequencer.newSequence(NOTE_32, &s2cb);
|
||||||
|
Sequencer.setInternal(s1, true);
|
||||||
|
Sequencer.setExternal(s1, false);
|
||||||
|
Sequencer.setInternal(s2, true);
|
||||||
|
Sequencer.setExternal(s2, false);
|
||||||
|
|
||||||
|
// start sequence 1 and 2
|
||||||
|
Sequencer.startSequence(s1);
|
||||||
|
Sequencer.startSequence(s2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// Checking for incoming MIDI to use dashboard
|
||||||
|
usbMIDI.read();
|
||||||
|
Sequencer.update();
|
||||||
|
Midi.checkSerialMidi();
|
||||||
|
}
|
||||||
|
|
||||||
|
// callback function for the step sequencer
|
||||||
|
|
||||||
|
void s1cb() {
|
||||||
|
Music.noteOn(notes1[indx1++] + 24, 127);
|
||||||
|
if(indx1 >= nbr_notes1) indx1 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void s2cb() {
|
||||||
|
Midi.controller(MIDI_CHANNEL - 1, midiCC[indx2], midiValue[indx2]);
|
||||||
|
indx2++;
|
||||||
|
if(indx2 >= nbr_steps2) indx2 = 0;
|
||||||
|
}
|
||||||
86
examples/sequenced_audio3/sequenced_audio3.ino
Executable file
86
examples/sequenced_audio3/sequenced_audio3.ino
Executable file
@ -0,0 +1,86 @@
|
|||||||
|
#define MIDI_CHANNEL 1
|
||||||
|
|
||||||
|
#include <spi4teensy3.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <CFO_BODYSEQ.h>
|
||||||
|
|
||||||
|
// sequence ID
|
||||||
|
int s1, s2, s3;
|
||||||
|
// sequence step index
|
||||||
|
int indx1 = 0;
|
||||||
|
int indx2 = 0;
|
||||||
|
int indx3 = 0;
|
||||||
|
const int nbr_steps1 = 16;
|
||||||
|
const int nbr_steps2 = 8;
|
||||||
|
const int nbr_steps3 = 15;
|
||||||
|
const int nbr_steps4 = 4;
|
||||||
|
const int notes1[] = {12, 24, 7, 15, 36, 12, 24, 15, 0, 12, 48, 36, 19, 24, 3, 36};
|
||||||
|
const int notes2[] = {0, 7, 15, 24, 12, 19, 3, 24};
|
||||||
|
const int midiCC2[] = {8, 8, 11, 21, 31, 11, 21, 31, 8};
|
||||||
|
const int midiValue2[] = {0, 80, 68, 68, 68, 72, 72, 72, 0};
|
||||||
|
const int midiCC3[] = {14, 24, 34, 14, 34, 24, 14, 34, 24, 14, 34, 14, 24, 14, 24, 34};
|
||||||
|
const int midiValue3[] = {1, 2, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4, 2, 2, 1, 4};
|
||||||
|
const int midiCC4[] = {11, 11, 11, 11};
|
||||||
|
const int midiValue4[] = {64, 67, 71, 76};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||||
|
Music.init();
|
||||||
|
|
||||||
|
Music.getPreset(11);
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.enableEnvelope2();
|
||||||
|
|
||||||
|
// These guys just have to be here...
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
|
||||||
|
// this is the sequencer code
|
||||||
|
Sequencer.init(112);
|
||||||
|
Sequencer.setInternalClock(true);
|
||||||
|
|
||||||
|
//Sequencer.newSequence(CALLBACK, SUBDIV);
|
||||||
|
// create new sequence and ID (s1)
|
||||||
|
s1 = Sequencer.newSequence(NOTE_8, &s1cb);
|
||||||
|
s2 = Sequencer.newSequence(NOTE_32, &s2cb);
|
||||||
|
s3 = Sequencer.newSequence(NOTE_96, &s3cb);
|
||||||
|
|
||||||
|
// start sequence 1
|
||||||
|
Sequencer.startSequence(s1);
|
||||||
|
// Sequencer.startSequence(s2);
|
||||||
|
Sequencer.startSequence(s3);
|
||||||
|
|
||||||
|
// Loading a preset from EEPROM
|
||||||
|
Music.setGain2(0.0);
|
||||||
|
Music.setGain3(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// Checking for incoming MIDI to use dashboard
|
||||||
|
usbMIDI.read();
|
||||||
|
Sequencer.update();
|
||||||
|
Midi.checkSerialMidi();
|
||||||
|
}
|
||||||
|
|
||||||
|
// callback function for the step sequencer
|
||||||
|
|
||||||
|
void s1cb() {
|
||||||
|
Music.noteOn(notes1[indx1++] + 48, 127);
|
||||||
|
if(indx1 >= nbr_steps1) indx1 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void s2cb() {
|
||||||
|
if(indx2 < nbr_steps2) Midi.controller(MIDI_CHANNEL - 1, midiCC2[indx2], midiValue2[indx2]);
|
||||||
|
indx2++;
|
||||||
|
if(indx2 >= nbr_steps2) indx2 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void s3cb() {
|
||||||
|
if(indx3 < nbr_steps4) Midi.controller(MIDI_CHANNEL - 1, midiCC4[indx3], midiValue4[indx3]);
|
||||||
|
indx3++;
|
||||||
|
if(indx3 >= nbr_steps4) indx3 = 0;
|
||||||
|
}
|
||||||
76
examples/sequenced_audio4/sequenced_audio4.ino
Executable file
76
examples/sequenced_audio4/sequenced_audio4.ino
Executable file
@ -0,0 +1,76 @@
|
|||||||
|
#define MIDI_CHANNEL 1
|
||||||
|
|
||||||
|
#include <spi4teensy3.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <CFO_BODYSEQ.h>
|
||||||
|
|
||||||
|
// sequence ID
|
||||||
|
int s1, s2;
|
||||||
|
// sequence step index
|
||||||
|
int indx1 = 0;
|
||||||
|
int indx2 = 0;
|
||||||
|
int indx3 = 0;
|
||||||
|
const int nbr_notes1 = 16;
|
||||||
|
const int nbr_notes2 = 8;
|
||||||
|
const int nbr_notes3 = 32;
|
||||||
|
const int notes1[] = {12, 24, 19, 12, 36, 12, 24, 15, 36, 12, 48, 36, 19, 24, 15, 36};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||||
|
Music.init();
|
||||||
|
|
||||||
|
Music.enableEnvelope1();
|
||||||
|
Music.enableEnvelope2();
|
||||||
|
|
||||||
|
// Loading a preset from EEPROM
|
||||||
|
Music.getPreset(13);
|
||||||
|
|
||||||
|
// These guys just have to be here...
|
||||||
|
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||||
|
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||||
|
usbMIDI.setHandleControlChange(OnControlChange);
|
||||||
|
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||||
|
|
||||||
|
// this is the sequencer code
|
||||||
|
Sequencer.init(128);
|
||||||
|
Sequencer.setInternalClock(true);
|
||||||
|
|
||||||
|
//Sequencer.newSequence(CALLBACK, SUBDIV);
|
||||||
|
// create new sequence and ID (s1)
|
||||||
|
s1 = Sequencer.newSequence(NOTE_8, &s1cb);
|
||||||
|
s2 = Sequencer.newSequence(NOTE_6, &s2cb);
|
||||||
|
|
||||||
|
// start sequence 1
|
||||||
|
Sequencer.startSequence(s1);
|
||||||
|
Sequencer.startSequence(s2);
|
||||||
|
|
||||||
|
Music.setPortamento(124);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// Checking for incoming MIDI to use dashboard
|
||||||
|
usbMIDI.read();
|
||||||
|
Sequencer.update();
|
||||||
|
Midi.checkSerialMidi();
|
||||||
|
}
|
||||||
|
|
||||||
|
// callback function for the step sequencer
|
||||||
|
|
||||||
|
void s1cb() {
|
||||||
|
Music.noteOn(notes1[indx1++] + 36, 127);
|
||||||
|
if(indx2 >= nbr_notes1) indx1 = 0;
|
||||||
|
indx3++;
|
||||||
|
if(indx3 >= nbr_notes3) {
|
||||||
|
indx1 = 0;
|
||||||
|
indx2 = 0;
|
||||||
|
indx3 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void s2cb() {
|
||||||
|
Music.noteOn(notes1[indx1++] + 36, 127);
|
||||||
|
if(indx1 >= nbr_notes2) indx2 = 0;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user