OpenShot Audio Library | OpenShotAudio  0.6.0
juce_UMPMidi1ToMidi2DefaultTranslator.cpp
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 namespace juce::universal_midi_packets
24 {
25 
26 PacketX2 Midi1ToMidi2DefaultTranslator::processNoteOnOrOff (const HelperValues helpers)
27 {
28  const auto velocity = helpers.byte2;
29  const auto needsConversion = (helpers.byte0 & std::byte { 0xf0 }) == std::byte { 0x90 } && velocity == std::byte { 0 };
30  const auto firstByte = needsConversion ? (std::byte { 0x80 } | (helpers.byte0 & std::byte { 0xf }))
31  : helpers.byte0;
32 
33  return PacketX2
34  {
35  Utils::bytesToWord (helpers.typeAndGroup, firstByte, helpers.byte1, std::byte { 0 }),
36  (uint32_t) (Conversion::scaleTo16 (uint8_t (velocity)) << 0x10)
37  };
38 }
39 
40 PacketX2 Midi1ToMidi2DefaultTranslator::processPolyPressure (const HelperValues helpers)
41 {
42  return PacketX2
43  {
44  Utils::bytesToWord (helpers.typeAndGroup, helpers.byte0, helpers.byte1, std::byte { 0 }),
45  Conversion::scaleTo32 (uint8_t (helpers.byte2))
46  };
47 }
48 
49 bool Midi1ToMidi2DefaultTranslator::processControlChange (const HelperValues helpers,
50  PacketX2& packet)
51 {
52  const auto statusAndChannel = helpers.byte0;
53  const auto cc = uint8_t (helpers.byte1);
54 
55  const auto shouldAccumulate = [&]
56  {
57  switch (cc)
58  {
59  case 6:
60  case 38:
61  case 98:
62  case 99:
63  case 100:
64  case 101:
65  return true;
66  }
67 
68  return false;
69  }();
70 
71  const auto group = (uint8_t) (helpers.typeAndGroup & std::byte { 0xf });
72  const auto channel = (uint8_t) (statusAndChannel & std::byte { 0xf });
73  const auto byte = helpers.byte2;
74 
75  if (shouldAccumulate)
76  {
77  auto& accumulator = groupAccumulators[group][channel];
78 
79  if (accumulator.addByte (cc, byte))
80  {
81  const auto& bytes = accumulator.getBytes();
82  const auto bank = bytes[0];
83  const auto index = bytes[1];
84  const auto msb = bytes[2];
85  const auto lsb = bytes[3];
86 
87  const auto value = uint16_t ((uint16_t (msb & std::byte { 0x7f }) << 7) | uint16_t (lsb & std::byte { 0x7f }));
88 
89  const auto newStatus = (uint8_t) (accumulator.getKind() == PnKind::nrpn ? 0x3 : 0x2);
90 
91  packet = PacketX2
92  {
93  Utils::bytesToWord (helpers.typeAndGroup, std::byte ((newStatus << 0x4) | channel), bank, index),
94  Conversion::scaleTo32 (value)
95  };
96  return true;
97  }
98 
99  return false;
100  }
101 
102  if (cc == 0)
103  {
104  groupBanks[group][channel].setMsb (uint8_t (byte));
105  return false;
106  }
107 
108  if (cc == 32)
109  {
110  groupBanks[group][channel].setLsb (uint8_t (byte));
111  return false;
112  }
113 
114  packet = PacketX2
115  {
116  Utils::bytesToWord (helpers.typeAndGroup, statusAndChannel, std::byte { cc }, std::byte { 0 }),
117  Conversion::scaleTo32 (uint8_t (helpers.byte2))
118  };
119  return true;
120 }
121 
122 PacketX2 Midi1ToMidi2DefaultTranslator::processProgramChange (const HelperValues helpers) const
123 {
124  const auto group = (uint8_t) (helpers.typeAndGroup & std::byte { 0xf });
125  const auto channel = (uint8_t) (helpers.byte0 & std::byte { 0xf });
126  const auto bank = groupBanks[group][channel];
127  const auto valid = bank.isValid();
128 
129  return PacketX2
130  {
131  Utils::bytesToWord (helpers.typeAndGroup,
132  helpers.byte0,
133  std::byte { 0 },
134  valid ? std::byte { 1 } : std::byte { 0 }),
135  Utils::bytesToWord (helpers.byte1,
136  std::byte { 0 },
137  valid ? std::byte { bank.getMsb() } : std::byte { 0 },
138  valid ? std::byte { bank.getLsb() } : std::byte { 0 })
139  };
140 }
141 
142 PacketX2 Midi1ToMidi2DefaultTranslator::processChannelPressure (const HelperValues helpers)
143 {
144  return PacketX2
145  {
146  Utils::bytesToWord (helpers.typeAndGroup, helpers.byte0, std::byte { 0 }, std::byte { 0 }),
147  Conversion::scaleTo32 (uint8_t (helpers.byte1))
148  };
149 }
150 
151 PacketX2 Midi1ToMidi2DefaultTranslator::processPitchBend (const HelperValues helpers)
152 {
153  const auto lsb = helpers.byte1;
154  const auto msb = helpers.byte2;
155  const auto value = uint16_t (uint16_t (msb) << 7 | uint16_t (lsb));
156 
157  return PacketX2
158  {
159  Utils::bytesToWord (helpers.typeAndGroup, helpers.byte0, std::byte { 0 }, std::byte { 0 }),
160  Conversion::scaleTo32 (value)
161  };
162 }
163 
164 bool Midi1ToMidi2DefaultTranslator::PnAccumulator::addByte (uint8_t cc, std::byte byte)
165 {
166  const auto isStart = cc == 99 || cc == 101;
167 
168  if (isStart)
169  {
170  kind = cc == 99 ? PnKind::nrpn : PnKind::rpn;
171  index = 0;
172  }
173 
174  bytes[index] = byte;
175 
176  const auto shouldContinue = [&]
177  {
178  switch (index)
179  {
180  case 0: return isStart;
181  case 1: return kind == PnKind::nrpn ? cc == 98 : cc == 100;
182  case 2: return cc == 6;
183  case 3: return cc == 38;
184  }
185 
186  return false;
187  }();
188 
189  index = shouldContinue ? index + 1 : 0;
190 
191  if (index != bytes.size())
192  return false;
193 
194  index = 0;
195  return true;
196 }
197 
198 } // namespace juce::universal_midi_packets
static uint32_t scaleTo32(uint8_t word7Bit)
static uint16_t scaleTo16(uint8_t word7Bit)
static constexpr uint32_t bytesToWord(std::byte a, std::byte b, std::byte c, std::byte d)
Definition: juce_UMPUtils.h:36