Commit graph

11 commits

Author SHA1 Message Date
monkey-w1n5t0n
53da84c425 chore(vcv): delete the dead test rig
Phase 1 group 7 (L33). vcv/test/smoke_test.cpp included a header that no longer
exists (a retired nisps-core path), asserted the pre-P6 2x12 module shape, and
ran in no gate; a compiled smoke_test binary was tracked alongside it. Removed
the directory plus Makefile.dist, updated BUILDING.md's two references, and
deleted the unreachable reply-to-sender branch in osc_server.hpp.

Gates: run-all-tests.sh ALL GREEN.
2026-07-21 12:49:25 +02:00
monkey-w1n5t0n
1b69254de2 feat(vcv): reunify module onto core MLP — thin iml.hpp adapter (P6)
Replace the vendored runtime MLP in vcv/src/iml.hpp (DetRng + 3D-weight-store
MLP + Dataset + IML) with a THIN, Rack-free adapter over the shared core:
nisps::ml::MLPCore<nisps::ml::DynamicStorage> (8->[16,24,16]->16, the P2 dynamic
case), nisps::Rng, and the core MLP's own FIFO dataset. Behaviour changes from
the vendored approximation to core-exact firmware/WASM semantics.

- MEMLNaut.cpp: staged/pending weight buffers and patch JSON now use the core's
  flat [weights..][biases..] vector (nisps::IML<float>::Weights); patch version
  bumped to 3. Double-buffer / single-writer threading discipline unchanged.
- New ctest tests/cpp/test_vcv_iml_parity.cpp: seeded train/infer/move_weights
  session through the adapter is memcmp-equal to a bare MLPCore<DynamicStorage>.
- Docs: vcv-module.md delta #5 marked CLOSED (2026-07-18); MAP.md vcv/ updated.

Closes vcv-module.md delta #5.
2026-07-18 13:01:28 +02:00
monkey-w1n5t0n
45f3ca5cae docs: restructure design docs into docs/specs (adr/plans/recon), update path references 2026-07-13 23:15:46 +03:00
monkey-w1n5t0n
fbc68ebfab feat(vcv): evolve module to 8x16 + LED rings + token palette + WS-OSC bridge
8 inputs x 16 outputs; per-output LED ring widget (drawLayer+nvgArc); palette
from frontend tokens; OSC bridge verbs for bidirectional browser training;
vendored self-contained iml.hpp (retired nisps-core); compiles against Rack
SDK 2.6.4. See SPEC.md BUILD DELTAS.
2026-06-28 04:14:30 +02:00
w1n5t0n
2060f10b40 fix(vcv): resolve 6 critical thread safety issues from code review
Fixes from Opus 4.6 review (C1-C6, I1, I3, I4, I8):

C1: static lastOutputs → per-instance lastOutputsForDelta member
C2: add_example() now on audio thread only (owns iml); worker reads
    from mutex-protected staging area (stagedFeatures/stagedLabels)
C3: Worker reads stagedWeightsForWorker (not iml.get_weights()),
    eliminating concurrent read/write on iml's MLP
C4: Worker spins on weightsPending before writing pendingWeights,
    preventing double-write race
C5: RAND and CLEAR now enqueue Randomize/Clear jobs through worker
    instead of directly mutating iml on the audio thread
C6: OSC callbacks stage JSON into oscStagedJson + atomic flag;
    audio thread applies in process() (no recv-thread mutation)

Also fixed:
- I4: Separate pendingJob field (enqueueJob no longer overwrites currentJob)
- I8: Removed redundant swapReady atomic
- noiseLevel, cachedNovelty, cachedConfidence now std::atomic<float>
- Worker syncs examples back to iml after training via load_examples()
2026-03-28 02:02:11 +02:00
w1n5t0n
c7964fd454 fix(vcv): implement proper double-buffered threading
Replace direct-mutation threading with shadow IML:
- Background thread clones weights from main → shadow IML
- Training and perturbation operate only on shadow instance
- New weights staged in pendingWeights, swapped atomically by audio thread
- Thumbs-down now enqueues Perturb job instead of calling move_weights directly
- Audio thread applies new weights via iml.set_weights() at safe point
- Examples copied to shadow for training, results copied back as weights only

Threading invariant now fully enforced: background thread never writes to
the inference IML. Audio thread applies staged weights between inference calls.
2026-03-28 01:55:30 +02:00
w1n5t0n
ba0fcab2a2 feat(vcv,playground): complete Phases 8, 9, 10 — all phases done
Phase 8 — Companion webapp bridge:
- NISPS-FORMAT.md: full .nisps JSON schema with validation rules
- Webapp iml.js: exportState() / importState() with bias handling
- osc_server.hpp: minimal UDP OSC server (cross-platform, no deps)
- VCV module: OSC toggle + port selection in right-click menu
- osc-client.js: WebSocket client with auto-reconnect
- Bridge scripts updated for bidirectional VCV↔webapp relay

Phase 9 — Panel layout variants:
- MEMLNaut.svg: 30HP standard panel (matches widget positions)
- MEMLNaut-wide.svg: 44HP with expanded display and 8 input slots
- MEMLNaut-expander.svg: 8HP with 6 extra inputs and LINK LED

Phase 10 — Polish & distribution:
- README.md: 267-line user guide (install, quick start, RL workflow,
  presets, OSC, technical details)
- BUILDING.md: build prerequisites, SDK setup, local install
- Makefile.dist: platform-stamped zip packaging
- SPEC.md: performance characteristics (1060 MADs/pass, ~46KB/instance)
- SPEC.md: v1 compatibility assessment (v2-only recommended)
2026-03-28 01:48:44 +02:00
w1n5t0n
74c52fadc7 feat(nisps-core,vcv): complete Phases 6 + 7 — persistence, derived outputs
Phase 6 — State persistence:
- Full state serialization: version, weights (3D), examples (features+labels),
  mlpConfig, noiseLevel, slewMs, output/input ranges
- Validation on load: version check, graceful missing field handling
- .nisps preset save/load via right-click menu (osdialog file dialogs)
- Param values included in preset files

Phase 7 — Derived outputs:
- Mean, STD, delta computed on audio thread (trivial cost)
- Novelty/confidence: nearest_example_distance() computed on background
  thread after each training/perturbation job, cached for audio thread
- Defaults with 0 examples: novelty=10V, confidence=0V

nisps-core IML additions:
- get_weights() / set_weights() for MLP weight serialization
- get_example_features/labels() / load_examples() for dataset serialization
- nearest_example_distance() for novelty/confidence metric
- get_example_count() / get_max_examples() for UI display
2026-03-28 01:27:19 +02:00
w1n5t0n
6a76f15736 feat(vcv): complete Phases 3, 4, 5 — RL feedback, display, configurability
Phase 3 — RL feedback system:
- Background worker thread with job queue, condition variable, atomic flags
- Thumbs up/down buttons + CV trigger inputs (Schmitt triggers)
- Learn enable toggle + gate input (OR logic)
- Noise level tracking (decay on +, increase on −, spread-dependent cap)
- Post-change output crossfade (configurable slew, default 10ms)
- Rapid feedback queueing with coalescing (max depth 1)
- Graceful thread shutdown (shouldStop flag, joins in destructor)

Phase 4 — Visual feedback:
- NanoVG bar graph display (12 hue-coded bars, noise level, TRAIN indicator)
- 12 output level LEDs, LEARN LED (green), training LED (yellow)

Phase 5 — Configurability:
- RATE knob: exponential decimation from block-rate to audio-rate
- Per-output range: unipolar (0-10V) / bipolar (±5V) via context menu
- Per-input range: unipolar / bipolar via context menu
- 12 attenuverter trimpots (-1 to +1)
- SPREAD CV input for knob modulation
- CLEAR button with 1-second long-press guard
- Output slew configurable via context menu (0-100ms)
- State serialization (ranges, noise, slew) via dataToJson/dataFromJson

Note: double-buffering uses direct IML access (not shadow copy) pending
IML weight get/set API (filed as meml-ft7).
2026-03-28 01:04:07 +02:00
w1n5t0n
e52b800a92 feat(vcv): complete Phase 2 — core engine wired up
- IML<float> with [16,24,16] hidden layers as module member
- CV inputs read, clamped 0-10V, normalized to [0,1]
- MLP inference in process(), 12 outputs scaled to 0-10V
- SPREAD knob (0-1, default 0.6) controls weight initialization
- RAND button randomizes weights using current spread value
- Panel: knob + button + 2 inputs + 12 outputs in 2x6 grid
2026-03-28 00:38:58 +02:00
w1n5t0n
d0ba1faaea feat(nisps-core,vcv): complete Phase 0 + Phase 1
Phase 0 — spread-aware API ported to nisps-core C++:
- MLP::DrawWeightsSpread(T spread) — interpolate uniform↔Xavier per layer
- MLP::MoveWeightsSpread(T speed, T spread) — per-layer noise + weight decay
- IML::randomise_weights(Float spread) and IML::move_weights(speed, spread)
- 5 unit tests (10/10 total pass)

Phase 1 — VCV Rack 2 plugin skeleton:
- Makefile with C++20, nisps-core include path
- plugin.json manifest
- Empty MEMLNaut module: 2 inputs, 12 outputs, placeholder SVG panel
- static_assert verifies nisps-core headers resolve
- C++20 confirmed working in VCV SDK (8 existing plugins use it)
2026-03-28 00:36:46 +02:00