Skip to content

audiograph: Graph.swap, and carry() from a graph the pump is parked on - #350

Merged
bdbarnett merged 1 commit into
mainfrom
graph/swap
Oct 30, 2026
Merged

bdbarnett merged 1 commit into
mainfrom
graph/swap

Conversation

@bdbarnett

Copy link
Copy Markdown
Contributor

A patch change on a graph the audio pump is playing can now land on a block boundary without the pump, an output or a mixer having to be handed a new object.

Graph.swap(other) trades the two graphs' patches (nodes, buffers, wiring, queue, borrowed tables) under the pump lock. The graph that is pulled keeps its identity, its output blocks and its frame count, and renders other's patch from the next block. It refuses a non-graph with TypeError and a graph of another sample rate, block size or channel count with ValueError. MicroPython, CPython and the CircuitPython binding all have it.

carry() used to refuse a graph the pump was pulling. It now works while the pump is parked (audiopump.park()), so the sequence is: build the new graph while the pump plays, park, carry, swap, unpark. On CPython's service-mode pump nothing renders between two calls, so it needs no park there.

It also fixes a leak in carry(): each carried node appended the source's whole list of borrowed wow tables, so a patch carrying many nodes multiplied that list with every change (2.3 MB after six changes of an eight-delay patch; an instrument with 99 nodes ran out of memory on the third). Each table is now held once. The new test fails on the old code with exactly that growth.

Docs: "Swapping while the pump plays" in docs/how-it-works/audiograph.md.

Checked: tests/test_cpython_audiograph.py (24 pass, the four new ones among them). Built into the MicroPython unix port and used by a rack that recompiles while the pump plays, where the stream stays byte-equal to a rack built with the change from the swap block on.

swap(other) trades two graphs' patches under the pump lock, so a patch built
and carried beside a playing graph takes its place on a block boundary while
whatever pulls the graph keeps pulling the same object. carry() now works on a
pumped graph while the pump is parked. carry() also holds each borrowed table
once, where it used to append the source's whole list per node carried, which
multiplied with each patch change.
@bdbarnett
bdbarnett merged commit 6d42ab7 into main Oct 30, 2026
31 checks passed
@bdbarnett
bdbarnett deleted the graph/swap branch October 30, 2026 16:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant