Pitch Bend values out of range [SOLVED]

Hi all,

Not sure if I’m right on this one, but I though I’ll report it just in case.

When sending Pitch Bend through a preset and capturing the sent MIDI, the message seems to be incorrect:

midi.sendPitchBend (PORT_1, 1, 0)
E0 00 64

midi.sendPitchBend (PORT_1, 1, 1)
E0 01 64

Using the firmware repo, I prepared a small test changing MainComponent.cpp from the outgoingmidi example:

(outgoingmidi/MianComponent.cpp line 11)

        MidiMessage pw = MidiMessage::pitchWheel(1, value);
        device1.sendMessageNow(pw);

The values that I see in my MIDI monitoring tool are the same as when trying it on a LUA preset.

When going through the source code of the firmware, and after quite some diving, I see that the MIDI message seems to be prepared correctly, but the usb_midi.h code handles PitchBend via positive and negative values:


(usb_midi.h line 146)

		void sendPitchBend (int value, uint8_t channel, uint8_t cable = 0) __attribute__((always_inline))
		{
			if (value < -8192)
			{
				value = -8192;
			}
			else if (value > 8191)
			{
				value = 8191;
			}
			value += 8192;
			send (0xE0, value, value >> 7, channel, cable);
		}

Which I believe does not play well with the way the a PitchBend message is prepared (0 to 16383, which seems to be right based on the MIDI specification).

Commenting out all the data mingling in usb_midi.h “fixes” the issue, although that might not be the intended solution. Obviously, considering the limits in this code as 0 to 16383 might be the way to go.

MidiMessage pw = MidiMessage::pitchWheel(1, 0);
E0 00 00

MidiMessage pw = MidiMessage::pitchWheel(1, 1);
E0 01 00
1 Like

I must be missing something… what is wrong here?

zero pitchbend is supposed to be sent as
E0 00 64
https://www.midi.org/specifications-old/item/table-1-summary-of-midi-message

this is because whilst its a 14 bit number 0…16384, its is actually always interpreted as a bipolar value,
so that we can have negative and positive pitchbend.
hence, the midpoint ( 8192) = zero/no pitchbend

I suspect the confusion here is the ‘api’
sendPitchbend is using a signed value -8192 to 8191…
this is why the last line is
value+=8192… since zero, is indeed meant to me no pitchbend (correctly)

if you hook up a synth, where pitchbend range is set to something wide e.g +/-24 semi
you will see that sending E0 00 00, will result in the note being played 2 octaves low. (i.e. bent)


also just to be clear here… for others reading (not OP)
sendPitchbend… should be considered a fractional value.

so if the PBR (pitchbend range) is an +/-24 semi (to make numbers easy :wink: )
if you want to pitch down one octave, you need to sendPitchbend(-8192/2)
if you want to pitch up by one octave sendPitchbend(+8192/2)

(this will actually send midi pitchbend values of 8192/2 , and 8192/2 + 8192 respectively)

Hi @thetechnobear - as I said I’m not a great expert, so if you can help me make better sense I appreciate it.

Zero pitch is indeed value 8192 - agreed on that.

Now, the LUA API in the documentation (Preset Lua extension | Electra One Documentation) states that this value is an uint8_t (well, that’s what it’s converted to in firmware after LUA parsing):

midi.sendPitchBend (port, channel, value)

A function to send a Pitch Bend MIDI message.

  • port - integer, a port identifier (see Globals for details).
  • channel - integer, a numeric representation of the MIDI channel (1 … 16).
  • value - integer, an amount of Pitch Bend to be applied (0 … 16383).

So I’d expect to send a E0 00 64 value (e.g. zero pitch) when the value in midi.sendPitchBend is setup at 8192.

Each of the following calls send the following message:

midi.sendPitchBend (PORT_1, channel, 0)          -- E0 00 64
midi.sendPitchBend (PORT_1, channel, 8192)       -- E0 127 127
midi.sendPitchBend (PORT_1, channel, 16383)      -- E0 127 127

So with the current API, I cannot send E0 00 00 as the API call does not allow for negative numbers. This in my view is either an issue with accepting negative values in the midi.sendPitchBend call, or changing the way the message is sent via the USB library.

For completeness, calling midi.sendPitchBend with negative numbers show an error in the console:

midi.sendPitchBend (PORT_1, channel, -8192)
error running function 'runFunction': ctrlv2/p000.lua:13: value is out of 14bit range: value=-8192

And no MIDI value is output.

Am I doing something wrong? How can I send the minimum pitch value (e.g. E0 00 00) via midi.sendPitchBend?

this seems like an error in the (lua) documentation.
as sendPitchbend is expecting -8192 to 8191

hmm, just read other parts of your message.
I’d say it feels like there is some inconsistent on what the lua and c++ are expecting.
(looks like the lua is expecting unsigned values)

notes/caveat:
it could be there are some changes in the lua/c++ api that have not caught up

I had a typo in my previous last example. Sending negative numbers does not work for me:

midi.sendPitchBend (PORT_1, channel, -8192)
error running function 'runFunction': ctrlv2/p000.lua:13: value is out of 14bit range: value=-8192

midi.sendPitchBend (PORT_1, channel, -1)
error running function 'runFunction': ctrlv2/p000.lua:12: value is out of 14bit range: value=-1

I don’t think it’s just a documentation issue, reading the source code from the firmware this value is indeed expected to be positive. Calling the API with negative numbers yields an error.

yeah, thats an issue in the lua ‘bridge’ to the C++ api, its been coded to expect an unsigned value. whereas it should be signed.

so two ‘issues’
a) lua documentation is wrong
b) lua bridge code is wrong.

well wrong = inconsistent to c++ layer , which I personally think is correct. (*)

given the lua documentation and bridge code are consistent in themselves, I think its likely the api was changed at some point… and the lua code is out of date


(*) correct here is a bit of a judgement call, depending on
a) which is more logical to devs using the calls
b) which is more likely to break existing code - aka which is easier to ‘fix’ :wink:

Yes, that is what I was trying to explain with low success :slight_smile:

LUA expects an unsigned int. MidiOutput::sendPitchBend() expects an unsigned integer as well (in this case uint16_t).

But usb_midi.h expects a signed int (as I wrote in my first message).

Ok, I believe I see where the issue is. Lua/luaMidi.h checks that the value passed to PitchWheel is a 14-bit number with this code:

#define check14bit(number, var)                                                \
    if ((number < 0) || (number > 16383)) {                                    \
        return (                                                               \
            luaL_error(L, "%s is out of 14bit range: value=%d", var, number)); \
    }

I think that given that usb_midi.h is expecting an signed integer, it’d make sense to create an equivalent macro check14bit_s that checks if the number is between -8192 and 8191. I would expect the same issue to happen for midi_sendSongPosition(), but I have not tried that one.

I’d say this should be an easy fix!

EDIT.- typos noted by @thetechnobear

1 Like

signed integer :wink:

it might be interesting to look at
a) the corresponding din/serial implementation … to ensure that the C++ layer is consistent in itself!
b) the git history on usb_midi.h, to see if this has changed recently.

as I said, obviously the API could be made to work either way (using unipolar or bipolar values), so really without looking at context/history - hard to say which is ‘right’.

I’ll admit, my bias is that the C++ layer is ‘usually’ correct - because I view the lua layer as a ‘simple’ bridge… but things are up for improvement, so others might prefer the unipolar api.

anyway, @martin will know what the intended api is, and so where which is ‘correct’ :wink:

I used this for validation of the pitchbend value prior to the calling the low level midi functions. That is incorrect as the function allows positive numbers only while, as you rightly stated, pitchbend value is bipolar. I am adding the fix to upcoming 2.1.4 and to make sure are on the same page: pitchbend will be in range -8192 … 8191.

Thanks for spotting this and providing brilliant input!

fixed in firmware 2.1.4

So happy to see the response and fast fix, thanks @martin - will test my preset now to see if this issues is fixed on it. Keep up the amazing work!