1 // Copyright 2021 Jean Pierre Cimalando
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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"
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
)
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
)
41 if (event
->bus
>= ysfx_max_midi_buses
)
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
)
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
);
63 void ysfx_midi_rewind(ysfx_midi_buffer_t
*midi
)
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
;
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
);
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
)
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
;
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
;
110 pos
+= sizeof(header
) + header
.size
;
111 avail
-= sizeof(header
) + header
.size
;
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
);
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
;
133 mp
->start
= midi
->data
.size();
137 if (!midi
->extensible
) {
138 size_t writable
= midi
->data
.capacity() - midi
->data
.size();
139 if (writable
< sizeof(header
)) {
146 header
.offset
= offset
;
149 const uint8_t *headp
= (const uint8_t *)&header
;
150 midi
->data
.insert(midi
->data
.end(), headp
, headp
+ sizeof(header
));
155 bool ysfx_midi_push_data(ysfx_midi_push_t
*mp
, const uint8_t *data
, uint32_t size
)
160 if (size
> ysfx_midi_message_max_size
|| mp
->count
+ size
> ysfx_midi_message_max_size
) {
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
) {
175 midi
->data
.insert(midi
->data
.end(), data
, data
+ size
);
180 bool ysfx_midi_push_end(ysfx_midi_push_t
*mp
)
183 mp
->midi
->data
.resize(mp
->start
);
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
));
195 //------------------------------------------------------------------------------
196 uint32_t ysfx_midi_sizeof(uint8_t id
)
198 if ((id
>> 7) == 0) {
201 else if ((id
>> 4) != 0b1111) {
202 static const uint8_t sizetable
[8] = {
205 return sizetable
[(id
>> 4) & 0b111];
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];