NRPNs Bits and Bytes

Hello. I’m a new user and very excited by what I have been able get set up in a very short time using the Electra One app. But I have run into my first snag. I am trying to set up a hardware synth module (Panda Audio’s Future Impact) that only responds to NRPNs. I have been able to set up most of the parameters successfully but a few of them use the same NRPN! Those ones make use of the bit information. For example, I have MSB 5, LSB 89 that controls both the keyboard trigger/gate switch and the portamento mode switch. It does this by assigning bit0:0 to gate, bit0:1 to trigger, bit1:0 to always glide, and bit1:1 to only glide when legato. Is there a way to program the Electra One to use the bit information? Hope my explanation makes sense to someone :slight_smile: Thanks in advance.
John

Here’s an example :slight_smile:

The first function I got from @oldgearguy . It’s a sendNrpn function, because the usual one is currently broken. So you better set it up yourself.

The second function is one I made for the Behringer UB-Xa. Same challenge as yours: I have 4 bits that together make 1 NRPN. So I gave all 4 controls the function bitMask007, which then serves to reconstruct the needed byte and send it off as NRPN.
Of course you could have other combinations of the bits.

function sendNrpn(port, channel, parameter, value)
    local parameterMSB = (parameter >> 7) & 0x7F
    local parameterLSB = parameter & 0x7F
    local valueMSB = (value >> 7) & 0x7F
    local valueLSB = value & 0x7F
    local messages = {
        {channel = channel, type = CONTROL_CHANGE, controllerNumber = 99, value = parameterMSB},
        {channel = channel, type = CONTROL_CHANGE, controllerNumber = 98, value = parameterLSB},
        {channel = channel, type = CONTROL_CHANGE, controllerNumber = 6, value = valueMSB},
        {channel = channel, type = CONTROL_CHANGE, controllerNumber = 38, value = valueLSB}
    }
    for i, msg in ipairs(messages) do
        midi.sendMessage(port, msg)
    end
end

function bitMask007() -- NRPN 0/7 = 7 ControlPortamentoSettings 
-- Bitmask: Match (0001) Quantize (0010) Bend (0100) Exponential (1000)
  local result = parameterMap.get (1, PT_VIRTUAL, 54) * 2^0
   + parameterMap.get (1, PT_VIRTUAL, 60) * 2^1
   + parameterMap.get (1, PT_VIRTUAL, 59) * 2^2
   + parameterMap.get (1, PT_VIRTUAL, 65) * 2^3
  sendNrpn(currentPort, currentChannel, 7, result)
end
1 Like

I can’t believe it. I managed to modify your examples to get it to do what I needed :slight_smile: Thank you! thank you! thank you!

@Newlgnis thanks again for posting the bitmask function. I got it to do what I needed, but without really understanding it. Moving on to a different case and I realize that my lack of understanding is a problem: I’m trying to unmask a NRPN where, according to the synth’s documentation, bit0: 0 1, bit1: 2 3, bit2: 0 1, and bit3: 0 1. Bits 1 and 2 control a parameter, bit 3 and bit 4 each control separate parameters. Any pointers on how to modify the function? Apologies for the high level of ignorance.

Please be more specific. Absolutely no clue what the above means :slight_smile:

:slight_smile: Apologies. Part of my problem is the documentation has scant details. Let me give you what I have:

NRPN 624 contains 4 midi sync options, turns osc2 hard sync off/on, and turns delay off/on. The values for the NRPN are 0,1,2,3,4,5,6,7. It then says
bit 0: 0: midi sync off, 1: midi sync lfo4,
bit 1: 2: midi sync delay1, 3: midi sync delay1+2
bit 2: 0: OSC2 sync off, 1: OSC2 sync on
bit 3: 0: Delay off, 1: Delay on

I created this monstrosity trying to extend your logic:

function bitMask764() – NRPN 5/124 = 764 Sync&PrioritySettings
– Bitmask: Sync off (000) LFO4 (001) Delay 1 (010) Delay1+2 (011) OscSync off (100) OscSync on (101) Delay off (110) Delay on (111)
local result = parameterMap.get (1, PT_VIRTUAL, 54) * 2^0
+ parameterMap.get (1, PT_VIRTUAL, 60) * 2^1
+ parameterMap.get (1, PT_VIRTUAL, 59) * 2^2
+ parameterMap.get (1, PT_VIRTUAL, 65) * 2^3
+ parameterMap.get (1, PT_VIRTUAL, 64) * 2^4
+ parameterMap.get (1, PT_VIRTUAL, 70) * 2^5
+ parameterMap.get (1, PT_VIRTUAL, 69) * 2^6
+ parameterMap.get (1, PT_VIRTUAL, 75) * 2^7
sendNrpn(currentPort, currentChannel, 764, result)
end

My interest is really in control of the hard sync function and I found that choosing values 0 and 5 turned osc2 sync off and on, respectively. I could just leave it at that and have a beer. But I want to know what it is I’m actually doing or should be doing :slight_smile:

Does that help? Cheers
John

Not sure if this is relevant, but FYI I have to select “LSB first” in the preset editor for any of my NRPNs to work. Here is the link to the preset Electra One App

It helps … a bit… but I think I got it.

There are contradictions however in the info: If a NRPN uses 4 bits, it should have at least one value above 7, but no values above 15. In your case it state the values are 0 to 7, which implies it only uses 3 bits.
That’s a contradiction you need to figure out. I believe in reality the NRPN will have values 0 to 15 and thus need 4 bits.

The bitmask will be as follows:

  • Midi Sync: off (00xx) LFO4 (10xx) Delay 1 (10xx) Delay1+2 (11xx)
  • OscSync off/on (xx0x)/(xx1x)
  • Delay off /on (xxx0)/(xxx1)

You then need one control “Midi Sync” with 4 options, and twon switches. The first control however will control 2 bits and therefor should be able to set values 0-3:

local result = parameterMap.get (1, PT_VIRTUAL, 1) * 2^0
+ parameterMap.get (1, PT_VIRTUAL, 2) * 2^2
+ parameterMap.get (1, PT_VIRTUAL, 3) * 2^3

Be aware control 2 is thus not multiplied by 2^1 but by 2^2 in order to set the third instead of the second bit.
If it all sounds too gibberish to you, familiarize yoursvelf with transforming bits and bytes into values and a new world will open up to you :smiley:

Your explanation helps a lot. Thanks! I followed your logic. I had assumed it was 3 bits since 2^3=8 options. But your logic makes sense if an NRPN is 4 bits. Interestingly, when I implemented your code I found the following for OSC sync (which really the only parameter I’m interested in). Values 0-3 were off, values 4-7 were on, values 8-11 were off, and 12-15 were on. But that doesn’t seem to fit with the logic. I will take your advice and do some reading.

The behaviour for osc sync is correct…

You’re right. I did some reading. I see now that the parameters are
0=(0000), 1=(0001), 2=(0010), 3=(0011),
4=(0100), 5=(0101), 6=(0110), 7=(0111)

But the bit mask (or whatever it should be called) is this:
Sync off: (xxx0), LFO4: (xxx1), Delay 1 (xx0x) Delay1+2 (xx1x)
OscSync off: (x0xx) OscSync on: (x1xx) Delay off: (0xxx) Delay on: 1=(1xxx)

So, OscSync is off for parameter values 0-3, and on for 4-7, etc.

New world opened. :slight_smile:

Yes, I just realised I’ve set my bitmask in the wrong order . Sorry to create confusion, and splendid you worked it out :grin:

Wrong order? [Edit: NM. I see what you did.]

1 Like