OpenShot Library | OpenShotAudio  0.2.1
juce_MPEMessages.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 MidiBuffer MPEMessages::setLowerZone (int numMemberChannels, int perNotePitchbendRange, int masterPitchbendRange)
27 {
28  auto buffer = MidiRPNGenerator::generate (1, zoneLayoutMessagesRpnNumber, numMemberChannels, false, false);
29 
30  buffer.addEvents (setLowerZonePerNotePitchbendRange (perNotePitchbendRange), 0, -1, 0);
31  buffer.addEvents (setLowerZoneMasterPitchbendRange (masterPitchbendRange), 0, -1, 0);
32 
33  return buffer;
34 }
35 
36 MidiBuffer MPEMessages::setUpperZone (int numMemberChannels, int perNotePitchbendRange, int masterPitchbendRange)
37 {
38  auto buffer = MidiRPNGenerator::generate (16, zoneLayoutMessagesRpnNumber, numMemberChannels, false, false);
39 
40  buffer.addEvents (setUpperZonePerNotePitchbendRange (perNotePitchbendRange), 0, -1, 0);
41  buffer.addEvents (setUpperZoneMasterPitchbendRange (masterPitchbendRange), 0, -1, 0);
42 
43  return buffer;
44 }
45 
47 {
48  return MidiRPNGenerator::generate (2, 0, perNotePitchbendRange, false, false);
49 }
50 
52 {
53  return MidiRPNGenerator::generate (15, 0, perNotePitchbendRange, false, false);
54 }
55 
57 {
58  return MidiRPNGenerator::generate (1, 0, masterPitchbendRange, false, false);
59 }
60 
62 {
63  return MidiRPNGenerator::generate (16, 0, masterPitchbendRange, false, false);
64 }
65 
67 {
68  return MidiRPNGenerator::generate (1, zoneLayoutMessagesRpnNumber, 0, false, false);
69 }
70 
72 {
73  return MidiRPNGenerator::generate (16, zoneLayoutMessagesRpnNumber, 0, false, false);
74 }
75 
77 {
78  MidiBuffer buffer;
79 
80  buffer.addEvents (clearLowerZone(), 0, -1, 0);
81  buffer.addEvents (clearUpperZone(), 0, -1, 0);
82 
83  return buffer;
84 }
85 
87 {
88  MidiBuffer buffer;
89 
90  buffer.addEvents (clearAllZones(), 0, -1, 0);
91 
92  auto lowerZone = layout.getLowerZone();
93  if (lowerZone.isActive())
94  buffer.addEvents (setLowerZone (lowerZone.numMemberChannels,
95  lowerZone.perNotePitchbendRange,
96  lowerZone.masterPitchbendRange),
97  0, -1, 0);
98 
99  auto upperZone = layout.getUpperZone();
100  if (upperZone.isActive())
101  buffer.addEvents (setUpperZone (upperZone.numMemberChannels,
102  upperZone.perNotePitchbendRange,
103  upperZone.masterPitchbendRange),
104  0, -1, 0);
105 
106  return buffer;
107 }
108 
109 
110 //==============================================================================
111 //==============================================================================
112 #if JUCE_UNIT_TESTS
113 
114 class MPEMessagesTests : public UnitTest
115 {
116 public:
117  MPEMessagesTests()
118  : UnitTest ("MPEMessages class", UnitTestCategories::midi)
119  {}
120 
121  void runTest() override
122  {
123  beginTest ("add zone");
124  {
125  {
127 
128  const uint8 expectedBytes[] =
129  {
130  0xb0, 0x64, 0x06, 0xb0, 0x65, 0x00, 0xb0, 0x06, 0x07, // set up zone
131  0xb1, 0x64, 0x00, 0xb1, 0x65, 0x00, 0xb1, 0x06, 0x30, // per-note pbrange (default = 48)
132  0xb0, 0x64, 0x00, 0xb0, 0x65, 0x00, 0xb0, 0x06, 0x02 // master pbrange (default = 2)
133  };
134 
135  testMidiBuffer (buffer, expectedBytes, sizeof (expectedBytes));
136  }
137  {
138  MidiBuffer buffer = MPEMessages::setUpperZone (5, 96, 0);
139 
140  const uint8 expectedBytes[] =
141  {
142  0xbf, 0x64, 0x06, 0xbf, 0x65, 0x00, 0xbf, 0x06, 0x05, // set up zone
143  0xbe, 0x64, 0x00, 0xbe, 0x65, 0x00, 0xbe, 0x06, 0x60, // per-note pbrange (custom)
144  0xbf, 0x64, 0x00, 0xbf, 0x65, 0x00, 0xbf, 0x06, 0x00 // master pbrange (custom)
145  };
146 
147  testMidiBuffer (buffer, expectedBytes, sizeof (expectedBytes));
148  }
149  }
150 
151  beginTest ("set per-note pitchbend range");
152  {
154 
155  const uint8 expectedBytes[] = { 0xb1, 0x64, 0x00, 0xb1, 0x65, 0x00, 0xb1, 0x06, 0x60 };
156 
157  testMidiBuffer (buffer, expectedBytes, sizeof (expectedBytes));
158  }
159 
160 
161  beginTest ("set master pitchbend range");
162  {
164 
165  const uint8 expectedBytes[] = { 0xbf, 0x64, 0x00, 0xbf, 0x65, 0x00, 0xbf, 0x06, 0x3c };
166 
167  testMidiBuffer (buffer, expectedBytes, sizeof (expectedBytes));
168  }
169 
170  beginTest ("clear all zones");
171  {
173 
174  const uint8 expectedBytes[] = { 0xb0, 0x64, 0x06, 0xb0, 0x65, 0x00, 0xb0, 0x06, 0x00, // clear lower zone
175  0xbf, 0x64, 0x06, 0xbf, 0x65, 0x00, 0xbf, 0x06, 0x00 // clear upper zone
176  };
177 
178  testMidiBuffer (buffer, expectedBytes, sizeof (expectedBytes));
179  }
180 
181  beginTest ("set complete state");
182  {
183  MPEZoneLayout layout;
184 
185  layout.setLowerZone (7, 96, 0);
186  layout.setUpperZone (7);
187 
188  MidiBuffer buffer = MPEMessages::setZoneLayout (layout);
189 
190  const uint8 expectedBytes[] = {
191  0xb0, 0x64, 0x06, 0xb0, 0x65, 0x00, 0xb0, 0x06, 0x00, // clear lower zone
192  0xbf, 0x64, 0x06, 0xbf, 0x65, 0x00, 0xbf, 0x06, 0x00, // clear upper zone
193  0xb0, 0x64, 0x06, 0xb0, 0x65, 0x00, 0xb0, 0x06, 0x07, // set lower zone
194  0xb1, 0x64, 0x00, 0xb1, 0x65, 0x00, 0xb1, 0x06, 0x60, // per-note pbrange (custom)
195  0xb0, 0x64, 0x00, 0xb0, 0x65, 0x00, 0xb0, 0x06, 0x00, // master pbrange (custom)
196  0xbf, 0x64, 0x06, 0xbf, 0x65, 0x00, 0xbf, 0x06, 0x07, // set upper zone
197  0xbe, 0x64, 0x00, 0xbe, 0x65, 0x00, 0xbe, 0x06, 0x30, // per-note pbrange (default = 48)
198  0xbf, 0x64, 0x00, 0xbf, 0x65, 0x00, 0xbf, 0x06, 0x02 // master pbrange (default = 2)
199  };
200 
201  testMidiBuffer (buffer, expectedBytes, sizeof (expectedBytes));
202  }
203  }
204 
205 private:
206  //==============================================================================
207  void testMidiBuffer (MidiBuffer& buffer, const uint8* expectedBytes, int expectedBytesSize)
208  {
209  uint8 actualBytes[128] = { 0 };
210  extractRawBinaryData (buffer, actualBytes, sizeof (actualBytes));
211 
212  expectEquals (std::memcmp (actualBytes, expectedBytes, (std::size_t) expectedBytesSize), 0);
213  }
214 
215  //==============================================================================
216  void extractRawBinaryData (const MidiBuffer& midiBuffer, const uint8* bufferToCopyTo, std::size_t maxBytes)
217  {
218  std::size_t pos = 0;
219  MidiBuffer::Iterator iter (midiBuffer);
220  MidiMessage midiMessage;
221  int samplePosition; // Note: Not actually used, so no need to initialise.
222 
223  while (iter.getNextEvent (midiMessage, samplePosition))
224  {
225  const uint8* data = midiMessage.getRawData();
226  std::size_t dataSize = (std::size_t) midiMessage.getRawDataSize();
227 
228  if (pos + dataSize > maxBytes)
229  return;
230 
231  std::memcpy ((void*) (bufferToCopyTo + pos), data, dataSize);
232  pos += dataSize;
233  }
234  }
235 };
236 
237 static MPEMessagesTests MPEMessagesUnitTests;
238 
239 #endif
240 
241 } // namespace juce
This class represents the current MPE zone layout of a device capable of handling MPE...
Encapsulates a MIDI message.
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.
static MidiBuffer setUpperZonePerNotePitchbendRange(int perNotePitchbendRange=48)
Returns the sequence of MIDI messages that, if sent to an Expressive MIDI device, will set the per-no...
int getRawDataSize() const noexcept
Returns the number of bytes of data in the message.
void setUpperZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2) noexcept
Sets the upper zone of this layout.
static MidiBuffer setUpperZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2)
Returns the sequence of MIDI messages that, if sent to an Expressive MIDI device, will set the upper ...
static MidiBuffer setLowerZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2)
Returns the sequence of MIDI messages that, if sent to an Expressive MIDI device, will set the lower ...
const Zone getUpperZone() const noexcept
Returns a struct representing the upper MPE zone.
static MidiBuffer clearAllZones()
Returns the sequence of MIDI messages that, if sent to an Expressive MIDI device, will clear the lowe...
This is a base class for classes that perform a unit test.
Definition: juce_UnitTest.h:73
const Zone getLowerZone() const noexcept
Returns a struct representing the lower MPE zone.
static MidiBuffer setLowerZonePerNotePitchbendRange(int perNotePitchbendRange=48)
Returns the sequence of MIDI messages that, if sent to an Expressive MIDI device, will set the per-no...
static MidiBuffer clearUpperZone()
Returns the sequence of MIDI messages that, if sent to an Expressive MIDI device, will clear the uppe...
static MidiBuffer clearLowerZone()
Returns the sequence of MIDI messages that, if sent to an Expressive MIDI device, will clear the lowe...
static MidiBuffer setLowerZoneMasterPitchbendRange(int masterPitchbendRange=2)
Returns the sequence of MIDI messages that, if sent to an Expressive MIDI device, will set the master...
Holds a sequence of time-stamped midi events.
const uint8 * getRawData() const noexcept
Returns a pointer to the raw midi data.
static MidiBuffer setZoneLayout(MPEZoneLayout layout)
Returns the sequence of MIDI messages that, if sent to an Expressive MIDI device, will reset the whol...
static MidiBuffer setUpperZoneMasterPitchbendRange(int masterPitchbendRange=2)
Returns the sequence of MIDI messages that, if sent to an Expressive MIDI device, will set the master...
Used to iterate through the events in a MidiBuffer.
void addEvents(const MidiBuffer &otherBuffer, int startSample, int numSamples, int sampleDeltaToAdd)
Adds some events from another buffer to this one.
static const int zoneLayoutMessagesRpnNumber
The RPN number used for MPE zone layout messages.
void setLowerZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2) noexcept
Sets the lower zone of this layout.