OpenShot Audio Library | OpenShotAudio: juce_UMPMidi1ToMidi2DefaultTranslator.h Source File

OpenShot Audio Library | OpenShotAudio 0.4.0

Loading...
Searching...
No Matches
juce_UMPMidi1ToMidi2DefaultTranslator.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
25namespace juce::universal_midi_packets
26{
27
34 class Midi1ToMidi2DefaultTranslator
35{
36public:
37 Midi1ToMidi2DefaultTranslator() = default;
38
48 template <typename PacketCallback>
49 void dispatch (const View& v, PacketCallback&& callback)
50 {
51 const auto firstWord = v[0];
52 const auto messageType = Utils::getMessageType (firstWord);
53
54 if (messageType != 0x2)
55 {
56 callback (v);
57 return;
58 }
59
60 const HelperValues helperValues
61 {
62 std::byte ((0x4 << 0x4) | Utils::getGroup (firstWord)),
63 std::byte ((firstWord >> 0x10) & 0xff),
64 std::byte ((firstWord >> 0x08) & 0x7f),
65 std::byte ((firstWord >> 0x00) & 0x7f),
66 };
67
68 switch (Utils::getStatus (firstWord))
69 {
70 case 0x8:
71 case 0x9:
72 {
73 const auto packet = processNoteOnOrOff (helperValues);
74 callback (View (packet.data()));
75 return;
76 }
77
78 case 0xa:
79 {
80 const auto packet = processPolyPressure (helperValues);
81 callback (View (packet.data()));
82 return;
83 }
84
85 case 0xb:
86 {
87 PacketX2 packet;
88
89 if (processControlChange (helperValues, packet))
90 callback (View (packet.data()));
91
92 return;
93 }
94
95 case 0xc:
96 {
97 const auto packet = processProgramChange (helperValues);
98 callback (View (packet.data()));
99 return;
100 }
101
102 case 0xd:
103 {
104 const auto packet = processChannelPressure (helperValues);
105 callback (View (packet.data()));
106 return;
107 }
108
109 case 0xe:
110 {
111 const auto packet = processPitchBend (helperValues);
112 callback (View (packet.data()));
113 return;
114 }
115 }
116 }
117
118 void reset()
119 {
120 groupAccumulators = {};
121 groupBanks = {};
122 }
123
124private:
125 enum class PnKind { nrpn, rpn };
126
127 struct HelperValues
128 {
129 std::byte typeAndGroup;
130 std::byte byte0;
131 std::byte byte1;
132 std::byte byte2;
133 };
134
135 static PacketX2 processNoteOnOrOff (HelperValues helpers);
136 static PacketX2 processPolyPressure (HelperValues helpers);
137
138 bool processControlChange (HelperValues helpers, PacketX2& packet);
139
140 PacketX2 processProgramChange (HelperValues helpers) const;
141
142 static PacketX2 processChannelPressure (HelperValues helpers);
143 static PacketX2 processPitchBend (HelperValues helpers);
144
145 class PnAccumulator
146 {
147 public:
148 bool addByte (uint8_t cc, std::byte byte);
149
150 const std::array<std::byte, 4>& getBytes() const noexcept { return bytes; }
151 PnKind getKind() const noexcept { return kind; }
152
153 private:
154 std::array<std::byte, 4> bytes;
155 uint8_t index = 0;
156 PnKind kind = PnKind::nrpn;
157 };
158
159 class Bank
160 {
161 public:
162 bool isValid() const noexcept { return ! (msb & 0x80); }
163
164 uint8_t getMsb() const noexcept { return msb & 0x7f; }
165 uint8_t getLsb() const noexcept { return lsb & 0x7f; }
166
167 void setMsb (uint8_t i) noexcept { msb = i & 0x7f; }
168 void setLsb (uint8_t i) noexcept { msb &= 0x7f; lsb = i & 0x7f; }
169
170 private:
171 // We use the top bit to indicate whether this bank is valid.
172 // After reading the spec, it's not clear how we should determine whether
173 // there are valid values, so we'll just assume that the bank is valid
174 // once either the lsb or msb have been written.
175 uint8_t msb = 0x80;
176 uint8_t lsb = 0x00;
177 };
178
179 using ChannelAccumulators = std::array<PnAccumulator, 16>;
180 std::array<ChannelAccumulators, 16> groupAccumulators;
181
182 using ChannelBanks = std::array<Bank, 16>;
183 std::array<ChannelBanks, 16> groupBanks;
184};
185
186} // namespace juce::universal_midi_packets
187
188#endif
juce::universal_midi_packets::Midi1ToMidi2DefaultTranslator
Definition juce_UMPMidi1ToMidi2DefaultTranslator.h:35
juce::universal_midi_packets::Midi1ToMidi2DefaultTranslator::dispatch
void dispatch(const View &v, PacketCallback &&callback)
Definition juce_UMPMidi1ToMidi2DefaultTranslator.h:49
juce::universal_midi_packets::Packet
Definition juce_UMPacket.h:35
juce::universal_midi_packets::View
Definition juce_UMPView.h:44