The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
6.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. The code included in this file is provided under the terms of the ISC license
  8. http://www.isc.org/downloads/software-support-policy/isc-license. Permission
  9. To use, copy, modify, and/or distribute this software for any purpose with or
  10. without fee is hereby granted provided that the above copyright notice and
  11. this permission notice appear in all copies.
  12. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  13. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  14. DISCLAIMED.
  15. ==============================================================================
  16. */
  17. namespace juce
  18. {
  19. //==============================================================================
  20. /** Represents a MIDI RPN (registered parameter number) or NRPN (non-registered
  21. parameter number) message.
  22. @tags{Audio}
  23. */
  24. struct MidiRPNMessage
  25. {
  26. /** Midi channel of the message, in the range 1 to 16. */
  27. int channel;
  28. /** The 14-bit parameter index, in the range 0 to 16383 (0x3fff). */
  29. int parameterNumber;
  30. /** The parameter value, in the range 0 to 16383 (0x3fff).
  31. If the message contains no value LSB, the value will be in the range
  32. 0 to 127 (0x7f).
  33. */
  34. int value;
  35. /** True if this message is an NRPN; false if it is an RPN. */
  36. bool isNRPN;
  37. /** True if the value uses 14-bit resolution (LSB + MSB); false if
  38. the value is 7-bit (MSB only).
  39. */
  40. bool is14BitValue;
  41. };
  42. //==============================================================================
  43. /**
  44. Parses a stream of MIDI data to assemble RPN and NRPN messages from their
  45. constituent MIDI CC messages.
  46. The detector uses the following parsing rules: the parameter number
  47. LSB/MSB can be sent/received in either order and must both come before the
  48. parameter value; for the parameter value, LSB always has to be sent/received
  49. before the value MSB, otherwise it will be treated as 7-bit (MSB only).
  50. @tags{Audio}
  51. */
  52. class JUCE_API MidiRPNDetector
  53. {
  54. public:
  55. /** Constructor. */
  56. MidiRPNDetector() noexcept = default;
  57. /** Destructor. */
  58. ~MidiRPNDetector() noexcept = default;
  59. /** Resets the RPN detector's internal state, so that it forgets about
  60. previously received MIDI CC messages.
  61. */
  62. void reset() noexcept;
  63. //==============================================================================
  64. /** @see tryParse() */
  65. [[deprecated ("Use tryParse() instead")]]
  66. bool parseControllerMessage (int midiChannel,
  67. int controllerNumber,
  68. int controllerValue,
  69. MidiRPNMessage& result) noexcept;
  70. /** Takes the next in a stream of incoming MIDI CC messages and returns
  71. a MidiRPNMessage if the current message produces a well-formed RPN or NRPN.
  72. Note that senders are expected to send the MSB before the LSB, but senders are
  73. not required to send a LSB at all. Therefore, tryParse() will return a non-null
  74. optional on all MSB messages (provided a parameter number has been set), and will
  75. also return a non-null optional for each LSB that follows the initial MSB.
  76. This behaviour allows senders to transmit a single MSB followed by multiple LSB
  77. messages to facilitate fine-tuning of parameters.
  78. The result of parsing a MSB will always be a 7-bit value.
  79. The result of parsing a LSB that follows an MSB will always be a 14-bit value.
  80. */
  81. std::optional<MidiRPNMessage> tryParse (int midiChannel,
  82. int controllerNumber,
  83. int controllerValue);
  84. private:
  85. //==============================================================================
  86. struct ChannelState
  87. {
  88. std::optional<MidiRPNMessage> handleController (int channel, int controllerNumber,
  89. int value) noexcept;
  90. void resetValue() noexcept;
  91. std::optional<MidiRPNMessage> sendIfReady (int channel) noexcept;
  92. uint8 parameterMSB = 0xff, parameterLSB = 0xff, valueMSB = 0xff, valueLSB = 0xff;
  93. bool isNRPN = false;
  94. };
  95. //==============================================================================
  96. ChannelState states[16];
  97. JUCE_LEAK_DETECTOR (MidiRPNDetector)
  98. };
  99. //==============================================================================
  100. /**
  101. Generates an appropriate sequence of MIDI CC messages to represent an RPN
  102. or NRPN message.
  103. This sequence (as a MidiBuffer) can then be directly sent to a MidiOutput.
  104. @tags{Audio}
  105. */
  106. class JUCE_API MidiRPNGenerator
  107. {
  108. public:
  109. //==============================================================================
  110. /** Generates a MIDI sequence representing the given RPN or NRPN message. */
  111. static MidiBuffer generate (MidiRPNMessage message);
  112. //==============================================================================
  113. /** Generates a MIDI sequence representing an RPN or NRPN message with the
  114. given parameters.
  115. @param channel The MIDI channel of the RPN/NRPN message.
  116. @param parameterNumber The parameter number, in the range 0 to 16383.
  117. @param value The parameter value, in the range 0 to 16383, or
  118. in the range 0 to 127 if sendAs14BitValue is false.
  119. @param isNRPN Whether you need a MIDI RPN or NRPN sequence (RPN is default).
  120. @param use14BitValue If true (default), the value will have 14-bit precision
  121. (two MIDI bytes). If false, instead the value will have
  122. 7-bit precision (a single MIDI byte).
  123. */
  124. static MidiBuffer generate (int channel,
  125. int parameterNumber,
  126. int value,
  127. bool isNRPN = false,
  128. bool use14BitValue = true);
  129. };
  130. } // namespace juce