From c9fa7b5854d6b4e4d68d289a971c41572ad1799c Mon Sep 17 00:00:00 2001 From: Javier Nonis Date: Thu, 26 Dec 2024 19:44:10 -0300 Subject: [PATCH] Added "As Played" velocity to Midi Arp --- src/effect_midi/modarpeggiator/arpeggiator.cpp | 13 ++++++++++++- src/effect_midi/modarpeggiator/arpeggiator.hpp | 3 ++- src/effect_midi/modarpeggiator/utils.cpp | 3 ++- src/effect_midi/modarpeggiator/utils.hpp | 2 +- src/midi_effects.h | 11 +++++++++++ src/uimenu.cpp | 2 +- 6 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/effect_midi/modarpeggiator/arpeggiator.cpp b/src/effect_midi/modarpeggiator/arpeggiator.cpp index 7bec02b..d04e26e 100644 --- a/src/effect_midi/modarpeggiator/arpeggiator.cpp +++ b/src/effect_midi/modarpeggiator/arpeggiator.cpp @@ -269,6 +269,7 @@ void Arpeggiator::reset() for (unsigned i = 0; i < NUM_VOICES; i++) { midiNotes[i][MIDI_NOTE] = EMPTY_SLOT; + midiNotes[i][MIDI_NOTE_VELOCITY] = 0; midiNotes[i][MIDI_CHANNEL] = 0; } } @@ -304,6 +305,7 @@ void Arpeggiator::process(const MidiEvent* events, uint32_t eventCount, uint32_t for (unsigned clear_notes = 0; clear_notes < NUM_VOICES; clear_notes++) { midiNotes[clear_notes][MIDI_NOTE] = EMPTY_SLOT; + midiNotes[clear_notes][MIDI_NOTE_VELOCITY] = 0; midiNotes[clear_notes][MIDI_CHANNEL] = 0; } } @@ -325,6 +327,7 @@ void Arpeggiator::process(const MidiEvent* events, uint32_t eventCount, uint32_t uint8_t status = events[i].data[0] & 0xF0; uint8_t midiNote = events[i].data[1]; + uint8_t midiNoteVelocity = events[i].data[2]; uint8_t noteToFind; uint8_t foundNote; size_t searchNote; @@ -364,6 +367,7 @@ void Arpeggiator::process(const MidiEvent* events, uint32_t eventCount, uint32_t activeNotes = 0; for (unsigned i = 0; i < NUM_VOICES; i++) { midiNotes[i][MIDI_NOTE] = EMPTY_SLOT; + midiNotes[i][MIDI_NOTE_VELOCITY] = 0; midiNotes[i][MIDI_CHANNEL] = 0; } } @@ -388,6 +392,7 @@ void Arpeggiator::process(const MidiEvent* events, uint32_t eventCount, uint32_t { if (midiNotes[findFreeVoice][MIDI_NOTE] == EMPTY_SLOT) { midiNotes[findFreeVoice][MIDI_NOTE] = midiNote; + midiNotes[findFreeVoice][MIDI_NOTE_VELOCITY] = midiNoteVelocity; midiNotes[findFreeVoice][MIDI_CHANNEL] = channel; voiceFound = true; } @@ -437,6 +442,7 @@ void Arpeggiator::process(const MidiEvent* events, uint32_t eventCount, uint32_t if (!latchMode) { midiNotes[foundNote][MIDI_NOTE] = EMPTY_SLOT; + midiNotes[foundNote][MIDI_NOTE_VELOCITY] = 0; midiNotes[foundNote][MIDI_CHANNEL] = 0; if (arpMode != ARP_PLAYED) utils.quicksort(midiNotes, 0, NUM_VOICES - 1); @@ -593,6 +599,7 @@ void Arpeggiator::process(const MidiEvent* events, uint32_t eventCount, uint32_t { //create MIDI note on message uint8_t midiNote = midiNotes[notePlayed][MIDI_NOTE]; + uint8_t midiNoteVelocity = midiNotes[notePlayed][MIDI_NOTE_VELOCITY]; uint8_t channel = midiNotes[notePlayed][MIDI_CHANNEL]; if (arpEnabled) { @@ -606,7 +613,11 @@ void Arpeggiator::process(const MidiEvent* events, uint32_t eventCount, uint32_t midiEvent.size = 3; midiEvent.data[0] = MIDI_NOTEON | channel; midiEvent.data[1] = midiNote; - midiEvent.data[2] = velocity; + if (velocity > 0) { + midiEvent.data[2] = velocity; + } else { + midiEvent.data[2] = midiNoteVelocity; + } midiHandler.appendMidiMessage(midiEvent); diff --git a/src/effect_midi/modarpeggiator/arpeggiator.hpp b/src/effect_midi/modarpeggiator/arpeggiator.hpp index f92b008..31ca6a4 100644 --- a/src/effect_midi/modarpeggiator/arpeggiator.hpp +++ b/src/effect_midi/modarpeggiator/arpeggiator.hpp @@ -18,6 +18,7 @@ #define MIDI_NOTE 0 #define MIDI_CHANNEL 1 +#define MIDI_NOTE_VELOCITY 2 #define TIMER 2 #define NUM_ARP_MODES 6 @@ -71,7 +72,7 @@ public: struct MidiBuffer getMidiBuffer(); void process(const MidiEvent* event, uint32_t eventCount, uint32_t n_frames); private: - uint8_t midiNotes[NUM_VOICES][2]; + uint8_t midiNotes[NUM_VOICES][3]; uint8_t midiNotesBypassed[NUM_VOICES]; uint32_t noteOffBuffer[NUM_NOTE_OFF_SLOTS][3]; diff --git a/src/effect_midi/modarpeggiator/utils.cpp b/src/effect_midi/modarpeggiator/utils.cpp index 16eebae..c0c24bb 100644 --- a/src/effect_midi/modarpeggiator/utils.cpp +++ b/src/effect_midi/modarpeggiator/utils.cpp @@ -18,7 +18,7 @@ void ArpUtils::swap(uint8_t *a, uint8_t *b) } //got the code for the quick sort algorithm here https://medium.com/human-in-a-machine-world/quicksort-the-best-sorting-algorithm-6ab461b5a9d0 -void ArpUtils::quicksort(uint8_t arr[][2], int l, int r) +void ArpUtils::quicksort(uint8_t arr[][3], int l, int r) { if (l >= r) { @@ -35,6 +35,7 @@ void ArpUtils::quicksort(uint8_t arr[][2], int l, int r) { swap(&arr[cnt][0], &arr[i][0]); swap(&arr[cnt][1], &arr[i][1]); + swap(&arr[cnt][2], &arr[i][2]); cnt++; } } diff --git a/src/effect_midi/modarpeggiator/utils.hpp b/src/effect_midi/modarpeggiator/utils.hpp index 2614440..b814d5f 100644 --- a/src/effect_midi/modarpeggiator/utils.hpp +++ b/src/effect_midi/modarpeggiator/utils.hpp @@ -7,7 +7,7 @@ class ArpUtils { public: ArpUtils(); ~ArpUtils(); - void quicksort(uint8_t arr[][2], int l, int r); + void quicksort(uint8_t arr[][3], int l, int r); private: void swap(uint8_t *a, uint8_t *b); }; diff --git a/src/midi_effects.h b/src/midi_effects.h index 745ece4..5dc3d76 100644 --- a/src/midi_effects.h +++ b/src/midi_effects.h @@ -116,4 +116,15 @@ inline std::string ToArpOctMode (int value) } } +inline std::string ToArpVelocity (int nValue) +{ + switch (nValue) + { + case 0: + return "As Played"; + default: + return std::to_string (nValue); + } +} + #endif // _MIDI_EFFECTS_H \ No newline at end of file diff --git a/src/uimenu.cpp b/src/uimenu.cpp index 1441ee8..09e55c7 100644 --- a/src/uimenu.cpp +++ b/src/uimenu.cpp @@ -651,7 +651,7 @@ const CUIMenu::TParameter CUIMenu::s_TGMidiFXArpParam[MidiArp::Param::UNKNOWN] = {0, 5, 1, ToArpMode}, // ARP_MODE {0, 12, 1, ToArpDivision}, // DIVISION {0, 100, 1}, // NOTE_LENGTH - {0, 127, 1}, // VELOCITY + {0, 127, 1, ToArpVelocity}, // VELOCITY {1, 4, 1}, // OCTAVE_SPREAD {0, 4, 1, ToArpOctMode}, // OCTAVE_MODE {0, 1, 1, ToOnOff} // PANIC