Skip to content

MIDI: sysex to the graph, removed devices, latency, loop WAV writer - #965

Merged
jcelerier merged 16 commits into
masterfrom
feature/midi-effects
Oct 28, 2026
Merged

jcelerier merged 16 commits into
masterfrom
feature/midi-effects

Conversation

@jcelerier

Copy link
Copy Markdown
Member

Engine changes for score's MIDI effects and loopers.

  • Sysex reaches the graph: MIDI inputs ask the backend for sysex (it was dropped) and pass each UMP packet on its own (it was cut to the first packet). A port bound to a MIDI channel takes only channel messages.
  • Removed MIDI devices are never read: each MIDI inlet records the stream it registered with; unregistering it uses that record, and a removed device's stream is dropped when the change is applied, now at the start of the tick. Fixes a crash when a document whose processes read a MIDI device is closed.
  • Midi node: note-on and note-off stamps stay inside their own tick.
  • Audio latency: audio_engine reports input / output latency (PortAudio; JACK, kept current by a latency callback, stored in atomics), exposed on execution_state.
  • write_loop_wav: 32-bit float WAV loops with ACID tempo and an smpl loop; RF64 past 4 GB; a file that failed to write is removed.
  • SDK: Qt QML headers installed when OSSIA_QML is on.
  • libremidi bumped: Pitch bend upscale and whole sysex across MIDI 1 and MIDI 2 celtera/libremidi#268.

Tested through score (ossia/score feature/midi-effects): 105 targeted test programs pass, including new execution_state tests for stale MIDI devices and closing a playing document.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr

@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 04:56 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 04:56 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 04:56 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 04:56 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 04:56 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 04:56 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 04:56 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 04:56 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 04:56 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 04:56 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 04:56 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 10:49 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 10:49 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 10:49 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 10:49 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 10:49 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 10:49 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 10:49 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 10:49 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 10:49 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 10:49 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 13:14 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 14:12 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 14:12 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 14:12 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 14:12 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 14:12 — with GitHub Actions Inactive
@jcelerier
jcelerier temporarily deployed to Apple Certificate October 25, 2026 14:12 — with GitHub Actions Inactive
jcelerier and others added 13 commits October 27, 2026 22:59
… the execution state

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
- JACK recomputes port latencies on its own thread when the graph changes;
  a latency callback stores them in atomics the engine reads.
- write_loop_wav writes RF64 when the data does not fit a RIFF header, and
  removes a file it failed to finish.
- libremidi: one 14 to 32 bit upscale for pitch bend.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
An inlet's MIDI stream is recorded when it registers, and unregistering it
uses that record rather than its address, whose device may be destroyed by
then. A removed device's stream is dropped when the device change is
applied, which now happens before a tick reads the streams.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
MIDI inputs ask the backend for sysex, and pass each UMP packet of it on
its own: a full-frame timecode was dropped by the backend, then truncated
to its first packet. A port bound to a channel takes only channel
messages, so sysex no longer leaks into it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
…ps its inlets

A device removed and registered again before a tick, or a new one
allocated where the old one was, kept losing the inlets already bound to
it: the removal erased them after they had registered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr
@jcelerier
jcelerier deployed to Apple Certificate October 28, 2026 03:43 — with GitHub Actions Active
jcelerier and others added 2 commits October 28, 2026 09:31
set_start_time and set_end_time scaled the musical position by t / date,
which only holds when the position is proportional to the date. An item
that starts later than musical time, e.g. a box later in a scenario, has
dates relative to itself and quarters relative to the timeline: a looper
there split at a grid point got a start of 18.45 quarters for 17. The
position is now interpolated within the tick, as the frames are.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qr9WkcUjEGCueg7eG1KxSr

This branch was successfully deployed

1 active deployment
Apple Certificate — 64a7ee1a Deployed Oct 28, 2026 by jcelerier via build-macos (0, Debug) #1320
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant