diff --git a/NuEVI/NuEVI.ino b/NuEVI/NuEVI.ino index 60d914b..4af1cd8 100644 --- a/NuEVI/NuEVI.ino +++ b/NuEVI/NuEVI.ino @@ -98,7 +98,7 @@ unsigned short harmSetting; // 0-7 unsigned short harmSelect; // 0-5 unsigned short brHarmSetting; // 0-7 unsigned short brHarmSelect; // 0-3 -unsigned short polySelect; // OFF, MGR, MGD, MND, MNH, FWC, RTA, RTB or RTC +EPolySelect polySelect; // OFF, MGR, MGD, MND, MNH, FWC, RTA, RTB or RTC unsigned short fwcType; // 6, m6, 7, m7 unsigned short fwcLockH; // OFF:ON unsigned short fwcDrop2; // OFF:ON @@ -132,12 +132,10 @@ uint16_t dacMode; byte rotatorOn = 0; byte currentRotation = 3; -uint16_t rotations[4]; // semitones { -5, -10, -7, -14 }; -uint16_t parallel; // = 7; // semitones -uint16_t rotationsb[4]; -uint16_t parallelb; // semitones -uint16_t rotationsc[4]; -uint16_t parallelc; // semitones + +Rotator rotations_a; +Rotator rotations_b; +Rotator rotations_c; byte gateOpen = 0; // setting for gate always open, note on sent for every time fingering changes, no matter the breath status uint16_t gateOpenEnable = 0; @@ -949,7 +947,7 @@ void loop() { #else specialKey = (touchRead(specialKeyPin) > touch_Thr); //S2 on pcb #endif - if (polySelect) { + if (polySelect != HarmonizerOff) { if (lastSpecialKey != specialKey) { if (specialKey) { // special key just pressed, check other keys @@ -1078,69 +1076,7 @@ void loop() { } } if (rotatorOn) { - if (MGR == polySelect){ // Triad Major Gospel Root - midiSendNoteOn(noteValueCheck(fingeredNote+majGosRootHmz[(fingeredNote-hmzKey)%12][0]), velocitySend); - if (hmzLimit>2) midiSendNoteOn(noteValueCheck(fingeredNote+majGosRootHmz[(fingeredNote-hmzKey)%12][1]), velocitySend); - if (hmzLimit>3) midiSendNoteOn(noteValueCheck(fingeredNote+majGosRootHmz[(fingeredNote-hmzKey)%12][2]), velocitySend); - } else if (MGD == polySelect){ // Triad Major Gospel Dominant - midiSendNoteOn(noteValueCheck(fingeredNote+majGosDomHmz[(fingeredNote-hmzKey)%12][0]), velocitySend); - if (hmzLimit>2) midiSendNoteOn(noteValueCheck(fingeredNote+majGosDomHmz[(fingeredNote-hmzKey)%12][1]), velocitySend); - if (hmzLimit>3) midiSendNoteOn(noteValueCheck(fingeredNote+majGosDomHmz[(fingeredNote-hmzKey)%12][2]), velocitySend); - } else if (MA9 == polySelect){ // Major add9 - midiSendNoteOn(noteValueCheck(fingeredNote+majAdd9Hmz[(fingeredNote-hmzKey)%12][0]), velocitySend); - if (hmzLimit>2) midiSendNoteOn(noteValueCheck(fingeredNote+majAdd9Hmz[(fingeredNote-hmzKey)%12][1]), velocitySend); - if (hmzLimit>3) midiSendNoteOn(noteValueCheck(fingeredNote+majAdd9Hmz[(fingeredNote-hmzKey)%12][2]), velocitySend); - } else if (MND == polySelect){ // Minor Dorian - midiSendNoteOn(noteValueCheck(fingeredNote+minDorHmz[(fingeredNote-hmzKey)%12][0]), velocitySend); - if (hmzLimit>2) midiSendNoteOn(noteValueCheck(fingeredNote+minDorHmz[(fingeredNote-hmzKey)%12][1]), velocitySend); - if (hmzLimit>3) midiSendNoteOn(noteValueCheck(fingeredNote+minDorHmz[(fingeredNote-hmzKey)%12][2]), velocitySend); - } else if (MNA == polySelect){ // Minor Aeolian - midiSendNoteOn(noteValueCheck(fingeredNote+minAeoHmz[(fingeredNote-hmzKey)%12][0]), velocitySend); - if (hmzLimit>2) midiSendNoteOn(noteValueCheck(fingeredNote+minAeoHmz[(fingeredNote-hmzKey)%12][1]), velocitySend); - if (hmzLimit>3) midiSendNoteOn(noteValueCheck(fingeredNote+minAeoHmz[(fingeredNote-hmzKey)%12][2]), velocitySend); - } else if (MNH == polySelect){ // Minor 4-voice Hip - midiSendNoteOn(noteValueCheck(fingeredNote+minHipHmz[(fingeredNote-hmzKey)%12][0]), velocitySend); - if (hmzLimit>2) midiSendNoteOn(noteValueCheck(fingeredNote+minHipHmz[(fingeredNote-hmzKey)%12][1]), velocitySend); - if (hmzLimit>3) midiSendNoteOn(noteValueCheck(fingeredNote+minHipHmz[(fingeredNote-hmzKey)%12][2]), velocitySend); - } else if (FWC == polySelect){ // Four Way Close Harmonizer - if (!fwcDrop2 || (hmzLimit>(3+fwcLockH))) midiSendNoteOn(noteValueCheck(fingeredNote+blockFWC[fwcType][(fingeredNote-hmzKey)%12][0]-12*fwcDrop2), velocitySend); - if ((hmzLimit+fwcDrop2)>2) midiSendNoteOn(noteValueCheck(fingeredNote+blockFWC[fwcType][(fingeredNote-hmzKey)%12][1]), velocitySend); - if ((hmzLimit+fwcDrop2)>3) midiSendNoteOn(noteValueCheck(fingeredNote+blockFWC[fwcType][(fingeredNote-hmzKey)%12][2]), velocitySend); - if (((hmzLimit+fwcDrop2)>4) && (1 == fwcLockH)) midiSendNoteOn(noteValueCheck(fingeredNote-12), velocitySend); - } else if (RT1 == polySelect) { // Rotator A - if (parallel-24) midiSendNoteOn(noteValueCheck(fingeredNote + parallel-24), velocitySend); // send Note On message for new note - if (currentRotation < 3) currentRotation++; - else currentRotation = 0; - int allCheck=4; - while ((0 == rotations[currentRotation]-24) && allCheck){ - if (currentRotation < 3) currentRotation++; - else currentRotation = 0; - allCheck--; - } - if (rotations[currentRotation]-24) midiSendNoteOn(noteValueCheck(fingeredNote + rotations[currentRotation]-24), velocitySend); // send Note On message for new note - } else if (RT2 == polySelect) { // Rotator B - if (parallelb-24) midiSendNoteOn(noteValueCheck(fingeredNote + parallelb-24), velocitySend); // send Note On message for new note - if (currentRotation < 3) currentRotation++; - else currentRotation = 0; - int allCheck=4; - while ((0 == rotationsb[currentRotation]-24) && allCheck){ - if (currentRotation < 3) currentRotation++; - else currentRotation = 0; - allCheck--; - } - if (rotationsb[currentRotation]-24) midiSendNoteOn(noteValueCheck(fingeredNote + rotationsb[currentRotation]-24), velocitySend); // send Note On message for new note - } else if (RT3 == polySelect) { // Rotator C - if (parallelc-24) midiSendNoteOn(noteValueCheck(fingeredNote + parallelc-24), velocitySend); // send Note On message for new note - if (currentRotation < 3) currentRotation++; - else currentRotation = 0; - int allCheck=4; - while ((0 == rotationsc[currentRotation]-24) && allCheck){ - if (currentRotation < 3) currentRotation++; - else currentRotation = 0; - allCheck--; - } - if (rotationsc[currentRotation]-24) midiSendNoteOn(noteValueCheck(fingeredNote + rotationsc[currentRotation]-24), velocitySend); // send Note On message for new note - } + startHarmonizerNotes(fingeredNote); } if (!priority) { // mono prio to base note midiSendNoteOn(fingeredNote, velocitySend); // send Note On message for new note @@ -1174,45 +1110,7 @@ void loop() { } } if (rotatorOn) { - if (MGR == polySelect){ // Triad Major Gospel Root - midiSendNoteOff(noteValueCheck(activeNote+majGosRootHmz[(activeNote-hmzKey)%12][0])); - if (hmzLimit>2) midiSendNoteOff(noteValueCheck(activeNote+majGosRootHmz[(activeNote-hmzKey)%12][1])); - if (hmzLimit>3) midiSendNoteOff(noteValueCheck(activeNote+majGosRootHmz[(activeNote-hmzKey)%12][2])); - } else if (MGD == polySelect){ // Triad Major Gospel Dominant - midiSendNoteOff(noteValueCheck(activeNote+majGosDomHmz[(activeNote-hmzKey)%12][0])); - if (hmzLimit>2) midiSendNoteOff(noteValueCheck(activeNote+majGosDomHmz[(activeNote-hmzKey)%12][1])); - if (hmzLimit>3) midiSendNoteOff(noteValueCheck(activeNote+majGosDomHmz[(activeNote-hmzKey)%12][2])); - } else if (MA9 == polySelect){ // Major add9 - midiSendNoteOff(noteValueCheck(activeNote+majAdd9Hmz[(activeNote-hmzKey)%12][0])); - if (hmzLimit>2) midiSendNoteOff(noteValueCheck(activeNote+majAdd9Hmz[(activeNote-hmzKey)%12][1])); - if (hmzLimit>3) midiSendNoteOff(noteValueCheck(activeNote+majAdd9Hmz[(activeNote-hmzKey)%12][2])); - } else if (MND == polySelect){ // Minor Dorian - midiSendNoteOff(noteValueCheck(activeNote+minDorHmz[(activeNote-hmzKey)%12][0])); - if (hmzLimit>2) midiSendNoteOff(noteValueCheck(activeNote+minDorHmz[(activeNote-hmzKey)%12][1])); - if (hmzLimit>3) midiSendNoteOff(noteValueCheck(activeNote+minDorHmz[(activeNote-hmzKey)%12][2])); - } else if (MNA == polySelect){ // Minor Dorian - midiSendNoteOff(noteValueCheck(activeNote+minAeoHmz[(activeNote-hmzKey)%12][0])); - if (hmzLimit>2) midiSendNoteOff(noteValueCheck(activeNote+minAeoHmz[(activeNote-hmzKey)%12][1])); - if (hmzLimit>3) midiSendNoteOff(noteValueCheck(activeNote+minAeoHmz[(activeNote-hmzKey)%12][2])); - } else if (MNH == polySelect){ // Minor 4-voice Hip - midiSendNoteOff(noteValueCheck(activeNote+minHipHmz[(activeNote-hmzKey)%12][0])); - if (hmzLimit>2) midiSendNoteOff(noteValueCheck(activeNote+minHipHmz[(activeNote-hmzKey)%12][1])); - if (hmzLimit>3) midiSendNoteOff(noteValueCheck(activeNote+minHipHmz[(activeNote-hmzKey)%12][2])); - } else if (FWC == polySelect){ // Four Way Close Harmonizer - if (!fwcDrop2 || (hmzLimit>(3+fwcLockH))) midiSendNoteOff(noteValueCheck(activeNote+blockFWC[fwcType][(activeNote-hmzKey)%12][0]-12*fwcDrop2)); - if ((hmzLimit+fwcDrop2)>2) midiSendNoteOff(noteValueCheck(activeNote+blockFWC[fwcType][(activeNote-hmzKey)%12][1])); - if ((hmzLimit+fwcDrop2)>3) midiSendNoteOff(noteValueCheck(activeNote+blockFWC[fwcType][(activeNote-hmzKey)%12][2])); - if (((hmzLimit+fwcDrop2)>4) && (1 == fwcLockH)) midiSendNoteOff(noteValueCheck(activeNote-12)); - } else if (RT1 == polySelect){ // Rotator A - if (parallel - 24) midiSendNoteOff(noteValueCheck(activeNote + parallel-24 )); // send Note Off message for old note - if (rotations[currentRotation]-24) midiSendNoteOff(noteValueCheck(activeNote + rotations[currentRotation]-24)); // send Note Off message for old note - } else if (RT2 == polySelect){ // Rotator B - if (parallelb - 24) midiSendNoteOff(noteValueCheck(activeNote + parallelb-24 )); // send Note Off message for old note - if (rotationsb[currentRotation]-24) midiSendNoteOff(noteValueCheck(activeNote + rotationsb[currentRotation]-24)); // send Note Off message for old note - } else if (RT3 == polySelect){ // Rotator C - if (parallelc - 24) midiSendNoteOff(noteValueCheck(activeNote + parallelc-24 )); // send Note Off message for old note - if (rotationsc[currentRotation]-24) midiSendNoteOff(noteValueCheck(activeNote + rotationsc[currentRotation]-24)); // send Note Off message for old note - } + stopHarmonizerNotes(activeNote); } if (!priority) { midiSendNoteOff(activeNote); // send Note Off message @@ -1252,46 +1150,9 @@ void loop() { } } if (rotatorOn) { - if (MGR == polySelect){ // Triad Major Gospel Root - midiSendNoteOff(noteValueCheck(activeNote+majGosRootHmz[(activeNote-hmzKey)%12][0])); - if (hmzLimit>2) midiSendNoteOff(noteValueCheck(activeNote+majGosRootHmz[(activeNote-hmzKey)%12][1])); - if (hmzLimit>3) midiSendNoteOff(noteValueCheck(activeNote+majGosRootHmz[(activeNote-hmzKey)%12][2])); - } else if (MGD == polySelect){ // Triad Major Gospel Dominant - midiSendNoteOff(noteValueCheck(activeNote+majGosDomHmz[(activeNote-hmzKey)%12][0])); - if (hmzLimit>2) midiSendNoteOff(noteValueCheck(activeNote+majGosDomHmz[(activeNote-hmzKey)%12][1])); - if (hmzLimit>3) midiSendNoteOff(noteValueCheck(activeNote+majGosDomHmz[(activeNote-hmzKey)%12][2])); - } else if (MA9 == polySelect){ // Major add9 - midiSendNoteOff(noteValueCheck(activeNote+majAdd9Hmz[(activeNote-hmzKey)%12][0])); - if (hmzLimit>2) midiSendNoteOff(noteValueCheck(activeNote+majAdd9Hmz[(activeNote-hmzKey)%12][1])); - if (hmzLimit>3) midiSendNoteOff(noteValueCheck(activeNote+majAdd9Hmz[(activeNote-hmzKey)%12][2])); - } else if (MND == polySelect){ // Minor Dorian - midiSendNoteOff(noteValueCheck(activeNote+minDorHmz[(activeNote-hmzKey)%12][0])); - if (hmzLimit>2) midiSendNoteOff(noteValueCheck(activeNote+minDorHmz[(activeNote-hmzKey)%12][1])); - if (hmzLimit>3) midiSendNoteOff(noteValueCheck(activeNote+minDorHmz[(activeNote-hmzKey)%12][2])); - } else if (MNA == polySelect){ // Minor Dorian - midiSendNoteOff(noteValueCheck(activeNote+minAeoHmz[(activeNote-hmzKey)%12][0])); - if (hmzLimit>2) midiSendNoteOff(noteValueCheck(activeNote+minAeoHmz[(activeNote-hmzKey)%12][1])); - if (hmzLimit>3) midiSendNoteOff(noteValueCheck(activeNote+minAeoHmz[(activeNote-hmzKey)%12][2])); - } else if (MNH == polySelect){ // Minor 4-voice Hip - midiSendNoteOff(noteValueCheck(activeNote+minHipHmz[(activeNote-hmzKey)%12][0])); - if (hmzLimit>2) midiSendNoteOff(noteValueCheck(activeNote+minHipHmz[(activeNote-hmzKey)%12][1])); - if (hmzLimit>3) midiSendNoteOff(noteValueCheck(activeNote+minHipHmz[(activeNote-hmzKey)%12][2])); - } else if (FWC == polySelect){ // Four Way Close Harmonizer - if (!fwcDrop2 || (hmzLimit>(3+fwcLockH))) midiSendNoteOff(noteValueCheck(activeNote+blockFWC[fwcType][(activeNote-hmzKey)%12][0]-12*fwcDrop2)); - if ((hmzLimit+fwcDrop2)>2) midiSendNoteOff(noteValueCheck(activeNote+blockFWC[fwcType][(activeNote-hmzKey)%12][1])); - if ((hmzLimit+fwcDrop2)>3) midiSendNoteOff(noteValueCheck(activeNote+blockFWC[fwcType][(activeNote-hmzKey)%12][2])); - if (((hmzLimit+fwcDrop2)>4) && (1 == fwcLockH)) midiSendNoteOff(noteValueCheck(activeNote-12)); - } else if (RT1 == polySelect){ // Rotator A - if (parallel - 24) midiSendNoteOff(noteValueCheck(activeNote + parallel-24 )); // send Note Off message for old note - if (rotations[currentRotation]-24) midiSendNoteOff(noteValueCheck(activeNote + rotations[currentRotation]-24)); // send Note Off message for old note - } else if (RT2 == polySelect){ // Rotator B - if (parallelb - 24) midiSendNoteOff(noteValueCheck(activeNote + parallelb-24 )); // send Note Off message for old note - if (rotationsb[currentRotation]-24) midiSendNoteOff(noteValueCheck(activeNote + rotationsb[currentRotation]-24)); // send Note Off message for old note - } else if (RT3 == polySelect){ // Rotator C - if (parallelc - 24) midiSendNoteOff(noteValueCheck(activeNote + parallelc-24 )); // send Note Off message for old note - if (rotationsc[currentRotation]-24) midiSendNoteOff(noteValueCheck(activeNote + rotationsc[currentRotation]-24)); // send Note Off message for old note - } + stopHarmonizerNotes(activeNote); } + if ((parallelChord || subOctaveDouble || rotatorOn) && !priority) { // poly playing, send old note off before new note on midiSendNoteOff(activeNote); // send Note Off message for old note } @@ -1314,69 +1175,7 @@ void loop() { } } if (rotatorOn) { - if (MGR == polySelect){ // Triad Major Gospel Root - midiSendNoteOn(noteValueCheck(fingeredNote+majGosRootHmz[(fingeredNote-hmzKey)%12][0]), velocitySend); - if (hmzLimit>2) midiSendNoteOn(noteValueCheck(fingeredNote+majGosRootHmz[(fingeredNote-hmzKey)%12][1]), velocitySend); - if (hmzLimit>3) midiSendNoteOn(noteValueCheck(fingeredNote+majGosRootHmz[(fingeredNote-hmzKey)%12][2]), velocitySend); - } else if (MGD == polySelect){ // Triad Major Gospel Dominant - midiSendNoteOn(noteValueCheck(fingeredNote+majGosDomHmz[(fingeredNote-hmzKey)%12][0]), velocitySend); - if (hmzLimit>2) midiSendNoteOn(noteValueCheck(fingeredNote+majGosDomHmz[(fingeredNote-hmzKey)%12][1]), velocitySend); - if (hmzLimit>3) midiSendNoteOn(noteValueCheck(fingeredNote+majGosDomHmz[(fingeredNote-hmzKey)%12][2]), velocitySend); - } else if (MA9 == polySelect){ // Major add9 - midiSendNoteOn(noteValueCheck(fingeredNote+majAdd9Hmz[(fingeredNote-hmzKey)%12][0]), velocitySend); - if (hmzLimit>2) midiSendNoteOn(noteValueCheck(fingeredNote+majAdd9Hmz[(fingeredNote-hmzKey)%12][1]), velocitySend); - if (hmzLimit>3) midiSendNoteOn(noteValueCheck(fingeredNote+majAdd9Hmz[(fingeredNote-hmzKey)%12][2]), velocitySend); - } else if (MND == polySelect){ // Minor Dorian - midiSendNoteOn(noteValueCheck(fingeredNote+minDorHmz[(fingeredNote-hmzKey)%12][0]), velocitySend); - if (hmzLimit>2) midiSendNoteOn(noteValueCheck(fingeredNote+minDorHmz[(fingeredNote-hmzKey)%12][1]), velocitySend); - if (hmzLimit>3) midiSendNoteOn(noteValueCheck(fingeredNote+minDorHmz[(fingeredNote-hmzKey)%12][2]), velocitySend); - } else if (MNA == polySelect){ // Minor Aeolian - midiSendNoteOn(noteValueCheck(fingeredNote+minAeoHmz[(fingeredNote-hmzKey)%12][0]), velocitySend); - if (hmzLimit>2) midiSendNoteOn(noteValueCheck(fingeredNote+minAeoHmz[(fingeredNote-hmzKey)%12][1]), velocitySend); - if (hmzLimit>3) midiSendNoteOn(noteValueCheck(fingeredNote+minAeoHmz[(fingeredNote-hmzKey)%12][2]), velocitySend); - } else if (MNH == polySelect){ // Minor 4-voice Hip - midiSendNoteOn(noteValueCheck(fingeredNote+minHipHmz[(fingeredNote-hmzKey)%12][0]), velocitySend); - if (hmzLimit>2) midiSendNoteOn(noteValueCheck(fingeredNote+minHipHmz[(fingeredNote-hmzKey)%12][1]), velocitySend); - if (hmzLimit>3) midiSendNoteOn(noteValueCheck(fingeredNote+minHipHmz[(fingeredNote-hmzKey)%12][2]), velocitySend); - } else if (FWC == polySelect){ // Four Way Close Harmonizer - if (!fwcDrop2 || (hmzLimit>(3+fwcLockH))) midiSendNoteOn(noteValueCheck(fingeredNote+blockFWC[fwcType][(fingeredNote-hmzKey)%12][0]-12*fwcDrop2), velocitySend); - if ((hmzLimit+fwcDrop2)>2) midiSendNoteOn(noteValueCheck(fingeredNote+blockFWC[fwcType][(fingeredNote-hmzKey)%12][1]), velocitySend); - if ((hmzLimit+fwcDrop2)>3) midiSendNoteOn(noteValueCheck(fingeredNote+blockFWC[fwcType][(fingeredNote-hmzKey)%12][2]), velocitySend); - if (((hmzLimit+fwcDrop2)>4) && (1 == fwcLockH)) midiSendNoteOn(noteValueCheck(fingeredNote-12), velocitySend); - } else if (RT1 == polySelect) { // Rotator A - if (parallel-24) midiSendNoteOn(noteValueCheck(fingeredNote + parallel-24), velocitySend); // send Note On message for new note - if (currentRotation < 3) currentRotation++; - else currentRotation = 0; - int allCheck=4; - while ((0 == rotations[currentRotation]-24) && allCheck){ - if (currentRotation < 3) currentRotation++; - else currentRotation = 0; - allCheck--; - } - if (rotations[currentRotation]-24) midiSendNoteOn(noteValueCheck(fingeredNote + rotations[currentRotation]-24), velocitySend); // send Note On message for new note - } else if (RT2 == polySelect) { // Rotator B - if (parallelb-24) midiSendNoteOn(noteValueCheck(fingeredNote + parallelb-24), velocitySend); // send Note On message for new note - if (currentRotation < 3) currentRotation++; - else currentRotation = 0; - int allCheck=4; - while ((0 == rotationsb[currentRotation]-24) && allCheck){ - if (currentRotation < 3) currentRotation++; - else currentRotation = 0; - allCheck--; - } - if (rotationsb[currentRotation]-24) midiSendNoteOn(noteValueCheck(fingeredNote + rotationsb[currentRotation]-24), velocitySend); // send Note On message for new note - } else if (RT3 == polySelect) { // Rotator C - if (parallelc-24) midiSendNoteOn(noteValueCheck(fingeredNote + parallelc-24), velocitySend); // send Note On message for new note - if (currentRotation < 3) currentRotation++; - else currentRotation = 0; - int allCheck=4; - while ((0 == rotationsc[currentRotation]-24) && allCheck){ - if (currentRotation < 3) currentRotation++; - else currentRotation = 0; - allCheck--; - } - if (rotationsc[currentRotation]-24) midiSendNoteOn(noteValueCheck(fingeredNote + rotationsc[currentRotation]-24), velocitySend); // send Note On message for new note - } + startHarmonizerNotes(fingeredNote); } if (!priority) { @@ -1401,7 +1200,7 @@ void loop() { } // Is it time to send more CC data? currentTime = millis(); - if (currentTime - ccBreathSendTime > (breathInterval-1)){ + if ((currentTime - ccBreathSendTime) > (breathInterval-1u)){ breath(); ccBreathSendTime = currentTime; } @@ -1486,7 +1285,103 @@ void loop() { //_______________________________________________________________________________________________ FUNCTIONS +static void sendHarmonizerData( uint8_t note, const int harmony[][3], bool sendOn ) +{ + const int* offs = harmony[(note-hmzKey)%12]; + if(sendOn) { + midiSendNoteOn(noteValueCheck(note+offs[0]), velocitySend); + if (hmzLimit>2) midiSendNoteOn(noteValueCheck(note+offs[1]), velocitySend); + if (hmzLimit>3) midiSendNoteOn(noteValueCheck(note+offs[2]), velocitySend); + } else { + midiSendNoteOff(noteValueCheck(note+offs[0])); + if (hmzLimit>2) midiSendNoteOff(noteValueCheck(note+offs[1])); + if (hmzLimit>3) midiSendNoteOff(noteValueCheck(note+offs[2])); + } +} +//************************************************************** + +static void updateRotator(byte note, const Rotator *rotator) { + auto parallel = rotator->parallel; + auto rotations = rotator->rotations; + + if (parallel-24) { + midiSendNoteOn(noteValueCheck(note + parallel-24), velocitySend); // send Note On message for new note + } + + currentRotation = (currentRotation +1) % 4; + + int allCheck=4; + while ((0 == rotations[currentRotation]-24) && allCheck){ + if (currentRotation < 3) currentRotation++; + else currentRotation = 0; + allCheck--; + } + if (rotations[currentRotation]-24) midiSendNoteOn(noteValueCheck(note + rotations[currentRotation]-24), velocitySend); // send Note On message for new note +} + +//************************************************************** + +static void stopRotatorNotes(byte note, const Rotator *rotator) { + if (rotator->parallel - 24) midiSendNoteOff(noteValueCheck(note + rotator->parallel-24 )); // send Note Off message for old note + if (rotator->rotations[currentRotation]-24) midiSendNoteOff(noteValueCheck(note + rotator->rotations[currentRotation]-24)); // send Note Off message for old note +} + +static void stopHarmonizerNotes(byte note) +{ + switch(polySelect) { + case TriadMajorGospelRoot: sendHarmonizerData(note, majGosRootHmz, false); break; + case TriadMajorGospelDominant: sendHarmonizerData(note, majGosDomHmz, false); break; + case MajorAddNine: sendHarmonizerData(note, majAdd9Hmz, false); break; + case MinorDorian: sendHarmonizerData(note, minDorHmz, false); break; + case MinorAeolian: sendHarmonizerData(note, minAeoHmz, false); break; + case MinorFourVoiceHip: sendHarmonizerData(note, minHipHmz, false); break; + case FourWayCloseHarmonizer: + { + if (!fwcDrop2 || (hmzLimit>(3+fwcLockH))) midiSendNoteOff(noteValueCheck(note+blockFWC[fwcType][(note-hmzKey)%12][0]-12*fwcDrop2)); + if ((hmzLimit+fwcDrop2)>2) midiSendNoteOff(noteValueCheck(note+blockFWC[fwcType][(note-hmzKey)%12][1])); + if ((hmzLimit+fwcDrop2)>3) midiSendNoteOff(noteValueCheck(note+blockFWC[fwcType][(note-hmzKey)%12][2])); + if (((hmzLimit+fwcDrop2)>4) && (1 == fwcLockH)) midiSendNoteOff(noteValueCheck(note-12)); + } + break; + + case RotatorA: stopRotatorNotes(note, &rotations_a); break; + case RotatorB: stopRotatorNotes(note, &rotations_b); break; + case RotatorC: stopRotatorNotes(note, &rotations_c); break; + + default: break; + } +} + +static void startHarmonizerNotes(byte note) +{ + switch(polySelect) { + case TriadMajorGospelRoot: sendHarmonizerData(note, majGosRootHmz, true); break; + case TriadMajorGospelDominant: sendHarmonizerData(note, majGosDomHmz, true); break; + case MajorAddNine: sendHarmonizerData(note, majAdd9Hmz, true); break; + case MinorDorian: sendHarmonizerData(note, minDorHmz, true); break; + case MinorAeolian: sendHarmonizerData(note, minAeoHmz, true); break; + case MinorFourVoiceHip: sendHarmonizerData(note, minHipHmz, true); break; + case FourWayCloseHarmonizer: + { + int limit = (hmzLimit+fwcDrop2); + if (!fwcDrop2 || (hmzLimit>(3+fwcLockH))) midiSendNoteOn(noteValueCheck(note+blockFWC[fwcType][(note-hmzKey)%12][0]-12*fwcDrop2), velocitySend); + if (limit>2) midiSendNoteOn(noteValueCheck(note+blockFWC[fwcType][(note-hmzKey)%12][1]), velocitySend); + if (limit>3) midiSendNoteOn(noteValueCheck(note+blockFWC[fwcType][(note-hmzKey)%12][2]), velocitySend); + if ((limit>4) && (1 == fwcLockH)) midiSendNoteOn(noteValueCheck(note-12), velocitySend); + } + break; + + case RotatorA: updateRotator(note, &rotations_a); break; + case RotatorB: updateRotator(note, &rotations_b); break; + case RotatorC: updateRotator(note, &rotations_c); break; + + default: break; + } +} + + +//************************************************************** // non linear mapping function (http://playground.arduino.cc/Main/MultiMap) // note: the _in array should have increasing values unsigned int multiMap(unsigned short val, const unsigned short * _in, const unsigned short * _out, uint8_t size) { @@ -1515,7 +1410,7 @@ unsigned int breathCurve(unsigned int inputVal) { } // MIDI note value check with out of range octave repeat -int noteValueCheck(int note) { +inline int noteValueCheck(int note) { if (note > 127) { note = 115 + (note - 127) % 12; } else if (note < 0) { @@ -2121,7 +2016,7 @@ void readSwitches() { else if (touchValueRollers[rPin1] < ctouchThrVal) octaveR = 1; //R1 else if (lastOctaveR > 1) { octaveR = lastOctaveR; - if (otfKey && polySelect && (polySelect 1) { octaveR = lastOctaveR; - if (otfKey && polySelect && (polySelect 3020) ? "USB" : "BAT", 3); - int vLowLimit; + int vLowLimit = NMH_BAT_LOW; switch (batteryType){ case 0: vLowLimit = ALK_BAT_LOW; @@ -546,31 +546,26 @@ static void clearFPS(int trills) { //*********************************************************** // Poly Play menu -static void rotatorSave(const MenuEntrySub& __unused sub) { +static void saveRotatorSetting(const Rotator * rotator, uint16_t settingAddr) +{ int16_t stored; for(int i = 0; i < 4; ++i) { - stored = readSetting(ROTN1_ADDR+2*i); - if(stored != rotations[i]) - writeSetting(ROTN1_ADDR+2*i,(rotations[i])); + stored = readSetting(settingAddr+2*i); + if(stored != rotator->rotations[i]) + writeSetting(settingAddr+2*i,(rotator->rotations[i])); } } +static void rotatorSave(const MenuEntrySub& __unused sub) { + saveRotatorSetting(&rotations_a, ROTN1_ADDR); +} + static void rotatorBSave(const MenuEntrySub& __unused sub) { - int16_t stored; - for(int i = 0; i < 4; ++i) { - stored = readSetting(ROTB1_ADDR+2*i); - if(stored != rotationsb[i]) - writeSetting(ROTB1_ADDR+2*i,(rotationsb[i])); - } + saveRotatorSetting(&rotations_b, ROTB1_ADDR); } static void rotatorCSave(const MenuEntrySub& __unused sub) { - int16_t stored; - for(int i = 0; i < 4; ++i) { - stored = readSetting(ROTC1_ADDR+2*i); - if(stored != rotationsc[i]) - writeSetting(ROTC1_ADDR+2*i,(rotationsc[i])); - } + saveRotatorSetting(&rotations_c, ROTC1_ADDR); } @@ -579,100 +574,100 @@ static void rotatorOptionGet(SubMenuRef sub, char *out, const char** __unused un } static void parallelOptionGet(SubMenuRef __unused, char *out, const char** __unused unit) { - numToString(parallel-24, out, true); + numToString(rotations_a.parallel-24, out, true); } static void parallelBOptionGet(SubMenuRef __unused, char *out, const char** __unused unit) { - numToString(parallelb-24, out, true); + numToString(rotations_b.parallel-24, out, true); } static void parallelCOptionGet(SubMenuRef __unused, char *out, const char** __unused unit) { - numToString(parallelc-24, out, true); + numToString(rotations_c.parallel-24, out, true); } static void parallelSave(SubMenuRef __unused) { - writeSetting(PARAL_ADDR, parallel); + writeSetting(PARAL_ADDR, rotations_a.parallel); } static void parallelBSave(SubMenuRef __unused) { - writeSetting(PARAB_ADDR, parallelb); + writeSetting(PARAB_ADDR, rotations_b.parallel); } static void parallelCSave(SubMenuRef __unused) { - writeSetting(PARAC_ADDR, parallelc); + writeSetting(PARAC_ADDR, rotations_c.parallel); } const MenuEntrySub rotatorParaMenu = { - MenuType::ESub, "RTA PARAL", "SEMITONES", ¶llel, 0, 48, MenuEntryFlags::ENone, + MenuType::ESub, "RTA PARAL", "SEMITONES", &rotations_a.parallel, 0, 48, MenuEntryFlags::ENone, parallelOptionGet, parallelSave, nullptr }; const MenuEntrySub rotator1Menu = { - MenuType::ESub, "RTA ROT 1", "SEMITONES", &rotations[0], 0, 48, MenuEntryFlags::ENone, + MenuType::ESub, "RTA ROT 1", "SEMITONES", &rotations_a.rotations[0], 0, 48, MenuEntryFlags::ENone, rotatorOptionGet, rotatorSave, nullptr }; const MenuEntrySub rotator2Menu = { - MenuType::ESub, "RTA ROT 2", "SEMITONES", &rotations[1], 0, 48, MenuEntryFlags::ENone, + MenuType::ESub, "RTA ROT 2", "SEMITONES", &rotations_a.rotations[1], 0, 48, MenuEntryFlags::ENone, rotatorOptionGet, rotatorSave, nullptr }; const MenuEntrySub rotator3Menu = { - MenuType::ESub, "RTA ROT 3", "SEMITONES", &rotations[2], 0, 48, MenuEntryFlags::ENone, + MenuType::ESub, "RTA ROT 3", "SEMITONES", &rotations_a.rotations[2], 0, 48, MenuEntryFlags::ENone, rotatorOptionGet, rotatorSave, nullptr }; const MenuEntrySub rotator4Menu = { - MenuType::ESub, "RTA ROT 4", "SEMITONES", &rotations[3], 0, 48, MenuEntryFlags::ENone, + MenuType::ESub, "RTA ROT 4", "SEMITONES", &rotations_a.rotations[3], 0, 48, MenuEntryFlags::ENone, rotatorOptionGet, rotatorSave, nullptr }; const MenuEntrySub rotatorParaBMenu = { - MenuType::ESub, "RTB PARAL", "SEMITONES", ¶llelb, 0, 48, MenuEntryFlags::ENone, + MenuType::ESub, "RTB PARAL", "SEMITONES", &rotations_b.parallel, 0, 48, MenuEntryFlags::ENone, parallelBOptionGet, parallelBSave, nullptr }; const MenuEntrySub rotatorB1Menu = { - MenuType::ESub, "RTB ROT 1", "SEMITONES", &rotationsb[0], 0, 48, MenuEntryFlags::ENone, + MenuType::ESub, "RTB ROT 1", "SEMITONES", &rotations_b.rotations[0], 0, 48, MenuEntryFlags::ENone, rotatorOptionGet, rotatorBSave, nullptr }; const MenuEntrySub rotatorB2Menu = { - MenuType::ESub, "RTB ROT 2", "SEMITONES", &rotationsb[1], 0, 48, MenuEntryFlags::ENone, + MenuType::ESub, "RTB ROT 2", "SEMITONES", &rotations_b.rotations[1], 0, 48, MenuEntryFlags::ENone, rotatorOptionGet, rotatorBSave, nullptr }; const MenuEntrySub rotatorB3Menu = { - MenuType::ESub, "RTB ROT 3", "SEMITONES", &rotationsb[2], 0, 48, MenuEntryFlags::ENone, + MenuType::ESub, "RTB ROT 3", "SEMITONES", &rotations_b.rotations[2], 0, 48, MenuEntryFlags::ENone, rotatorOptionGet, rotatorBSave, nullptr }; const MenuEntrySub rotatorB4Menu = { - MenuType::ESub, "RTB ROT 4", "SEMITONES", &rotationsb[3], 0, 48, MenuEntryFlags::ENone, + MenuType::ESub, "RTB ROT 4", "SEMITONES", &rotations_b.rotations[3], 0, 48, MenuEntryFlags::ENone, rotatorOptionGet, rotatorBSave, nullptr }; const MenuEntrySub rotatorParaCMenu = { - MenuType::ESub, "RTC PARAL", "SEMITONES", ¶llelc, 0, 48, MenuEntryFlags::ENone, + MenuType::ESub, "RTC PARAL", "SEMITONES", &rotations_c.parallel, 0, 48, MenuEntryFlags::ENone, parallelCOptionGet, parallelCSave, nullptr }; const MenuEntrySub rotatorC1Menu = { - MenuType::ESub, "RTC ROT 1", "SEMITONES", &rotationsc[0], 0, 48, MenuEntryFlags::ENone, + MenuType::ESub, "RTC ROT 1", "SEMITONES", &rotations_c.rotations[0], 0, 48, MenuEntryFlags::ENone, rotatorOptionGet, rotatorCSave, nullptr }; const MenuEntrySub rotatorC2Menu = { - MenuType::ESub, "RTC ROT 2", "SEMITONES", &rotationsc[1], 0, 48, MenuEntryFlags::ENone, + MenuType::ESub, "RTC ROT 2", "SEMITONES", &rotations_c.rotations[1], 0, 48, MenuEntryFlags::ENone, rotatorOptionGet, rotatorCSave, nullptr }; const MenuEntrySub rotatorC3Menu = { - MenuType::ESub, "RTC ROT 3", "SEMITONES", &rotationsc[2], 0, 48, MenuEntryFlags::ENone, + MenuType::ESub, "RTC ROT 3", "SEMITONES", &rotations_c.rotations[2], 0, 48, MenuEntryFlags::ENone, rotatorOptionGet, rotatorCSave, nullptr }; const MenuEntrySub rotatorC4Menu = { - MenuType::ESub, "RTC ROT 4", "SEMITONES", &rotationsc[3], 0, 48, MenuEntryFlags::ENone, + MenuType::ESub, "RTC ROT 4", "SEMITONES", &rotations_c.rotations[3], 0, 48, MenuEntryFlags::ENone, rotatorOptionGet, rotatorCSave, nullptr }; @@ -839,7 +834,7 @@ static void polySelectSave(SubMenuRef __unused) { } const MenuEntrySub polySelectMenu = { - MenuType::ESub, "POLY MODE", "SELECT", &polySelect, 0,10, MenuEntryFlags::EMenuEntryWrap, + MenuType::ESub, "POLY MODE", "SELECT", (uint16_t*)&polySelect, 0,10, MenuEntryFlags::EMenuEntryWrap, polySelectOptionGet, polySelectSave, nullptr, }; diff --git a/NuEVI/settings.cpp b/NuEVI/settings.cpp index e836569..fbb2d86 100644 --- a/NuEVI/settings.cpp +++ b/NuEVI/settings.cpp @@ -216,11 +216,11 @@ void readEEPROM(const bool factoryReset) { fastPatch[5] = readSettingBounded(FP6_ADDR, 0, 127, 0); fastPatch[6] = readSettingBounded(FP7_ADDR, 0, 127, 0); dipSwBits = readSetting(DIPSW_BITS_ADDR); - parallel = readSettingBounded(PARAL_ADDR, 0, 48, PARAL_FACTORY); - rotations[0] = readSettingBounded(ROTN1_ADDR, 0, 48, ROTN1_FACTORY); - rotations[1] = readSettingBounded(ROTN2_ADDR, 0, 48, ROTN2_FACTORY); - rotations[2] = readSettingBounded(ROTN3_ADDR, 0, 48, ROTN3_FACTORY); - rotations[3] = readSettingBounded(ROTN4_ADDR, 0, 48, ROTN4_FACTORY); + rotations_a.parallel = readSettingBounded(PARAL_ADDR, 0, 48, PARAL_FACTORY); + rotations_a.rotations[0] = readSettingBounded(ROTN1_ADDR, 0, 48, ROTN1_FACTORY); + rotations_a.rotations[1] = readSettingBounded(ROTN2_ADDR, 0, 48, ROTN2_FACTORY); + rotations_a.rotations[2] = readSettingBounded(ROTN3_ADDR, 0, 48, ROTN3_FACTORY); + rotations_a.rotations[3] = readSettingBounded(ROTN4_ADDR, 0, 48, ROTN4_FACTORY); priority = readSettingBounded(PRIO_ADDR, 0, 1, PRIO_FACTORY); vibSens = readSettingBounded(VIB_SENS_ADDR, 1, 12, VIB_SENS_FACTORY); vibRetn = readSettingBounded(VIB_RETN_ADDR, 0, 4, VIB_RETN_FACTORY); @@ -245,22 +245,22 @@ void readEEPROM(const bool factoryReset) { batteryType = readSettingBounded(BATTYPE_ADDR, 0, 2, BATTYPE_FACTORY); harmSetting = readSettingBounded(HARMSET_ADDR, 0, 6, HARMSET_FACTORY); harmSelect = readSettingBounded(HARMSEL_ADDR, 0, 7, HARMSEL_FACTORY); - polySelect = readSettingBounded(POLYSEL_ADDR, 0, 10, POLYSEL_FACTORY); + polySelect = (EPolySelect)readSettingBounded(POLYSEL_ADDR, 0, 10, POLYSEL_FACTORY); fwcType = readSettingBounded(FWCTYPE_ADDR, 0, 4, FWCTYPE_FACTORY); fwcLockH = readSettingBounded(FWCLCH_ADDR, 0, 1, FWCLCH_FACTORY); fwcDrop2 = readSettingBounded(FWCDP2_ADDR, 0, 1, FWCDP2_FACTORY); hmzKey = readSettingBounded(HMZKEY_ADDR, 0, 11, HMZKEY_FACTORY); hmzLimit = readSettingBounded(HMZLIMIT_ADDR, 2, 5, HMZLIMIT_FACTORY); - parallelb = readSettingBounded(PARAB_ADDR, 0, 48, PARAB_FACTORY); - rotationsb[0] = readSettingBounded(ROTB1_ADDR, 0, 48, ROTB1_FACTORY); - rotationsb[1] = readSettingBounded(ROTB2_ADDR, 0, 48, ROTB2_FACTORY); - rotationsb[2] = readSettingBounded(ROTB3_ADDR, 0, 48, ROTB3_FACTORY); - rotationsb[3] = readSettingBounded(ROTB4_ADDR, 0, 48, ROTB4_FACTORY); - parallelc = readSettingBounded(PARAC_ADDR, 0, 48, PARAC_FACTORY); - rotationsc[0] = readSettingBounded(ROTC1_ADDR, 0, 48, ROTC1_FACTORY); - rotationsc[1] = readSettingBounded(ROTC2_ADDR, 0, 48, ROTC2_FACTORY); - rotationsc[2] = readSettingBounded(ROTC3_ADDR, 0, 48, ROTC3_FACTORY); - rotationsc[3] = readSettingBounded(ROTC4_ADDR, 0, 48, ROTC4_FACTORY); + rotations_b.parallel = readSettingBounded(PARAB_ADDR, 0, 48, PARAB_FACTORY); + rotations_b.rotations[0] = readSettingBounded(ROTB1_ADDR, 0, 48, ROTB1_FACTORY); + rotations_b.rotations[1] = readSettingBounded(ROTB2_ADDR, 0, 48, ROTB2_FACTORY); + rotations_b.rotations[2] = readSettingBounded(ROTB3_ADDR, 0, 48, ROTB3_FACTORY); + rotations_b.rotations[3] = readSettingBounded(ROTB4_ADDR, 0, 48, ROTB4_FACTORY); + rotations_c.parallel = readSettingBounded(PARAC_ADDR, 0, 48, PARAC_FACTORY); + rotations_c.rotations[0] = readSettingBounded(ROTC1_ADDR, 0, 48, ROTC1_FACTORY); + rotations_c.rotations[1] = readSettingBounded(ROTC2_ADDR, 0, 48, ROTC2_FACTORY); + rotations_c.rotations[2] = readSettingBounded(ROTC3_ADDR, 0, 48, ROTC3_FACTORY); + rotations_c.rotations[3] = readSettingBounded(ROTC4_ADDR, 0, 48, ROTC4_FACTORY); otfKey = readSettingBounded(OTFKEY_ADDR, 0, 1, OTFKEY_FACTORY); breathInterval = readSettingBounded(BRINTERV_ADDR, 3, 15, BRINTERV_FACTORY); portLimit = readSettingBounded(PORTLIMIT_ADDR, 1, 127, PORTLIMIT_FACTORY);