LMMS
Loading...
Searching...
No Matches
juce_UMPConversion.h
Go to the documentation of this file.
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
25namespace juce
26{
28{
29
37{
42 template <typename PacketCallbackFunction>
43 static void toMidi1 (const MidiMessage& m, PacketCallbackFunction&& callback)
44 {
45 const auto* data = m.getRawData();
46 const auto firstByte = data[0];
47 const auto size = m.getRawDataSize();
48
49 if (firstByte != 0xf0)
50 {
51 const auto mask = [size]() -> uint32_t
52 {
53 switch (size)
54 {
55 case 0: return 0xff000000;
56 case 1: return 0xffff0000;
57 case 2: return 0xffffff00;
58 case 3: return 0xffffffff;
59 }
60
61 return 0x00000000;
62 }();
63
64 const auto extraByte = (uint8_t) ((((firstByte & 0xf0) == 0xf0) ? 0x1 : 0x2) << 0x4);
65 const PacketX1 packet { mask & Utils::bytesToWord (extraByte, data[0], data[1], data[2]) };
66 callback (View (packet.data()));
67 return;
68 }
69
70 const auto numSysExBytes = m.getSysExDataSize();
71 const auto numMessages = SysEx7::getNumPacketsRequiredForDataSize ((uint32_t) numSysExBytes);
72 auto* dataOffset = m.getSysExData();
73
74 if (numMessages <= 1)
75 {
76 const auto packet = Factory::makeSysExIn1Packet (0, (uint8_t) numSysExBytes, dataOffset);
77 callback (View (packet.data()));
78 return;
79 }
80
81 constexpr auto byteIncrement = 6;
82
83 for (auto i = numSysExBytes; i > 0; i -= byteIncrement, dataOffset += byteIncrement)
84 {
85 const auto func = [&]
86 {
87 if (i == numSysExBytes)
89
90 if (i <= byteIncrement)
92
94 }();
95
96 const auto bytesNow = std::min (byteIncrement, i);
97 const auto packet = func (0, (uint8_t) bytesNow, dataOffset);
98 callback (View (packet.data()));
99 }
100 }
101
111 static void toMidi1 (const MidiMessage& m, Packets& packets)
112 {
113 toMidi1 (m, [&] (const View& view) { packets.add (view); });
114 }
115
117 static uint8_t scaleTo8 (uint8_t word7Bit)
118 {
119 const auto shifted = (uint8_t) (word7Bit << 0x1);
120 const auto repeat = (uint8_t) (word7Bit & 0x3f);
121 const auto mask = (uint8_t) (word7Bit <= 0x40 ? 0x0 : 0xff);
122 return (uint8_t) (shifted | ((repeat >> 5) & mask));
123 }
124
126 static uint16_t scaleTo16 (uint8_t word7Bit)
127 {
128 const auto shifted = (uint16_t) (word7Bit << 0x9);
129 const auto repeat = (uint16_t) (word7Bit & 0x3f);
130 const auto mask = (uint16_t) (word7Bit <= 0x40 ? 0x0 : 0xffff);
131 return (uint16_t) (shifted | (((repeat << 3) | (repeat >> 3)) & mask));
132 }
133
135 static uint16_t scaleTo16 (uint16_t word14Bit)
136 {
137 const auto shifted = (uint16_t) (word14Bit << 0x2);
138 const auto repeat = (uint16_t) (word14Bit & 0x1fff);
139 const auto mask = (uint16_t) (word14Bit <= 0x2000 ? 0x0 : 0xffff);
140 return (uint16_t) (shifted | ((repeat >> 11) & mask));
141 }
142
144 static uint32_t scaleTo32 (uint8_t word7Bit)
145 {
146 const auto shifted = (uint32_t) (word7Bit << 0x19);
147 const auto repeat = (uint32_t) (word7Bit & 0x3f);
148 const auto mask = (uint32_t) (word7Bit <= 0x40 ? 0x0 : 0xffffffff);
149 return (uint32_t) (shifted | (((repeat << 19)
150 | (repeat << 13)
151 | (repeat << 7)
152 | (repeat << 1)
153 | (repeat >> 5)) & mask));
154 }
155
157 static uint32_t scaleTo32 (uint16_t word14Bit)
158 {
159 const auto shifted = (uint32_t) (word14Bit << 0x12);
160 const auto repeat = (uint32_t) (word14Bit & 0x1fff);
161 const auto mask = (uint32_t) (word14Bit <= 0x2000 ? 0x0 : 0xffffffff);
162 return (uint32_t) (shifted | (((repeat << 5) | (repeat >> 8)) & mask));
163 }
164
166 static uint8_t scaleTo7 (uint8_t word8Bit) { return (uint8_t) (word8Bit >> 1); }
167
169 static uint8_t scaleTo7 (uint16_t word16Bit) { return (uint8_t) (word16Bit >> 9); }
170
172 static uint8_t scaleTo7 (uint32_t word32Bit) { return (uint8_t) (word32Bit >> 25); }
173
175 static uint16_t scaleTo14 (uint16_t word16Bit) { return (uint16_t) (word16Bit >> 2); }
176
178 static uint16_t scaleTo14 (uint32_t word32Bit) { return (uint16_t) (word32Bit >> 18); }
179
189 template <typename Callback>
190 static void midi2ToMidi1DefaultTranslation (const View& v, Callback&& callback)
191 {
192 const auto firstWord = v[0];
193
194 if (Utils::getMessageType (firstWord) != 0x4)
195 {
196 callback (v);
197 return;
198 }
199
200 const auto status = Utils::getStatus (firstWord);
201 const auto typeAndGroup = (uint8_t) ((0x2 << 0x4) | Utils::getGroup (firstWord));
202
203 switch (status)
204 {
205 case 0x8: // note off
206 case 0x9: // note on
207 case 0xa: // poly pressure
208 case 0xb: // control change
209 {
210 const auto statusAndChannel = (uint8_t) ((firstWord >> 0x10) & 0xff);
211 const auto byte2 = (uint8_t) ((firstWord >> 0x08) & 0xff);
212 const auto byte3 = scaleTo7 (v[1]);
213
214 // If this is a note-on, and the scaled byte is 0,
215 // the scaled velocity should be 1 instead of 0
216 const auto needsCorrection = status == 0x9 && byte3 == 0;
217 const auto correctedByte = (uint8_t) (needsCorrection ? 1 : byte3);
218
219 const auto shouldIgnore = status == 0xb && [&]
220 {
221 switch (byte2)
222 {
223 case 0:
224 case 6:
225 case 32:
226 case 38:
227 case 98:
228 case 99:
229 case 100:
230 case 101:
231 return true;
232 }
233
234 return false;
235 }();
236
237 if (shouldIgnore)
238 return;
239
240 const PacketX1 packet { Utils::bytesToWord (typeAndGroup,
241 statusAndChannel,
242 byte2,
243 correctedByte) };
244 callback (View (packet.data()));
245 return;
246 }
247
248 case 0xd: // channel pressure
249 {
250 const auto statusAndChannel = (uint8_t) ((firstWord >> 0x10) & 0xff);
251 const auto byte2 = scaleTo7 (v[1]);
252
253 const PacketX1 packet { Utils::bytesToWord (typeAndGroup,
254 statusAndChannel,
255 byte2,
256 0) };
257 callback (View (packet.data()));
258 return;
259 }
260
261 case 0x2: // rpn
262 case 0x3: // nrpn
263 {
264 const auto ccX = (uint8_t) (status == 0x2 ? 101 : 99);
265 const auto ccY = (uint8_t) (status == 0x2 ? 100 : 98);
266 const auto statusAndChannel = (uint8_t) ((0xb << 0x4) | Utils::getChannel (firstWord));
267 const auto data = scaleTo14 (v[1]);
268
269 const PacketX1 packets[]
270 {
271 PacketX1 { Utils::bytesToWord (typeAndGroup, statusAndChannel, ccX, (uint8_t) ((firstWord >> 0x8) & 0x7f)) },
272 PacketX1 { Utils::bytesToWord (typeAndGroup, statusAndChannel, ccY, (uint8_t) ((firstWord >> 0x0) & 0x7f)) },
273 PacketX1 { Utils::bytesToWord (typeAndGroup, statusAndChannel, 6, (uint8_t) ((data >> 0x7) & 0x7f)) },
274 PacketX1 { Utils::bytesToWord (typeAndGroup, statusAndChannel, 38, (uint8_t) ((data >> 0x0) & 0x7f)) },
275 };
276
277 for (const auto& packet : packets)
278 callback (View (packet.data()));
279
280 return;
281 }
282
283 case 0xc: // program change / bank select
284 {
285 if (firstWord & 1)
286 {
287 const auto statusAndChannel = (uint8_t) ((0xb << 0x4) | Utils::getChannel (firstWord));
288 const auto secondWord = v[1];
289
290 const PacketX1 packets[]
291 {
292 PacketX1 { Utils::bytesToWord (typeAndGroup, statusAndChannel, 0, (uint8_t) ((secondWord >> 0x8) & 0x7f)) },
293 PacketX1 { Utils::bytesToWord (typeAndGroup, statusAndChannel, 32, (uint8_t) ((secondWord >> 0x0) & 0x7f)) },
294 };
295
296 for (const auto& packet : packets)
297 callback (View (packet.data()));
298 }
299
300 const auto statusAndChannel = (uint8_t) ((0xc << 0x4) | Utils::getChannel (firstWord));
301 const PacketX1 packet { Utils::bytesToWord (typeAndGroup,
302 statusAndChannel,
303 (uint8_t) ((v[1] >> 0x18) & 0x7f),
304 0) };
305 callback (View (packet.data()));
306 return;
307 }
308
309 case 0xe: // pitch bend
310 {
311 const auto data = scaleTo14 (v[1]);
312 const auto statusAndChannel = (uint8_t) ((firstWord >> 0x10) & 0xff);
313 const PacketX1 packet { Utils::bytesToWord (typeAndGroup,
314 statusAndChannel,
315 (uint8_t) (data & 0x7f),
316 (uint8_t) ((data >> 7) & 0x7f)) };
317 callback (View (packet.data()));
318 return;
319 }
320
321 default: // other message types do not translate
322 return;
323 }
324 }
325};
326
327}
328}
329
330#endif
static const unsigned long mask[]
Definition bitwise.c:31
Definition juce_MidiMessage.h:35
const uint32_t * data() const noexcept
Definition juce_UMPacket.h:174
Definition juce_UMPackets.h:42
void add(const View &v)
Definition juce_UMPackets.h:51
Definition juce_UMPView.h:46
unsigned * m
Definition inflate.c:1559
unsigned v[N_MAX]
Definition inflate.c:1584
register unsigned i
Definition inflate.c:1575
JSAMPIMAGE data
Definition jpeglib.h:945
unsigned short uint16_t
Definition mid.cpp:99
unsigned int uint32_t
Definition mid.cpp:100
unsigned char uint8_t
Definition mid.cpp:98
Definition juce_UMP_test.cpp:26
Packet< 1 > PacketX1
Definition juce_UMPacket.h:185
Definition carla_juce.cpp:31
jack_client_t client jack_client_t client jack_client_t client jack_client_t JackInfoShutdownCallback void arg jack_client_t jack_port_t port void(* func)(const char *))
Definition juce_linux_JackAudio.cpp:67
Definition juce_UMPConversion.h:37
static uint16_t scaleTo14(uint32_t word32Bit)
Definition juce_UMPConversion.h:178
static uint16_t scaleTo16(uint16_t word14Bit)
Definition juce_UMPConversion.h:135
static uint16_t scaleTo14(uint16_t word16Bit)
Definition juce_UMPConversion.h:175
static void midi2ToMidi1DefaultTranslation(const View &v, Callback &&callback)
Definition juce_UMPConversion.h:190
static void toMidi1(const MidiMessage &m, Packets &packets)
Definition juce_UMPConversion.h:111
static uint32_t scaleTo32(uint8_t word7Bit)
Definition juce_UMPConversion.h:144
static uint32_t scaleTo32(uint16_t word14Bit)
Definition juce_UMPConversion.h:157
static uint16_t scaleTo16(uint8_t word7Bit)
Definition juce_UMPConversion.h:126
static uint8_t scaleTo7(uint16_t word16Bit)
Definition juce_UMPConversion.h:169
static uint8_t scaleTo8(uint8_t word7Bit)
Definition juce_UMPConversion.h:117
static uint8_t scaleTo7(uint8_t word8Bit)
Definition juce_UMPConversion.h:166
static void toMidi1(const MidiMessage &m, PacketCallbackFunction &&callback)
Definition juce_UMPConversion.h:43
static uint8_t scaleTo7(uint32_t word32Bit)
Definition juce_UMPConversion.h:172
static PacketX2 makeSysExIn1Packet(uint8_t group, uint8_t numBytes, const uint8_t *data)
Definition juce_UMPFactory.h:251
static PacketX2 makeSysExContinue(uint8_t group, uint8_t numBytes, const uint8_t *data)
Definition juce_UMPFactory.h:265
static PacketX2 makeSysExEnd(uint8_t group, uint8_t numBytes, const uint8_t *data)
Definition juce_UMPFactory.h:272
static PacketX2 makeSysExStart(uint8_t group, uint8_t numBytes, const uint8_t *data)
Definition juce_UMPFactory.h:258
static uint32_t getNumPacketsRequiredForDataSize(uint32_t)
Definition juce_UMPSysEx7.cpp:28
static constexpr uint8_t getStatus(uint32_t w) noexcept
Definition juce_UMPUtils.h:110
static constexpr uint32_t bytesToWord(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
Definition juce_UMPUtils.h:38
static constexpr uint8_t getGroup(uint32_t w) noexcept
Definition juce_UMPUtils.h:109
static constexpr uint8_t getChannel(uint32_t w) noexcept
Definition juce_UMPUtils.h:111
static constexpr uint8_t getMessageType(uint32_t w) noexcept
Definition juce_UMPUtils.h:108
RECT const char void(* callback)(const char *droppath))) SWELL_API_DEFINE(BOOL
Definition swell-functions.h:1004
ulg size
Definition extract.c:2350