From dd0197fa428de8c31309120aa5c67eb463ff1e5e Mon Sep 17 00:00:00 2001 From: gauthiier Date: Sat, 1 Dec 2018 12:57:32 +0100 Subject: [PATCH] examples --- .../CFO_BODYSEQ_2buttons.ino | 447 +++++++++++++++ .../CFO_BODYSEQ_3buttons.ino | 465 +++++++++++++++ .../CFO_BODYSEQ_3buttons_experimental.ino | 524 +++++++++++++++++ .../CFO_BODYSEQ_3buttons_midi_synced.ino | 539 ++++++++++++++++++ .../CFO_BODYSEQ_3buttons_sequenced_audio.ino | 81 +++ examples/CFO_BODYSEQ_O/CFO_BODYSEQ_O.ino | 234 ++++++++ examples/CFO_BODYSEQ_O/interface.ino | 157 +++++ examples/CFO_BODYSEQ_P/CFO_BODYSEQ_P.ino | 110 ++++ examples/CFO_BODYSEQ_Q/CFO_BODYSEQ_Q.ino | 103 ++++ .../CFO_BODYSEQ_SAMPLER.ino | 286 ++++++++++ examples/CFO_BODYSEQ_SAMPLER/interface.ino | 201 +++++++ examples/CFO_PROTOSEQ/CFO_PROTOSEQ.ino | 53 ++ .../CFO_PROTOSEQ_KLOCKMEISTER.ino | 58 ++ .../CFO_PROTOSEQ_SLAVE/CFO_PROTOSEQ_SLAVE.ino | 53 ++ examples/Music/Init_midi/Init_midi.ino | 66 +++ examples/Music/Music_tutorial_files.txt | 1 + .../_6_noteOn_noteOff/_6_noteOn_noteOff.ino | 60 ++ examples/sampler/sampler.ino | 84 +++ .../sampler_and_sequenced_audio.ino | 131 +++++ examples/sequenced_audio/sequenced_audio.ino | 60 ++ .../sequenced_audio2/sequenced_audio2.ino | 79 +++ .../sequenced_audio3/sequenced_audio3.ino | 86 +++ .../sequenced_audio4/sequenced_audio4.ino | 76 +++ 23 files changed, 3954 insertions(+) create mode 100755 examples/CFO_BODYSEQ_2buttons/CFO_BODYSEQ_2buttons.ino create mode 100755 examples/CFO_BODYSEQ_3buttons/CFO_BODYSEQ_3buttons.ino create mode 100755 examples/CFO_BODYSEQ_3buttons_experimental/CFO_BODYSEQ_3buttons_experimental.ino create mode 100755 examples/CFO_BODYSEQ_3buttons_midi_synced/CFO_BODYSEQ_3buttons_midi_synced.ino create mode 100755 examples/CFO_BODYSEQ_3buttons_sequenced_audio/CFO_BODYSEQ_3buttons_sequenced_audio.ino create mode 100755 examples/CFO_BODYSEQ_O/CFO_BODYSEQ_O.ino create mode 100755 examples/CFO_BODYSEQ_O/interface.ino create mode 100755 examples/CFO_BODYSEQ_P/CFO_BODYSEQ_P.ino create mode 100755 examples/CFO_BODYSEQ_Q/CFO_BODYSEQ_Q.ino create mode 100755 examples/CFO_BODYSEQ_SAMPLER/CFO_BODYSEQ_SAMPLER.ino create mode 100755 examples/CFO_BODYSEQ_SAMPLER/interface.ino create mode 100755 examples/CFO_PROTOSEQ/CFO_PROTOSEQ.ino create mode 100755 examples/CFO_PROTOSEQ_KLOCKMEISTER/CFO_PROTOSEQ_KLOCKMEISTER.ino create mode 100755 examples/CFO_PROTOSEQ_SLAVE/CFO_PROTOSEQ_SLAVE.ino create mode 100755 examples/Music/Init_midi/Init_midi.ino create mode 100755 examples/Music/Music_tutorial_files.txt create mode 100755 examples/Music/_6_noteOn_noteOff/_6_noteOn_noteOff.ino create mode 100755 examples/sampler/sampler.ino create mode 100755 examples/sampler_and_sequenced_audio/sampler_and_sequenced_audio.ino create mode 100755 examples/sequenced_audio/sequenced_audio.ino create mode 100755 examples/sequenced_audio2/sequenced_audio2.ino create mode 100755 examples/sequenced_audio3/sequenced_audio3.ino create mode 100755 examples/sequenced_audio4/sequenced_audio4.ino diff --git a/examples/CFO_BODYSEQ_2buttons/CFO_BODYSEQ_2buttons.ino b/examples/CFO_BODYSEQ_2buttons/CFO_BODYSEQ_2buttons.ino new file mode 100755 index 0000000..8dff7d5 --- /dev/null +++ b/examples/CFO_BODYSEQ_2buttons/CFO_BODYSEQ_2buttons.ino @@ -0,0 +1,447 @@ +//______________________/\\\\\__________________________/\\\______________________________/\\\__________________________________________________________ +// ____________________/\\\///__________________________\/\\\_____________________________\/\\\__________________________________________________________ +// ___________________/\\\______________________________\/\\\_____________________________\/\\\_____/\\\__/\\\_______________________________/\\\\\\\\___ +// _____/\\\\\\\\__/\\\\\\\\\_______/\\\\\______________\/\\\____________/\\\\\___________\/\\\____\//\\\/\\\___/\\\\\\\\\\_____/\\\\\\\\___/\\\////\\\__ +// ___/\\\//////__\////\\\//______/\\\///\\\____________\/\\\\\\\\\____/\\\///\\\____/\\\\\\\\\_____\//\\\\\___\/\\\//////____/\\\/////\\\_\//\\\\\\\\\__ +// __/\\\____________\/\\\_______/\\\__\//\\\___________\/\\\////\\\__/\\\__\//\\\__/\\\////\\\______\//\\\____\/\\\\\\\\\\__/\\\\\\\\\\\___\///////\\\__ +// _\//\\\___________\/\\\______\//\\\__/\\\____________\/\\\__\/\\\_\//\\\__/\\\__\/\\\__\/\\\___/\\_/\\\_____\////////\\\_\//\\///////__________\/\\\__ +// __\///\\\\\\\\____\/\\\_______\///\\\\\/_____________\/\\\\\\\\\___\///\\\\\/___\//\\\\\\\/\\_\//\\\\/_______/\\\\\\\\\\__\//\\\\\\\\\\________\/\\\\_ +// ____\////////_____\///__________\/////_______________\/////////______\/////______\///////\//___\////________\//////////____\//////////_________\////__ +// CFO BODYSEQ sequencer, 2 button version, reworked interaction, http://www.vsionhairies.info/ + +#define MIDI_CHANNEL 1 +#include +#include +#include + +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 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; + } + } + } +} diff --git a/examples/CFO_BODYSEQ_3buttons/CFO_BODYSEQ_3buttons.ino b/examples/CFO_BODYSEQ_3buttons/CFO_BODYSEQ_3buttons.ino new file mode 100755 index 0000000..590f9da --- /dev/null +++ b/examples/CFO_BODYSEQ_3buttons/CFO_BODYSEQ_3buttons.ino @@ -0,0 +1,465 @@ +//______________________/\\\\\__________________________/\\\______________________________/\\\__________________________________________________________ +// ____________________/\\\///__________________________\/\\\_____________________________\/\\\__________________________________________________________ +// ___________________/\\\______________________________\/\\\_____________________________\/\\\_____/\\\__/\\\_______________________________/\\\\\\\\___ +// _____/\\\\\\\\__/\\\\\\\\\_______/\\\\\______________\/\\\____________/\\\\\___________\/\\\____\//\\\/\\\___/\\\\\\\\\\_____/\\\\\\\\___/\\\////\\\__ +// ___/\\\//////__\////\\\//______/\\\///\\\____________\/\\\\\\\\\____/\\\///\\\____/\\\\\\\\\_____\//\\\\\___\/\\\//////____/\\\/////\\\_\//\\\\\\\\\__ +// __/\\\____________\/\\\_______/\\\__\//\\\___________\/\\\////\\\__/\\\__\//\\\__/\\\////\\\______\//\\\____\/\\\\\\\\\\__/\\\\\\\\\\\___\///////\\\__ +// _\//\\\___________\/\\\______\//\\\__/\\\____________\/\\\__\/\\\_\//\\\__/\\\__\/\\\__\/\\\___/\\_/\\\_____\////////\\\_\//\\///////__________\/\\\__ +// __\///\\\\\\\\____\/\\\_______\///\\\\\/_____________\/\\\\\\\\\___\///\\\\\/___\//\\\\\\\/\\_\//\\\\/_______/\\\\\\\\\\__\//\\\\\\\\\\________\/\\\\_ +// ____\////////_____\///__________\/////_______________\/////////______\/////______\///////\//___\////________\//////////____\//////////_________\////__ +// CFO BODYSEQ sequencer, 3 button version, reworked interaction, http://www.vsionhairies.info/ + +#define MIDI_CHANNEL 1 +#include +#include +#include + +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 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; + } + } + } +} + + diff --git a/examples/CFO_BODYSEQ_3buttons_experimental/CFO_BODYSEQ_3buttons_experimental.ino b/examples/CFO_BODYSEQ_3buttons_experimental/CFO_BODYSEQ_3buttons_experimental.ino new file mode 100755 index 0000000..b4593f9 --- /dev/null +++ b/examples/CFO_BODYSEQ_3buttons_experimental/CFO_BODYSEQ_3buttons_experimental.ino @@ -0,0 +1,524 @@ +//______________________/\\\\\__________________________/\\\______________________________/\\\__________________________________________________________ +// ____________________/\\\///__________________________\/\\\_____________________________\/\\\__________________________________________________________ +// ___________________/\\\______________________________\/\\\_____________________________\/\\\_____/\\\__/\\\_______________________________/\\\\\\\\___ +// _____/\\\\\\\\__/\\\\\\\\\_______/\\\\\______________\/\\\____________/\\\\\___________\/\\\____\//\\\/\\\___/\\\\\\\\\\_____/\\\\\\\\___/\\\////\\\__ +// ___/\\\//////__\////\\\//______/\\\///\\\____________\/\\\\\\\\\____/\\\///\\\____/\\\\\\\\\_____\//\\\\\___\/\\\//////____/\\\/////\\\_\//\\\\\\\\\__ +// __/\\\____________\/\\\_______/\\\__\//\\\___________\/\\\////\\\__/\\\__\//\\\__/\\\////\\\______\//\\\____\/\\\\\\\\\\__/\\\\\\\\\\\___\///////\\\__ +// _\//\\\___________\/\\\______\//\\\__/\\\____________\/\\\__\/\\\_\//\\\__/\\\__\/\\\__\/\\\___/\\_/\\\_____\////////\\\_\//\\///////__________\/\\\__ +// __\///\\\\\\\\____\/\\\_______\///\\\\\/_____________\/\\\\\\\\\___\///\\\\\/___\//\\\\\\\/\\_\//\\\\/_______/\\\\\\\\\\__\//\\\\\\\\\\________\/\\\\_ +// ____\////////_____\///__________\/////_______________\/////////______\/////______\///////\//___\////________\//////////____\//////////_________\////__ +// CFO BODYSEQ sequencer, 3 button version, reworked interaction, http://www.vsionhairies.info/ + +#define MIDI_CHANNEL 1 +#include +#include +#include + +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 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(); + +} diff --git a/examples/CFO_BODYSEQ_3buttons_midi_synced/CFO_BODYSEQ_3buttons_midi_synced.ino b/examples/CFO_BODYSEQ_3buttons_midi_synced/CFO_BODYSEQ_3buttons_midi_synced.ino new file mode 100755 index 0000000..1b24d1b --- /dev/null +++ b/examples/CFO_BODYSEQ_3buttons_midi_synced/CFO_BODYSEQ_3buttons_midi_synced.ino @@ -0,0 +1,539 @@ +//______________________/\\\\\__________________________/\\\______________________________/\\\__________________________________________________________ +// ____________________/\\\///__________________________\/\\\_____________________________\/\\\__________________________________________________________ +// ___________________/\\\______________________________\/\\\_____________________________\/\\\_____/\\\__/\\\_______________________________/\\\\\\\\___ +// _____/\\\\\\\\__/\\\\\\\\\_______/\\\\\______________\/\\\____________/\\\\\___________\/\\\____\//\\\/\\\___/\\\\\\\\\\_____/\\\\\\\\___/\\\////\\\__ +// ___/\\\//////__\////\\\//______/\\\///\\\____________\/\\\\\\\\\____/\\\///\\\____/\\\\\\\\\_____\//\\\\\___\/\\\//////____/\\\/////\\\_\//\\\\\\\\\__ +// __/\\\____________\/\\\_______/\\\__\//\\\___________\/\\\////\\\__/\\\__\//\\\__/\\\////\\\______\//\\\____\/\\\\\\\\\\__/\\\\\\\\\\\___\///////\\\__ +// _\//\\\___________\/\\\______\//\\\__/\\\____________\/\\\__\/\\\_\//\\\__/\\\__\/\\\__\/\\\___/\\_/\\\_____\////////\\\_\//\\///////__________\/\\\__ +// __\///\\\\\\\\____\/\\\_______\///\\\\\/_____________\/\\\\\\\\\___\///\\\\\/___\//\\\\\\\/\\_\//\\\\/_______/\\\\\\\\\\__\//\\\\\\\\\\________\/\\\\_ +// ____\////////_____\///__________\/////_______________\/////////______\/////______\///////\//___\////________\//////////____\//////////_________\////__ +// CFO BODYSEQ sequencer, 3 button version, reworked interaction, http://www.vsionhairies.info/ + +#define MIDI_CHANNEL 1 +#include +#include +#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(); + } + } +} diff --git a/examples/CFO_BODYSEQ_3buttons_sequenced_audio/CFO_BODYSEQ_3buttons_sequenced_audio.ino b/examples/CFO_BODYSEQ_3buttons_sequenced_audio/CFO_BODYSEQ_3buttons_sequenced_audio.ino new file mode 100755 index 0000000..3c28a36 --- /dev/null +++ b/examples/CFO_BODYSEQ_3buttons_sequenced_audio/CFO_BODYSEQ_3buttons_sequenced_audio.ino @@ -0,0 +1,81 @@ +#define MIDI_CHANNEL 1 + +#include +#include +#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(); + } + } +} diff --git a/examples/CFO_BODYSEQ_O/CFO_BODYSEQ_O.ino b/examples/CFO_BODYSEQ_O/CFO_BODYSEQ_O.ino new file mode 100755 index 0000000..1873185 --- /dev/null +++ b/examples/CFO_BODYSEQ_O/CFO_BODYSEQ_O.ino @@ -0,0 +1,234 @@ +//______________________/\\\\\__________________________/\\\______________________________/\\\__________________________________________________________ +// ____________________/\\\///__________________________\/\\\_____________________________\/\\\__________________________________________________________ +// ___________________/\\\______________________________\/\\\_____________________________\/\\\_____/\\\__/\\\_______________________________/\\\\\\\\___ +// _____/\\\\\\\\__/\\\\\\\\\_______/\\\\\______________\/\\\____________/\\\\\___________\/\\\____\//\\\/\\\___/\\\\\\\\\\_____/\\\\\\\\___/\\\////\\\__ +// ___/\\\//////__\////\\\//______/\\\///\\\____________\/\\\\\\\\\____/\\\///\\\____/\\\\\\\\\_____\//\\\\\___\/\\\//////____/\\\/////\\\_\//\\\\\\\\\__ +// __/\\\____________\/\\\_______/\\\__\//\\\___________\/\\\////\\\__/\\\__\//\\\__/\\\////\\\______\//\\\____\/\\\\\\\\\\__/\\\\\\\\\\\___\///////\\\__ +// _\//\\\___________\/\\\______\//\\\__/\\\____________\/\\\__\/\\\_\//\\\__/\\\__\/\\\__\/\\\___/\\_/\\\_____\////////\\\_\//\\///////__________\/\\\__ +// __\///\\\\\\\\____\/\\\_______\///\\\\\/_____________\/\\\\\\\\\___\///\\\\\/___\//\\\\\\\/\\_\//\\\\/_______/\\\\\\\\\\__\//\\\\\\\\\\________\/\\\\_ +// ____\////////_____\///__________\/////_______________\/////////______\/////______\///////\//___\////________\//////////____\//////////_________\////__ +// CFO BODYSEQ sequencer, 3 button version, reworked interaction, http://www.vsionhairies.info/ + +#define MIDI_CHANNEL 1 +#include +#include +#include + +#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]); + } +} diff --git a/examples/CFO_BODYSEQ_O/interface.ino b/examples/CFO_BODYSEQ_O/interface.ino new file mode 100755 index 0000000..6b16c59 --- /dev/null +++ b/examples/CFO_BODYSEQ_O/interface.ino @@ -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<= 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<>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); +} + diff --git a/examples/CFO_BODYSEQ_P/CFO_BODYSEQ_P.ino b/examples/CFO_BODYSEQ_P/CFO_BODYSEQ_P.ino new file mode 100755 index 0000000..a8e24fa --- /dev/null +++ b/examples/CFO_BODYSEQ_P/CFO_BODYSEQ_P.ino @@ -0,0 +1,110 @@ +#define MIDI_CHANNEL 1 + +#include +#include +#include + +// 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); + } +} diff --git a/examples/CFO_BODYSEQ_Q/CFO_BODYSEQ_Q.ino b/examples/CFO_BODYSEQ_Q/CFO_BODYSEQ_Q.ino new file mode 100755 index 0000000..82bd44a --- /dev/null +++ b/examples/CFO_BODYSEQ_Q/CFO_BODYSEQ_Q.ino @@ -0,0 +1,103 @@ +#define MIDI_CHANNEL 1 + +#include +#include +#include + +// 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); + } +} diff --git a/examples/CFO_BODYSEQ_SAMPLER/CFO_BODYSEQ_SAMPLER.ino b/examples/CFO_BODYSEQ_SAMPLER/CFO_BODYSEQ_SAMPLER.ino new file mode 100755 index 0000000..6cae0b5 --- /dev/null +++ b/examples/CFO_BODYSEQ_SAMPLER/CFO_BODYSEQ_SAMPLER.ino @@ -0,0 +1,286 @@ +//______________________/\\\\\__________________________/\\\______________________________/\\\__________________________________________________________ +// ____________________/\\\///__________________________\/\\\_____________________________\/\\\__________________________________________________________ +// ___________________/\\\______________________________\/\\\_____________________________\/\\\_____/\\\__/\\\_______________________________/\\\\\\\\___ +// _____/\\\\\\\\__/\\\\\\\\\_______/\\\\\______________\/\\\____________/\\\\\___________\/\\\____\//\\\/\\\___/\\\\\\\\\\_____/\\\\\\\\___/\\\////\\\__ +// ___/\\\//////__\////\\\//______/\\\///\\\____________\/\\\\\\\\\____/\\\///\\\____/\\\\\\\\\_____\//\\\\\___\/\\\//////____/\\\/////\\\_\//\\\\\\\\\__ +// __/\\\____________\/\\\_______/\\\__\//\\\___________\/\\\////\\\__/\\\__\//\\\__/\\\////\\\______\//\\\____\/\\\\\\\\\\__/\\\\\\\\\\\___\///////\\\__ +// _\//\\\___________\/\\\______\//\\\__/\\\____________\/\\\__\/\\\_\//\\\__/\\\__\/\\\__\/\\\___/\\_/\\\_____\////////\\\_\//\\///////__________\/\\\__ +// __\///\\\\\\\\____\/\\\_______\///\\\\\/_____________\/\\\\\\\\\___\///\\\\\/___\//\\\\\\\/\\_\//\\\\/_______/\\\\\\\\\\__\//\\\\\\\\\\________\/\\\\_ +// ____\////////_____\///__________\/////_______________\/////////______\/////______\///////\//___\////________\//////////____\//////////_________\////__ +// CFO BODYSEQ sequencer, 3 button version, reworked interaction, http://www.vsionhairies.info/ + +#define MIDI_CHANNEL 1 +#include +#include +#include + +#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_STEPS) { + indx = 0; + if(trackChained < 0); + else { + int t = trackPlaying; + trackPlaying = trackChained; + trackChained = t; + } + } +} + diff --git a/examples/CFO_BODYSEQ_SAMPLER/interface.ino b/examples/CFO_BODYSEQ_SAMPLER/interface.ino new file mode 100755 index 0000000..60d098d --- /dev/null +++ b/examples/CFO_BODYSEQ_SAMPLER/interface.ino @@ -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< 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<>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= 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 +#include +#include + +// 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(); +} + diff --git a/examples/CFO_PROTOSEQ_KLOCKMEISTER/CFO_PROTOSEQ_KLOCKMEISTER.ino b/examples/CFO_PROTOSEQ_KLOCKMEISTER/CFO_PROTOSEQ_KLOCKMEISTER.ino new file mode 100755 index 0000000..01c0dec --- /dev/null +++ b/examples/CFO_PROTOSEQ_KLOCKMEISTER/CFO_PROTOSEQ_KLOCKMEISTER.ino @@ -0,0 +1,58 @@ +#define MIDI_CHANNEL 1 + +#include +#include +#include + +// 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()"); +} + diff --git a/examples/CFO_PROTOSEQ_SLAVE/CFO_PROTOSEQ_SLAVE.ino b/examples/CFO_PROTOSEQ_SLAVE/CFO_PROTOSEQ_SLAVE.ino new file mode 100755 index 0000000..e56bd50 --- /dev/null +++ b/examples/CFO_PROTOSEQ_SLAVE/CFO_PROTOSEQ_SLAVE.ino @@ -0,0 +1,53 @@ +#define MIDI_CHANNEL 2 + +#include +#include +#include + +// 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(); +} + diff --git a/examples/Music/Init_midi/Init_midi.ino b/examples/Music/Init_midi/Init_midi.ino new file mode 100755 index 0000000..a1481d3 --- /dev/null +++ b/examples/Music/Init_midi/Init_midi.ino @@ -0,0 +1,66 @@ +#define MIDI_CHANNEL 1 + +#include +#include +#include + +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; + } +} diff --git a/examples/Music/Music_tutorial_files.txt b/examples/Music/Music_tutorial_files.txt new file mode 100755 index 0000000..e5416d3 --- /dev/null +++ b/examples/Music/Music_tutorial_files.txt @@ -0,0 +1 @@ +Put Music Tutorial sketches in this folder \ No newline at end of file diff --git a/examples/Music/_6_noteOn_noteOff/_6_noteOn_noteOff.ino b/examples/Music/_6_noteOn_noteOff/_6_noteOn_noteOff.ino new file mode 100755 index 0000000..696ccc3 --- /dev/null +++ b/examples/Music/_6_noteOn_noteOff/_6_noteOn_noteOff.ino @@ -0,0 +1,60 @@ +#include +#include +#include + +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; + } + +} diff --git a/examples/sampler/sampler.ino b/examples/sampler/sampler.ino new file mode 100755 index 0000000..7a76600 --- /dev/null +++ b/examples/sampler/sampler.ino @@ -0,0 +1,84 @@ +#define MIDI_CHANNEL 1 + +#include +#include +#include + +// 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; +} diff --git a/examples/sampler_and_sequenced_audio/sampler_and_sequenced_audio.ino b/examples/sampler_and_sequenced_audio/sampler_and_sequenced_audio.ino new file mode 100755 index 0000000..b782ad4 --- /dev/null +++ b/examples/sampler_and_sequenced_audio/sampler_and_sequenced_audio.ino @@ -0,0 +1,131 @@ +#define MIDI_CHANNEL 1 + +#include +#include +#include + +// 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; +} diff --git a/examples/sequenced_audio/sequenced_audio.ino b/examples/sequenced_audio/sequenced_audio.ino new file mode 100755 index 0000000..e6b640d --- /dev/null +++ b/examples/sequenced_audio/sequenced_audio.ino @@ -0,0 +1,60 @@ +#define MIDI_CHANNEL 1 + +#include +#include +#include + +// 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; +} diff --git a/examples/sequenced_audio2/sequenced_audio2.ino b/examples/sequenced_audio2/sequenced_audio2.ino new file mode 100755 index 0000000..bd18f5f --- /dev/null +++ b/examples/sequenced_audio2/sequenced_audio2.ino @@ -0,0 +1,79 @@ +#define MIDI_CHANNEL 1 + +#include +#include +#include + +// 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; +} diff --git a/examples/sequenced_audio3/sequenced_audio3.ino b/examples/sequenced_audio3/sequenced_audio3.ino new file mode 100755 index 0000000..73f60c1 --- /dev/null +++ b/examples/sequenced_audio3/sequenced_audio3.ino @@ -0,0 +1,86 @@ +#define MIDI_CHANNEL 1 + +#include +#include +#include + +// 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; +} diff --git a/examples/sequenced_audio4/sequenced_audio4.ino b/examples/sequenced_audio4/sequenced_audio4.ino new file mode 100755 index 0000000..627b71c --- /dev/null +++ b/examples/sequenced_audio4/sequenced_audio4.ino @@ -0,0 +1,76 @@ +#define MIDI_CHANNEL 1 + +#include +#include +#include + +// 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; +}