0

If volume level is represented as a float value between 0 and 1, how to create data bytes of the Universal SysEx Master Volume message?

This is Sysex message constructor, with given Sysex message status byte (0xF0) and data bytes:

new SysexMessage(0xF0, data, data.length)

According to MIDI specification, there are 2 status bytes and 6 data bytes in the Master Volume message (without status bytes), with the last two data bytes specifying volume level:

0xF0 SysEx (Status)
0x7F Universal Realtime
0x7F Disregards channel
0x04 Sub-ID -- Device Control
0x01 Sub-ID2 -- Master Volume
0xLL Bits 0 to 6 of a 14-bit volume
0xMM Bits 7 to 13 of a 14-bit volume
0xF7 End of SysEx (Status)

So, if I'm not wrong, data bytes should look like this:

data = new byte[] { 0x7F, 0x7F, 0x04, 0x01, LL, MM }

My question is how to get LL and MM bytes from a float volume level between 0 and 1?

krsi
  • 1,045
  • 2
  • 14
  • 24

1 Answers1

3

For an unsigned type like this, the smalles 14-bit value is zero, and the largest value is 214-1 = 16383. So to convert 1.0 to 16383, just multiply by that:

int value_14bits = (int)(float_value * 16383);

If you are paranoid, check the range:

value_14bits = Math.max(Math.min(value_14bits, 16383), 0);

Then extract the lower and upper seven-bit fields:

data = new byte[] {
            0x7F, 0x7F, 0x04, 0x01,
            value_14bits & 0x7f,
            value_14bits >> 7 };
CL.
  • 173,858
  • 17
  • 217
  • 259