Skip to content

Commit

Permalink
Release MIDI Force Notes to Range v0.5 (Initial Release) (#394)
Browse files Browse the repository at this point in the history
  • Loading branch information
BenTalagan authored Nov 14, 2024
1 parent 1ea3489 commit 75226ff
Showing 1 changed file with 237 additions and 0 deletions.
237 changes: 237 additions & 0 deletions MIDI/talagan_MIDI Force Notes to Range.jsfx
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
desc: MIDI Force Notes To Range
author: Ben 'Talagan' Babut
version: 0.5
changelog:
- Initial version
donation:
https://www.paypal.com/donate/?business=3YEZMY9D6U8NC&no_recurring=1&currency_code=EUR
about:
With a specific note range defined, all notes that are outside that range will be remapped
inside of it by either adding octavi (if too low) or removing octavi (if too high)
until falling again into it.

This is more or less a port to JSFX of pizzmidi's midiForceToRange as requested on
the REAPER forum in this thread: https://forum.cockos.com/showthread.php?t=295480.

ATM, the script may be installed on a selected MIDI Bus (or any), and a selected MIDI Channel (or any).
and does not offer bus/chan routing (thus, it does not offer a passthrough option either).
Not sure yet if it's really useful.

Since multiple keys may be routed on the same note, the script implements a system to avoid
overlapping notes (successive Note ON events without Note OFF events in the between are not
allowed, so in that case a Note OFF event is inserted before the Note ON event).


// 0 == ANY, Use only MIDI Bus 1 by default
slider1: 1 <0,16,1{Any,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}>Input MIDI Bus
// 0 == AS_INPUT, so copy input by default
// slider2: 0 <0,16,1{As Input,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}>Output MIDI Bus

// 0 == ANY, Use ANY
slider3: 0 <0,16,1{Any,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}>Input MIDI Channel
// 0 == AS_INPUT, so copy input by default
// slider4: 0 <0,16,1{As Input,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}>Output MIDI Channel

slider5: 0 <0,127, 1{Note 0 - C-1,Note 1 - C#-1 / Db-1,Note 2 - D-1,Note 3 - D#-1 / Eb-1,Note 4 - E-1,Note 5 - F-1,Note 6 - F#-1 / Gb-1,Note 7 - G-1,Note 8 - G#-1 / Ab-1,Note 9 - A-1,Note 10 - A#-1 / Bb-1,Note 11 - B-1,Note 12 - C0,Note 13 - C#0 / Db0,Note 14 - D0,Note 15 - D#0 / Eb0,Note 16 - E0,Note 17 - F0,Note 18 - F#0 / Gb0,Note 19 - G0,Note 20 - G#0 / Ab0,Note 21 - A0,Note 22 - A#0 / Bb0,Note 23 - B0,Note 24 - C1,Note 25 - C#1 / Db1,Note 26 - D1,Note 27 - D#1 / Eb1,Note 28 - E1,Note 29 - F1,Note 30 - F#1 / Gb1,Note 31 - G1,Note 32 - G#1 / Ab1,Note 33 - A1,Note 34 - A#1 / Bb1,Note 35 - B1,Note 36 - C2,Note 37 - C#2 / Db2,Note 38 - D2,Note 39 - D#2 / Eb2,Note 40 - E2,Note 41 - F2,Note 42 - F#2 / Gb2,Note 43 - G2,Note 44 - G#2 / Ab2,Note 45 - A2,Note 46 - A#2 / Bb2,Note 47 - B2,Note 48 - C3,Note 49 - C#3 / Db3,Note 50 - D3,Note 51 - D#3 / Eb3,Note 52 - E3,Note 53 - F3,Note 54 - F#3 / Gb3,Note 55 - G3,Note 56 - G#3 / Ab3,Note 57 - A3,Note 58 - A#3 / Bb3,Note 59 - B3,Note 60 - C4,Note 61 - C#4 / Db4,Note 62 - D4,Note 63 - D#4 / Eb4,Note 64 - E4,Note 65 - F4,Note 66 - F#4 / Gb4,Note 67 - G4,Note 68 - G#4 / Ab4,Note 69 - A4,Note 70 - A#4 / Bb4,Note 71 - B4,Note 72 - C5,Note 73 - C#5 / Db5,Note 74 - D5,Note 75 - D#5 / Eb5,Note 76 - E5,Note 77 - F5,Note 78 - F#5 / Gb5,Note 79 - G5,Note 80 - G#5 / Ab5,Note 81 - A5,Note 82 - A#5 / Bb5,Note 83 - B5,Note 84 - C6,Note 85 - C#6 / Db6,Note 86 - D6,Note 87 - D#6 / Eb6,Note 88 - E6,Note 89 - F6,Note 90 - F#6 / Gb6,Note 91 - G6,Note 92 - G#6 / Ab6,Note 93 - A6,Note 94 - A#6 / Bb6,Note 95 - B6,Note 96 - C7,Note 97 - C#7 / Db7,Note 98 - D7,Note 99 - D#7 / Eb7,Note 100 - E7,Note 101 - F7,Note 102 - F#7 / Gb7,Note 103 - G7,Note 104 - G#7 / Ab7,Note 105 - A7,Note 106 - A#7 / Bb7,Note 107 - B7,Note 108 - C8,Note 109 - C#8 / Db8,Note 110 - D8,Note 111 - D#8 / Eb8,Note 112 - E8,Note 113 - F8,Note 114 - F#8 / Gb8,Note 115 - G8,Note 116 - G#8 / Ab8,Note 117 - A8,Note 118 - A#8 / Bb8,Note 119 - B8,Note 120 - C9,Note 121 - C#9 / Db9,Note 122 - D9,Note 123 - D#9 / Eb9,Note 124 - E9,Note 125 - F9,Note 126 - F#9 / Gb9,Note 127 - G9}>Bottom Note
slider6: 127 <0,127, 1{Note 0 - C-1,Note 1 - C#-1 / Db-1,Note 2 - D-1,Note 3 - D#-1 / Eb-1,Note 4 - E-1,Note 5 - F-1,Note 6 - F#-1 / Gb-1,Note 7 - G-1,Note 8 - G#-1 / Ab-1,Note 9 - A-1,Note 10 - A#-1 / Bb-1,Note 11 - B-1,Note 12 - C0,Note 13 - C#0 / Db0,Note 14 - D0,Note 15 - D#0 / Eb0,Note 16 - E0,Note 17 - F0,Note 18 - F#0 / Gb0,Note 19 - G0,Note 20 - G#0 / Ab0,Note 21 - A0,Note 22 - A#0 / Bb0,Note 23 - B0,Note 24 - C1,Note 25 - C#1 / Db1,Note 26 - D1,Note 27 - D#1 / Eb1,Note 28 - E1,Note 29 - F1,Note 30 - F#1 / Gb1,Note 31 - G1,Note 32 - G#1 / Ab1,Note 33 - A1,Note 34 - A#1 / Bb1,Note 35 - B1,Note 36 - C2,Note 37 - C#2 / Db2,Note 38 - D2,Note 39 - D#2 / Eb2,Note 40 - E2,Note 41 - F2,Note 42 - F#2 / Gb2,Note 43 - G2,Note 44 - G#2 / Ab2,Note 45 - A2,Note 46 - A#2 / Bb2,Note 47 - B2,Note 48 - C3,Note 49 - C#3 / Db3,Note 50 - D3,Note 51 - D#3 / Eb3,Note 52 - E3,Note 53 - F3,Note 54 - F#3 / Gb3,Note 55 - G3,Note 56 - G#3 / Ab3,Note 57 - A3,Note 58 - A#3 / Bb3,Note 59 - B3,Note 60 - C4,Note 61 - C#4 / Db4,Note 62 - D4,Note 63 - D#4 / Eb4,Note 64 - E4,Note 65 - F4,Note 66 - F#4 / Gb4,Note 67 - G4,Note 68 - G#4 / Ab4,Note 69 - A4,Note 70 - A#4 / Bb4,Note 71 - B4,Note 72 - C5,Note 73 - C#5 / Db5,Note 74 - D5,Note 75 - D#5 / Eb5,Note 76 - E5,Note 77 - F5,Note 78 - F#5 / Gb5,Note 79 - G5,Note 80 - G#5 / Ab5,Note 81 - A5,Note 82 - A#5 / Bb5,Note 83 - B5,Note 84 - C6,Note 85 - C#6 / Db6,Note 86 - D6,Note 87 - D#6 / Eb6,Note 88 - E6,Note 89 - F6,Note 90 - F#6 / Gb6,Note 91 - G6,Note 92 - G#6 / Ab6,Note 93 - A6,Note 94 - A#6 / Bb6,Note 95 - B6,Note 96 - C7,Note 97 - C#7 / Db7,Note 98 - D7,Note 99 - D#7 / Eb7,Note 100 - E7,Note 101 - F7,Note 102 - F#7 / Gb7,Note 103 - G7,Note 104 - G#7 / Ab7,Note 105 - A7,Note 106 - A#7 / Bb7,Note 107 - B7,Note 108 - C8,Note 109 - C#8 / Db8,Note 110 - D8,Note 111 - D#8 / Eb8,Note 112 - E8,Note 113 - F8,Note 114 - F#8 / Gb8,Note 115 - G8,Note 116 - G#8 / Ab8,Note 117 - A8,Note 118 - A#8 / Bb8,Note 119 - B8,Note 120 - C9,Note 121 - C#9 / Db9,Note 122 - D9,Note 123 - D#9 / Eb9,Note 124 - E9,Note 125 - F9,Note 126 - F#9 / Gb9,Note 127 - G9}>Top Note

@init

ext_midi_bus = 1; // Have MIDI Bus support
ext_noinit = 1; // One and only one init

// MIDI msg types
MSG_NOTE_OFF = 8;
MSG_NOTE_ON = 9;
MSG_AT_POLY = 10; // 0x0A
MSG_CC = 11; // 0x0B

SLIDER_MIDI_BUS_IN = 1;
SLIDER_MIDI_BUS_OUT = 2;
SLIDER_MIDI_CHAN_IN = 3;
SLIDER_MIDI_CHAN_OUT = 4;
SLIDER_NOTE_BOTTOM = 5;
SLIDER_NOTE_TOP = 6;

ANY = 0;
AS_SRC = 0;


function malloc(msize)
local(ret)
(
ret = MEM_PTR;
MEM_PTR += msize;
ret;
);

// Memory initialisation for this JSFX instance
function instanceMemoryMapInit()
local(ci, ni)
(
MEM_PTR = 0;

// Allocate a buffer to memorize note states for each channel
NOTE_PRESSED = malloc(128*16);
ni = 0;
ci = 0;
while(ci < 16) (
while(ni < 128) (
NOTE_PRESSED[ci][ni] = 0;
ni = ni+1;
);
ci = ci+1;
);

freembuf(MEM_PTR);
);

@serialize

2;

@block

function midiBusInput() ( slider(SLIDER_MIDI_BUS_IN) );
// function midiBusOutput() ( slider(SLIDER_MIDI_BUS_OUT) );

function midiChanInput() ( slider(SLIDER_MIDI_CHAN_IN) );
// function midiChanOutput() ( slider(SLIDER_MIDI_CHAN_OUT) );

function bottomNote() ( slider(SLIDER_NOTE_BOTTOM) );
function topNote() ( slider(SLIDER_NOTE_TOP) );

function rangeTest(note)
local(b,t)
(
b = bottomNote();
t = topNote();

(note >= b && note <=t)?(0):(
(note > t)?(1):(
(-1)));
);


function receive()
local(mpos,msg1,msg2,msg3)
(
evt.present = 0;

(midirecv(mpos, msg1, msg2, msg3))?(
evt.bus = midi_bus + 1; // 1-16, not 0-15
evt.mpos = mpos;
evt.msg1 = msg1;
evt.msg2 = msg2;
evt.msg3 = msg3;
evt.status = msg1;
evt.type = (msg1 >> 4) & 0x0F;
evt.chan = (msg1 & 0x0F) + 1; // 1-16, not 0-15
evt.present = 1;

(evt.type == MSG_NOTE_ON || evt.type == MSG_NOTE_OFF)?(
evt.note = evt.msg2;
evt.velocity = evt.msg3;
evt.after_touch = 0;
);

(evt.type == MSG_AT_POLY)?(
evt.note = evt.msg2;
evt.after_touch = evt.msg3;
);
);
);

function forwardCurrentEvent() (
midisend(evt.mpos, evt.msg1, evt.msg2, evt.msg3)
);

function treatCurrentEvent()
local(midi_bus_matches, midi_chan_matches, event_type_matches, test,
out_bus, out_note, out_chan, out_type)
(
midi_bus_matches = ((midiBusInput() == ANY) || (midiBusInput() == evt.bus));
midi_chan_matches = ((midiChanInput() == ANY) || (midiChanInput() == evt.chan));
event_type_matches = (evt.type == MSG_NOTE_ON || evt.type == MSG_NOTE_OFF || evt.type == MSG_AT_POLY);

(midi_bus_matches && midi_chan_matches && event_type_matches)?(

out_note = evt.note;
test = rangeTest(out_note);

(test == 1)?(
while(test == 1 && out_note >= 0)
(
out_note -= 12;
test = rangeTest(out_note);
);
):(
(test == -1)?(
while(test == -1 && out_note <= 127)
(
out_note += 12;
test = rangeTest(out_note);
);
));

(out_note >= 0 && out_note <= 127 && test == 0)?(

// ATM we don't reroute, but only use input bus/chan
out_bus = evt.bus-1;
out_chan = evt.chan-1;
midi_bus = out_bus;

// NOTE ON
(evt.type == MSG_NOTE_ON && evt.velocity > 0)?(
// True note on.
(NOTE_PRESSED[out_chan][out_note])?(
// Send note off before sending note on if we were already pressed.
// Since we are mapping multiple keys on the same note, we may generate
// overlapping notes, so take special care.
midisend(evt.mpos, (out_chan | (MSG_NOTE_OFF << 4)), out_note, 0);
);
NOTE_PRESSED[out_chan][out_note] = 1;
midisend(evt.mpos, (out_chan | (MSG_NOTE_ON << 4)), out_note, evt.velocity);
);

// NOTE OFF
((evt.type == MSG_NOTE_ON && evt.velocity == 0) || evt.type == MSG_NOTE_OFF)?(
// Note off.
(NOTE_PRESSED[out_chan][out_note] != 0)?(
// Only send note off if we were pressed
// (else it's a bounce due to overlapping configuration)
midisend(evt.mpos, (out_chan | (MSG_NOTE_OFF << 4)), out_note, evt.velocity);
);
NOTE_PRESSED[out_chan][out_note] = 0;
);

// POLY AT
(evt.type == MSG_AT_POLY)?(
midisend(evt.mpos, (out_chan | (MSG_AT_POLY << 4)), out_note, evt.after_touch);
);

);

):(
forwardCurrentEvent();
); // <-- Bus & event type matching
);

function handleMidiEvents()
(
evt = 0;

receive();
while(evt.present)
(
treatCurrentEvent();
receive();
);
);

function mainLoop() (
handleMidiEvents();
);

mainLoop();

0 comments on commit 75226ff

Please sign in to comment.