Old 11-24-2019, 06:04 AM   #1
LuCsa
Human being with feelings
 
Join Date: Aug 2016
Posts: 51
Default JSFX MIDI Route Note-on to CC Event

Hello Reapers,

I'm in the middle of learning ReaScripting with Lua, creating custom tools to help with my MIDI orchestration template, and today I tackled JSFX, because I need some MIDI routing.

I want to filter for a specific note-on event. If that occurs, I want to change it into a CC event (with the same "velocity" value). The corresponding note-off has to be eliminated. All other events remain unmodified. This goes independent from the MIDI channel.

This is what I tried, but it doesn't work. The MIDI notes appear instead of the CC events, and I don't understand why...


Code:
desc: LCjs_MIDI Note to CC
//tags: MIDI processing routing

in_pin:none
out_pin:none

@init

CC = 0xB0;        //CC
NOTE_ON = 0x90;   //Note on
NOTE_OFF = 0x80;  //Note off

nC9 = 0x73;        //115 = C9 --> CC28
nCs9 = 0x74;       //116 = C#9 --> CC15
nD9 = 0x75;        //117 = D9 --> CC29

cc28 = 0x1C;       //CC28
cc15 = 0x0F;       //CC15
cc29 = 0x1D;       //CC29


@block

while (
  midirecv(mpos, msg1, msg2, msg3) ? (
    status = msg1&0xF0;                                 //ignore channel (right nibble)
    status==NOTE_ON ? (
      msg2==nC9  ? (status=CC; msg2=cc28; active = 1;); //active=1 means specified note was hit
      msg2==nCs9 ? (status=CC; msg2=cc15; active = 1;);
      msg2==nD9  ? (status=CC; msg2=cc29; active = 1;);
      active==1 ? msg1 = (msg1&0x0F) + status;          //reset and update left nibble (status to CC) for specified notes
      midisend(mpos, msg1, msg2, msg3);                 //send updated info or pass-thru (if active==0)
    );
    (active==1 && status==NOTE_OFF) ? active = 0;       //ignore note-off of specified notes, because they are not converted to CC
  );
);
I would really appreciate if you could shed some light on that problem...

Thanks!
Lukas
LuCsa is offline   Reply With Quote
Old 11-24-2019, 09:59 AM   #2
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 6,117
Default

X-Raym_Note to CC.jsfx

free on my reapack :P

First JSFX I made.


https://forum.cockos.com/showthread.php?t=181105
X-Raym is offline   Reply With Quote
Old 11-24-2019, 04:29 PM   #3
LuCsa
Human being with feelings
 
Join Date: Aug 2016
Posts: 51
Default

Quote:
Originally Posted by X-Raym View Post
X-Raym_Note to CC.jsfx

free on my reapack :P

First JSFX I made.


https://forum.cockos.com/showthread.php?t=181105

Haha, what a coincidence! :'D

Still, would you be so kind and quickly check what's wrong with my code?
For reasons of learning... :-)

I have some questions about your code:

1) Line 75 where you check if "any" CC is picked by slider5. This just translates the note to the corresponding CC, right?

2) Line 78 prepares the msg23 for midisend(...). Is there a reason why you don't use the 4-argument-syntax like below in line 90? Also, I'm confused: Isn't the note information the one that comes in the first nibble and thus should be multiplied by 256?

3) Still line 78: Why is the |0 necessary? It just reproduces the bit mask, doesn't it?

4) You hardcoded msg1 to be 0xB0 in line 80: This means that the MIDI inside this branch will always be sent to channel 0 (as a CC event)?

5) What's the secret behind line 92...?

Thank you very much! :-)

Lukas
LuCsa is offline   Reply With Quote
Old 11-25-2019, 12:14 AM   #4
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 6,117
Default

Most of your point can be answered by the fact that, as it was my first script, I just took the closest JSFX I could find and strip it down to something like this before extend it to my needs :P


So the 4 arguments syntax is better yes, I just used old legacy code which was written with the 3 one.


And I indeed messed the channel out ^^


I'm not fluent enough with MIDI JSFX syntax to explain all this so!



https://www.reaper.fm/sdk/js/midi.php#js_midi


This may help you better
X-Raym is offline   Reply With Quote
Old 11-25-2019, 07:17 AM   #5
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,007
Default

Quote:
Originally Posted by LuCsa View Post
Still, would you be so kind and quickly check what's wrong with my code?
Well, you are using the "oldskool" JSFX while syntax, which requires that the last statement returns non-zero, or it won't loop. In this case the last statement is:

Code:
    (active==1 && status==NOTE_OFF) ? active = 0;       //ignore note-off of specified notes, because they are not converted to CC
This will always return zero, so it will always execute the while loop only once. You can fix this by adding a forced non-zero statement i.e.:

Code:
    (active==1 && status==NOTE_OFF) ? active = 0;       //ignore note-off of specified notes, because they are not converted to CC
    1; // <-- Force while to loop
Alternatively you can use the "modern" while syntax, see:
https://www.reaper.fm/sdk/js/basiccode.php#while.

But otherwise your code seems to work just fine here.
Tale is offline   Reply With Quote
Old 11-26-2019, 02:53 PM   #6
LuCsa
Human being with feelings
 
Join Date: Aug 2016
Posts: 51
Default

Hey guys, thank you for your time!

I still have some questions, my script is not working, and I do not understand why.

Quote:
Originally Posted by X-Raym View Post
So the 4 arguments syntax is better yes, I just used old legacy code which was written with the 3 one.
https://www.reaper.fm/sdk/js/midi.php#js_midi
Okay, thanks - I checked these, but I will ask a question about that in a separate track.


Quote:
Originally Posted by Tale View Post
Well, you are using the "oldskool" JSFX while syntax, which requires that the last statement returns non-zero, or it won't loop. In this case the last statement is:

Code:
    (active==1 && status==NOTE_OFF) ? active = 0;       //ignore note-off of specified notes, because they are not converted to CC
This will always return zero, so it will always execute the while loop only once. You can fix this by adding a forced non-zero statement i.e.:

Code:
    (active==1 && status==NOTE_OFF) ? active = 0;       //ignore note-off of specified notes, because they are not converted to CC
    1; // <-- Force while to loop
Alternatively you can use the "modern" while syntax, see:
https://www.reaper.fm/sdk/js/basiccode.php#while.

But otherwise your code seems to work just fine here.
Even with the corrected while loop, it doesn't work for some reason?

Code:
while (midirecv(mpos, msg1, msg2, msg3)) (
  //my code here
);
...nope.
Did I get something wrong with the bit stuff? I'm really confused...

Cheers,
Lukas

###

EDIT:
Jesus fu- programming Christ, I think I just made some stupid control flow mistakes. The following code works just fine:

Code:
desc: LCjs_MIDI Note to CC
//tags: MIDI processing routing

in_pin:none
out_pin:none

@init

CC = 0xB0;        //11=CC on channel 1
NOTE_ON = 0x90;   //9=Note on
NOTE_OFF = 0x80;  //8=Note off

nC9 = 0x78;        //120 = C9
nCs9 = 0x79;       //121 = C#9
nD9 = 0x7A;        //122 = D9

cc28 = 0x1C;       //CC28
cc15 = 0x0F;       //CC15
cc29 = 0x1D;       //CC29


@block

while (midirecv(mpos, msg1, msg2, msg3)) (
  status = msg1&0xF0;                                 //ignore channel (right nibble)
  thru = 1;                                           //thru = 1 means pass thru; set to 0 later in case of a change
  (status==NOTE_ON || status==NOTE_OFF) ? (
    msg2==nC9  ? (msg2=cc28; thru = 0;);              //thru = 0 means specified note was hit, assign CC instead of note
    msg2==nCs9 ? (msg2=cc15; thru = 0;);
    msg2==nD9  ? (msg2=cc29; thru = 0;);
    (thru==0 && status!=NOTE_OFF) ? (                 //exclude note-offs, because they should be eliminated
      msg1 = (msg1&0x0F) + CC;                        //reset and update left nibble (status to CC) for specified notes
      midisend(mpos, msg1, msg2, msg3);               //send updated event (note became CC according to mapping)
    );
  );
  thru==1 ? midisend(mpos, msg1, msg2, msg3);         //pass thru unmodified events; this can not be reached, in case of change
);
I still have the problem with a note-off, but I think that's a problem with my MIDI controller...

Last edited by LuCsa; 11-26-2019 at 04:11 PM. Reason: Solution
LuCsa is offline   Reply With Quote
Old 11-26-2019, 03:41 PM   #7
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,007
Default

Quote:
Originally Posted by LuCsa View Post
Even with the corrected while loop, it doesn't work for some reason?

Code:
while (midirecv(mpos, msg1, msg2, msg3)) (
  //my code here
);
Yeah, that looks good.

Are you sure you are playing the correct notes (115..117)? Because a standard 88 key MIDI controller only goes up to 108...
Tale is offline   Reply With Quote
Old 11-27-2019, 12:32 PM   #8
LuCsa
Human being with feelings
 
Join Date: Aug 2016
Posts: 51
Default

Quote:
Originally Posted by Tale View Post
Yeah, that looks good.

Are you sure you are playing the correct notes (115..117)? Because a standard 88 key MIDI controller only goes up to 108...
Hey,

thanks. And now (see my edit) it works, I think I made some rather simple mistakes in control flow.

I assign the MIDI note to a switch on the keyboard, not to one of its keys.
Assigned to a key it works perfectly as it should - just need to find out how that button sends its MIDI info.
LuCsa is offline   Reply With Quote
Old 11-27-2019, 12:38 PM   #9
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,007
Default

Quote:
Originally Posted by LuCsa View Post
I still have the problem with a note-off, but I think that's a problem with my MIDI controller...
Or maybe it sends Note On with zero velocity instead of Note Off? Most MIDI controllers do.
Tale is offline   Reply With Quote
Old 11-27-2019, 02:17 PM   #10
LuCsa
Human being with feelings
 
Join Date: Aug 2016
Posts: 51
Default

Quote:
Originally Posted by Tale View Post
Or maybe it sends Note On with zero velocity instead of Note Off? Most MIDI controllers do.
That's actually what my quick tests showed yesterday before I went to sleep. :-D
In that case, I'd just need to filter them together with the corresponding note-offs.
LuCsa is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 03:22 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, vBulletin Solutions Inc.