midi: don't write trailing continuation 0xf0 for SysEx

Because our midi messages already have a size, we don't need the 0xf0
continuation terminator. Also having the terminator optionally requires
you to check and strip it if it's there.

The easiest algorithm is to check the first byte for start (0xf0) or
continuation (0xf7) and the last byte for end (0xf7) and that should be
enough to process the messages without having to ever stip the last
byte.
This commit is contained in:
Wim Taymans 2026-06-01 13:08:11 +02:00
parent b41d117609
commit 350eb9a041
10 changed files with 52 additions and 35 deletions

View file

@ -354,6 +354,10 @@ static void midi_to_ffado(struct port *p, float *src, uint32_t n_samples)
if (index < c.offset)
index = SPA_ROUND_UP_N(c.offset, 8);
if (size > 1 && data[0] == 0xf7) {
data++;
size--;
}
for (j = 0; j < size; j++) {
if (index >= n_samples) {
/* keep events that don't fit for the next cycle */

View file

@ -284,6 +284,10 @@ static void midi_to_jack(struct impl *impl, float *dst, float *src, uint32_t n_s
data = tmp;
size = 3;
}
if (size > 1 && data[0] == 0xf7) {
data++;
size--;
}
if ((res = jack.midi_event_write(dst, c.offset, data, size)) < 0)
pw_log_warn("midi %p: can't write event: %s", dst,
spa_strerror(res));

View file

@ -351,6 +351,10 @@ static void midi_to_netjack2(struct netjack2_peer *peer,
buf->lost_events++;
continue;
}
if (size > 1 && data[0] == 0xf7) {
data++;
size--;
}
n2j_midi_buffer_write(buf, c.offset, data, size, peer->fix_midi);
}
if (buf->write_pos > 0)

View file

@ -270,7 +270,7 @@ static int rtp_midi_receive_midi(struct impl *impl, uint8_t *packet, uint32_t ti
while (offs < end) {
uint32_t delta;
int size;
int size, tail_trim = 0;
if (first && !hdr.z)
delta = 0;
@ -290,9 +290,11 @@ static int rtp_midi_receive_midi(struct impl *impl, uint8_t *packet, uint32_t ti
packet[offs], size, offs, end);
return -EINVAL;
}
if (packet[offs + size-1] == 0xf0)
tail_trim++;
spa_pod_builder_control(&b, timestamp, SPA_CONTROL_Midi);
spa_pod_builder_bytes(&b, &packet[offs], size);
spa_pod_builder_bytes(&b, &packet[offs], size - tail_trim);
offs += size;
first = false;
@ -372,34 +374,41 @@ unexpected_ssrc:
return -EINVAL;
}
static int write_event(uint8_t *p, uint32_t buffer_size, uint32_t value, const void *ev, uint32_t size)
static int write_event(uint8_t *p, uint32_t buffer_size, uint32_t delta, const uint8_t *ev, uint32_t size)
{
uint64_t buffer;
uint8_t b;
uint64_t buffer;
uint8_t b;
unsigned int count = 0;
uint32_t total;
if (buffer_size <= size)
total = size;
if (ev[size-1] != 0xf7)
total++;
if (buffer_size <= total)
return -ENOSPC;
buffer = value & 0x7f;
while ((value >>= 7)) {
buffer = delta & 0x7f;
while ((delta >>= 7)) {
if (buffer > (UINT64_MAX >> 8))
return -ERANGE;
buffer <<= 8;
buffer |= ((value & 0x7f) | 0x80);
}
do {
if (count >= buffer_size)
return -ENOSPC;
buffer <<= 8;
buffer |= ((delta & 0x7f) | 0x80);
}
do {
if (count >= buffer_size)
return -ENOSPC;
b = buffer & 0xff;
p[count++] = b;
buffer >>= 8;
} while (b & 0x80);
p[count++] = b;
buffer >>= 8;
} while (b & 0x80);
if (buffer_size - size < count ||
count + size > (unsigned int)INT_MAX)
if (buffer_size - total < count ||
count + total > (unsigned int)INT_MAX)
return -ENOSPC;
memcpy(&p[count], ev, size);
return (int)(count + size);
if (size < total)
p[count+size] = 0xf0;
return (int)(count + total);
}
static void rtp_midi_flush_packets(struct impl *impl,

View file

@ -51,7 +51,7 @@ static void vban_midi_process_playback(void *data)
goto done;
/* the ringbuffer contains series of sequences, one for each
* received packet. This is not share mem so we can use the
* received packet. This is not shared mem so we can use the
* iterator. */
SPA_POD_SEQUENCE_FOREACH((struct spa_pod_sequence*)pod, c) {
#if 0

View file

@ -560,9 +560,6 @@ int midi_file_write_event(struct midi_file *mf, const struct midi_event *event)
ev_size--;
ev_data++;
if (ev_data[ev_size-1] == 0xf0)
ev_size--;
CHECK_RES(write_varlen(mf, tr, ev_size));
tr->size += 1;

View file

@ -1569,11 +1569,6 @@ static int sysex_play(struct data *d, void *dst, uint32_t maxsize, unsigned int
bytes[size] = 0xf7;
size += 1;
}
} else {
if (bytes[size-1] != 0xf0) {
bytes[size] = 0xf0;
size += 1;
}
}
if (d->sysex.first) {
if (bytes[0] != 0xf0) {