General

Nrpn messages?

Started by PongFu on .

Sign in or create an account to join the conversation.

33 posts

I just want to know how to make a fader control the LFO 4 frequency from 00 to 16,
and the make a few buttons for the specific synchronized LFO values;
17,18, 19, 1A, 1B, 1C, 1D, 1E, 1F, 20, 21, 22, 23, 24, 25 and 26
So what are the different kinds of messages I can choose from,
what's the difference between them, and do I use cc's? a script? a custom midi message?
Hi
Based loosely on the other script - This one sends NRPNs - only MSB data atm . . .

Add it as a script to a Fader . . .

// NRPN script - MM

decl target=0; // MIDI Target
decl nrpn_msb = 99, nrpn_lsb = 98; // NRPN MSB - LSB
decl data_msb = 6, data_lsb = 38; // DATA MSB - LSB
decl nrpn_param = 52;
decl null=0, value; // Vars
decl chan = 1; // MIDI Chan

value= Fader.x*16; // value * range

ctlout(target,nrpn_msb,null,chan);
ctlout(target,nrpn_lsb,nrpn_param,chan);
ctlout(target,data_msb,null,chan);
ctlout(target,data_lsb,value,chan);

Only LSB data is sent as per your pic MSB=0 so you may need to check what range you want to send and adjust to suit,
usually the MSB would be used and LSB could be left off - you will need to check the synth's sysex ref . . .

Hope that help in some way - there are no doubt other ways to achieve the same thing

Cheers
MM

#PS Just wanted to add that this is just one way to do and by no means the best way particularly in a larger app . . .
Hi
Try a net search on NRPN they are particular CCs sent in a particular order . .

Reading your pic - B0 means CC on channel 1
CC 99 and 98 (63 and 62 hex)are MSB and LSB for the NRPN number - 0 and 52 (thats 34 hex ib decimal) are sent
CC6 and 38 are used for the data part to send your values

Hope that helps
MM
Hi PongFu
No Don't have a Tetra - but I had a quick look at the manual - check the nrpn info and tables at the end . . .
We can using running status which means we don't have to retransmit some redundant info.
So you just need to send the info it details - convert the binary to hex or decimal as you wish . ..
It helps to use a calculator that can do the decimal, hex, binary conversion for you
Check you are setup to send and recieve nrpns in global parameters
Then go through the Program Parameter table . .
LFO 4 Freq is param 57 which is for layer A is nrpn 52 and takes 0 -166 as values same as LFO 1
0-166 = 0 - 150 unsynced frequencies then 151 to 166 are the synced divisions . . .
Have a look at what values are being sent when you twist the knob - you need to mimic that range . .

So it's probably better to use midiout and send the data described

ie something like - midiout(0{0xB0,99,0,98,52,6,val_msb,38,val_lsb})
So it just comes down to how you want your interface to work and how to map the values properly

Once you have selected an nrpn you can use the value increment/decrement messages as well
Also remember to use the reset message - looks like its 37 & 36 with 127 as the data

Hope that makes sense
Cheers
MM
Hi
Welcome to the world of computer/midi numerics . . the joys of binary and base16 aka Hexadecimal . . .
There are 10 types of people in the world - those who know binary and those who don't . . .
and Hexadecimal is easy if you have three extra fingers on each hand . . .

In that pic the numbers are in Hex - the 63 and 62 are hex for 99 and 98 ie 6*16 = 3, and 6*16 + 2 - does that help . . .
The MIDI monitoring program is showing hex but we talk CCs in decimal - the status B0 gives it away . . .
57 is just a parameter number for the Tetra and the 52 is the actual nrpn number Layer A 252 LayerB . . .

It does get confusing at times particularly when mixing bases and forgetting which base you need . . .

Have a good read of the manual regarding nrpn's . . .

Cheers
MM
To make it easier, you can download the free version of the Tetra editor http://www.soundtower.com/tetra/index.htm
Then set the midi port to a virtual midi port and see the output message with some midi spy app.
This is what I get when moving the o/c 1 frequency knob full right (max value)

msg chn cc val
Control 1 99 0
Control 1 98 0
Control 1 6 0
Control 1 38 120

so you would send 0xb0 , 99,0,98,0,6,0, 38, floor(x*120)

If the usb is not null (value greater than 127) then the full range is :
msb * 128 + lsb

example if the max value is
Control 1 6 2
Control 1 38 100
2*128 + 100 =356, which means that when x = 1.0, the value is 356

and you would send:
0xb0 , 99,0,98,0,6,floor((x*356)/128), 38, floor((x*356)%128)

if x is to the max ( = 1.0) then we would have
1.0 * 356 / 128 = 2.7 , floor(2.7) = 2; msb = 2
1.0 * 356 % 128 = 100; lsb = 100

if x is in half position ( = 0.5) then we would have
0.5 * 356 / 128 = 1.39 , floor(1.39) = 1; msb = 1
0.5 * 356 % 128 = 50; lsb = 50

Off course you can use the full formula in all situations, even if the total value is smaller than 128
If I take the first example where the max value is 120

1 * 120 / 128 = 0.93 , floor(0.93) = 0; msb = 0
1 * 120 % 128 = 120; lsb = 120

% means modulo, it returns the remainder of a division ( 10 % 3 = 1 is the same as 10- floor(10/3)*3 = 1


Hope you are a little more confused now ;)
Hi,
I have been making good progress with my tetra editor, thanks to the excellent replies in this post. I am struggling, however, as soon as the parameter number is >127.

The script framework I have been applying to controllers is as follows (example being for a fader controlling LFO amount, parameter number 39):

decl target=0; // MIDI Target
decl nrpn_msb = 99, nrpn_lsb = 98; // NRPN MSB - LSB
decl data_msb = 6, data_lsb = 38; // DATA MSB - LSB
decl nrpn_param = 39;
decl null=0, value; //VARS
decl chan = 1; // MIDI Chan

value= LFO1Amt.x*127; // value * range

ctlout(target,nrpn_msb,null,chan);
ctlout(target,nrpn_lsb,nrpn_param,chan);
ctlout(target,data_msb,null,chan);
ctlout(target,data_lsb,value,chan);

This seems to work just fine. However I have been trying to map a multislider to control the 16 steps of the internal sequencer, and I'm runnning into problems. For the first 8 steps (parameter numbers 120-127), I have no issues, but once I get to step 9 and above (param number 128 onwards) it no longer works. I am presuming this is something to do with the null not being zero, but nothing happens if I change it to 1. Adjusting the sequencer nine step to 50 in the tetra editor, gives this readout on a midi monitor:

Control 1 99 1
Control 1 98 0
Control 1 6 0
Control 1 38 50

So does this mean that the null is now 1 for the NRPN MSB, but 0 for the Data MSB?
How can I change this ion my script?

Any help greatly appreciated!
Figured it out:

If I change to end of my script to:

ctlout(target,nrpn_msb,(null+1),chan);
ctlout(target,nrpn_lsb,nrpn_param,chan);
ctlout(target,data_msb,null,chan);
ctlout(target,data_lsb,value,chan);

It seems to work
so it does work when I leave out the "LFO1Amt." part

value= LFO1Amt.x*127; // value * range

changed it to

value= x*127; // value * range

execution set to
on frame
instead of
manual

but now the tetra screen displays the "LFO 1 amount" constantly and i can't use the other cc's I have set up or the tetra buttons.

Also I was looking for the LFO 4 FREQUENCY not the LFO 1 AMOUNT

ok..... LFO1Amt. is the name of your slider
PongFu wrote:s
Also I was looking for the LFO 4 FREQUENCY not the LFO 1 AMOUNT

ok..... LFO1Amt. is the name of your slider
Yes. Just replace the LFO1Amt with the name of your fader, and change the nrpn_param to whichever parameter number you want to control. I just gave the example for LFO 1 amount, parameter number 39.

Also you need to change the execution to On Expression, and put x into the script field of the variable.
I would like to set up a bunch of buttons to send NRPN messages. So far this thread and especially dc_Sux Tetra library have been a great help.

Right now I am using one of these scripts to send an NRPN. Execution on expression. It works great for a switch, sending 0 when the switch is off and 1 when the switch is on. But if I change the line from

value= switchname.x*1;

to

value= 1;

It sends a command when I touch the button and sends it again when I release the button. How do I get it to send only one time?

[edit] Figured out that it was sending this when the custom button behavior was a pad but not as a switch. I guess the fix is to make it a switch and have the on and off states look identical? Or is there a way to make a pad not send data when you let up?

[edit 2] The trick is to change the pulldown menu at the end of "On Expression= x" from ANY to _/ [arrow pointing to 1:00]