Determining NRPNs and Automation CCs for Instrument Definitions

Hello everyone,
I just received my Hapax, and am really loving it so far!

I’m a bit confused on how to go about setting up an instrument definition for my prophet 12 though. The P12 uses NRPNs, and I don’t understand how to determine the MSB and LSB. The template says the values should be between 0-127, but the P12 manual states that the values can be as high as 200+? Maybe I’m not reading it correctly…

Also, will the automation CCs be essentially the same as the normal CCs in the template?


You have to do a little binary math to calculate the MSB and LSB.

msb = (cc >> 7) & 0x7f
lsb = cc & 0x7f

So if you’re trying to write an entry for Master Course Tune (1024) you’d get this:

cc = 1024
msb = 8
lsb = 0

I wrote a Python script to do this for me when I was creating the GR-1’s definition. Looks like the same formula.

As for the larger values… NRPNs support 7-bit or 14-bit values. That would be the DEPTH parameter for NRPNs in the instrument definition. 7-bit values have a maximum of 127, so anything larger than that would need to be defined as 14-bit.

Not sure on the Automations. I think those entries just automatically create the automation lane for you.

1 Like

Thank you for that!

Although that’s definitely a bit over my head, and I’m not sure how to implement it for a number of CCs. Can I take your script and run it on my Mac or something? There are a ton of CCs/NRPNs for the P12, so no way I’m doing that by hand.

Give this a try.

Go to, replace the text in the top box with that from my script, enter the CC number in the middle box (to the right of share), and then click Run. Should give you a result in the bottom box!


SUPER USEFUL! thank you @endless_coil

Thank you so much for this !

I’ll add a feature request for a Instrument Definition syntax change that would allow a single number for NRPN definition, for ease of use.


That worked! Very cool, and great job. :grinning:


That would definitely be welcome, especially since some people may not find this thread. :+1:

Since the title seems appropriate I wanted to share a little tool I found along the way:


  • you are like me and don’t like typing, but
  • you already found the great manual of the instrument you want to create the definition for, however
  • the creator printed a PDF and copy-pasting the CC/NRPN tables doesn’t quite work and you’re about to start swearing

then you should try tabula.

It let’s you mark the areas in a PDF that shall be extracted as tables and returns a .CSV file.

From there on, possibilites are endless…(further sanitize with spreadsheet software, write python script to transform to hapax definition, upload to and hope they’ll add Hapax definitions soon, …).

1 Like

I know I’m splitting hairs here, but I wanted y’all’s opinion on the new syntax.

Due to observed non-compliant syntax usage (folks omitting “DEFAULT=”, and only putting the value), my desired syntax becomes ambiguous.
Example of an ambiguous use case:

5:7:14 Spread

5:7:14 Spread

Is it NRPN 640 (5<<7 | 7) with a bit depth of 14, or NRPN 5 with a bitdepth of 7 and 14 as a default value?

A countermeasure would be to distinguish the fullnumber with either a particular added symbol, or different separator, for example:

_5_:7:14 Spread

I could use a semicolon instead of a colon also, but it would be difficult to see at first glance.

TL;DR: I’m just not sure what’s both elegant and not ‘humanly ambiguous’ as well.

I’m tempted to just go with the _number_ syntax.

What do y’all think?

PS, for my fellow regex nerds out here:

^(_(?<number>\d{1,5})_|(?<msb>\d{1,3}):(?<lsb>\d{1,3})):(?<bitdepth>(7|14))(|:(|DEFAULT=)(?<default>\d{1,5})) (?<name>.*)$



Looks wise I actually like the semicolon, but agree that it may be hard to differentiate at times.

I think the _number_ solution is good, as it’s very clear and obvious :+1:

Not sure I understand every aspect of this issue, but could it be a solution to allow for FULLNUMBER to be put in place where the LSB number is - requiring the user to put a zero in front of it 0:FULLNUMBER:DEPTH
Then if the NRPN line has a LSB higher than 127, Hapax then knows it’s a full number and ignores the MSB, doing the bit shift internally upon load? If a ‘FULLNUMBER’ is lower than 128, then it is not differently written from a “normal” NRPN.
Then you don’t need to make changes to the definition format :slight_smile:
Fully anticipate there are reasons for not being able to do this internally, or that I am forgetting something/not fully understanding the problem.

I never thought about that, it’s a clever workaround.
It might be confusing, though?

I think I’d rather enforce that MSB is zero in such a case, otherwise you might end up with cursed syntax like:
2:1024:7 which would resolve to what ? 1024 ? 1280 ?

For sure. I think this depends on how you “normally” enforce formatting. If you emit warnings but let unambiguous, but wrong formatting through (like omitting DEFAULT=) I guess you can allow this cursed syntax :mage: The answer is clear to me that it can only be 1024, because Hapax would make one exception to how NRPN is interpreted, which is the one suggested.
I anticipate the general user formatting aspect to be a much broader, internally long-running discussion :slight_smile:

I’ve discussed it with the team, we’re going with this ‘extended LSB’ idea. BUT MSB must be zero, or omitted altogether, so the following would all be strictly equivalent:


Supporting the omission of DEFAULT= was an unintended feature which was -of course- very quickly exploited. I feel like taking this syntax away would be cruel to users who already shared their files. So we’ll support it going forward.


It would be really nice to be able to restrict the range of a named CC/NRPN - I‘m thinking of having additional MIN= MAX= fields in the definition.
Not every parameter uses the full range and automation editing is a bit pointless if the legal range is e.g. 0-5 for OSC Shape, but the grid is trying to display the full 7bit.

On top, this can allow to split parameters in certain cases, e.g. synced and unsynced LFO speeds.

I understand, that this currently isn’t a feature of automation and knob assignments, but I believe and hope that it will one day. So if you already touch the parser, please account for that :slight_smile:

1 Like

That’s been on my roadmap for a while, don’t worry :wink:


Then I‘ll add my nice-to-have, too: for knob assign I would love to name discrete value ranges. Say

43:51:7:DEFAULT=1:MIN=0:MAX=5:NAMED=(0:Saw;1:Sin;2:Tri;3-5:Squ) OSCShape

But really only nice to have…


Would you happen to have this to share??? :slight_smile: