OpenShot Audio Library | OpenShotAudio 0.3.2
Loading...
Searching...
No Matches
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
23namespace juce
24{
25
26MidiBuffer 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
36MidiBuffer 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
70
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
114class MPEMessagesTests : public UnitTest
115{
116public:
118 : UnitTest ("MPEMessages class", UnitTestCategories::midi)
119 {}
120
121 void runTest() override
122 {
123 beginTest ("add zone");
124 {
125 {
126 MidiBuffer buffer = MPEMessages::setLowerZone (7);
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 {
153 MidiBuffer buffer = MPEMessages::setLowerZonePerNotePitchbendRange (96);
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 {
163 MidiBuffer buffer = MPEMessages::setUpperZoneMasterPitchbendRange (60);
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 {
172 MidiBuffer buffer = MPEMessages::clearAllZones();
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
205private:
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
237static MPEMessagesTests MPEMessagesUnitTests;
238
239#endif
240
241} // namespace juce
Array()=default
ElementType * data() noexcept
Definition juce_Array.h:360
static MidiBuffer setUpperZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2)
static MidiBuffer setUpperZoneMasterPitchbendRange(int masterPitchbendRange=2)
static MidiBuffer clearAllZones()
static MidiBuffer setZoneLayout(MPEZoneLayout layout)
static MidiBuffer setLowerZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2)
static MidiBuffer clearUpperZone()
static MidiBuffer clearLowerZone()
static const int zoneLayoutMessagesRpnNumber
static MidiBuffer setLowerZoneMasterPitchbendRange(int masterPitchbendRange=2)
static MidiBuffer setLowerZonePerNotePitchbendRange(int perNotePitchbendRange=48)
static MidiBuffer setUpperZonePerNotePitchbendRange(int perNotePitchbendRange=48)
void addEvents(const MidiBuffer &otherBuffer, int startSample, int numSamples, int sampleDeltaToAdd)
static MidiBuffer generate(MidiRPNMessage message)