39 jassert (midiChannel >= 1 && midiChannel <= 16);
40 jassert (controllerNumber >= 0 && controllerNumber < 128);
41 jassert (controllerValue >= 0 && controllerValue < 128);
43 return states[midiChannel - 1].handleController (midiChannel, controllerNumber, controllerValue, result);
48 for (
int i = 0; i < 16; ++i)
50 states[i].parameterMSB = 0xff;
51 states[i].parameterLSB = 0xff;
52 states[i].resetValue();
53 states[i].isNRPN =
false;
58 MidiRPNDetector::ChannelState::ChannelState() noexcept
59 : parameterMSB (0xff), parameterLSB (0xff), valueMSB (0xff), valueLSB (0xff), isNRPN (
false)
63 bool MidiRPNDetector::ChannelState::handleController (
int channel,
68 switch (controllerNumber)
70 case 0x62: parameterLSB = uint8 (value); resetValue(); isNRPN =
true;
break;
71 case 0x63: parameterMSB = uint8 (value); resetValue(); isNRPN =
true;
break;
73 case 0x64: parameterLSB = uint8 (value); resetValue(); isNRPN =
false;
break;
74 case 0x65: parameterMSB = uint8 (value); resetValue(); isNRPN =
false;
break;
76 case 0x06: valueMSB = uint8 (value);
return sendIfReady (channel, result);
77 case 0x26: valueLSB = uint8 (value);
break;
85 void MidiRPNDetector::ChannelState::resetValue() noexcept
92 bool MidiRPNDetector::ChannelState::sendIfReady (
int channel,
MidiRPNMessage& result) noexcept
94 if (parameterMSB < 0x80 && parameterLSB < 0x80)
104 result.
value = (valueMSB << 7) + valueLSB;
109 result.
value = valueMSB;
123 return generate (message.
channel,
136 jassert (midiChannel > 0 && midiChannel <= 16);
137 jassert (parameterNumber >= 0 && parameterNumber < 16384);
138 jassert (value >= 0 && value < (use14BitValue ? 16384 : 128));
140 uint8 parameterLSB = uint8 (parameterNumber & 0x0000007f);
141 uint8 parameterMSB = uint8 (parameterNumber >> 7);
143 uint8 valueLSB = use14BitValue ? uint8 (value & 0x0000007f) : 0x00;
144 uint8 valueMSB = use14BitValue ? uint8 (value >> 7) : uint8 (value);
146 uint8 channelByte = uint8 (0xb0 + midiChannel - 1);
166 class MidiRPNDetectorTests :
public UnitTest 169 MidiRPNDetectorTests() :
UnitTest (
"MidiRPNDetector class",
"MIDI/MPE") {}
171 void runTest()
override 173 beginTest (
"7-bit RPN");
183 expectEquals (rpn.
value, 42);
188 beginTest (
"14-bit RPN");
199 expectEquals (rpn.
value, 222);
204 beginTest (
"RPNs on multiple channels simultaneously");
217 expectEquals (rpn.
value, 42);
225 expectEquals (rpn.
value, 222);
230 beginTest (
"14-bit RPN with value within 7-bit range");
239 expectEquals (rpn.
channel, 16);
241 expectEquals (rpn.
value, 3);
246 beginTest (
"invalid RPN (wrong order)");
255 beginTest (
"14-bit RPN interspersed with unrelated CC messages");
270 expectEquals (rpn.
channel, 16);
272 expectEquals (rpn.
value, 3);
277 beginTest (
"14-bit NRPN");
288 expectEquals (rpn.
value, 222);
305 static MidiRPNDetectorTests MidiRPNDetectorUnitTests;
308 class MidiRPNGeneratorTests :
public UnitTest 311 MidiRPNGeneratorTests() :
UnitTest (
"MidiRPNGenerator class",
"MIDI/MPE") {}
313 void runTest()
override 315 beginTest (
"generating RPN/NRPN");
319 expectContainsRPN (buffer, 1, 23, 1337,
true,
true);
323 expectContainsRPN (buffer, 16, 101, 34,
false,
false);
328 expectContainsRPN (buffer, message);
335 void expectContainsRPN (
const MidiBuffer& midiBuffer,
342 MidiRPNMessage expected = { channel, parameterNumber, value, isNRPN, is14BitValue };
343 expectContainsRPN (midiBuffer, expected);
372 static MidiRPNGeneratorTests MidiRPNGeneratorUnitTests;
374 #endif // JUCE_UNIT_TESTS
Encapsulates a MIDI message.
~MidiRPNDetector() noexcept
Destructor.
static MidiBuffer generate(MidiRPNMessage message)
Generates a MIDI sequence representing the given RPN or NRPN message.
bool getNextEvent(MidiMessage &result, int &samplePosition) noexcept
Retrieves a copy of the next event from the buffer.
MidiRPNDetector() noexcept
Constructor.
int channel
Midi channel of the message, in the range 1 to 16.
bool is14BitValue
True if the value uses 14-bit resolution (LSB + MSB); false if the value is 7-bit (MSB only)...
int value
The parameter value, in the range 0 to 16383 (0x3fff).
This is a base class for classes that perform a unit test.
int getControllerNumber() const noexcept
Returns the controller number of a controller message.
int getChannel() const noexcept
Returns the midi channel associated with the message.
void reset() noexcept
Resets the RPN detector's internal state, so that it forgets about previously received MIDI CC messag...
Represents a MIDI RPN (registered parameter number) or NRPN (non-registered parameter number) message...
bool isNRPN
True if this message is an NRPN; false if it is an RPN.
int parameterNumber
The 14-bit parameter index, in the range 0 to 16383 (0x3fff).
Holds a sequence of time-stamped midi events.
int getControllerValue() const noexcept
Returns the controller value from a controller message.
void addEvent(const MidiMessage &midiMessage, int sampleNumber)
Adds an event to the buffer.
Used to iterate through the events in a MidiBuffer.
bool parseControllerMessage(int midiChannel, int controllerNumber, int controllerValue, MidiRPNMessage &result) noexcept
Takes the next in a stream of incoming MIDI CC messages and returns true if it forms the last of a se...
Parses a stream of MIDI data to assemble RPN and NRPN messages from their constituent MIDI CC message...