memlnaut-nisps/vcv/res/MEMLNaut-wide.svg
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

217 lines
14 KiB
XML

<svg xmlns="http://www.w3.org/2000/svg" width="223.52mm" height="128.5mm" viewBox="0 0 223.52 128.5">
<defs>
<style>
text { font-family: 'Courier New', monospace; }
.title { font-size: 6; fill: #e0e0e0; }
.subtitle { font-size: 3; fill: #4a9eff; }
.section-label { font-size: 3; fill: #808080; }
.component-label { font-size: 2.5; fill: #808080; }
.output-num { font-size: 2.5; fill: #4a9eff; }
.footer { font-size: 2.5; fill: #808080; }
</style>
</defs>
<!-- Background -->
<rect width="223.52" height="128.5" fill="#1a1a2e"/>
<!-- Panel border -->
<rect x="0.5" y="0.5" width="222.52" height="127.5" fill="none" stroke="#2a2a3e" stroke-width="0.5"/>
<!-- Title -->
<text x="111.76" y="8" text-anchor="middle" class="title">MEMLNaut</text>
<text x="111.76" y="12" text-anchor="middle" class="subtitle">Neural Interactive Shaping of Parameter Spaces</text>
<line x1="20" y1="13.5" x2="203" y2="13.5" stroke="#2a2a3e" stroke-width="0.3"/>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- DISPLAY AREA: wider — (2, 16) to (60, 34) -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<rect x="2" y="16" width="56" height="18" rx="1" fill="#0a0a18" stroke="#2a2a3e" stroke-width="0.4"/>
<text x="30" y="26" text-anchor="middle" class="component-label" fill="#4a9eff">DISPLAY</text>
<text x="30" y="30" text-anchor="middle" class="component-label" fill="#333355">input space / output map</text>
<line x1="0" y1="36" x2="223.52" y2="36" stroke="#2a2a3e" stroke-width="0.3"/>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- KNOBS ROW: y=40 -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<text x="14" y="38" text-anchor="middle" class="section-label">SPREAD</text>
<circle cx="14" cy="41" r="4" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<circle cx="14" cy="41" r="0.7" fill="#4a9eff"/>
<text x="28" y="38" text-anchor="middle" class="component-label">CV</text>
<circle cx="28" cy="41" r="2.5" fill="none" stroke="#808080" stroke-width="0.4"/>
<text x="42" y="38" text-anchor="middle" class="section-label">RATE</text>
<circle cx="42" cy="41" r="4" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<circle cx="42" cy="41" r="0.7" fill="#4a9eff"/>
<line x1="0" y1="48" x2="223.52" y2="48" stroke="#2a2a3e" stroke-width="0.3"/>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- BUTTONS ROW: y=53 -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<text x="10" y="50.5" text-anchor="middle" class="section-label" fill="#4a9eff">+</text>
<rect x="7" y="51" width="6" height="4.5" rx="0.8" fill="none" stroke="#808080" stroke-width="0.4"/>
<text x="20" y="50.5" text-anchor="middle" class="section-label" fill="#4a9eff">&minus;</text>
<rect x="17" y="51" width="6" height="4.5" rx="0.8" fill="none" stroke="#808080" stroke-width="0.4"/>
<text x="32" y="50.5" text-anchor="middle" class="section-label">LEARN</text>
<rect x="30" y="51" width="4" height="5.5" rx="0.5" fill="none" stroke="#808080" stroke-width="0.4"/>
<circle cx="32" cy="49" r="0.8" fill="none" stroke="#00cc00" stroke-width="0.3"/>
<text x="44" y="50.5" text-anchor="middle" class="section-label">RAND</text>
<rect x="41" y="51" width="6" height="4.5" rx="0.8" fill="none" stroke="#808080" stroke-width="0.4"/>
<text x="56" y="50.5" text-anchor="middle" class="section-label">CLR</text>
<rect x="53" y="51" width="6" height="4.5" rx="0.8" fill="none" stroke="#808080" stroke-width="0.4"/>
<circle cx="56" cy="49" r="0.8" fill="none" stroke="#cccc00" stroke-width="0.3"/>
<line x1="0" y1="59" x2="223.52" y2="59" stroke="#2a2a3e" stroke-width="0.3"/>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- INPUTS: 8 jacks (future configurable) -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<text x="50" y="61.5" text-anchor="middle" class="section-label" fill="#e0e0e0">IN</text>
<!-- Row 1: X, Y, IN3-IN6 -->
<text x="10" y="63.5" text-anchor="middle" class="component-label">X</text>
<circle cx="10" cy="66" r="2.5" fill="none" stroke="#808080" stroke-width="0.4"/>
<text x="22" y="63.5" text-anchor="middle" class="component-label">Y</text>
<circle cx="22" cy="66" r="2.5" fill="none" stroke="#808080" stroke-width="0.4"/>
<text x="34" y="63.5" text-anchor="middle" class="component-label">IN 3</text>
<circle cx="34" cy="66" r="2.5" fill="none" stroke="#555555" stroke-width="0.4" stroke-dasharray="1,0.5"/>
<text x="46" y="63.5" text-anchor="middle" class="component-label">IN 4</text>
<circle cx="46" cy="66" r="2.5" fill="none" stroke="#555555" stroke-width="0.4" stroke-dasharray="1,0.5"/>
<text x="58" y="63.5" text-anchor="middle" class="component-label">IN 5</text>
<circle cx="58" cy="66" r="2.5" fill="none" stroke="#555555" stroke-width="0.4" stroke-dasharray="1,0.5"/>
<text x="70" y="63.5" text-anchor="middle" class="component-label">IN 6</text>
<circle cx="70" cy="66" r="2.5" fill="none" stroke="#555555" stroke-width="0.4" stroke-dasharray="1,0.5"/>
<!-- Row 2: IN7, IN8, LEARN gate, +TRIG, -TRIG -->
<text x="10" y="72" text-anchor="middle" class="component-label">IN 7</text>
<circle cx="10" cy="74.5" r="2.5" fill="none" stroke="#555555" stroke-width="0.4" stroke-dasharray="1,0.5"/>
<text x="22" y="72" text-anchor="middle" class="component-label">IN 8</text>
<circle cx="22" cy="74.5" r="2.5" fill="none" stroke="#555555" stroke-width="0.4" stroke-dasharray="1,0.5"/>
<text x="46" y="72" text-anchor="middle" class="component-label">LEARN</text>
<circle cx="46" cy="74.5" r="2.5" fill="none" stroke="#808080" stroke-width="0.4"/>
<text x="58" y="72" text-anchor="middle" class="component-label">+TRIG</text>
<circle cx="58" cy="74.5" r="2.5" fill="none" stroke="#808080" stroke-width="0.4"/>
<text x="70" y="72" text-anchor="middle" class="component-label">&minus;TRIG</text>
<circle cx="70" cy="74.5" r="2.5" fill="none" stroke="#808080" stroke-width="0.4"/>
<!-- Vertical divider between inputs and outputs -->
<line x1="85" y1="59" x2="85" y2="118" stroke="#2a2a3e" stroke-width="0.4"/>
<line x1="0" y1="80" x2="85" y2="80" stroke="#2a2a3e" stroke-width="0.3"/>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- OUTPUTS: right side, 4 cols x 3 rows for generous spacing -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<text x="154" y="61.5" text-anchor="middle" class="section-label" fill="#e0e0e0">OUT</text>
<!-- Output grid: 4 columns x 3 rows, generous spacing -->
<!-- Col centers: 100, 120, 140, 160 Row centers: 68, 80, 92 -->
<!-- Row 0: 1-4 -->
<text x="100" y="65" text-anchor="middle" class="output-num">1</text>
<circle cx="96" cy="68" r="1.8" fill="none" stroke="#808080" stroke-width="0.3"/>
<circle cx="100.5" cy="68" r="0.6" fill="none" stroke="#ffffff" stroke-width="0.2"/>
<circle cx="105" cy="68" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<text x="120" y="65" text-anchor="middle" class="output-num">2</text>
<circle cx="116" cy="68" r="1.8" fill="none" stroke="#808080" stroke-width="0.3"/>
<circle cx="120.5" cy="68" r="0.6" fill="none" stroke="#ffffff" stroke-width="0.2"/>
<circle cx="125" cy="68" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<text x="140" y="65" text-anchor="middle" class="output-num">3</text>
<circle cx="136" cy="68" r="1.8" fill="none" stroke="#808080" stroke-width="0.3"/>
<circle cx="140.5" cy="68" r="0.6" fill="none" stroke="#ffffff" stroke-width="0.2"/>
<circle cx="145" cy="68" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<text x="160" y="65" text-anchor="middle" class="output-num">4</text>
<circle cx="156" cy="68" r="1.8" fill="none" stroke="#808080" stroke-width="0.3"/>
<circle cx="160.5" cy="68" r="0.6" fill="none" stroke="#ffffff" stroke-width="0.2"/>
<circle cx="165" cy="68" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<!-- Row 1: 5-8 -->
<text x="100" y="77" text-anchor="middle" class="output-num">5</text>
<circle cx="96" cy="80" r="1.8" fill="none" stroke="#808080" stroke-width="0.3"/>
<circle cx="100.5" cy="80" r="0.6" fill="none" stroke="#ffffff" stroke-width="0.2"/>
<circle cx="105" cy="80" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<text x="120" y="77" text-anchor="middle" class="output-num">6</text>
<circle cx="116" cy="80" r="1.8" fill="none" stroke="#808080" stroke-width="0.3"/>
<circle cx="120.5" cy="80" r="0.6" fill="none" stroke="#ffffff" stroke-width="0.2"/>
<circle cx="125" cy="80" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<text x="140" y="77" text-anchor="middle" class="output-num">7</text>
<circle cx="136" cy="80" r="1.8" fill="none" stroke="#808080" stroke-width="0.3"/>
<circle cx="140.5" cy="80" r="0.6" fill="none" stroke="#ffffff" stroke-width="0.2"/>
<circle cx="145" cy="80" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<text x="160" y="77" text-anchor="middle" class="output-num">8</text>
<circle cx="156" cy="80" r="1.8" fill="none" stroke="#808080" stroke-width="0.3"/>
<circle cx="160.5" cy="80" r="0.6" fill="none" stroke="#ffffff" stroke-width="0.2"/>
<circle cx="165" cy="80" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<!-- Row 2: 9-12 -->
<text x="100" y="89" text-anchor="middle" class="output-num">9</text>
<circle cx="96" cy="92" r="1.8" fill="none" stroke="#808080" stroke-width="0.3"/>
<circle cx="100.5" cy="92" r="0.6" fill="none" stroke="#ffffff" stroke-width="0.2"/>
<circle cx="105" cy="92" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<text x="120" y="89" text-anchor="middle" class="output-num">10</text>
<circle cx="116" cy="92" r="1.8" fill="none" stroke="#808080" stroke-width="0.3"/>
<circle cx="120.5" cy="92" r="0.6" fill="none" stroke="#ffffff" stroke-width="0.2"/>
<circle cx="125" cy="92" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<text x="140" y="89" text-anchor="middle" class="output-num">11</text>
<circle cx="136" cy="92" r="1.8" fill="none" stroke="#808080" stroke-width="0.3"/>
<circle cx="140.5" cy="92" r="0.6" fill="none" stroke="#ffffff" stroke-width="0.2"/>
<circle cx="145" cy="92" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<text x="160" y="89" text-anchor="middle" class="output-num">12</text>
<circle cx="156" cy="92" r="1.8" fill="none" stroke="#808080" stroke-width="0.3"/>
<circle cx="160.5" cy="92" r="0.6" fill="none" stroke="#ffffff" stroke-width="0.2"/>
<circle cx="165" cy="92" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<line x1="85" y1="99" x2="223.52" y2="99" stroke="#2a2a3e" stroke-width="0.3"/>
<!-- ══════════════════════════════════════════════════════════════════ -->
<!-- DERIVED OUTPUTS: wide spacing -->
<!-- ══════════════════════════════════════════════════════════════════ -->
<text x="100" y="103" text-anchor="middle" class="component-label">MN</text>
<circle cx="100" cy="106" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<text x="117" y="103" text-anchor="middle" class="component-label">SD</text>
<circle cx="117" cy="106" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<text x="134" y="103" text-anchor="middle" class="component-label">&#x0394;T</text>
<circle cx="134" cy="106" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<text x="151" y="103" text-anchor="middle" class="component-label">NV</text>
<circle cx="151" cy="106" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<text x="168" y="103" text-anchor="middle" class="component-label">CF</text>
<circle cx="168" cy="106" r="2.5" fill="none" stroke="#4a9eff" stroke-width="0.4"/>
<!-- Footer -->
<line x1="20" y1="122" x2="203" y2="122" stroke="#2a2a3e" stroke-width="0.3"/>
<text x="111.76" y="126" text-anchor="middle" class="footer">NISPS v0.1</text>
<!-- Mounting holes -->
<circle cx="5.08" cy="3" r="1.2" fill="none" stroke="#2a2a3e" stroke-width="0.3"/>
<circle cx="218.44" cy="3" r="1.2" fill="none" stroke="#2a2a3e" stroke-width="0.3"/>
<circle cx="5.08" cy="125.5" r="1.2" fill="none" stroke="#2a2a3e" stroke-width="0.3"/>
<circle cx="218.44" cy="125.5" r="1.2" fill="none" stroke="#2a2a3e" stroke-width="0.3"/>
</svg>