Is there a way to send NRPN's?

Is there a way to send NRPN MIDI messages? Search doesn’t find one mention of “NRPN” on the forum, so does that mean feature request?

Not really tried this but midi_raw might meet your requirements. Might be nice to have this wrapped in a SPi command though for when the occasion arises.

1 Like

Thanks, I didn’t notice that when I looked through the MIDI functions. I guess it’ll be reasonable enough to hack my own midi_nrpn().

Oh, wait: a NRPN is apparently just a sequence of CC’s, so I guess using midi_cc should make it pretty easy. But it’s 4 calls to midi_cc per NRPN.

It’s just 4 midi_cc to do this.
Try the function below. Since it is channel based I would define your port and channel or you will send lots of messages.

use_midi_defaults port: "iac_driver_sonicpi",channel: 1

define :nrpn do |num,val|
  numMsb = num / 128;numLsb = num % 128
  valMsb = val / 128;valLsb = val % 128
  midi_cc 99,numMsb #nrpn msb
  midi_cc 98,numLsb #nrpn,lsb
  midi_cc 6 ,valMsb #data msb
  midi_cc 38,valLsb #data lsb
end

nrpn 9,500 #will set nrpn 9 on channel :1 to data 500

The midi data specs say send the nrpn number to midi_cc 99 and 98 (msb and lsb) and then send the associated data to midi_cc 6 and 38. both the number and the data can be up to 16383

EDIT here is output on ProtoKol midi monitor

RECEIVE    | ENDPOINT(IAC Driver sonicpi) TYPE(CONTROLCHANGE) CHANNEL(1) DATA1(99) DATA2(0)
RECEIVE    | ENDPOINT(IAC Driver sonicpi) TYPE(CONTROLCHANGE) CHANNEL(1) DATA1(98) DATA2(9)
RECEIVE    | ENDPOINT(IAC Driver sonicpi) TYPE(CONTROLCHANGE) CHANNEL(1) DATA1(6) DATA2(3)
RECEIVE    | ENDPOINT(IAC Driver sonicpi) TYPE(CONTROLCHANGE) CHANNEL(1) DATA1(38) DATA2(116)
RECEIVE    | ENDPOINT(IAC Driver sonicpi) TYPE(NRPN) CHANNEL(1) PARAMETER(9) VALUE(500)
2 Likes

sweet
(useless characters to reach the minimum of 20)

Oh nice, I wasn’t aware of this. Definitely sounds like something to add to the API. I’ll make sure this goes in v4-BETA2 which I’ll push out in a couple of weeks.

Thanks so much for the heads up!

3 Likes

Thanks. Sequential Pro-3 has 353 NRPN’s!

Also, please note that, along with setting the values, NRPN values can be incremented and decremented via CC 96 and CC 97, respectively. That’s very handy compared to a CC, whose modulation requires additional user code to track the current value.

ADDED: My Pro-3 responds to NRPN set correctly, but is not responding to NRPN increment and decrement. I simply substitute CC 96 or 97, then continue to use CC 6 and 38 for the data. I hear that not all devices respond to NRPN increment and decrement the same way. Can anyone verify?

ADDED 2: I had a typo. It is in fact responding to increment and decrement, but the response is bizarre. For example, I increment by a value once and it responds correctly, but subsequent increments of the same value don’t work or the result oscillates instead of going in one direction. Other values work, but it is, to put it briefly, inconsistent. The log shows repeated:

{run: 125, time: 6.2, thread: :live_loop_myloop}
 ├─ midi_cc 96, 9, port: "mioxl_din_5", channel: 1
 ├─ midi_cc 6, 0, port: "mioxl_din_5", channel: 1
 └─ midi_cc 38, 10, port: "mioxl_din_5", channel: 1

but the Pro-3 doesn’t update to new values after the first time when I try to increment NRPN #9 by 10.

For NRPN increment and decrement, I found the following information:

Data Increment and Data Decrement controllers are not consistently supported. The value portion of these messages is sometimes given a value or step size, but the transmitted value byte is commonly set to zero. Many slave devices will ignore the value byte, and a default step size (often equal to one) will be employed.

For the Pro-3, if I send any data at all after increment (CC 96) or decrement (CC 97), then the device behaves oddly. So I rearranged the routine @robin.newman wrote to provide a separate NRPN increment/decrement for devices that ignore the increment amount:

define :midi_nrpn_increment do |nrpn, amount, port, channel|
  #
  # Amount is irrelevant in many cases, such as the Pro-3, but we use the sign.
  #

  if nrpn.class == Integer && nrpn >= 0 && amount.class == Integer
    if amount > 0
      midi_cc 96, nrpn, port: port, channel: channel
    elsif  amount < 0
      midi_cc 97, nrpn, port: port, channel: channel
    elsif amount == 0
    end
  else
    puts "midi_nrpn_increment got a bad amount."
  end
end # midi_nrpn_increment