Skip to content

audiograph on CPython and CircuitPython, with a three-way render comparison - #301

Merged
bdbarnett merged 1 commit into
mainfrom
feat/graph-bindings
Oct 21, 2026
Merged

bdbarnett merged 1 commit into
mainfrom
feat/graph-bindings

Conversation

@bdbarnett

Copy link
Copy Markdown
Contributor

audiograph is no longer MicroPython only. The wheel has it (import audiograph on CPython), and the CircuitPython build compiles it, both the unix port and the firmware, through circuitpython.mk's module list. All three bind the same src/shared/audiodsp_graph.c with the same arguments and the same refusals, and no node file changed.

  • CPython: a Graph type in _audiodsp.c, re-exported as is by src/cpython/audiograph.py. The constants are read by name from the C enums. A delay's wow table is held through a memoryview, so the array can't be resized under it.
  • CircuitPython: src/circuitpython_spike/shared-bindings/audiograph/ and shared-module/audiograph/, laid out like the other modules.

The comparison. tests/parity/verify_graph.py runs graph_parity_probe.py on CPython and on each interpreter you name, then compares every output sample. The patch has two voices with every node kind, groups that park, a fed buffer, moved gains and cutoffs, a delay reset mid-tail, and a mono graph. The tolerance is 0 counts. Locally, CPython, MicroPython unix (double and single precision) and CircuitPython unix agree on all 41,221 samples.

Two planted faults, applied to every interpreter after the first, each make the comparison fail:

  • lsb: one fed input sample is one count off, and 615 samples differ by up to 2.
  • late: one set() lands a block late, and 3,197 samples differ by up to 183.

CI runs both faults first, then the CPython against MicroPython comparison, beside graph_probe. As with verify_dsp, the three-way that includes CircuitPython is a local run. graph_probe.py passes on all three, with the same digests on each.

Tests. tests/test_cpython_audiograph.py runs the runner's probe on the wheel. It also checks that the module exports every name the board module does, that a borrowed table is held, and that a dropped graph frees its memory; a planted leak fails that last check. test_binding_parity now covers audiograph (22 types), and Graph is exempt from the node deinit rule because nothing plays it.

…rison

The wheel carries audiograph now (a Graph type in _audiodsp, re-exported by
src/cpython/audiograph.py), and the CircuitPython build compiles it from
circuitpython_spike/shared-bindings/audiograph, so unix CircuitPython and the
CircuitPython firmware both have it. All three bind the same
shared/audiodsp_graph.c with the same arguments and refusals; no node file
changed.

tests/parity/verify_graph.py renders one patch with every node kind in it on
CPython and each interpreter named and compares every output sample, with a
tolerance of 0 counts. CPython, MicroPython (double and single precision) and
CircuitPython unix agree on all 41221 samples. Its planted faults, one fed
input sample one count off and one set() a block late, each fail it (615 and
3197 samples differ). CI runs the faults, then the comparison, beside
graph_probe.
@bdbarnett
bdbarnett force-pushed the feat/graph-bindings branch from 19f2f69 to 7d57975 Compare October 21, 2026 17:28
@bdbarnett
bdbarnett merged commit 1f97fcc into main Oct 21, 2026
32 checks passed
@bdbarnett
bdbarnett deleted the feat/graph-bindings branch October 21, 2026 17:36
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