From 4fbe2ef421ea5200c234b2bc90e2577a37efbaf7 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 22 May 2026 17:13:41 +0200 Subject: [PATCH] ump-utils: fix MIDI 2.0 pitch bend and mask program number Fix spa_ump_to_midi() MIDI 2.0 pitch bend (0xE0) to extract both LSB and MSB from the 32-bit value in word 2, giving full 14-bit resolution. Previously the LSB came from a reserved field and was always zero. Mask the program number with 0x7f for consistency with bank byte masking. Co-Authored-By: Claude Opus 4.6 --- spa/include/spa/control/ump-utils.h | 7 ++++++- spa/tests/test-ump-utils.c | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/spa/include/spa/control/ump-utils.h b/spa/include/spa/control/ump-utils.h index 2b833cd72..be0897e31 100644 --- a/spa/include/spa/control/ump-utils.h +++ b/spa/include/spa/control/ump-utils.h @@ -118,7 +118,7 @@ SPA_API_CONTROL_UMP_UTILS int spa_ump_to_midi(const uint32_t **ump, size_t *ump_ } else if (*state == 2) { midi[size++] = status; - midi[size++] = (u[1] >> 24); + midi[size++] = (u[1] >> 24) & 0x7f; *state = 0; } break; @@ -126,6 +126,11 @@ SPA_API_CONTROL_UMP_UTILS int spa_ump_to_midi(const uint32_t **ump, size_t *ump_ midi[size++] = status; midi[size++] = (u[1] >> 25); break; + case 0xe0: + midi[size++] = status; + midi[size++] = (u[1] >> 18) & 0x7f; + midi[size++] = (u[1] >> 25); + break; default: midi[size++] = status; midi[size++] = (u[0] >> 8) & 0x7f; diff --git a/spa/tests/test-ump-utils.c b/spa/tests/test-ump-utils.c index fce1940c0..c73cc813e 100644 --- a/spa/tests/test-ump-utils.c +++ b/spa/tests/test-ump-utils.c @@ -571,6 +571,24 @@ static void test_ump_to_midi2_note_on(void) spa_assert(midi[2] == 0x7e); } +static void test_ump_to_midi2_pitch_bend(void) +{ + /* MIDI 2.0 pitch bend: type 4, status E, channel 0 + * 32-bit value 0x80A00000 → 14-bit = 0x80A00000 >> 18 = 0x2028 + * LSB = 0x28, MSB = 0x40 */ + uint32_t ump[] = { 0x40E00000, 0x80A00000 }; + const uint32_t *p = ump; + size_t ump_size = sizeof(ump); + uint8_t midi[8]; + uint64_t state = 0; + + int size = spa_ump_to_midi(&p, &ump_size, midi, sizeof(midi), &state); + spa_assert(size == 3); + spa_assert(midi[0] == 0xe0); + spa_assert(midi[1] == 0x28); + spa_assert(midi[2] == 0x40); +} + static void test_ump_to_midi2_program_change_with_bank(void) { /* MIDI 2.0 program change with bank valid, bank bytes have bit 7 set @@ -646,6 +664,7 @@ int main(void) test_ump_from_midi_sysex_split_with_f7(); test_ump_to_midi2_channel_pressure(); test_ump_to_midi2_note_on(); + test_ump_to_midi2_pitch_bend(); test_ump_to_midi2_program_change_with_bank(); test_ump_to_midi2_program_change_no_bank();