JSON Schema Draft 2020-12 meta-schema (schemas/schema.json) plus 8 per-mode schemas authored against the firmware sources: - paf_synth (33 params, 7 voice spaces) - channel_strip (24 params, 6 voice spaces) - xiasri (24 params, direct mapping) - verb_fx (47 params, 12 voice spaces) - memlcelium (56 params, sequencer + dual PAF) - breakor (56 params, 8-track ratio sequencer) - elysiamorf (40 params, 8-track FM/CC sequencer) - sound_analysis_midi (8 params, audio-feature -> MIDI CC) schemas/modes/params_notes.md captures provenance and judgement calls for each mode.
5.5 KiB
5.5 KiB
Schema authoring notes
This document captures provenance and judgement calls for each mode schema. Read alongside the firmware sources of truth.
Conventions
- All
paramsranges are normalised[0,1]. The firmware voice spaces apply per-mode scaling (e.g.peak0Freq = 200.f + (params[1] * params[1] * 1800.f)); we expose the NN-output-space here, not the engine-state-space, because the same NN slot drives different engine values across voice spaces. curveis a hint about the dominant scaling pattern, not a hard contract:squareindicates the dominant voice space squares the value (p * p),linearindicates direct passthrough.output_sizematches the actual number of params consumed inProcessParams(). Where the firmware's templated NPARAMS is larger than what's consumed, we follow consumption (seeelysiamorf).
Per-mode notes
paf_synth (33 params, 7 voice spaces)
- Source of truth:
PAFSynthAudioApp.hpp+voicespaces/VoiceSpace*.hpp. - Voice space 1 (Rowantares) uses param indices 2,3,5,6,8,9,11,12,14,15,17,19,20,26,27,28,29,30,31,32 — 20 of 33 slots have a clear meaning. Other voice spaces use overlapping but not identical subsets. We named the meaningful slots after the dominant Rowantares mapping; unused-by-VS1 slots get generic
pXXnames. A future cleanup could canonicalise these names per-voice-space, but the schema is mode-wide so a single canonical name set is correct. curveofsquareindicates voice spaces consistently applyparams[i] * params[i]to that slot.
channel_strip (24 params, 6 voice spaces)
- Source of truth:
ChannelStripAudioApp.hpp+voicespaces/ChannelStrip/basic.hpp. - All 6 voice spaces touch the same param indices (0,1,4,5,6,7,8,10,11,12,13,14..19,23). Indices 2,3,9,20,21,22 are NN-output slots with no engine effect — exposed as raw
pXXfor future voice-space designers.
xiasri (24 params, 0 voice spaces — direct mapping)
- Source of truth:
XIASRIAudioApp.hpp::Process(). - The current firmware bypasses voice spaces and reads
smoothParams[]directly. We expose a synthetic "Direct" voice space name so consumers don't crash; the engine semantics are fixed byProcess(). Indices 3, (and unused) align with code. - Index 12 (
pitch_transp) maps to12.f + smoothParams[12]semitones (a strange offset; flagged inALIGNMENT.mdcandidate).
verb_fx (47 params, 12 voice spaces)
- Source of truth:
modes/AudioApps/VerbFXAudioApp.hpp+voicespaces/VerbFX/*.hpp. - The "Default" voice space is fully exposed; other voice spaces remap the same 47 slots with different scalings.
- Hidden layers tweaked to
[10, 14, 18]for the larger output size.
memlcelium (56 params, 0 effective voice spaces)
- Source of truth:
modes/AudioApps/MEMLCeliumAudioApp.hpp::ProcessParams(). - Voice spaces are commented out in firmware; we expose a "Direct" placeholder.
- Param 0-13 = sequencer (2 RatioSeq tracks × 7), 14-55 = synth (matches
kFocusSeq/kFocusSynmask). - Some env params are scaled with
sqParam()(squared) — flagged withcurve: "square".
breakor (56 params, 0 voice spaces)
- Source of truth:
modes/AudioApps/BreakOrAudioApp.hpp+RatioSeqEngine::updateParams(). - 8 sequences × 7 ratio-seq params each. Track names (kick, snare, tom, etc.) are inferred from the General-MIDI-style note assignments in
Setup():{36,37,38,39,40,42,43,45}→ kick, snare, low tom, mid tom, high tom, closed hat, open hat, ride. We named tracks by typical drum semantics; firmware doesn't enforce this naming. - BPM and clock-mode are not ML-controlled (they're hardware-side knobs/MIDI clock).
elysiamorf (40 params, 0 voice spaces)
- Source of truth:
modes/AudioApps/ElysiamorfAudioApp.hpp::ProcessParams(). - Firmware NPARAMS=56 by template default, but only 40 are consumed (5 per FM-seq × 8 seqs).
fbLevelis hard-coded to 0; the historicalparamIdx++for it was commented out, so the param layout is 5 wide per seq, not 6. The remaining 16 NN outputs are unused and we don't expose them — the rewrite should template the engine to NPARAMS=40.
sound_analysis_midi (8 params, 0 voice spaces)
- Source of truth:
modes/MEMLNautModeSoundAnalysisMIDI.hpp+XiasriAnalysis.hpp+ThruAudioApp.hpp. - Inputs are 6 audio analysis features (XiasriAnalysis) + 4 analog joystick channels = 10 inputs. The engine is Thru (passthrough); the 8 NN outputs become MIDI CCs sent on channel 1.
- This is the only mode where input channels include audio analysis features — the rewrite's mode concept treats these as just more abstract
[0,1]channels, same as a joystick axis.
Open questions for the orchestrator
- Hidden-layer architecture per mode: I used
[10, 10, 14]for ≤33-output modes and[10, 14, 18]for larger ones. The architecture doc shows[10, 10, 14, 126]for the playground default. Confirm whether per-mode hidden-layer tuning is actually warranted or whether all modes should share one architecture sized for the largest output. engine_idfor sequencers: BreakOr and Elysiamorf produce no audio (only MIDI/i2c). I gave themengine_idmatching theirmode_id; the AudioEngine concept may need a sentinel "no-op" engine in the rewrite. Flagged for stream 3 (engines).- Voice space naming: PAF voice spaces have planet/star names (Ellipticacacia, Rowantares, …); VerbFX uses descriptive names (Default, Resonant, …); ChannelStrip uses console emulations (WannabeNeve66, …). The schema preserves these as opaque strings — consumers must match them against the C++ lambda registry.