Skip to content

Conformance test vectors, and decisions on note-offs, rounding, duplicate mappings, ranged CCs and timescale - #104

Merged
cpmpercussion merged 6 commits into
mainfrom
conformance-vectors
Sep 26, 2026
Merged

cpmpercussion merged 6 commits into
mainfrom
conformance-vectors

Conversation

@cpmpercussion

@cpmpercussion cpmpercussion commented Sep 26, 2026 •

Copy link
Copy Markdown
Owner

Adds spec/: JSON conformance vectors that record how IMPSY maps input to model input, output back to messages, logs to datasets, and how it reads a .tflite model. It also implements the decisions from #99, #100, #102, #103 and #105, so the vectors describe the behaviour we want, not just what the code happened to do.

Conformance vectors

spec/vectors/ holds 29 cases:

  • midi_input.json / websocket_input.json: messages → the [index, value] updates they make to the input vector, or ignored
  • midi_output.json / websocket_output.json: output vectors → messages, including clipping, note-offs and polyphony
  • pipeline.json: timed MIDI bytes → the [dt, x_1..x_n] vectors sent to the model, plus log rows
  • playback.json: model outputs → wait time, values played, and the next model input
  • dataset.json: log lines → training rows
  • model.json: a fixed-weight 3-d TFLite model in spec/models/. For each step it records the scaled input, raw MDN output, pi/mu/std after temperatures, which output tensor feeds which LSTM state, and which mixture a given uniform draw selects.

impsy/conformance.py defines the cases and runs them through the real MIDIServer, WebSocketServer, InteractionServer, dataset and TfliteMDRNN code with fake ports and a scripted clock. tests/test_conformance.py runs every vector and fails if the committed files are stale. spec/README.md explains the format and how impsy-auv3 and impsy-web should vendor the vectors.

Behaviour changes

docs/config.md describes the new note-off, rounding, duplicate-mapping and ranged-CC behaviour.

Downstream

As they stand, impsy-auv3 and impsy-web will need these changes to pass: rounding (AUv3 already rounds), velocity-0 handling (AUv3 already skips these), one interaction per message, per-dimension note polyphony, and the unscaled dt feedback.

Also un-ignores spec/models/, since models is in .gitignore.

🤖 Generated with Claude Code

cpmpercussion and others added 2 commits September 26, 2026 13:49
…t behaviour

spec/vectors/ records what the reference implementation does so other
front ends (impsy-auv3, impsy-web) can run the same cases. Expected values
come from driving the real IO, interaction and dataset code with fakes.
Cases that depend on open design questions link #99-#102.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
spec/models/ holds a tiny 3-d, 2x16-unit, 5-mixture model with seeded
weights. model.json records, per step, the scaled input, raw MDN output,
mixture weights/means/stds and which tensor feeds which LSTM state, so
other implementations can check they read .tflite files the way IMPSY
does. Floats are compared with a per-file tolerance because TFLite kernels
differ slightly between CPUs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Copilot AI lite review requested due to automatic review settings September 26, 2026 03:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved critical pipeline-vector aliasing and moderate WebSocket clipping coverage issues remain.

Review effort: Lite
Findings: 1 High severity · 1 Medium severity · 1 Low severity

Open (3)
What changed in this PR

Adds machine-readable conformance vectors and tests for IMPSY’s MIDI, WebSocket, pipeline, dataset, and TFLite representations.

Changes:

  • Adds JSON conformance vectors and a deterministic model fixture.
  • Adds generation and validation runners.
  • Documents vector usage and repository conventions.
File Summary
tests/​test_conformance.py Validates committed conformance vectors.
spec/​vectors/​websocket_output.json Defines WebSocket output cases.
spec/​vectors/​websocket_input.json Defines WebSocket input cases.
spec/​vectors/​pipeline.json Defines pipeline timing and model-input cases; contains an unresolved aliasing issue.
spec/​vectors/​model.json Defines TFLite model behavior cases.
spec/​vectors/​midi_output.json Defines MIDI output cases.
spec/​vectors/​midi_input.json Defines MIDI input cases.
spec/​vectors/​dataset.json Defines dataset conversion cases.
spec/​README.md Documents vector formats and usage; model fixture instructions need correction.
impsy/​conformance.py Generates conformance vectors; WebSocket clipping coverage is incomplete.
CLAUDE.md Documents the conformance workflow.
.gitignore Allows the committed model directory.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread spec/vectors/pipeline.json Outdated
Comment thread impsy/conformance.py Outdated
Comment thread spec/README.md Outdated
cpmpercussion and others added 2 commits September 26, 2026 14:28
Leaves room for half-precision runtimes (~1.6e-3 error) while still
catching reader bugs, which produce errors of 3-5.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…mescale

- #99: note-ons with velocity 0 are note-offs and are ignored on MIDI and
  WebSocket input. WebSocket input now goes through the same decoder as
  MIDI, so malformed messages are skipped instead of ending the handler.
- #100: output values round to nearest (half up) for notes, CCs and CC
  min/max scaling, instead of ceil.
- #102: a message mapped to several dimensions sets all of them as one
  interaction (callbacks now take a list of indices). On output, note
  dimensions that share a channel play polyphonically; MidiOutputState
  replaces the per-channel note-off logic duplicated across the MIDI,
  serial MIDI and WebSocket servers.
- #103: playback feeds the model its own clamped dt; timescale only sets
  the wait. The step is now InteractionServer.prepare_rnn_playback and
  has its own vector file, playback.json.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@cpmpercussion cpmpercussion changed the title Add conformance test vectors for IMPSY's data representation Conformance test vectors, and decisions on note-offs, rounding, duplicate mappings and timescale Sep 26, 2026
- #105: a CC mapped as [..., min, max] now matches on input; the raw
  value is clamped to [min, max] and mapped to (raw - min) / (max - min),
  inverting the output scaling, as impsy-auv3 and impsy-web already do.
- Ranged CC output rounds once, round(min + v * (max - min)), instead of
  rounding to 0-127 first and again after scaling.
- The same message can now give different values for different
  dimensions, so IO callbacks and construct_input_list take a list of
  (index, value) updates.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@cpmpercussion cpmpercussion changed the title Conformance test vectors, and decisions on note-offs, rounding, duplicate mappings and timescale Conformance test vectors, and decisions on note-offs, rounding, duplicate mappings, ranged CCs and timescale Sep 26, 2026
construct_input_list edited the previous input vector in place through a
view, but that vector could still be waiting in the model's queue. When
several messages arrived in one handle() pass, the model received vectors
already changed by later events. The pipeline vectors had recorded this
as expected; they now match the log rows, and a test checks that.

Also, from review: WebSocket output vectors go through send_back_values
so clipping is covered, and the README says to copy spec/models/ too.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants