Add initial bits for Qt6 support
[carla.git] / source / modules / ysfx / sources / ysfx_midi.cpp
blob2e13faf1b6cad3e78a8497c90528422f9c0a6c88
1 // Copyright 2021 Jean Pierre Cimalando
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 // SPDX-License-Identifier: Apache-2.0
18 #include "ysfx_midi.hpp"
19 #include <cstring>
20 #include <cassert>
22 void ysfx_midi_reserve(ysfx_midi_buffer_t *midi, uint32_t capacity, bool extensible)
24 std::vector<uint8_t> data;
25 data.reserve(capacity);
26 std::swap(data, midi->data);
27 midi->extensible = extensible;
28 ysfx_midi_rewind(midi);
31 void ysfx_midi_clear(ysfx_midi_buffer_t *midi)
33 midi->data.clear();
34 ysfx_midi_rewind(midi);
37 bool ysfx_midi_push(ysfx_midi_buffer_t *midi, const ysfx_midi_event_t *event)
39 if (event->size > ysfx_midi_message_max_size)
40 return false;
41 if (event->bus >= ysfx_max_midi_buses)
42 return false;
44 ysfx_midi_header_t header;
46 if (!midi->extensible) {
47 size_t writable = midi->data.capacity() - midi->data.size();
48 if (writable < sizeof(header) + event->size)
49 return false;
52 const uint8_t *data = event->data;
53 const uint8_t *headp = (const uint8_t *)&header;
54 header.bus = event->bus;
55 header.offset = event->offset;
56 header.size = event->size;
58 midi->data.insert(midi->data.end(), headp, headp + sizeof(header));
59 midi->data.insert(midi->data.end(), data, data + header.size);
60 return true;
63 void ysfx_midi_rewind(ysfx_midi_buffer_t *midi)
65 midi->read_pos = 0;
66 for (uint32_t i = 0; i < ysfx_max_midi_buses; ++i)
67 midi->read_pos_for_bus[i] = 0;
70 bool ysfx_midi_get_next(ysfx_midi_buffer_t *midi, ysfx_midi_event_t *event)
72 size_t *pos_ptr = &midi->read_pos;
73 size_t pos = *pos_ptr;
75 size_t avail = midi->data.size() - pos;
76 ysfx_midi_header_t header;
77 if (avail == 0)
78 return false;
80 assert(avail >= sizeof(header));
81 memcpy(&header, &midi->data[pos], sizeof(header));
82 assert(avail >= sizeof(header) + header.size);
84 event->bus = header.bus;
85 event->offset = header.offset;
86 event->size = header.size;
87 event->data = &midi->data[pos + sizeof(header)];
88 *pos_ptr = pos + (sizeof(header) + header.size);
89 return true;
92 bool ysfx_midi_get_next_from_bus(ysfx_midi_buffer_t *midi, uint32_t bus, ysfx_midi_event_t *event)
94 if (bus >= ysfx_max_midi_buses)
95 return false;
97 size_t *pos_ptr = &midi->read_pos_for_bus[bus];
98 size_t pos = *pos_ptr;
99 size_t avail = midi->data.size() - pos;
100 ysfx_midi_header_t header;
102 bool found = false;
103 while (!found && avail > 0) {
104 assert(avail >= sizeof(header));
105 memcpy(&header, &midi->data[pos], sizeof(header));
106 assert(avail >= sizeof(header) + header.size);
108 found = header.bus == bus;
109 if (!found) {
110 pos += sizeof(header) + header.size;
111 avail -= sizeof(header) + header.size;
115 if (!found) {
116 *pos_ptr = pos;
117 return false;
120 event->bus = header.bus;
121 event->offset = header.offset;
122 event->size = header.size;
123 event->data = &midi->data[pos + sizeof(header)];
124 *pos_ptr = pos + (sizeof(header) + header.size);
125 return true;
128 bool ysfx_midi_push_begin(ysfx_midi_buffer_t *midi, uint32_t bus, uint32_t offset, ysfx_midi_push_t *mp)
130 ysfx_midi_header_t header;
132 mp->midi = midi;
133 mp->start = midi->data.size();
134 mp->count = 0;
135 mp->eob = false;
137 if (!midi->extensible) {
138 size_t writable = midi->data.capacity() - midi->data.size();
139 if (writable < sizeof(header)) {
140 mp->eob = true;
141 return false;
145 header.bus = bus;
146 header.offset = offset;
147 header.size = 0;
149 const uint8_t *headp = (const uint8_t *)&header;
150 midi->data.insert(midi->data.end(), headp, headp + sizeof(header));
152 return true;
155 bool ysfx_midi_push_data(ysfx_midi_push_t *mp, const uint8_t *data, uint32_t size)
157 if (mp->eob)
158 return false;
160 if (size > ysfx_midi_message_max_size || mp->count + size > ysfx_midi_message_max_size) {
161 mp->eob = true;
162 return false;
165 ysfx_midi_buffer_t *midi = mp->midi;
167 if (!midi->extensible) {
168 size_t writable = midi->data.capacity() - midi->data.size();
169 if (writable < size) {
170 mp->eob = true;
171 return false;
175 midi->data.insert(midi->data.end(), data, data + size);
176 mp->count += size;
177 return true;
180 bool ysfx_midi_push_end(ysfx_midi_push_t *mp)
182 if (mp->eob) {
183 mp->midi->data.resize(mp->start);
184 return false;
187 ysfx_midi_header_t header;
188 uint8_t *headp = &mp->midi->data[mp->start];
189 memcpy(&header, headp, sizeof(header));
190 header.size = mp->count;
191 memcpy(headp, &header, sizeof(header));
192 return true;
195 //------------------------------------------------------------------------------
196 uint32_t ysfx_midi_sizeof(uint8_t id)
198 if ((id >> 7) == 0) {
199 return 0;
201 else if ((id >> 4) != 0b1111) {
202 static const uint8_t sizetable[8] = {
203 3, 3, 3, 3, 2, 2, 3,
205 return sizetable[(id >> 4) & 0b111];
207 else {
208 static const uint8_t sizetable[16] = {
209 0, 2, 3, 2, 1, 1, 1, 0,
210 1, 1, 1, 1, 1, 1, 1, 1,
212 return sizetable[id & 0b1111];