OpenShot Audio Library | OpenShotAudio  0.6.0
juce_UMPFactory.h
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2022 - Raw Material Software Limited
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 #ifndef DOXYGEN
24 
25 namespace juce::universal_midi_packets
26 {
27 
34 struct Factory
35 {
37  struct Detail
38  {
39  static PacketX1 makeSystem() { return PacketX1{}.withMessageType (1); }
40  static PacketX1 makeV1() { return PacketX1{}.withMessageType (2); }
41  static PacketX2 makeV2() { return PacketX2{}.withMessageType (4); }
42 
43  static PacketX2 makeSysEx (uint8_t group,
44  uint8_t status,
45  uint8_t numBytes,
46  const std::byte* data)
47  {
48  jassert (numBytes <= 6);
49 
50  std::array<uint8_t, 8> bytes{{}};
51  bytes[0] = (0x3 << 0x4) | group;
52  bytes[1] = (uint8_t) (status << 0x4) | numBytes;
53 
54  std::memcpy (bytes.data() + 2, data, numBytes);
55 
56  std::array<uint32_t, 2> words;
57 
58  for (const auto [index, word] : enumerate (words))
59  word = ByteOrder::bigEndianInt (bytes.data() + 4 * index);
60 
61  return PacketX2 { words };
62  }
63 
64  static PacketX4 makeSysEx8 (uint8_t group,
65  uint8_t status,
66  uint8_t numBytes,
67  uint8_t dataStart,
68  const uint8_t* data)
69  {
70  jassert (numBytes <= 16 - dataStart);
71 
72  std::array<uint8_t, 16> bytes{{}};
73  bytes[0] = (0x5 << 0x4) | group;
74  bytes[1] = (uint8_t) (status << 0x4) | numBytes;
75 
76  std::memcpy (bytes.data() + dataStart, data, numBytes);
77 
78  std::array<uint32_t, 4> words;
79 
80  for (const auto [index, word] : enumerate (words))
81  word = ByteOrder::bigEndianInt (bytes.data() + 4 * index);
82 
83  return PacketX4 { words };
84  }
85  };
86 
87  static PacketX1 makeNoop (uint8_t group)
88  {
89  return PacketX1{}.withGroup (group);
90  }
91 
92  static PacketX1 makeJRClock (uint8_t group, uint16_t time)
93  {
94  return PacketX1 { time }.withStatus (1).withGroup (group);
95  }
96 
97  static PacketX1 makeJRTimestamp (uint8_t group, uint16_t time)
98  {
99  return PacketX1 { time }.withStatus (2).withGroup (group);
100  }
101 
102  static PacketX1 makeTimeCode (uint8_t group, uint8_t code)
103  {
104  return Detail::makeSystem().withGroup (group)
105  .withU8<1> (0xf1)
106  .withU8<2> (code & 0x7f);
107  }
108 
109  static PacketX1 makeSongPositionPointer (uint8_t group, uint16_t pos)
110  {
111  return Detail::makeSystem().withGroup (group)
112  .withU8<1> (0xf2)
113  .withU8<2> (pos & 0x7f)
114  .withU8<3> ((pos >> 7) & 0x7f);
115  }
116 
117  static PacketX1 makeSongSelect (uint8_t group, uint8_t song)
118  {
119  return Detail::makeSystem().withGroup (group)
120  .withU8<1> (0xf3)
121  .withU8<2> (song & 0x7f);
122  }
123 
124  static PacketX1 makeTuneRequest (uint8_t group)
125  {
126  return Detail::makeSystem().withGroup (group)
127  .withU8<1> (0xf6);
128  }
129 
130  static PacketX1 makeTimingClock (uint8_t group)
131  {
132  return Detail::makeSystem().withGroup (group)
133  .withU8<1> (0xf8);
134  }
135 
136  static PacketX1 makeStart (uint8_t group)
137  {
138  return Detail::makeSystem().withGroup (group)
139  .withU8<1> (0xfa);
140  }
141 
142  static PacketX1 makeContinue (uint8_t group)
143  {
144  return Detail::makeSystem().withGroup (group)
145  .withU8<1> (0xfb);
146  }
147 
148  static PacketX1 makeStop (uint8_t group)
149  {
150  return Detail::makeSystem().withGroup (group)
151  .withU8<1> (0xfc);
152  }
153 
154  static PacketX1 makeActiveSensing (uint8_t group)
155  {
156  return Detail::makeSystem().withGroup (group)
157  .withU8<1> (0xfe);
158  }
159 
160  static PacketX1 makeReset (uint8_t group)
161  {
162  return Detail::makeSystem().withGroup (group)
163  .withU8<1> (0xff);
164  }
165 
166  static PacketX1 makeNoteOffV1 (uint8_t group,
167  uint8_t channel,
168  uint8_t note,
169  uint8_t velocity)
170  {
171  return Detail::makeV1().withGroup (group)
172  .withStatus (0x8)
173  .withChannel (channel)
174  .withU8<2> (note & 0x7f)
175  .withU8<3> (velocity & 0x7f);
176  }
177 
178  static PacketX1 makeNoteOnV1 (uint8_t group,
179  uint8_t channel,
180  uint8_t note,
181  uint8_t velocity)
182  {
183  return Detail::makeV1().withGroup (group)
184  .withStatus (0x9)
185  .withChannel (channel)
186  .withU8<2> (note & 0x7f)
187  .withU8<3> (velocity & 0x7f);
188  }
189 
190  static PacketX1 makePolyPressureV1 (uint8_t group,
191  uint8_t channel,
192  uint8_t note,
193  uint8_t pressure)
194  {
195  return Detail::makeV1().withGroup (group)
196  .withStatus (0xa)
197  .withChannel (channel)
198  .withU8<2> (note & 0x7f)
199  .withU8<3> (pressure & 0x7f);
200  }
201 
202  static PacketX1 makeControlChangeV1 (uint8_t group,
203  uint8_t channel,
204  uint8_t controller,
205  uint8_t value)
206  {
207  return Detail::makeV1().withGroup (group)
208  .withStatus (0xb)
209  .withChannel (channel)
210  .withU8<2> (controller & 0x7f)
211  .withU8<3> (value & 0x7f);
212  }
213 
214  static PacketX1 makeProgramChangeV1 (uint8_t group,
215  uint8_t channel,
216  uint8_t program)
217  {
218  return Detail::makeV1().withGroup (group)
219  .withStatus (0xc)
220  .withChannel (channel)
221  .withU8<2> (program & 0x7f);
222  }
223 
224  static PacketX1 makeChannelPressureV1 (uint8_t group,
225  uint8_t channel,
226  uint8_t pressure)
227  {
228  return Detail::makeV1().withGroup (group)
229  .withStatus (0xd)
230  .withChannel (channel)
231  .withU8<2> (pressure & 0x7f);
232  }
233 
234  static PacketX1 makePitchBend (uint8_t group,
235  uint8_t channel,
236  uint16_t pitchbend)
237  {
238  return Detail::makeV1().withGroup (group)
239  .withStatus (0xe)
240  .withChannel (channel)
241  .withU8<2> (pitchbend & 0x7f)
242  .withU8<3> ((pitchbend >> 7) & 0x7f);
243  }
244 
245  static PacketX2 makeSysExIn1Packet (uint8_t group,
246  uint8_t numBytes,
247  const std::byte* data)
248  {
249  return Detail::makeSysEx (group, 0x0, numBytes, data);
250  }
251 
252  static PacketX2 makeSysExStart (uint8_t group,
253  uint8_t numBytes,
254  const std::byte* data)
255  {
256  return Detail::makeSysEx (group, 0x1, numBytes, data);
257  }
258 
259  static PacketX2 makeSysExContinue (uint8_t group,
260  uint8_t numBytes,
261  const std::byte* data)
262  {
263  return Detail::makeSysEx (group, 0x2, numBytes, data);
264  }
265 
266  static PacketX2 makeSysExEnd (uint8_t group,
267  uint8_t numBytes,
268  const std::byte* data)
269  {
270  return Detail::makeSysEx (group, 0x3, numBytes, data);
271  }
272 
273  static PacketX2 makeRegisteredPerNoteControllerV2 (uint8_t group,
274  uint8_t channel,
275  uint8_t note,
276  uint8_t controller,
277  uint32_t data)
278  {
279  return Detail::makeV2().withGroup (group)
280  .withStatus (0x0)
281  .withChannel (channel)
282  .withU8<2> (note & 0x7f)
283  .withU8<3> (controller & 0x7f)
284  .withU32<1> (data);
285  }
286 
287  static PacketX2 makeAssignablePerNoteControllerV2 (uint8_t group,
288  uint8_t channel,
289  uint8_t note,
290  uint8_t controller,
291  uint32_t data)
292  {
293  return Detail::makeV2().withGroup (group)
294  .withStatus (0x1)
295  .withChannel (channel)
296  .withU8<2> (note & 0x7f)
297  .withU8<3> (controller & 0x7f)
298  .withU32<1> (data);
299  }
300 
301  static PacketX2 makeRegisteredControllerV2 (uint8_t group,
302  uint8_t channel,
303  uint8_t bank,
304  uint8_t index,
305  uint32_t data)
306  {
307  return Detail::makeV2().withGroup (group)
308  .withStatus (0x2)
309  .withChannel (channel)
310  .withU8<2> (bank & 0x7f)
311  .withU8<3> (index & 0x7f)
312  .withU32<1> (data);
313  }
314 
315  static PacketX2 makeAssignableControllerV2 (uint8_t group,
316  uint8_t channel,
317  uint8_t bank,
318  uint8_t index,
319  uint32_t data)
320  {
321  return Detail::makeV2().withGroup (group)
322  .withStatus (0x3)
323  .withChannel (channel)
324  .withU8<2> (bank & 0x7f)
325  .withU8<3> (index & 0x7f)
326  .withU32<1> (data);
327  }
328 
329  static PacketX2 makeRelativeRegisteredControllerV2 (uint8_t group,
330  uint8_t channel,
331  uint8_t bank,
332  uint8_t index,
333  uint32_t data)
334  {
335  return Detail::makeV2().withGroup (group)
336  .withStatus (0x4)
337  .withChannel (channel)
338  .withU8<2> (bank & 0x7f)
339  .withU8<3> (index & 0x7f)
340  .withU32<1> (data);
341  }
342 
343  static PacketX2 makeRelativeAssignableControllerV2 (uint8_t group,
344  uint8_t channel,
345  uint8_t bank,
346  uint8_t index,
347  uint32_t data)
348  {
349  return Detail::makeV2().withGroup (group)
350  .withStatus (0x5)
351  .withChannel (channel)
352  .withU8<2> (bank & 0x7f)
353  .withU8<3> (index & 0x7f)
354  .withU32<1> (data);
355  }
356 
357  static PacketX2 makePerNotePitchBendV2 (uint8_t group,
358  uint8_t channel,
359  uint8_t note,
360  uint32_t data)
361  {
362  return Detail::makeV2().withGroup (group)
363  .withStatus (0x6)
364  .withChannel (channel)
365  .withU8<2> (note & 0x7f)
366  .withU32<1> (data);
367  }
368 
369  enum class NoteAttributeKind : uint8_t
370  {
371  none = 0x00,
372  manufacturer = 0x01,
373  profile = 0x02,
374  pitch7_9 = 0x03
375  };
376 
377  static PacketX2 makeNoteOffV2 (uint8_t group,
378  uint8_t channel,
379  uint8_t note,
380  NoteAttributeKind attribute,
381  uint16_t velocity,
382  uint16_t attributeValue)
383  {
384  return Detail::makeV2().withGroup (group)
385  .withStatus (0x8)
386  .withChannel (channel)
387  .withU8<2> (note & 0x7f)
388  .withU8<3> ((uint8_t) attribute)
389  .withU16<2> (velocity)
390  .withU16<3> (attributeValue);
391  }
392 
393  static PacketX2 makeNoteOnV2 (uint8_t group,
394  uint8_t channel,
395  uint8_t note,
396  NoteAttributeKind attribute,
397  uint16_t velocity,
398  uint16_t attributeValue)
399  {
400  return Detail::makeV2().withGroup (group)
401  .withStatus (0x9)
402  .withChannel (channel)
403  .withU8<2> (note & 0x7f)
404  .withU8<3> ((uint8_t) attribute)
405  .withU16<2> (velocity)
406  .withU16<3> (attributeValue);
407  }
408 
409  static PacketX2 makePolyPressureV2 (uint8_t group,
410  uint8_t channel,
411  uint8_t note,
412  uint32_t data)
413  {
414  return Detail::makeV2().withGroup (group)
415  .withStatus (0xa)
416  .withChannel (channel)
417  .withU8<2> (note & 0x7f)
418  .withU32<1> (data);
419  }
420 
421  static PacketX2 makeControlChangeV2 (uint8_t group,
422  uint8_t channel,
423  uint8_t controller,
424  uint32_t data)
425  {
426  return Detail::makeV2().withGroup (group)
427  .withStatus (0xb)
428  .withChannel (channel)
429  .withU8<2> (controller & 0x7f)
430  .withU32<1> (data);
431  }
432 
433  static PacketX2 makeProgramChangeV2 (uint8_t group,
434  uint8_t channel,
435  uint8_t optionFlags,
436  uint8_t program,
437  uint8_t bankMsb,
438  uint8_t bankLsb)
439  {
440  return Detail::makeV2().withGroup (group)
441  .withStatus (0xc)
442  .withChannel (channel)
443  .withU8<3> (optionFlags)
444  .withU8<4> (program)
445  .withU8<6> (bankMsb)
446  .withU8<7> (bankLsb);
447  }
448 
449  static PacketX2 makeChannelPressureV2 (uint8_t group,
450  uint8_t channel,
451  uint32_t data)
452  {
453  return Detail::makeV2().withGroup (group)
454  .withStatus (0xd)
455  .withChannel (channel)
456  .withU32<1> (data);
457  }
458 
459  static PacketX2 makePitchBendV2 (uint8_t group,
460  uint8_t channel,
461  uint32_t data)
462  {
463  return Detail::makeV2().withGroup (group)
464  .withStatus (0xe)
465  .withChannel (channel)
466  .withU32<1> (data);
467  }
468 
469  static PacketX2 makePerNoteManagementV2 (uint8_t group,
470  uint8_t channel,
471  uint8_t note,
472  uint8_t optionFlags)
473  {
474  return Detail::makeV2().withGroup (group)
475  .withStatus (0xf)
476  .withChannel (channel)
477  .withU8<2> (note)
478  .withU8<3> (optionFlags);
479  }
480 
481 
482  static PacketX4 makeSysEx8in1Packet (uint8_t group,
483  uint8_t numBytes,
484  uint8_t streamId,
485  const uint8_t* data)
486  {
487  return Detail::makeSysEx8 (group, 0x0, numBytes, 3, data).withU8<2> (streamId);
488  }
489 
490  static PacketX4 makeSysEx8Start (uint8_t group,
491  uint8_t numBytes,
492  uint8_t streamId,
493  const uint8_t* data)
494  {
495  return Detail::makeSysEx8 (group, 0x1, numBytes, 3, data).withU8<2> (streamId);
496  }
497 
498  static PacketX4 makeSysEx8Continue (uint8_t group,
499  uint8_t numBytes,
500  uint8_t streamId,
501  const uint8_t* data)
502  {
503  return Detail::makeSysEx8 (group, 0x2, numBytes, 3, data).withU8<2> (streamId);
504  }
505 
506  static PacketX4 makeSysEx8End (uint8_t group,
507  uint8_t numBytes,
508  uint8_t streamId,
509  const uint8_t* data)
510  {
511  return Detail::makeSysEx8 (group, 0x3, numBytes, 3, data).withU8<2> (streamId);
512  }
513 
514  static PacketX4 makeMixedDataSetHeader (uint8_t group,
515  uint8_t dataSetId,
516  const uint8_t* data)
517  {
518  return Detail::makeSysEx8 (group, 0x8, 14, 2, data).withChannel (dataSetId);
519  }
520 
521  static PacketX4 makeDataSetPayload (uint8_t group,
522  uint8_t dataSetId,
523  const uint8_t* data)
524  {
525  return Detail::makeSysEx8 (group, 0x9, 14, 2, data).withChannel (dataSetId);
526  }
527 };
528 
529 } // namespace juce::universal_midi_packets
530 
531 #endif
constexpr static uint32 bigEndianInt(const void *bytes) noexcept