monkey-w1n5t0n
22efb1c411
feat(nisps/ml): crystallise Explore-and-place into shared FeedbackController
...
Add FeedbackMode::ExploreAndPlace + Idle/Exploring/Placing state machine
(no-heap, deterministic nisps::Rng): enter/exit_explore, reroll, nudge, undo,
begin_place, commit_place, cancel_place + on_down/on_up browser policy. Wire
the nisps_ml_feedback_* C API + EXPORTED_FUNCTIONS, extend parity Stage 5d.
Fix set_mode(3) falling back to Avoid. Native ctest 4/4; parity native==WASM
within 1e-5 (max delta 2.4e-7). Rebuilt nisps.{js,wasm}.
2026-06-28 04:14:12 +02:00
w1n5t0n
3138701100
Stream 11: verification infrastructure (golden vectors + parity + lint + CI + Playwright migration)
...
Agent ran out of API credits before committing. Files staged + committed by orchestrator. Coverage:
- tests/cpp/ml_golden_vectors.cpp: fixed-seed regression tests for MLP determinism
- tests/cpp/engine_impulse.cpp: white-noise impulse responses with binary baseline
- tests/cpp/parity_check.cpp + parity_wasm.mjs + parity_diff.mjs: native vs WASM bit-equivalence
- scripts/build-cpp-tests.sh, lint-cpp.sh, parity-check.sh, run-all-tests.sh
- playground/tests/e2e/{ml-engine,modes,persistence,ui-interactions}.spec.ts (+helpers)
- .github/workflows/ci.yml
(meml-x06)
2026-04-29 19:50:55 +03:00
w1n5t0n
4964037da0
test(nisps/modes): host C++ tests for stream 4 mode layer (meml-beb)
...
Adds `nisps_modes_tests` executable to nisps/CMakeLists.txt with four TUs:
- `test_mode_concepts.cpp`: 8 `static_assert(Mode<...>)` (concept
satisfaction), plus runtime metadata sanity for each mode (mode_id,
input_channel_count, schema sizes match engine param_count).
- `test_mode_paf_synth.cpp`: end-to-end exercise — setup, set_input,
tick_control, process audio. Verifies idle process is finite, output
bounds [0,1] hold, note_on triggers nonzero audio, input clamping,
and engine/ml accessors round-trip.
- `test_mode_voice_space.cpp`: voice-space round trip for PAFSynth,
ChannelStrip and VerbFX (all dispatched modes). Confirms
out-of-range index is silently ignored.
- `test_mode_breakor_events.cpp`: sequencer event pumping. BreakOr
emits Clock + NoteOn/Off, Elysiamorf emits CC, SoundAnalysisMIDI
converts 8 ML outputs → 8 ControlEvents (CC 0..7) per tick, ring
buffer overflow drops cleanly.
Total: 22 new tests (110 across nisps/), all passing under -Werror
-Wpedantic. Build remains clean.
2026-04-29 16:27:03 +03:00
w1n5t0n
8d0d47b992
feat(nisps/engines): port firmware audio engines to AudioEngine concept (meml-1v6)
...
Concept-based, no virtual dispatch, per-engine voice spaces as inline
methods. Each engine satisfies nisps::AudioEngine via static_assert.
- NoOpEngine: silent passthrough; used for sequencer-only modes and
for the SoundAnalysisMIDI mode's audio path.
- PAFSynthEngine (33 params, 7 voice spaces): 4-voice PAF synth with
detune cascade, ring-mod, sine-shaper, ADSR, feedback delay. note_on/
note_off interface for MIDI keyboard.
- ChannelStripEngine (24 params, 6 voice spaces): stereo console strip
(pre-gain/HPF/LPF/2x peak/low-shelf/high-shelf/comp/post-gain). Voice
spaces: WannabeNeve66, SSL4K, SSL9K, MaleVox, FemaleVox, Neve80
(stepped-frequency).
- XIASRIEngine (24 params, "Direct" voice space): pitch-shift + 6 allpass
+ 2 comb + 4 delays. Direct NN→param mapping per firmware semantics.
- VerbFXEngine (47 params, 12 voice spaces): 8-band SVF filterbank +
3-lane dynamic delay + 8-lpcomb/4-allpass Freeverb-style tail with
cross-fades. All 12 voice spaces ported from voicespaces/VerbFX/*.hpp.
- MEMLCeliumEngine (56 params): 2-track ratio sequencer + dual-voice
PAF synth (7+7+22+20 layout). Sequencer triggers V0/V1 ADSR.
- BreakOrEngine (56 params): 8-track ratio sequencer; emits NoteOn/
NoteOff/Clock events via pop_events(span). process() returns silence.
- ElysiamorfEngine (40 params): 8-track FM-pair sequencer; emits CC
events on CCs {1,2,3,4,5,9,11,12}. Silent audio path.
- AnalysisEngine (0 params, 6 features): port of XiasriAnalysis (pitch
via zero-crossing, aperiodicity via MAD, log-domain energy + attack
derivative + brightness ratio). Inputs to ML on SoundAnalysisMIDI mode.
All param_count() values match schemas/modes/*.json output_size.
4074 LOC total. CMake adds nisps_dsp_engine_tests target with 38
passing tests under -Wall -Wextra -Werror -Wpedantic.
2026-04-29 16:09:12 +03:00
w1n5t0n
825ed6ad33
feat(nisps/ml): MLP library with fixed-architecture template + spread-aware RL (meml-wmh)
...
Stream 2 of the clean-slate rewrite: nisps/ml/ replaces src/memlp/ with a
header-only, heap-free MLP that satisfies nisps::core::MLEngine.
Files (nisps/ml/):
- activations.hpp — ReLU (leaky 0.01 for parity), sigmoid, tanh
- loss.hpp — MSE per-sample (fixes meml-ues double-scaling: returns the
sample's MSE without an extra 1/N multiplication; the training loop
averages explicitly)
- init.hpp — uniform/Xavier/spread-aware weight init
- training.hpp — gradient clip helper (±10.0 matches legacy)
- rl.hpp — move_weights with per-layer Xavier scaling, weight decay
(10% * spread), gaussian noise via the deterministic Rng (matches the
legacy JS sum-of-three-uniforms shape); draw_weights also spread-aware
- stats.hpp — per-layer mean/max/dead/saturating diagnostics
- mlp.hpp — 4-layer (3 hidden + sigmoid output) MLP class with
std::array-backed weights, biases, gradient accumulators, dataset
ring buffer (default 128 examples), loss history (default 4096 iters).
Bias is a separate per-layer parameter — no input-vector mutation.
Flat get_weights/set_weights layout: weights all layers (row-major,
layer order), then biases all layers.
Tests (tests/cpp/, all 50 passing under -Wall -Wextra -Werror -Wpedantic):
- test_mlp_init.cpp — deterministic seeding, spread regimes,
static_assert MLEngine concept satisfied
- test_mlp_inference.cpp — golden hand-computed forward pass match,
sigmoid output range, set_input bounds
- test_mlp_training.cpp — XOR convergence (loss < 0.01 in <2k iters),
ring-buffer eviction
- test_mlp_loss.cpp — meml-ues regression test: reported loss equals
hand-computed average MSE without extra 1/N scaling; sample weights
honoured
- test_mlp_rl.cpp — move_weights respects output_pin_mask (final-layer
rows + biases preserved); spread regimes; grad clear after draw_weights
- test_mlp_serialize.cpp — get_weights/set_weights round-trip preserves
inference exactly; eval_loss is non-mutating; infer_batch matches
individual inference
Verification:
- Clean build, no warnings
- 50 tests pass (22 prior + 28 new)
- No std::vector / new / malloc in nisps/ml/
- All float literals .f-suffixed in code (comments excepted)
2026-04-29 15:55:43 +03:00
w1n5t0n
e5bf2aa055
feat: nisps build + host test harness
...
CMakeLists.txt:
- Native host build by default; Emscripten-target detection plumbed but
WASM emit deferred to stream 7 (playground build script).
- Header-only INTERFACE library `nisps_core`.
- Host test executable `nisps_core_tests` compiled with -Wall -Wextra
-Werror -Wpedantic (Chris's rules: clean build is non-negotiable).
tests/cpp/test_helpers.hpp:
- Minimal NISPS_TEST / NISPS_EXPECT / NISPS_EXPECT_NEAR macros, no external
deps. Rationale documented in-file: Catch2/doctest would add ~10MB and 30s
for what is currently <100 LOC of test runtime.
22 unit tests covering FixedBuffer (5), RingBuffer (5), Rng (7), math (5).
All green; verified via `cmake --build nisps/build && ./nisps/build/nisps_core_tests`.
2026-04-29 15:22:01 +03:00