PDA

View Full Version : Receive input MIDI message from device into reascript


Claudiohbsantos
01-21-2015, 05:58 PM
I'm am repurposing the faders and knobs on a BCF 2000 I have and have been trying to get the midi messages into a reascript to use them to control different things.

I must admit I am fairly new to dealing with midi messages so I'm sorry if I talk utter crap at any point.

Basically what I want is to read the midi value (1 -> 127) from the midi input device, store it into a variable as an int and play around with it from there on. But I can't seem to figure out how to read these values if the midi is not recorded into a media item. but the API function kbd_OnMidiEvent(MIDI_event_t* evt, int dev_index) keeps on giving me hope that it might be possible due to it's naming.

Has anyone had any luck with anything similar?

X-Raym
10-17-2018, 04:59 AM
cfillion answered me about the role of this function :
kbd_OnMidiEvent is for sending a midi event to reaper's control path (triggering midi-assigned actions)



Another trick has to be found.

Meo-Ada Mespotine
10-17-2018, 05:19 AM
The only way to read a Midi-Value is using reaper.get_action_context(), but this contains only the Midi-values, when this script was triggered by a MIDI-shortcut.

Another way would be using JSFX and use parameter-values to "transmit" the Midi-Values to your Lua-Script, as you can read these values.
But how to do that, I can't tell. I'm still trying to figure it out properly with some guys...

Apart from that...no chance currently...

lb0
10-17-2018, 05:58 AM
My Smart Knobs script (see sig) does exactly this - uses a JSFX (faderbox) to capture MIDI input from a controller.

The Smart Knobs script then simply monitors the values of the sliders in the faderbox - knowing exactly where the controllers controls are positioned.

Xenakios
10-17-2018, 06:01 AM
the API function kbd_OnMidiEvent(MIDI_event_t* evt, int dev_index)
The API functions with "on" in their names are not callback functions that can be set by the extension plugin or script code to be called by Reaper when something happens. They are simply functions to be called from the extension or script code. The naming convention is weird and unfortunate but I suppose it can no longer be changed. (There is in fact very minimal support in the Reaper API to get callbacks of any kind, especially on the ReaScript side but the situation isn't great for C++ plugins either.)

Meo-Ada Mespotine
10-17-2018, 06:37 AM
My Smart Knobs script (see sig) does exactly this - uses a JSFX (faderbox) to capture MIDI input from a controller.

The Smart Knobs script then simply monitors the values of the sliders in the faderbox - knowing exactly where the controllers controls are positioned.

Oh! I will look into that, it will probably help us to make a nice tool possible :D

mschnell
10-17-2018, 06:59 AM
You also can use the MidiToReaControlPath VST to route Midi messages to where a script or a "Learn" function of a control can make use of them.

-Michael

X-Raym
10-17-2018, 03:47 PM
@lb0
Thanks for the confirmation,

JSFX Slider + defer script is actually how I do it in some script already. Seems there is no real alternative.


ReaLearn can also take some MIDI input but you can't really tie that to a script to apply custom processing.

NextLevel
10-17-2018, 04:18 PM
I believe that using reaper.get_action_context() inside of a defer script also works pretty well.

mschnell
10-17-2018, 10:08 PM
Seems there is no real alternative.
Yes there is: MidiToReaControlPath. I use it a lot. With that you can avoid a cyclic (deferred) script running all the time, and do an event driven design.

-Michael

X-Raym
10-18-2018, 01:15 AM
@mschnell
And can the action triggered by this take argument based on value for eg ? (cc value,.note velocity/pitch...) ?

mschnell
10-18-2018, 06:22 AM
AFAIK, only CCs can be used for "Learn" and for triggering a script (or for driving LiveConfigs which is what I mostly use this for).

But you can use a JSFX to convert any kind of massages to CCs.

My initial encounter with this was the necessity to drive LiveCionfigs by Program Change messages from a master keyboard and here "PS2CC" JSFX plus "MidiToReaControlPath" did the trick. Simple solution, but at that time it was rather hard to find. ;)

-Michael

X-Raym
10-18-2018, 04:15 PM
@mschnell
I tried the solution with MIDIToReaControlPath and it seems to work !


The funny thing is that I need to use your MIDI convert to CC JSFX effects shared in Reapack to make it works as I intend to :P


Thanks for sharing !!

mschnell
10-18-2018, 09:30 PM
Great !

As PC2CC soon proved to be too limited for my needs I started to do a lot of JSFXes (including "Midi Convert"). Happily with the JSFX system, Reaper provides a means to build anything necessary for creating a versatile Live playing setup for all kinds of Midi controllers and software instruments.

-Michael

X-Raym
10-19-2018, 04:37 AM
@mschnell
Yes, JSFX is a very nice way to build simple and efficient MIDI converter !



There is just something missing in MIDI convert to CC,



Could we have a 'all' switch for MIDI chan in and MIDI chan out ? This would be great, cause for know we have to duplicate the JSFX for each channel :P



(also I think PS label should PC for program change, right ?)


--


I just faced an issue using get_action_context:
https://forum.cockos.com/showthread.php?t=212403


Have you ever faced that before ?


Cheers !

mschnell
10-19-2018, 06:48 AM
Yep.

I think I'll add "All" to the input channel, resulting in that the channel of an output message is set to the one it had been received with.

-Michael

X-Raym
10-19-2018, 09:50 AM
yes All in input and Same in ouput would be nice solutions.

mschnell
10-19-2018, 11:37 PM
I added the options all" and "all unchanged" to the input channel selection

Please test the code posted here. If it works, I'll upload it to ReaPack.

Thanks,
-Michael


desc: MIDI convert to CC
author: Michael Schnell (mschnell@bschnell.de)
version: 3.0
changelog: added "all" and "all unchanged" input channel setting, bugfixes
donation: United Nations Foundation http://www.unfoundation.org/
about:
## Description

Midi CC, PC, Note On or Note Off messages are converted to Midi CC messages with a predefined Channel and CC #. The CC value is calculated from the incoming value.

All midi messages that don't fit the "In" specifications are passed through.

The slider "In Channel" defines the channel the messages to be converted are expected in. "all" accepts any channel, "all unchanged" accepts all channels and forwards the channel unchanged.

The slider "Midi Message" selects if CC, PC, Note on or Note Off messages are converted.

The slider "In CC" is only used when "CC" is selected and defines the CC# of the eligible input messages.

The sliders "Min Input Value" and "Max Input Value" d3efine the range of the eligible input values.

The slider "Out Channel" defines the Channel the converted messages are sent in.

The slider "Out CC" defines the Midi CC message # to be sent

The slider "Min CC Value" defines the value to be sent when the Min Input Value is received. Hence there will be an offset of Min_Input_Value - Min_Outout_Value.

The slider "Max CC Value" defines the value to be sent when the Max Input Value is received. Hence there will be an appropriate stretching of the input range.

// License: LGPL - http://www.gnu.org/licenses/lgpl.html



slider1:0<0,15,1{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,all, all unchanged}>In Channel
slider2:0<0,4,1{CC,PC,Note On,Note Off}>MIDI Message
slider3:1<0,128,1{0 Bank Sel M,1 Mod Wheel M,2 Breath M,3,4 Foot P M,5 Porta M,6 Data Entry M,7 Vol M,8 Balance M,9,10 Pan M,11 Expression M,12 Ctrl 1 M,13 Ctrl 2 M,14,15,16 GP Slider 1,17 GP Slider 2,18 GP Slider 3,19 GP Slider 4,20,21,22,23,24,25,26,27,28,29,30,31,32 Bank Sel L,33 Mod Wheel L,34 Breath L,35,36 Foot P L,37 Porta L,38 Data Entry L,39 Vol L,40 Balance L,41,42 Pan L,43 Expression L,44 Ctrl 1 L,45 Ctrl 2 L,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61, 62,63,64 Hold P sw,65 Porta sw,66 Sustenuto sw,67 Soft P sw,68 Legato P sw,69 Hold 2 P sw,70 S.Variation,71 S.Timbre,72 S.Release,73 S.Attack,74 S.Brightness,75 S.Ctrl 6,76 S.Ctrl 7,77 S.Ctrl 8,78 S.Ctrl 9,79 S.Ctrl 10,80 GP B.1 sw,81 GP B.2 sw,82 GP B.3 sw,83 GP B.4 sw,84,85,86,87,88,89,90,91 Effects Lv,92 Trem Lv,93 Chorus Lv,94 Celeste Lv,95 Phaser Lv,96 Data B. Inc,97 Data B. Dec,98 NRP L,99 NRP M,100 RP L,101 RP M,102,103,104,105,106,107,108,109,110,111,112,113, 114,115,116,117,118,119,120,121,122,123,124,125,12 6,127,N/A}>In CC#
slider4:0<0,127,1)>Min Input Value
slider5:127<0,127,1)>Max Input Value
slider6:0<0,15,1{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}>Out Channel
slider7:1<0,127,1{0 Bank Sel M,1 Mod Wheel M,2 Breath M,3,4 Foot P M,5 Porta M,6 Data Entry M,7 Vol M,8 Balance M,9,10 Pan M,11 Expression M,12 Ctrl 1 M,13 Ctrl 2 M,14,15,16 GP Slider 1,17 GP Slider 2,18 GP Slider 3,19 GP Slider 4,20,21,22,23,24,25,26,27,28,29,30,31,32 Bank Sel L,33 Mod Wheel L,34 Breath L,35,36 Foot P L,37 Porta L,38 Data Entry L,39 Vol L,40 Balance L,41,42 Pan L,43 Expression L,44 Ctrl 1 L,45 Ctrl 2 L,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61, 62,63,64 Hold P sw,65 Porta sw,66 Sustenuto sw,67 Soft P sw,68 Legato P sw,69 Hold 2 P sw,70 S.Variation,71 S.Timbre,72 S.Release,73 S.Attack,74 S.Brightness,75 S.Ctrl 6,76 S.Ctrl 7,77 S.Ctrl 8,78 S.Ctrl 9,79 S.Ctrl 10,80 GP B.1 sw,81 GP B.2 sw,82 GP B.3 sw,83 GP B.4 sw,84,85,86,87,88,89,90,91 Effects Lv,92 Trem Lv,93 Chorus Lv,94 Celeste Lv,95 Phaser Lv,96 Data B. Inc,97 Data B. Dec,98 NRP L,99 NRP M,100 RP L,101 RP M,102,103,104,105,106,107,108,109,110,111,112,113, 114,115,116,117,118,119,120,121,122,123,124,125,12 6,127}>Out CC#
slider8:0<0,127,1)>Min CC Value
slider9:127<0,127,1)>Max CC Value

@slider
inchannel = slider1;
inchannel > 15 ? (
inmask = 0xf0;
inchannel = 0;
) : (
inmask = 0xff;
);
m11 = -1;
type = slider2;
type == 0 ? ( // CC
m1 = 0xb0 + inchannel;
m2 = slider3;
m2 >= 128 ? (
slider3 = 1;
m2 = 1;
);
) : type == 1 ? ( // PC
m1 = 0xc0 + inchannel;
slider3 = 128;
) : type == 2 ? ( // Note On
m1 = 0x90 + inchannel;
slider3 = 128;
) : type == 3 ? ( // Note Off
m1 = 0x80 + inchannel;
m11= 0x90 + inchannel;
slider3 = 128;
);
inmin = slider4;
inmax = slider5;
inmin >= inmax ? (
inmax = inmin+1;
slider5 = inmax;
);
inmax = slider5;
mm1 = 0xb0 + slider6;
outCC = slider7;
outmin = slider8;
outmax = slider9;
factor = (outmax-outmin) / (inmax - inmin);

@block

function convert (mm) (
mm >= inmin ? (
mm <= inmax ? (
m3 = ((((mm-inmin) * factor) + 0.5) | 0) + outmin;
m3 > 127 ? m3 = 127;
m = mm1;
msg11 = -1;
);
);
);

while (midirecv(offset, msg1, msg2, msg3)) (
msg11 = msg1 & inmask;
m = 0;
type = slider2;
type == 0 ? ( // CC
msg11 == m1 ? (
msg2 == m2 ? (
convert(msg3);
);
);
) : (type == 1) || (type == 3) ? ( // PC or Note off
msg11 == m1 ? (
convert(msg2);
) : (msg11 == m11) && (msg3 == 0) ? ( // Note On, Velocity 0 -> Note off
convert(msg2);
);
) : type == 2 ? ( // Note On
msg11 == m1 ? (
msg3 != 0 ? ( // Velocity 0 -> Note off
convert(msg2);
);
);
);
m ? (
slider1 == 17 ? (
m = (m & 0xf0) | (msg1 & 0x0f); // replace predefined channel by received channel
);
midisend(offset, m, outCC, m3);
);
msg11 >= 0 ? midisend(offset, msg1, msg2, msg3); // pass through
);

X-Raym
10-22-2018, 03:40 AM
@mschnell
Hmmm, The All and All unchanged are both under the IN button, I would have expect the All Unchanged to be in the out button, don't you think it would be more intuitive ?

mschnell
10-22-2018, 06:13 AM
As "All" does not need an in channel any more, IMHO, it's rather intuitive to use that menu for these options, as well.

-Michael

X-Raym
10-22-2018, 07:06 AM
As "All" does not need an in channel any more,


But what if we want All in to be mapped in channel 2 ?


That's why IMHO having All as input and All kepping channel as output would be more ergonomic, as essentially, All keeping channel is an "output mode" not an input one.


That's nipticking I know :P

mschnell
10-22-2018, 07:58 AM
But what if we want All in to be mapped in channel 2
That is the out channel and can be set appropriately (using "all" and not "all unchanged" for the in channel).

"All" as out channel would mean to send 16 messages for any in message. which I don't intend to implement.

-Michael

X-Raym
10-22-2018, 10:05 AM
"All" as out channel
It would not be All, it will be the Out unchanged there.


So the script would have
IN (what you want the JSFX to consider), channel 1>16 or all of them


OUT (where you want to send the signal) channel1>16 or keep original.


So it is more about having an Original switch in the Out menu.


Cause having a All unchanged in Input, means that the Out value isn't relevant, and because there is no way to deactivate this via JSFX, it is a bit disturbing to have that behavior.

mschnell
10-22-2018, 11:30 AM
in "out channel" it would be "same".

lets see...

-Michael

mschnell
10-23-2018, 09:34 PM
Uploaded a new version to ReaPack:

version: 3.1

changelog: added "all" input channel and "same as received" output setting, added Note On/Off Velocity and Pitch Bend as input source, pass through now optional, bugfixes

-Michael

X-Raym
10-24-2018, 01:25 AM
@mschnell
Excellent thanks !

X-Raym
10-24-2018, 01:30 AM
Hmmm the file still seems in v2.0 ?
https://github.com/ReaTeam/JSFX/blob/master/Utility/mschnell_MIDI%20Convert%20to%20CC.jsfx

mschnell
10-24-2018, 06:15 AM
I uploaded it yesterday. Now the "powers" of ReaPack need to "merge" it to make it public.

...checking...

it's there :)

-Michael

X-Raym
10-24-2018, 04:21 PM
@mschnell
Synced !
Thanks for your work on this :P