refactor(codegen): codegen owns mode identity, per-mode schemas and net dims
Phase 3 (S1, S5, S6, S25, L11, L37, ST11, ST12). Behaviour-preserving by construction: the diff on the generated directories is PURELY ADDITIVE (217 insertions, 0 deletions), so no emitted constant changed value. This moves where truth lives; it does not change what truth says. - S5: nine mode headers each carried a mechanically identical 12-field positional ParamSchema aggregate. codegen now emits one `inline constexpr ParamSchema k<Mode>Schema` per mode, and the struct itself moved into generated/schema_types.hpp. Each param_schema() is a one-line return. - S6 + S25: every mode hand-typed its net shape a second time as MLP template args, duplicating the schema's own dims. codegen emits a `<Mode>MLP` alias built from the already-emitted constants (not re-literalled), and all nine modes use it. NMaxExamples still defaults from kDefaultMaxExamples (Phase 2). - S1: model.ts hand-imported all nine schemas by name and hand-paired each with its overlay — so the SET of modes was hand-maintained and could silently drift from codegen. codegen now emits ALL_MODE_SCHEMAS; SCHEMA_MODE_OVERLAYS is purely display truth (label/glyph/css/order), which stays hand-curated. - L37: deleted the hand-written modeEngineId switch, which duplicated schema.engine_id and silently defaulted unknown modes to 'thru'. Routes on MFMode.engineId with exactly one documented exception: sound_analysis_midi declares engine_id 'thru' because its ModeBase audio slot really is NoOpEngine, while it separately drives the real AnalysisEngine. - L11: ExternalSynthMIDIMode's shape was literal in two places; now named once in an ext_synth_defaults namespace with an ExtSynthMIDIMLP alias. Full folding into the JSON pipeline is NOT done and the reason is recorded in-file: it is a template family over an externally-supplied Device and variable NOut, with no single (device, NOut) schema to author. - ST12: extracted codegen/lib.ts for the helpers both generators duplicated, and corrected the comment that claimed they had to be separate. Proof the extraction was behaviour-free: regenerating the MIDI-device outputs produces a byte-identical tree. - ST11: deleted codegen/templates/ — dead "reference" files no generator reads, already drifted from the real emitters. Gates: run-all-tests.sh ALL GREEN; codegen idempotent (re-running both generators yields no further diff), which is what CI's dirty-diff gate checks.
This commit is contained in:
parent
a1a158b8d0
commit
f5b571412f
30 changed files with 652 additions and 458 deletions
|
|
@ -14,14 +14,18 @@
|
||||||
* by name, and selects which the ML drives over MIDI CC. Idempotent: regenerating the
|
* by name, and selects which the ML drives over MIDI CC. Idempotent: regenerating the
|
||||||
* same schemas yields byte-identical output. Exits non-zero on validation failure.
|
* same schemas yields byte-identical output. Exits non-zero on validation failure.
|
||||||
*
|
*
|
||||||
* Deliberately separate from codegen/generate.ts (the mode-schema pipeline) so it cannot
|
* Deliberately a separate DRIVER from codegen/generate.ts (the mode-schema
|
||||||
* disturb the mode golden test.
|
* pipeline): different schema dir, different meta-schema, different output
|
||||||
|
* dirs, and generate.ts's golden test must not depend on MIDI-device schema
|
||||||
|
* state. That does not require duplicate helpers, though — the small
|
||||||
|
* string/fs helpers both drivers need live once in ./lib.ts (ST12).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { readFileSync, writeFileSync, readdirSync, mkdirSync, existsSync } from "node:fs";
|
import { writeFileSync, readdirSync, existsSync } from "node:fs";
|
||||||
import { join, dirname, resolve } from "node:path";
|
import { join, dirname, resolve } from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
import Ajv2020, { type AnySchemaObject } from "ajv/dist/2020.js";
|
import Ajv2020, { type AnySchemaObject } from "ajv/dist/2020.js";
|
||||||
|
import { ensureDir, readJSON, toPascalCase, cppStringLit, tsStringLit } from "./lib.ts";
|
||||||
|
|
||||||
// ----- Types ----------------------------------------------------------------
|
// ----- Types ----------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -62,22 +66,8 @@ const CPP_OUT_DIR = join(REPO_ROOT, "nisps", "midi", "generated");
|
||||||
const TS_OUT_DIR = join(REPO_ROOT, "manifold", "src", "midi-devices", "generated");
|
const TS_OUT_DIR = join(REPO_ROOT, "manifold", "src", "midi-devices", "generated");
|
||||||
|
|
||||||
// ----- Helpers --------------------------------------------------------------
|
// ----- Helpers --------------------------------------------------------------
|
||||||
|
// ensureDir/readJSON/toPascalCase/cppStringLit/tsStringLit now live in
|
||||||
function ensureDir(d: string): void {
|
// ./lib.ts (ST12, shared with generate.ts).
|
||||||
if (!existsSync(d)) mkdirSync(d, { recursive: true });
|
|
||||||
}
|
|
||||||
function readJSON<T>(path: string): T {
|
|
||||||
return JSON.parse(readFileSync(path, "utf8")) as T;
|
|
||||||
}
|
|
||||||
function toPascalCase(snake: string): string {
|
|
||||||
return snake.split("_").map(s => (s.length === 0 ? s : s[0].toUpperCase() + s.slice(1))).join("");
|
|
||||||
}
|
|
||||||
function cppStringLit(s: string): string {
|
|
||||||
return '"' + s.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"';
|
|
||||||
}
|
|
||||||
function tsStringLit(s: string): string {
|
|
||||||
return "'" + s.replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'";
|
|
||||||
}
|
|
||||||
|
|
||||||
const BANNER = "// AUTOGENERATED — do not edit. Source: schemas/midi_devices/*.json. " +
|
const BANNER = "// AUTOGENERATED — do not edit. Source: schemas/midi_devices/*.json. " +
|
||||||
"Run `bun run codegen/generate-midi-devices.ts` to regenerate.";
|
"Run `bun run codegen/generate-midi-devices.ts` to regenerate.";
|
||||||
|
|
|
||||||
|
|
@ -14,14 +14,26 @@
|
||||||
* (The TS target moved playground → manifold at P5 of
|
* (The TS target moved playground → manifold at P5 of
|
||||||
* docs/specs/plans/one-core-engine-refactor.md.)
|
* docs/specs/plans/one-core-engine-refactor.md.)
|
||||||
*
|
*
|
||||||
|
* Per-mode C++ headers also emit (simplification 2026-07, S1/S5/S6/S25):
|
||||||
|
* - `k<Mode>Schema` — the `nisps::ParamSchema` aggregate; each mode's
|
||||||
|
* `param_schema()` becomes a one-line `return generated::k<Mode>Schema;`
|
||||||
|
* instead of hand-assembling the same 12-field struct.
|
||||||
|
* - `<Mode>MLP` — the mode's `nisps::ml::MLP<...>` net-shape alias,
|
||||||
|
* built from the constants above instead of a second hand-typed copy of
|
||||||
|
* the dims in nisps/modes/*.hpp.
|
||||||
|
* The TS `index.ts` also emits `ALL_MODE_SCHEMAS` (every mode schema, in
|
||||||
|
* generation order) so manifold's mode catalogue no longer hand-imports each
|
||||||
|
* schema by name — see manifold/src/console/model.ts's `SCHEMA_MODES` overlay.
|
||||||
|
*
|
||||||
* Idempotent: regenerating the same schemas yields byte-identical output.
|
* Idempotent: regenerating the same schemas yields byte-identical output.
|
||||||
* Exits non-zero on validation failure.
|
* Exits non-zero on validation failure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { readFileSync, writeFileSync, readdirSync, mkdirSync, existsSync } from "node:fs";
|
import { writeFileSync, readdirSync, existsSync } from "node:fs";
|
||||||
import { join, dirname, resolve, basename } from "node:path";
|
import { join, dirname, resolve, basename } from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
import Ajv2020, { type AnySchemaObject } from "ajv/dist/2020.js";
|
import Ajv2020, { type AnySchemaObject } from "ajv/dist/2020.js";
|
||||||
|
import { ensureDir, readJSON, toPascalCase, cppStringLit, tsStringLit } from "./lib.ts";
|
||||||
|
|
||||||
// ----- Types ----------------------------------------------------------------
|
// ----- Types ----------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -70,27 +82,8 @@ const CPP_OUT_DIR = join(REPO_ROOT, "nisps", "modes", "generated");
|
||||||
const TS_OUT_DIR = join(REPO_ROOT, "manifold", "src", "modes", "generated");
|
const TS_OUT_DIR = join(REPO_ROOT, "manifold", "src", "modes", "generated");
|
||||||
|
|
||||||
// ----- Helpers --------------------------------------------------------------
|
// ----- Helpers --------------------------------------------------------------
|
||||||
|
// ensureDir/readJSON/toPascalCase/cppStringLit/tsStringLit now live in
|
||||||
function ensureDir(d: string): void {
|
// ./lib.ts (ST12, shared with generate-midi-devices.ts).
|
||||||
if (!existsSync(d)) {
|
|
||||||
mkdirSync(d, { recursive: true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function readJSON<T>(path: string): T {
|
|
||||||
return JSON.parse(readFileSync(path, "utf8")) as T;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert snake_case to PascalCase.
|
|
||||||
* "paf_synth" -> "PafSynth", "memlcelium" -> "Memlcelium"
|
|
||||||
*/
|
|
||||||
function toPascalCase(snake: string): string {
|
|
||||||
return snake
|
|
||||||
.split("_")
|
|
||||||
.map(s => s.length === 0 ? s : s[0].toUpperCase() + s.slice(1))
|
|
||||||
.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert mode_id to UPPER_SNAKE for #define guards.
|
* Convert mode_id to UPPER_SNAKE for #define guards.
|
||||||
|
|
@ -99,21 +92,6 @@ function toUpperSnake(snake: string): string {
|
||||||
return snake.toUpperCase();
|
return snake.toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Escape a string literal for embedding into a C++ string.
|
|
||||||
* We expect ASCII identifiers + label text only; quote and backslash are escaped.
|
|
||||||
*/
|
|
||||||
function cppStringLit(s: string): string {
|
|
||||||
return '"' + s.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Escape a string for a TS single-line single-quoted literal.
|
|
||||||
*/
|
|
||||||
function tsStringLit(s: string): string {
|
|
||||||
return "'" + s.replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format a float literal for C++ ensuring `.f` suffix and explicit decimal point.
|
* Format a float literal for C++ ensuring `.f` suffix and explicit decimal point.
|
||||||
* Required by the perf contract (architecture §3.3).
|
* Required by the perf contract (architecture §3.3).
|
||||||
|
|
@ -161,11 +139,18 @@ function emitSchemaTypesHpp(): string {
|
||||||
"//",
|
"//",
|
||||||
"// `Curve` is the authoritative enum from nisps/core/math.hpp; we re-export it",
|
"// `Curve` is the authoritative enum from nisps/core/math.hpp; we re-export it",
|
||||||
"// into this namespace so generated headers can refer to plain `Curve::linear`.",
|
"// into this namespace so generated headers can refer to plain `Curve::linear`.",
|
||||||
|
"//",
|
||||||
|
"// `ParamSchema` lives in the top-level `nisps` namespace, not",
|
||||||
|
"// `nisps::modes::generated`: nisps/core/concepts.hpp forward-declares",
|
||||||
|
"// `nisps::ParamSchema` and requires `T::param_schema()` to return",
|
||||||
|
"// `const nisps::ParamSchema&`, so the definition has to match that",
|
||||||
|
"// forward declaration exactly (S5, one-core simplification 2026-07).",
|
||||||
"#ifndef NISPS_GENERATED_SCHEMA_TYPES_HPP",
|
"#ifndef NISPS_GENERATED_SCHEMA_TYPES_HPP",
|
||||||
"#define NISPS_GENERATED_SCHEMA_TYPES_HPP",
|
"#define NISPS_GENERATED_SCHEMA_TYPES_HPP",
|
||||||
"",
|
"",
|
||||||
"#include <array>",
|
"#include <array>",
|
||||||
"#include <cstddef>",
|
"#include <cstddef>",
|
||||||
|
"#include <span>",
|
||||||
"#include <string_view>",
|
"#include <string_view>",
|
||||||
"",
|
"",
|
||||||
"#include \"../../core/math.hpp\"",
|
"#include \"../../core/math.hpp\"",
|
||||||
|
|
@ -209,6 +194,30 @@ function emitSchemaTypesHpp(): string {
|
||||||
"",
|
"",
|
||||||
"} // namespace nisps::modes::generated",
|
"} // namespace nisps::modes::generated",
|
||||||
"",
|
"",
|
||||||
|
"namespace nisps {",
|
||||||
|
"",
|
||||||
|
"// View-style aggregate satisfying the `nisps::Mode` concept's",
|
||||||
|
"// `param_schema()` requirement. All members are spans/views into",
|
||||||
|
"// compile-time generated arrays; codegen emits one",
|
||||||
|
"// `inline constexpr ParamSchema k<Mode>Schema` per mode (see the",
|
||||||
|
"// per-mode <mode_id>_schema.hpp in this directory).",
|
||||||
|
"struct ParamSchema {",
|
||||||
|
" std::string_view mode_id;",
|
||||||
|
" std::string_view engine_id;",
|
||||||
|
" std::span<const std::string_view> input_channels;",
|
||||||
|
" std::size_t input_size;",
|
||||||
|
" std::span<const std::size_t> hidden_layers;",
|
||||||
|
" std::size_t output_size;",
|
||||||
|
" float default_spread;",
|
||||||
|
" float default_learning_rate;",
|
||||||
|
" std::size_t default_max_iterations;",
|
||||||
|
" std::span<const ::nisps::modes::generated::Param> params;",
|
||||||
|
" std::span<const std::string_view> voice_spaces;",
|
||||||
|
" ::nisps::modes::generated::UIConfig ui;",
|
||||||
|
"};",
|
||||||
|
"",
|
||||||
|
"} // namespace nisps",
|
||||||
|
"",
|
||||||
"#endif // NISPS_GENERATED_SCHEMA_TYPES_HPP",
|
"#endif // NISPS_GENERATED_SCHEMA_TYPES_HPP",
|
||||||
"",
|
"",
|
||||||
].join("\n");
|
].join("\n");
|
||||||
|
|
@ -286,6 +295,7 @@ function emitModeHpp(schema: ModeSchema, sourceFile: string): string {
|
||||||
lines.push(`#define ${guard}`);
|
lines.push(`#define ${guard}`);
|
||||||
lines.push("");
|
lines.push("");
|
||||||
lines.push("#include \"schema_types.hpp\"");
|
lines.push("#include \"schema_types.hpp\"");
|
||||||
|
lines.push("#include \"../../ml/mlp.hpp\"");
|
||||||
lines.push("");
|
lines.push("");
|
||||||
lines.push("namespace nisps::modes::generated {");
|
lines.push("namespace nisps::modes::generated {");
|
||||||
lines.push("");
|
lines.push("");
|
||||||
|
|
@ -368,6 +378,35 @@ function emitModeHpp(schema: ModeSchema, sourceFile: string): string {
|
||||||
lines.push("};");
|
lines.push("};");
|
||||||
lines.push("");
|
lines.push("");
|
||||||
|
|
||||||
|
// Net-shape alias (S6/S25): the mode's MLP<> template args, built from the
|
||||||
|
// constants above rather than hand-typed a second time in nisps/modes/*.hpp.
|
||||||
|
const modeMlpName = `${toPascalCase(schema.mode_id)}MLP`;
|
||||||
|
lines.push(
|
||||||
|
`using ${modeMlpName} = ::nisps::ml::MLP<` +
|
||||||
|
`${constName}MLConfig.input_size, ` +
|
||||||
|
`${constName}HiddenLayers[0], ${constName}HiddenLayers[1], ${constName}HiddenLayers[2], ` +
|
||||||
|
`${constName}MLConfig.output_size>;`
|
||||||
|
);
|
||||||
|
lines.push("");
|
||||||
|
|
||||||
|
// ParamSchema aggregate (S5): the one-line `param_schema()` body every mode
|
||||||
|
// used to hand-assemble as a private `kSchema` positional-init block.
|
||||||
|
lines.push(`inline constexpr ::nisps::ParamSchema ${constName}Schema = {`);
|
||||||
|
lines.push(` ${constName}ModeId,`);
|
||||||
|
lines.push(` ${constName}EngineId,`);
|
||||||
|
lines.push(` std::span<const std::string_view>(${constName}InputChannels),`);
|
||||||
|
lines.push(` ${constName}MLConfig.input_size,`);
|
||||||
|
lines.push(` std::span<const std::size_t>(${constName}HiddenLayers),`);
|
||||||
|
lines.push(` ${constName}MLConfig.output_size,`);
|
||||||
|
lines.push(` ${constName}MLConfig.default_spread,`);
|
||||||
|
lines.push(` ${constName}MLConfig.default_learning_rate,`);
|
||||||
|
lines.push(` ${constName}MLConfig.default_max_iterations,`);
|
||||||
|
lines.push(` std::span<const Param>(${constName}Params),`);
|
||||||
|
lines.push(` std::span<const std::string_view>(${constName}VoiceSpaces),`);
|
||||||
|
lines.push(` ${constName}UI,`);
|
||||||
|
lines.push("};");
|
||||||
|
lines.push("");
|
||||||
|
|
||||||
lines.push("} // namespace nisps::modes::generated");
|
lines.push("} // namespace nisps::modes::generated");
|
||||||
lines.push("");
|
lines.push("");
|
||||||
lines.push(`#endif // ${guard}`);
|
lines.push(`#endif // ${guard}`);
|
||||||
|
|
@ -454,11 +493,29 @@ function emitTsIndex(modeIds: string[]): string {
|
||||||
lines.push("// AUTOGENERATED — do not edit. Run `bun run codegen/generate.ts` to regenerate.");
|
lines.push("// AUTOGENERATED — do not edit. Run `bun run codegen/generate.ts` to regenerate.");
|
||||||
lines.push("// Re-exports every generated mode schema.");
|
lines.push("// Re-exports every generated mode schema.");
|
||||||
lines.push("");
|
lines.push("");
|
||||||
|
lines.push("import type { ModeSchema } from './types';");
|
||||||
|
for (const id of modeIds) {
|
||||||
|
lines.push(`import { ${toPascalCase(id)}Schema } from './${id}_schema';`);
|
||||||
|
}
|
||||||
|
lines.push("");
|
||||||
lines.push("export * from './types';");
|
lines.push("export * from './types';");
|
||||||
for (const id of modeIds) {
|
for (const id of modeIds) {
|
||||||
lines.push(`export * from './${id}_schema';`);
|
lines.push(`export * from './${id}_schema';`);
|
||||||
}
|
}
|
||||||
lines.push("");
|
lines.push("");
|
||||||
|
// Mechanically-derived mode-identity registry (S1): every generated mode
|
||||||
|
// schema, in generation (mode_id-sorted) order. NOT display order — that
|
||||||
|
// ordering is hand-curated overlay truth (manifold/src/console/model.ts's
|
||||||
|
// `SCHEMA_MODES`).
|
||||||
|
lines.push(
|
||||||
|
"/** Every generated mode schema, mode_id-sorted. Mechanically-derived mode-identity truth. */"
|
||||||
|
);
|
||||||
|
lines.push("export const ALL_MODE_SCHEMAS: readonly ModeSchema[] = [");
|
||||||
|
for (const id of modeIds) {
|
||||||
|
lines.push(` ${toPascalCase(id)}Schema,`);
|
||||||
|
}
|
||||||
|
lines.push("];");
|
||||||
|
lines.push("");
|
||||||
return lines.join("\n");
|
return lines.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
51
codegen/lib.ts
Normal file
51
codegen/lib.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
/**
|
||||||
|
* Shared helpers for the two codegen drivers (generate.ts — mode schemas —
|
||||||
|
* and generate-midi-devices.ts — MIDI device templates).
|
||||||
|
*
|
||||||
|
* The two drivers stay separate FILES on purpose: they read different schema
|
||||||
|
* directories, validate against different meta-schemas, write to different
|
||||||
|
* output dirs, and generate.ts's golden test (codegen/tests/golden_test.ts)
|
||||||
|
* must not depend on MIDI-device schema state. None of that requires
|
||||||
|
* duplicating these small string/fs helpers — they carry no per-driver
|
||||||
|
* behaviour, so they live here once (ST12, simplification 2026-07).
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { readFileSync, existsSync, mkdirSync } from "node:fs";
|
||||||
|
|
||||||
|
/** Create a directory (and parents) if it doesn't already exist. */
|
||||||
|
export function ensureDir(d: string): void {
|
||||||
|
if (!existsSync(d)) {
|
||||||
|
mkdirSync(d, { recursive: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Read and JSON-parse a file. */
|
||||||
|
export function readJSON<T>(path: string): T {
|
||||||
|
return JSON.parse(readFileSync(path, "utf8")) as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert snake_case to PascalCase.
|
||||||
|
* "paf_synth" -> "PafSynth", "memlcelium" -> "Memlcelium"
|
||||||
|
*/
|
||||||
|
export function toPascalCase(snake: string): string {
|
||||||
|
return snake
|
||||||
|
.split("_")
|
||||||
|
.map(s => (s.length === 0 ? s : s[0].toUpperCase() + s.slice(1)))
|
||||||
|
.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape a string literal for embedding into a C++ string.
|
||||||
|
* We expect ASCII identifiers + label text only; quote and backslash are escaped.
|
||||||
|
*/
|
||||||
|
export function cppStringLit(s: string): string {
|
||||||
|
return '"' + s.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape a string for a TS single-line single-quoted literal.
|
||||||
|
*/
|
||||||
|
export function tsStringLit(s: string): string {
|
||||||
|
return "'" + s.replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'";
|
||||||
|
}
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
// AUTOGENERATED — do not edit. Source: schemas/modes/{{SOURCE_FILE}}. Run `bun run codegen/generate.ts` to regenerate.
|
|
||||||
//
|
|
||||||
// This file is a reference template showing the shape of each generated C++
|
|
||||||
// header. It is NOT consumed at codegen time — `codegen/generate.ts` builds the
|
|
||||||
// strings programmatically (see emitModeHpp). The template lives here so that:
|
|
||||||
// 1. reviewers can see the intended structure at a glance,
|
|
||||||
// 2. anyone tweaking the codegen has a "what should this look like?" anchor.
|
|
||||||
//
|
|
||||||
// Placeholders use {{NAME}} syntax purely for documentation.
|
|
||||||
|
|
||||||
#ifndef NISPS_GENERATED_{{MODE_ID_UPPER}}_SCHEMA_HPP
|
|
||||||
#define NISPS_GENERATED_{{MODE_ID_UPPER}}_SCHEMA_HPP
|
|
||||||
|
|
||||||
#include "schema_types.hpp"
|
|
||||||
|
|
||||||
namespace nisps::modes::generated {
|
|
||||||
|
|
||||||
inline constexpr std::string_view k{{ModeId}}ModeId = "{{mode_id}}";
|
|
||||||
inline constexpr std::string_view k{{ModeId}}EngineId = "{{engine_id}}";
|
|
||||||
|
|
||||||
inline constexpr std::array<std::string_view, {{N_INPUTS}}> k{{ModeId}}InputChannels = {{
|
|
||||||
"{{input_channel_0}}",
|
|
||||||
/* ... */
|
|
||||||
}};
|
|
||||||
|
|
||||||
inline constexpr std::array<std::size_t, {{N_HIDDEN}}> k{{ModeId}}HiddenLayers = {{
|
|
||||||
/* ... */
|
|
||||||
}};
|
|
||||||
|
|
||||||
inline constexpr MLConfig k{{ModeId}}MLConfig = {
|
|
||||||
{{input_size}}u, {{output_size}}u,
|
|
||||||
{{default_spread}}f, {{default_lr}}f, {{default_iter}}u,
|
|
||||||
};
|
|
||||||
|
|
||||||
inline constexpr std::size_t k{{ModeId}}ParamCount = {{N_PARAMS}}u;
|
|
||||||
inline constexpr std::array<Param, k{{ModeId}}ParamCount> k{{ModeId}}Params = {{
|
|
||||||
Param{ "{{name}}", "{{label}}", {{min}}f, {{max}}f, {{default}}f, Curve::{{Curve}}, "{{group}}" },
|
|
||||||
/* ... */
|
|
||||||
}};
|
|
||||||
|
|
||||||
inline constexpr std::size_t k{{ModeId}}VoiceSpaceCount = {{N_VS}}u;
|
|
||||||
inline constexpr std::array<std::string_view, k{{ModeId}}VoiceSpaceCount> k{{ModeId}}VoiceSpaces = {{
|
|
||||||
/* ... */
|
|
||||||
}};
|
|
||||||
|
|
||||||
inline constexpr UIConfig k{{ModeId}}UI = {
|
|
||||||
PrimaryInput::{{PrimaryInput}},
|
|
||||||
{{show_voice_space_selector}}, {{show_synth_visualizer}},
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace nisps::modes::generated
|
|
||||||
|
|
||||||
#endif // NISPS_GENERATED_{{MODE_ID_UPPER}}_SCHEMA_HPP
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
// AUTOGENERATED — do not edit. Source: schemas/modes/{{SOURCE_FILE}}. Run `bun run codegen/generate.ts` to regenerate.
|
|
||||||
//
|
|
||||||
// Reference template for the TypeScript codegen output. Not consumed at runtime
|
|
||||||
// (the codegen builds strings programmatically in emitModeTs). Lives here for
|
|
||||||
// human reviewers — placeholders use {{NAME}} syntax.
|
|
||||||
|
|
||||||
import type { ModeSchema } from './types';
|
|
||||||
|
|
||||||
export interface {{ModeId}}Params {
|
|
||||||
readonly {{param_name_0}}: number;
|
|
||||||
/* ... */
|
|
||||||
}
|
|
||||||
|
|
||||||
export const {{ModeId}}Schema: ModeSchema = {
|
|
||||||
mode_id: '{{mode_id}}',
|
|
||||||
engine_id: '{{engine_id}}',
|
|
||||||
ml: {
|
|
||||||
input_channels: ['{{input_channel_0}}', /* ... */],
|
|
||||||
input_size: {{input_size}},
|
|
||||||
hidden_layers: [/* ... */],
|
|
||||||
output_size: {{output_size}},
|
|
||||||
default_spread: {{default_spread}},
|
|
||||||
default_learning_rate: {{default_lr}},
|
|
||||||
default_max_iterations: {{default_iter}},
|
|
||||||
},
|
|
||||||
params: [
|
|
||||||
{
|
|
||||||
name: '{{name}}',
|
|
||||||
label: '{{label}}',
|
|
||||||
min: {{min}},
|
|
||||||
max: {{max}},
|
|
||||||
default: {{default}},
|
|
||||||
curve: '{{curve}}',
|
|
||||||
group: '{{group}}',
|
|
||||||
},
|
|
||||||
/* ... */
|
|
||||||
],
|
|
||||||
voice_spaces: [/* ... */],
|
|
||||||
ui: {
|
|
||||||
primary_input: '{{primary_input}}',
|
|
||||||
show_voice_space_selector: {{show_voice_space_selector}},
|
|
||||||
show_synth_visualizer: {{show_synth_visualizer}},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#define NISPS_GENERATED_PAF_SYNTH_SCHEMA_HPP
|
#define NISPS_GENERATED_PAF_SYNTH_SCHEMA_HPP
|
||||||
|
|
||||||
#include "schema_types.hpp"
|
#include "schema_types.hpp"
|
||||||
|
#include "../../ml/mlp.hpp"
|
||||||
|
|
||||||
namespace nisps::modes::generated {
|
namespace nisps::modes::generated {
|
||||||
|
|
||||||
|
|
@ -348,6 +349,23 @@ inline constexpr UIConfig kPafSynthUI = {
|
||||||
true,
|
true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using PafSynthMLP = ::nisps::ml::MLP<kPafSynthMLConfig.input_size, kPafSynthHiddenLayers[0], kPafSynthHiddenLayers[1], kPafSynthHiddenLayers[2], kPafSynthMLConfig.output_size>;
|
||||||
|
|
||||||
|
inline constexpr ::nisps::ParamSchema kPafSynthSchema = {
|
||||||
|
kPafSynthModeId,
|
||||||
|
kPafSynthEngineId,
|
||||||
|
std::span<const std::string_view>(kPafSynthInputChannels),
|
||||||
|
kPafSynthMLConfig.input_size,
|
||||||
|
std::span<const std::size_t>(kPafSynthHiddenLayers),
|
||||||
|
kPafSynthMLConfig.output_size,
|
||||||
|
kPafSynthMLConfig.default_spread,
|
||||||
|
kPafSynthMLConfig.default_learning_rate,
|
||||||
|
kPafSynthMLConfig.default_max_iterations,
|
||||||
|
std::span<const Param>(kPafSynthParams),
|
||||||
|
std::span<const std::string_view>(kPafSynthVoiceSpaces),
|
||||||
|
kPafSynthUI,
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace nisps::modes::generated
|
} // namespace nisps::modes::generated
|
||||||
|
|
||||||
#endif // NISPS_GENERATED_PAF_SYNTH_SCHEMA_HPP
|
#endif // NISPS_GENERATED_PAF_SYNTH_SCHEMA_HPP
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -2,14 +2,18 @@
|
||||||
* Console — shared instrument model: the modes catalogue + per-param shaping
|
* Console — shared instrument model: the modes catalogue + per-param shaping
|
||||||
* helpers.
|
* helpers.
|
||||||
*
|
*
|
||||||
* SOURCE OF TRUTH (one-core-engine P5.2): the schema-backed modes are DERIVED
|
* SOURCE OF TRUTH (one-core-engine P5.2, mode-identity consolidation S1 —
|
||||||
* from the codegen-produced schemas in `src/modes/generated/` — real param
|
* simplification 2026-07): the schema-backed modes are DERIVED from
|
||||||
* names, groups, count, and each mode's `ml` config + `engine_id` come from
|
* `ALL_MODE_SCHEMAS`, codegen's mechanically-generated registry of every
|
||||||
* schema truth, never hand-written. A thin manifold-side OVERLAY supplies only
|
* schema in `src/modes/generated/` — real param names, groups, count, each
|
||||||
* the display concerns a schema has no opinion on: label, glyph, ModeClass,
|
* mode's `ml` config + `engine_id`, AND the set of mode ids itself all come
|
||||||
* input kind, and ordering. Two manifold-only modes with no schema
|
* from schema truth, never hand-imported one-by-one. A thin manifold-side
|
||||||
* (`visualizer`, `c15` placeholder) stay hand-written and use the default net
|
* OVERLAY (`SCHEMA_MODE_OVERLAYS`, keyed by mode_id) supplies only the display
|
||||||
* shape.
|
* concerns a schema has no opinion on: label, glyph, ModeClass, input kind,
|
||||||
|
* and catalogue ORDER (insertion order of the object's keys) — those are
|
||||||
|
* legitimately hand-curated display truth, not mechanically derivable, and
|
||||||
|
* survive here. Two manifold-only modes with no schema (`visualizer`, `c15`
|
||||||
|
* placeholder) stay hand-written and use the default net shape.
|
||||||
*
|
*
|
||||||
* KEY CHANGE vs the JSX reference: the pseudo-inference `MF_infer` (sin/cos
|
* KEY CHANGE vs the JSX reference: the pseudo-inference `MF_infer` (sin/cos
|
||||||
* placeholder) and the `useInstrument` hook are GONE. The `values` every
|
* placeholder) and the `useInstrument` hook are GONE. The `values` every
|
||||||
|
|
@ -23,29 +27,49 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ModeSchema } from '../modes/generated/types';
|
import type { ModeSchema } from '../modes/generated/types';
|
||||||
import {
|
import { ALL_MODE_SCHEMAS } from '../modes/generated';
|
||||||
BreakorSchema,
|
import { applyCurve } from '../backends/mapping';
|
||||||
ChannelStripSchema,
|
|
||||||
ElysiamorfSchema,
|
|
||||||
MemlceliumSchema,
|
|
||||||
PafSynthSchema,
|
|
||||||
SlpWorkshopSchema,
|
|
||||||
SoundAnalysisMidiSchema,
|
|
||||||
VerbFxSchema,
|
|
||||||
XiasriSchema,
|
|
||||||
} from '../modes/generated';
|
|
||||||
|
|
||||||
export type ParamStatus = 'off' | 'fixed' | 'live';
|
export type ParamStatus = 'off' | 'fixed' | 'live';
|
||||||
/**
|
/**
|
||||||
* Param GROUP. Historically a small hand-picked union; now the group is the raw
|
* Param GROUP. Historically a small hand-picked union; now the group is the raw
|
||||||
* schema string (`'operators'`, `'envelope'`, `'kick'`, …) so the type is just
|
* schema string (`'operators'`, `'envelope'`, `'kick'`, …) so the type is just
|
||||||
* `string`. Unknown groups fall back to the accent colour in the GROUP_COLOR
|
* `string`. Unknown groups fall back to the accent colour in {@link GROUP_COLOR}.
|
||||||
* maps that key off this field.
|
|
||||||
*/
|
*/
|
||||||
export type ParamGroup = string;
|
export type ParamGroup = string;
|
||||||
export type ModeClass = 'Synth' | 'Sequencer' | 'Controller' | 'Visual';
|
export type ModeClass = 'Synth' | 'Sequencer' | 'Controller' | 'Visual';
|
||||||
export type ModeInput = 'xy' | 'joystick' | 'audio_in';
|
export type ModeInput = 'xy' | 'joystick' | 'audio_in';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group → CSS custom-property name, for colouring per-output UI (bars, dots,
|
||||||
|
* meters). ST4 (simplification 2026-07): this was four byte-identical copies
|
||||||
|
* (console/shared-ui.tsx, console/OutputStage.tsx, console/CompositeStage.tsx,
|
||||||
|
* dock/OutputControlRow.tsx) — one canonical map now lives here.
|
||||||
|
*
|
||||||
|
* The keys are JSX-era placeholder group names, NOT the real schema group
|
||||||
|
* strings (`schemas/modes/*.json` uses `verb`, `sequencer`, `kick`, `snare`,
|
||||||
|
* `filterbank`, `operators`, … — only `pitch` overlaps). For every
|
||||||
|
* schema-backed mode this means almost every param falls through to the
|
||||||
|
* `--accent` default; the map only does real work for the two hand-written
|
||||||
|
* manifold-only modes (`visualizer`, `c15`), whose {@link MANIFOLD_ONLY_MODES}
|
||||||
|
* groups (`mod`/`amp`/`fx`) were chosen to match it. A hash-to-palette
|
||||||
|
* function over arbitrary group strings would fix this for schema-driven
|
||||||
|
* groups too, but `console/OutputStage.tsx` — the hero output view, and the
|
||||||
|
* highest-traffic consumer of group colour — is outside this pass's file
|
||||||
|
* ownership; changing the strategy here alone would make the demoted/dock
|
||||||
|
* views (this map's consumers) disagree with the hero view instead of
|
||||||
|
* agreeing, which is the opposite of ST4's goal. Left as a plain map;
|
||||||
|
* revisit keys/strategy together with OutputStage.tsx in one change.
|
||||||
|
*/
|
||||||
|
export const GROUP_COLOR: Readonly<Record<string, string>> = {
|
||||||
|
formant: '--accent',
|
||||||
|
pitch: '--accent-2',
|
||||||
|
amp: '--good',
|
||||||
|
filter: '--warn',
|
||||||
|
fx: '--info',
|
||||||
|
mod: '--accent-3',
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mode's net shape — the engine dims the runtime-shaped WASM MLP is reshaped
|
* A mode's net shape — the engine dims the runtime-shaped WASM MLP is reshaped
|
||||||
* to when this mode is active (one-core-engine P5.3). Schema-backed modes carry
|
* to when this mode is active (one-core-engine P5.3). Schema-backed modes carry
|
||||||
|
|
@ -123,9 +147,11 @@ export interface MFMode {
|
||||||
*/
|
*/
|
||||||
ml: ModeML;
|
ml: ModeML;
|
||||||
/**
|
/**
|
||||||
* The schema's `engine_id` (audio-engine metadata). NOTE: audio backend
|
* The schema's `engine_id` (audio-engine metadata). {@link modeEngineId}
|
||||||
* SELECTION still routes through {@link modeEngineId}, which is unchanged —
|
* routes the actual backend SELECTION off this field for every mode except
|
||||||
* this field is the schema-truth annotation, not the routing decision.
|
* `sound_analysis_midi` (see that function's doc comment for why it needs
|
||||||
|
* an exception) — this field stays the schema-truth annotation;
|
||||||
|
* `modeEngineId` is the routing decision.
|
||||||
*/
|
*/
|
||||||
engineId: string;
|
engineId: string;
|
||||||
placeholder?: boolean;
|
placeholder?: boolean;
|
||||||
|
|
@ -191,34 +217,31 @@ interface ModeOverlay {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ORDERED list of schema-backed modes: `{ schema, overlay }`. Order here is the
|
* Mode-identity display OVERLAY, keyed by mode_id (S1 — simplification
|
||||||
* catalogue order. `xiasri` + `slp_workshop` are new browser-viable entries
|
* 2026-07): labels, glyphs, `ModeClass`, input kind, and CATALOGUE ORDER
|
||||||
* (they have schemas but weren't in the hand-written catalogue). The overlay is
|
* (this object's key insertion order) are hand-curated display truth with no
|
||||||
* hand-picked display; the params/ml/engine_id come from the schema.
|
* schema opinion, so they stay hand-written here. Everything else a mode
|
||||||
|
* needs (which mode ids exist, their params/ml/engine_id) is mechanically
|
||||||
|
* derived from `ALL_MODE_SCHEMAS` (codegen output) below — `xiasri` +
|
||||||
|
* `slp_workshop` are browser-viable entries that have schemas but weren't in
|
||||||
|
* the pre-P5 hand-written catalogue.
|
||||||
*/
|
*/
|
||||||
const SCHEMA_MODES: ReadonlyArray<{ schema: ModeSchema; overlay: ModeOverlay }> = [
|
const SCHEMA_MODE_OVERLAYS: Readonly<Record<string, ModeOverlay>> = {
|
||||||
{ schema: PafSynthSchema, overlay: { label: 'PAF Synth', glyph: '∿', cls: 'Synth', input: 'xy' } },
|
paf_synth: { label: 'PAF Synth', glyph: '∿', cls: 'Synth', input: 'xy' },
|
||||||
{
|
channel_strip: { label: 'Channel Strip', glyph: '▤', cls: 'Synth', input: 'joystick' },
|
||||||
schema: ChannelStripSchema,
|
verb_fx: { label: 'Verb FX', glyph: '◞', cls: 'Synth', input: 'joystick' },
|
||||||
overlay: { label: 'Channel Strip', glyph: '▤', cls: 'Synth', input: 'joystick' },
|
elysiamorf: { label: 'Elysiamorf', glyph: '❋', cls: 'Synth', input: 'xy' },
|
||||||
|
memlcelium: { label: 'MEML Celium', glyph: '☷', cls: 'Sequencer', input: 'xy' },
|
||||||
|
breakor: { label: 'Breakor', glyph: '⊟', cls: 'Sequencer', input: 'joystick' },
|
||||||
|
xiasri: { label: 'Xiasri', glyph: '✴', cls: 'Synth', input: 'joystick' },
|
||||||
|
slp_workshop: { label: 'SLP Workshop', glyph: '☷', cls: 'Sequencer', input: 'xy' },
|
||||||
|
sound_analysis_midi: {
|
||||||
|
label: 'Sound Analysis → MIDI',
|
||||||
|
glyph: '⇉',
|
||||||
|
cls: 'Controller',
|
||||||
|
input: 'audio_in',
|
||||||
},
|
},
|
||||||
{ schema: VerbFxSchema, overlay: { label: 'Verb FX', glyph: '◞', cls: 'Synth', input: 'joystick' } },
|
};
|
||||||
{ schema: ElysiamorfSchema, overlay: { label: 'Elysiamorf', glyph: '❋', cls: 'Synth', input: 'xy' } },
|
|
||||||
{
|
|
||||||
schema: MemlceliumSchema,
|
|
||||||
overlay: { label: 'MEML Celium', glyph: '☷', cls: 'Sequencer', input: 'xy' },
|
|
||||||
},
|
|
||||||
{ schema: BreakorSchema, overlay: { label: 'Breakor', glyph: '⊟', cls: 'Sequencer', input: 'joystick' } },
|
|
||||||
{ schema: XiasriSchema, overlay: { label: 'Xiasri', glyph: '✴', cls: 'Synth', input: 'joystick' } },
|
|
||||||
{
|
|
||||||
schema: SlpWorkshopSchema,
|
|
||||||
overlay: { label: 'SLP Workshop', glyph: '☷', cls: 'Sequencer', input: 'xy' },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
schema: SoundAnalysisMidiSchema,
|
|
||||||
overlay: { label: 'Sound Analysis → MIDI', glyph: '⇉', cls: 'Controller', input: 'audio_in' },
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
function modeFromSchema(schema: ModeSchema, overlay: ModeOverlay): MFMode {
|
function modeFromSchema(schema: ModeSchema, overlay: ModeOverlay): MFMode {
|
||||||
return {
|
return {
|
||||||
|
|
@ -234,6 +257,27 @@ function modeFromSchema(schema: ModeSchema, overlay: ModeOverlay): MFMode {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schema-backed modes, in {@link SCHEMA_MODE_OVERLAYS}'s curated catalogue
|
||||||
|
* order. A mode_id with no matching generated schema is dropped (loudly, via
|
||||||
|
* console.error) rather than crashing the console — this should only be
|
||||||
|
* reachable mid-edit, between adding/removing a schema and updating the
|
||||||
|
* overlay map.
|
||||||
|
*/
|
||||||
|
const SCHEMA_MODES: MFMode[] = Object.entries(SCHEMA_MODE_OVERLAYS).flatMap(
|
||||||
|
([modeId, overlay]) => {
|
||||||
|
const schema = ALL_MODE_SCHEMAS.find((s) => s.mode_id === modeId);
|
||||||
|
if (!schema) {
|
||||||
|
console.error(
|
||||||
|
`model.ts: SCHEMA_MODE_OVERLAYS has an entry for mode_id '${modeId}' but no ` +
|
||||||
|
'matching generated schema exists (check codegen output) — dropped from MF_MODES.',
|
||||||
|
);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return [modeFromSchema(schema, overlay)];
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manifold-only modes with NO schema — hand-written params on the DEFAULT net
|
* Manifold-only modes with NO schema — hand-written params on the DEFAULT net
|
||||||
* shape. `visualizer` is a pure browser visual; `c15` is the "Powerful Synth
|
* shape. `visualizer` is a pure browser visual; `c15` is the "Powerful Synth
|
||||||
|
|
@ -269,16 +313,41 @@ const MANIFOLD_ONLY_MODES: MFMode[] = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const MF_MODES: MFMode[] = [
|
export const MF_MODES: MFMode[] = [...SCHEMA_MODES, ...MANIFOLD_ONLY_MODES];
|
||||||
...SCHEMA_MODES.map(({ schema, overlay }) => modeFromSchema(schema, overlay)),
|
|
||||||
...MANIFOLD_ONLY_MODES,
|
|
||||||
];
|
|
||||||
|
|
||||||
/** Mirrors the engine's `applyCurve` (≈0.43 ≈ linear). */
|
/**
|
||||||
export function applyCurve(v: number, c: number): number {
|
* L38 (simplification 2026-07): this used to be a SECOND, divergent
|
||||||
const e = 0.25 + c * 1.75;
|
* `applyCurve` (`e = 0.25 + c * 1.75`, linear at c≈0.43) alongside
|
||||||
return Math.pow(Math.max(0, Math.min(1, v)), e);
|
* `backends/mapping.ts`'s spec-anchored version (0.5 = exact linear
|
||||||
}
|
* midpoint, backends-spec §3). Deleted in favour of the mapping.ts survivor,
|
||||||
|
* imported above and re-exported below so `console/index.ts`'s existing
|
||||||
|
* `export { applyCurve } from './model'` keeps working.
|
||||||
|
*
|
||||||
|
* Behaviour change: {@link shapeValues} (below) and Drawers.tsx's bar
|
||||||
|
* snapshot are the only consumers of this UI-display curve — they shape the
|
||||||
|
* on-screen output value/bar for every mode, at every param's `curve`
|
||||||
|
* setting (default 0.5). Actual backend signals (MIDI/OSC/VCV/CV, via
|
||||||
|
* `backends/*.ts`'s `mapOutput`) already used mapping.ts's formula
|
||||||
|
* exclusively, so this change makes the on-screen numbers agree with what is
|
||||||
|
* actually sent to a sink, rather than diverging from it as before. At the
|
||||||
|
* default curve (0.5) the exponent moves from 1.125 to an exact 1.0
|
||||||
|
* (linear); away from 0.5 the whole response-curve shape changes (mapping.ts
|
||||||
|
* is symmetric in log-exponent space, 0.25 at c=0, 4.0 at c=1; the deleted
|
||||||
|
* version ranged 0.25→2.0 linearly) — every displayed output value moves
|
||||||
|
* visibly, for every mode, at every curve setting except the shared endpoint
|
||||||
|
* c=0 (both give exponent 0.25). No schema, engine, or backend-emitted value
|
||||||
|
* changes.
|
||||||
|
*
|
||||||
|
* NOTE for a follow-up: `console/CurvePad.tsx` (out of this pass's file
|
||||||
|
* ownership) has its own THIRD inlined copy of the deleted formula
|
||||||
|
* (`e = 0.25 + curve * 1.75`) to draw its response-curve preview canvas and
|
||||||
|
* the numeric readout beside it. That preview matched this file's curve
|
||||||
|
* before today; now it matches neither this file's (now mapping.ts's) curve
|
||||||
|
* nor the value the backends actually emit. Repoint it at the same
|
||||||
|
* `applyCurve` import so the knob preview, the on-screen bars, and the
|
||||||
|
* emitted signal all agree.
|
||||||
|
*/
|
||||||
|
export { applyCurve };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map the engine's raw output vector onto a mode's params, applying each
|
* Map the engine's raw output vector onto a mode's params, applying each
|
||||||
|
|
@ -302,24 +371,25 @@ export function shapeValues(params: MFParam[], engineOut: Float32Array | null):
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Map a mode id → the audio-engine backend id. Mode ids align with engine ids
|
/**
|
||||||
* except `slp_workshop` (runs the memlcelium engine), the analysis controller,
|
* Map a mode id → the audio-engine backend id. Routes on `MFMode.engineId`
|
||||||
* and the relabelled `c15`. */
|
* (schema truth — `slp_workshop`'s schema already declares `engine_id:
|
||||||
|
* 'memlcelium'`, so it needs no special case here; unknown ids, including the
|
||||||
|
* two manifold-only modes, fall back to `'thru'` via their own `engineId`)
|
||||||
|
* (L37 — simplification 2026-07, deleted the hand-`switch`ed duplicate of
|
||||||
|
* schema `engine_id` that silently dropped any new mode never added to it).
|
||||||
|
*
|
||||||
|
* ONE named exception: `sound_analysis_midi`. Its schema declares `engine_id:
|
||||||
|
* 'thru'` because `SoundAnalysisMIDIMode`'s own `ModeBase` audio-engine slot
|
||||||
|
* really is `NoOpEngine` (nisps/modes/sound_analysis_midi.hpp) — audio passes
|
||||||
|
* through silently. But the mode also runs a SEPARATE real engine, the
|
||||||
|
* spectral-feature tap `AnalysisEngine` (engine_id "analysis",
|
||||||
|
* nisps/engines/analysis.hpp:95) — the browser must instantiate THAT as its
|
||||||
|
* audio backend for feature extraction to run at all. `schema.engine_id`
|
||||||
|
* ('thru') and the backend to actually select ('analysis') are genuinely
|
||||||
|
* different facts for this one mode; every other mode has them equal.
|
||||||
|
*/
|
||||||
export function modeEngineId(modeId: string): string {
|
export function modeEngineId(modeId: string): string {
|
||||||
switch (modeId) {
|
if (modeId === 'sound_analysis_midi') return 'analysis';
|
||||||
case 'paf_synth':
|
return MF_MODES.find((m) => m.id === modeId)?.engineId ?? 'thru';
|
||||||
case 'channel_strip':
|
|
||||||
case 'verb_fx':
|
|
||||||
case 'elysiamorf':
|
|
||||||
case 'memlcelium':
|
|
||||||
case 'breakor':
|
|
||||||
case 'xiasri':
|
|
||||||
return modeId;
|
|
||||||
case 'slp_workshop':
|
|
||||||
return 'memlcelium';
|
|
||||||
case 'sound_analysis_midi':
|
|
||||||
return 'analysis';
|
|
||||||
default:
|
|
||||||
return 'thru';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,17 @@
|
||||||
// AUTOGENERATED — do not edit. Run `bun run codegen/generate.ts` to regenerate.
|
// AUTOGENERATED — do not edit. Run `bun run codegen/generate.ts` to regenerate.
|
||||||
// Re-exports every generated mode schema.
|
// Re-exports every generated mode schema.
|
||||||
|
|
||||||
|
import type { ModeSchema } from './types';
|
||||||
|
import { BreakorSchema } from './breakor_schema';
|
||||||
|
import { ChannelStripSchema } from './channel_strip_schema';
|
||||||
|
import { ElysiamorfSchema } from './elysiamorf_schema';
|
||||||
|
import { MemlceliumSchema } from './memlcelium_schema';
|
||||||
|
import { PafSynthSchema } from './paf_synth_schema';
|
||||||
|
import { SlpWorkshopSchema } from './slp_workshop_schema';
|
||||||
|
import { SoundAnalysisMidiSchema } from './sound_analysis_midi_schema';
|
||||||
|
import { VerbFxSchema } from './verb_fx_schema';
|
||||||
|
import { XiasriSchema } from './xiasri_schema';
|
||||||
|
|
||||||
export * from './types';
|
export * from './types';
|
||||||
export * from './breakor_schema';
|
export * from './breakor_schema';
|
||||||
export * from './channel_strip_schema';
|
export * from './channel_strip_schema';
|
||||||
|
|
@ -11,3 +22,16 @@ export * from './slp_workshop_schema';
|
||||||
export * from './sound_analysis_midi_schema';
|
export * from './sound_analysis_midi_schema';
|
||||||
export * from './verb_fx_schema';
|
export * from './verb_fx_schema';
|
||||||
export * from './xiasri_schema';
|
export * from './xiasri_schema';
|
||||||
|
|
||||||
|
/** Every generated mode schema, mode_id-sorted. Mechanically-derived mode-identity truth. */
|
||||||
|
export const ALL_MODE_SCHEMAS: readonly ModeSchema[] = [
|
||||||
|
BreakorSchema,
|
||||||
|
ChannelStripSchema,
|
||||||
|
ElysiamorfSchema,
|
||||||
|
MemlceliumSchema,
|
||||||
|
PafSynthSchema,
|
||||||
|
SlpWorkshopSchema,
|
||||||
|
SoundAnalysisMidiSchema,
|
||||||
|
VerbFxSchema,
|
||||||
|
XiasriSchema,
|
||||||
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,14 @@
|
||||||
// nisps/modes/base.hpp — Common scaffolding for every concrete mode.
|
// nisps/modes/base.hpp — Common scaffolding for every concrete mode.
|
||||||
//
|
//
|
||||||
// Two responsibilities:
|
// Provides `ModeBase<Derived, EngineT, MLPType, NInputs>` — a CRTP base
|
||||||
// 1. Define `nisps::ParamSchema` (the aggregate type that the `Mode`
|
|
||||||
// concept's `param_schema()` returns a const-reference to). The codegen
|
|
||||||
// output in `nisps/modes/generated/` lives in a different namespace and
|
|
||||||
// provides typed constants per mode; we wrap those in a uniform view-
|
|
||||||
// style `ParamSchema` here so the concept is satisfied without touching
|
|
||||||
// generated code.
|
|
||||||
//
|
|
||||||
// 2. Provide `ModeBase<Derived, EngineT, MLPType, NInputs>` — a CRTP base
|
|
||||||
// that absorbs the per-mode boilerplate (input forwarding, ML inference
|
// that absorbs the per-mode boilerplate (input forwarding, ML inference
|
||||||
// driving engine params, voice space selection, control event ring
|
// driving engine params, voice space selection, control event ring
|
||||||
// buffer). Concrete modes derive from this and only specialise:
|
// buffer). Concrete modes derive from this and only specialise:
|
||||||
// - the schema reference (static),
|
// - the schema reference (static; `nisps::ParamSchema` — the aggregate
|
||||||
|
// type the `Mode` concept's `param_schema()` returns a const-reference
|
||||||
|
// to — is now DEFINED in the codegen output, `generated/schema_types.hpp`,
|
||||||
|
// included below; codegen also emits one `inline constexpr ParamSchema
|
||||||
|
// k<Mode>Schema` per mode, so `param_schema()` is a one-line return),
|
||||||
// - the "extra" pre-mapping done before set_params (e.g. analysis
|
// - the "extra" pre-mapping done before set_params (e.g. analysis
|
||||||
// features stitched into ML inputs in SoundAnalysisMIDI),
|
// features stitched into ML inputs in SoundAnalysisMIDI),
|
||||||
// - any engine-specific control glue (note_on/note_off, sequencer
|
// - any engine-specific control glue (note_on/note_off, sequencer
|
||||||
|
|
@ -43,25 +39,11 @@
|
||||||
|
|
||||||
namespace nisps {
|
namespace nisps {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// `nisps::ParamSchema` is defined in generated/schema_types.hpp (included
|
||||||
// ParamSchema — view-style aggregate matching the concept's forward decl.
|
// above) — codegen owns it (S5, one-core simplification 2026-07) since its
|
||||||
// All members are spans/views into compile-time generated arrays; the
|
// shape must match the `nisps::Mode` concept's forward declaration
|
||||||
// schema itself can be `inline constexpr` per mode.
|
// (nisps/core/concepts.hpp) exactly, and every mode's actual schema VALUE is
|
||||||
// ---------------------------------------------------------------------------
|
// itself codegen output (`generated::k<Mode>Schema`).
|
||||||
struct ParamSchema {
|
|
||||||
std::string_view mode_id;
|
|
||||||
std::string_view engine_id;
|
|
||||||
std::span<const std::string_view> input_channels;
|
|
||||||
std::size_t input_size;
|
|
||||||
std::span<const std::size_t> hidden_layers;
|
|
||||||
std::size_t output_size;
|
|
||||||
float default_spread;
|
|
||||||
float default_learning_rate;
|
|
||||||
std::size_t default_max_iterations;
|
|
||||||
std::span<const ::nisps::modes::generated::Param> params;
|
|
||||||
std::span<const std::string_view> voice_spaces;
|
|
||||||
::nisps::modes::generated::UIConfig ui;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Abstract control event — emitted by modes for the platform glue to drain.
|
// Abstract control event — emitted by modes for the platform glue to drain.
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
#include "../core/perf.hpp"
|
#include "../core/perf.hpp"
|
||||||
#include "../core/types.hpp"
|
#include "../core/types.hpp"
|
||||||
#include "../engines/breakor.hpp"
|
#include "../engines/breakor.hpp"
|
||||||
#include "../ml/mlp.hpp"
|
|
||||||
#include "base.hpp"
|
#include "base.hpp"
|
||||||
#include "generated/breakor_schema.hpp"
|
#include "generated/breakor_schema.hpp"
|
||||||
|
|
||||||
|
|
@ -26,17 +25,19 @@ namespace nisps::modes {
|
||||||
class BreakOrMode : public ModeBase<
|
class BreakOrMode : public ModeBase<
|
||||||
BreakOrMode,
|
BreakOrMode,
|
||||||
BreakOrEngine,
|
BreakOrEngine,
|
||||||
ml::MLP<4u, 10u, 14u, 18u, 56u>,
|
generated::BreakorMLP,
|
||||||
4u> {
|
4u> {
|
||||||
public:
|
public:
|
||||||
using Base = ModeBase<BreakOrMode, BreakOrEngine,
|
using Base = ModeBase<BreakOrMode, BreakOrEngine,
|
||||||
ml::MLP<4u, 10u, 14u, 18u, 56u>, 4u>;
|
generated::BreakorMLP, 4u>;
|
||||||
using Base::Base;
|
using Base::Base;
|
||||||
|
|
||||||
static constexpr std::string_view mode_id() noexcept {
|
static constexpr std::string_view mode_id() noexcept {
|
||||||
return generated::kBreakorModeId;
|
return generated::kBreakorModeId;
|
||||||
}
|
}
|
||||||
static constexpr const ParamSchema& param_schema() noexcept { return kSchema; }
|
static constexpr const ParamSchema& param_schema() noexcept {
|
||||||
|
return generated::kBreakorSchema;
|
||||||
|
}
|
||||||
|
|
||||||
NISPS_FORCE_INLINE void set_playing(bool playing) noexcept {
|
NISPS_FORCE_INLINE void set_playing(bool playing) noexcept {
|
||||||
engine_.set_playing(playing);
|
engine_.set_playing(playing);
|
||||||
|
|
@ -71,22 +72,6 @@ class BreakOrMode : public ModeBase<
|
||||||
(void)push_control_event(ce);
|
(void)push_control_event(ce);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
static inline constexpr ParamSchema kSchema = ParamSchema{
|
|
||||||
generated::kBreakorModeId,
|
|
||||||
generated::kBreakorEngineId,
|
|
||||||
std::span<const std::string_view>(generated::kBreakorInputChannels),
|
|
||||||
generated::kBreakorMLConfig.input_size,
|
|
||||||
std::span<const std::size_t>(generated::kBreakorHiddenLayers),
|
|
||||||
generated::kBreakorMLConfig.output_size,
|
|
||||||
generated::kBreakorMLConfig.default_spread,
|
|
||||||
generated::kBreakorMLConfig.default_learning_rate,
|
|
||||||
generated::kBreakorMLConfig.default_max_iterations,
|
|
||||||
std::span<const generated::Param>(generated::kBreakorParams),
|
|
||||||
std::span<const std::string_view>(generated::kBreakorVoiceSpaces),
|
|
||||||
generated::kBreakorUI,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(Mode<BreakOrMode>, "BreakOrMode must satisfy nisps::Mode");
|
static_assert(Mode<BreakOrMode>, "BreakOrMode must satisfy nisps::Mode");
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
#include "../core/concepts.hpp"
|
#include "../core/concepts.hpp"
|
||||||
#include "../core/types.hpp"
|
#include "../core/types.hpp"
|
||||||
#include "../engines/channel_strip.hpp"
|
#include "../engines/channel_strip.hpp"
|
||||||
#include "../ml/mlp.hpp"
|
|
||||||
#include "base.hpp"
|
#include "base.hpp"
|
||||||
#include "generated/channel_strip_schema.hpp"
|
#include "generated/channel_strip_schema.hpp"
|
||||||
|
|
||||||
|
|
@ -22,33 +21,19 @@ namespace nisps::modes {
|
||||||
class ChannelStripMode : public ModeBase<
|
class ChannelStripMode : public ModeBase<
|
||||||
ChannelStripMode,
|
ChannelStripMode,
|
||||||
ChannelStripEngine,
|
ChannelStripEngine,
|
||||||
ml::MLP<4u, 10u, 10u, 14u, 24u>,
|
generated::ChannelStripMLP,
|
||||||
4u> {
|
4u> {
|
||||||
public:
|
public:
|
||||||
using Base = ModeBase<ChannelStripMode, ChannelStripEngine,
|
using Base = ModeBase<ChannelStripMode, ChannelStripEngine,
|
||||||
ml::MLP<4u, 10u, 10u, 14u, 24u>, 4u>;
|
generated::ChannelStripMLP, 4u>;
|
||||||
using Base::Base;
|
using Base::Base;
|
||||||
|
|
||||||
static constexpr std::string_view mode_id() noexcept {
|
static constexpr std::string_view mode_id() noexcept {
|
||||||
return generated::kChannelStripModeId;
|
return generated::kChannelStripModeId;
|
||||||
}
|
}
|
||||||
static constexpr const ParamSchema& param_schema() noexcept { return kSchema; }
|
static constexpr const ParamSchema& param_schema() noexcept {
|
||||||
|
return generated::kChannelStripSchema;
|
||||||
private:
|
}
|
||||||
static inline constexpr ParamSchema kSchema = ParamSchema{
|
|
||||||
generated::kChannelStripModeId,
|
|
||||||
generated::kChannelStripEngineId,
|
|
||||||
std::span<const std::string_view>(generated::kChannelStripInputChannels),
|
|
||||||
generated::kChannelStripMLConfig.input_size,
|
|
||||||
std::span<const std::size_t>(generated::kChannelStripHiddenLayers),
|
|
||||||
generated::kChannelStripMLConfig.output_size,
|
|
||||||
generated::kChannelStripMLConfig.default_spread,
|
|
||||||
generated::kChannelStripMLConfig.default_learning_rate,
|
|
||||||
generated::kChannelStripMLConfig.default_max_iterations,
|
|
||||||
std::span<const generated::Param>(generated::kChannelStripParams),
|
|
||||||
std::span<const std::string_view>(generated::kChannelStripVoiceSpaces),
|
|
||||||
generated::kChannelStripUI,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(Mode<ChannelStripMode>, "ChannelStripMode must satisfy nisps::Mode");
|
static_assert(Mode<ChannelStripMode>, "ChannelStripMode must satisfy nisps::Mode");
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
#include "../core/perf.hpp"
|
#include "../core/perf.hpp"
|
||||||
#include "../core/types.hpp"
|
#include "../core/types.hpp"
|
||||||
#include "../engines/elysiamorf.hpp"
|
#include "../engines/elysiamorf.hpp"
|
||||||
#include "../ml/mlp.hpp"
|
|
||||||
#include "base.hpp"
|
#include "base.hpp"
|
||||||
#include "generated/elysiamorf_schema.hpp"
|
#include "generated/elysiamorf_schema.hpp"
|
||||||
|
|
||||||
|
|
@ -25,17 +24,19 @@ namespace nisps::modes {
|
||||||
class ElysiamorfMode : public ModeBase<
|
class ElysiamorfMode : public ModeBase<
|
||||||
ElysiamorfMode,
|
ElysiamorfMode,
|
||||||
ElysiamorfEngine,
|
ElysiamorfEngine,
|
||||||
ml::MLP<4u, 10u, 14u, 18u, 40u>,
|
generated::ElysiamorfMLP,
|
||||||
4u> {
|
4u> {
|
||||||
public:
|
public:
|
||||||
using Base = ModeBase<ElysiamorfMode, ElysiamorfEngine,
|
using Base = ModeBase<ElysiamorfMode, ElysiamorfEngine,
|
||||||
ml::MLP<4u, 10u, 14u, 18u, 40u>, 4u>;
|
generated::ElysiamorfMLP, 4u>;
|
||||||
using Base::Base;
|
using Base::Base;
|
||||||
|
|
||||||
static constexpr std::string_view mode_id() noexcept {
|
static constexpr std::string_view mode_id() noexcept {
|
||||||
return generated::kElysiamorfModeId;
|
return generated::kElysiamorfModeId;
|
||||||
}
|
}
|
||||||
static constexpr const ParamSchema& param_schema() noexcept { return kSchema; }
|
static constexpr const ParamSchema& param_schema() noexcept {
|
||||||
|
return generated::kElysiamorfSchema;
|
||||||
|
}
|
||||||
|
|
||||||
NISPS_FORCE_INLINE void set_playing(bool playing) noexcept {
|
NISPS_FORCE_INLINE void set_playing(bool playing) noexcept {
|
||||||
engine_.set_playing(playing);
|
engine_.set_playing(playing);
|
||||||
|
|
@ -64,22 +65,6 @@ class ElysiamorfMode : public ModeBase<
|
||||||
(void)push_control_event(ce);
|
(void)push_control_event(ce);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
static inline constexpr ParamSchema kSchema = ParamSchema{
|
|
||||||
generated::kElysiamorfModeId,
|
|
||||||
generated::kElysiamorfEngineId,
|
|
||||||
std::span<const std::string_view>(generated::kElysiamorfInputChannels),
|
|
||||||
generated::kElysiamorfMLConfig.input_size,
|
|
||||||
std::span<const std::size_t>(generated::kElysiamorfHiddenLayers),
|
|
||||||
generated::kElysiamorfMLConfig.output_size,
|
|
||||||
generated::kElysiamorfMLConfig.default_spread,
|
|
||||||
generated::kElysiamorfMLConfig.default_learning_rate,
|
|
||||||
generated::kElysiamorfMLConfig.default_max_iterations,
|
|
||||||
std::span<const generated::Param>(generated::kElysiamorfParams),
|
|
||||||
std::span<const std::string_view>(generated::kElysiamorfVoiceSpaces),
|
|
||||||
generated::kElysiamorfUI,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(Mode<ElysiamorfMode>, "ElysiamorfMode must satisfy nisps::Mode");
|
static_assert(Mode<ElysiamorfMode>, "ElysiamorfMode must satisfy nisps::Mode");
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,22 @@
|
||||||
//
|
//
|
||||||
// `kRouteOutputsToEngine = false` (specialised below) so ModeBase skips routing
|
// `kRouteOutputsToEngine = false` (specialised below) so ModeBase skips routing
|
||||||
// ML outputs into engine params, exactly like SoundAnalysisMIDIMode.
|
// ML outputs into engine params, exactly like SoundAnalysisMIDIMode.
|
||||||
|
//
|
||||||
|
// NOT folded into the schemas/modes/*.json codegen pipeline (L11, one-core
|
||||||
|
// simplification 2026-07): that pipeline emits ONE static schema per JSON
|
||||||
|
// file, but this "mode" is a C++ template family over an externally supplied
|
||||||
|
// `Device` (one of the nisps/midi/generated device templates) and an output
|
||||||
|
// count `NOut` — there is no single (device, NOut) pair to author a JSON
|
||||||
|
// schema for, and its per-output "params" aren't independently named at all;
|
||||||
|
// they're whichever NOut slots `pick_cc_slots` selects from `Device.params`,
|
||||||
|
// which is ITSELF already schema-generated (codegen/generate-midi-devices.ts,
|
||||||
|
// schemas/midi_devices/). Folding would mean inventing a new
|
||||||
|
// device-templated schema kind for a single, already-degenerate consumer —
|
||||||
|
// not a behaviour-preserving consolidation. Instead: the net-shape + ML
|
||||||
|
// defaults this mode needs (identical to every other 4-joystick-input mode —
|
||||||
|
// see e.g. schemas/modes/memlcelium.json) are named ONCE below
|
||||||
|
// (`ext_synth_defaults`), so the `MLP<>` shape and the `ParamSchema` instance
|
||||||
|
// both read from the same place instead of re-typing the same literals.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
@ -37,6 +53,34 @@
|
||||||
|
|
||||||
namespace nisps::modes {
|
namespace nisps::modes {
|
||||||
|
|
||||||
|
// Shared net-shape + ML defaults for every ExternalSynthMIDIMode
|
||||||
|
// instantiation (see the file-header comment for why these are hand-named
|
||||||
|
// rather than codegen'd): 4 joystick inputs -> [10,14,18] hidden -> NOut
|
||||||
|
// (device-CC-count-driven) outputs, matching every other 4-joystick-input
|
||||||
|
// mode's schema defaults (default_spread 0.6, default_learning_rate 1.0,
|
||||||
|
// default_max_iterations 1000).
|
||||||
|
namespace ext_synth_defaults {
|
||||||
|
inline constexpr std::size_t kInputSize = 4u;
|
||||||
|
inline constexpr std::array<std::string_view, 4> kInputChannels{
|
||||||
|
std::string_view{"joy_x"}, std::string_view{"joy_y"},
|
||||||
|
std::string_view{"joy_z"}, std::string_view{"joy_w"}};
|
||||||
|
inline constexpr std::array<std::size_t, 3> kHiddenLayers{10u, 14u, 18u};
|
||||||
|
inline constexpr float kDefaultSpread = 0.6f;
|
||||||
|
inline constexpr float kDefaultLearningRate = 1.0f;
|
||||||
|
inline constexpr std::size_t kDefaultMaxIterations = 1000u;
|
||||||
|
} // namespace ext_synth_defaults
|
||||||
|
|
||||||
|
// The net-shape alias every instantiation uses (mirrors S6/S25's per-mode
|
||||||
|
// `<Mode>MLP` codegen alias, generalised to a template parameter since NOut
|
||||||
|
// varies per device/output-count combination).
|
||||||
|
template <std::size_t NOut>
|
||||||
|
using ExtSynthMIDIMLP = ::nisps::ml::MLP<
|
||||||
|
ext_synth_defaults::kInputSize,
|
||||||
|
ext_synth_defaults::kHiddenLayers[0],
|
||||||
|
ext_synth_defaults::kHiddenLayers[1],
|
||||||
|
ext_synth_defaults::kHiddenLayers[2],
|
||||||
|
NOut>;
|
||||||
|
|
||||||
template <const ::nisps::midi::generated::MidiDevice& Device, std::size_t NOut>
|
template <const ::nisps::midi::generated::MidiDevice& Device, std::size_t NOut>
|
||||||
class ExternalSynthMIDIMode;
|
class ExternalSynthMIDIMode;
|
||||||
|
|
||||||
|
|
@ -74,14 +118,14 @@ template <const ::nisps::midi::generated::MidiDevice& Device, std::size_t NOut =
|
||||||
class ExternalSynthMIDIMode : public ModeBase<
|
class ExternalSynthMIDIMode : public ModeBase<
|
||||||
ExternalSynthMIDIMode<Device, NOut>,
|
ExternalSynthMIDIMode<Device, NOut>,
|
||||||
NoOpEngine,
|
NoOpEngine,
|
||||||
ml::MLP<4u, 10u, 14u, 18u, NOut>,
|
ExtSynthMIDIMLP<NOut>,
|
||||||
4u> {
|
4u> {
|
||||||
static_assert(Device.params.size() >= NOut,
|
static_assert(Device.params.size() >= NOut,
|
||||||
"device template has fewer params than the mode's output count");
|
"device template has fewer params than the mode's output count");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Base = ModeBase<ExternalSynthMIDIMode<Device, NOut>, NoOpEngine,
|
using Base = ModeBase<ExternalSynthMIDIMode<Device, NOut>, NoOpEngine,
|
||||||
ml::MLP<4u, 10u, 14u, 18u, NOut>, 4u>;
|
ExtSynthMIDIMLP<NOut>, 4u>;
|
||||||
using Base::Base;
|
using Base::Base;
|
||||||
|
|
||||||
static constexpr std::string_view mode_id() noexcept { return Device.device_id; }
|
static constexpr std::string_view mode_id() noexcept { return Device.device_id; }
|
||||||
|
|
@ -129,10 +173,6 @@ class ExternalSynthMIDIMode : public ModeBase<
|
||||||
return a;
|
return a;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
static constexpr std::array<std::string_view, 4> kInputs{
|
|
||||||
std::string_view{"joy_x"}, std::string_view{"joy_y"},
|
|
||||||
std::string_view{"joy_z"}, std::string_view{"joy_w"}};
|
|
||||||
static constexpr std::array<std::size_t, 3> kHidden{10u, 14u, 18u};
|
|
||||||
static constexpr std::array<generated::Param, 0> kNoParams{};
|
static constexpr std::array<generated::Param, 0> kNoParams{};
|
||||||
static constexpr std::array<std::string_view, 0> kNoVoiceSpaces{};
|
static constexpr std::array<std::string_view, 0> kNoVoiceSpaces{};
|
||||||
static constexpr generated::UIConfig kUI{generated::PrimaryInput::Joystick, false, false};
|
static constexpr generated::UIConfig kUI{generated::PrimaryInput::Joystick, false, false};
|
||||||
|
|
@ -140,13 +180,13 @@ class ExternalSynthMIDIMode : public ModeBase<
|
||||||
static inline constexpr ParamSchema kSchema = ParamSchema{
|
static inline constexpr ParamSchema kSchema = ParamSchema{
|
||||||
Device.device_id,
|
Device.device_id,
|
||||||
std::string_view{"thru"},
|
std::string_view{"thru"},
|
||||||
std::span<const std::string_view>(kInputs),
|
std::span<const std::string_view>(ext_synth_defaults::kInputChannels),
|
||||||
4u,
|
ext_synth_defaults::kInputSize,
|
||||||
std::span<const std::size_t>(kHidden),
|
std::span<const std::size_t>(ext_synth_defaults::kHiddenLayers),
|
||||||
NOut,
|
NOut,
|
||||||
0.6f,
|
ext_synth_defaults::kDefaultSpread,
|
||||||
1.0f,
|
ext_synth_defaults::kDefaultLearningRate,
|
||||||
1000u,
|
ext_synth_defaults::kDefaultMaxIterations,
|
||||||
std::span<const generated::Param>(kNoParams),
|
std::span<const generated::Param>(kNoParams),
|
||||||
std::span<const std::string_view>(kNoVoiceSpaces),
|
std::span<const std::string_view>(kNoVoiceSpaces),
|
||||||
kUI,
|
kUI,
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#define NISPS_GENERATED_BREAKOR_SCHEMA_HPP
|
#define NISPS_GENERATED_BREAKOR_SCHEMA_HPP
|
||||||
|
|
||||||
#include "schema_types.hpp"
|
#include "schema_types.hpp"
|
||||||
|
#include "../../ml/mlp.hpp"
|
||||||
|
|
||||||
namespace nisps::modes::generated {
|
namespace nisps::modes::generated {
|
||||||
|
|
||||||
|
|
@ -547,6 +548,23 @@ inline constexpr UIConfig kBreakorUI = {
|
||||||
false,
|
false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using BreakorMLP = ::nisps::ml::MLP<kBreakorMLConfig.input_size, kBreakorHiddenLayers[0], kBreakorHiddenLayers[1], kBreakorHiddenLayers[2], kBreakorMLConfig.output_size>;
|
||||||
|
|
||||||
|
inline constexpr ::nisps::ParamSchema kBreakorSchema = {
|
||||||
|
kBreakorModeId,
|
||||||
|
kBreakorEngineId,
|
||||||
|
std::span<const std::string_view>(kBreakorInputChannels),
|
||||||
|
kBreakorMLConfig.input_size,
|
||||||
|
std::span<const std::size_t>(kBreakorHiddenLayers),
|
||||||
|
kBreakorMLConfig.output_size,
|
||||||
|
kBreakorMLConfig.default_spread,
|
||||||
|
kBreakorMLConfig.default_learning_rate,
|
||||||
|
kBreakorMLConfig.default_max_iterations,
|
||||||
|
std::span<const Param>(kBreakorParams),
|
||||||
|
std::span<const std::string_view>(kBreakorVoiceSpaces),
|
||||||
|
kBreakorUI,
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace nisps::modes::generated
|
} // namespace nisps::modes::generated
|
||||||
|
|
||||||
#endif // NISPS_GENERATED_BREAKOR_SCHEMA_HPP
|
#endif // NISPS_GENERATED_BREAKOR_SCHEMA_HPP
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#define NISPS_GENERATED_CHANNEL_STRIP_SCHEMA_HPP
|
#define NISPS_GENERATED_CHANNEL_STRIP_SCHEMA_HPP
|
||||||
|
|
||||||
#include "schema_types.hpp"
|
#include "schema_types.hpp"
|
||||||
|
#include "../../ml/mlp.hpp"
|
||||||
|
|
||||||
namespace nisps::modes::generated {
|
namespace nisps::modes::generated {
|
||||||
|
|
||||||
|
|
@ -266,6 +267,23 @@ inline constexpr UIConfig kChannelStripUI = {
|
||||||
false,
|
false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using ChannelStripMLP = ::nisps::ml::MLP<kChannelStripMLConfig.input_size, kChannelStripHiddenLayers[0], kChannelStripHiddenLayers[1], kChannelStripHiddenLayers[2], kChannelStripMLConfig.output_size>;
|
||||||
|
|
||||||
|
inline constexpr ::nisps::ParamSchema kChannelStripSchema = {
|
||||||
|
kChannelStripModeId,
|
||||||
|
kChannelStripEngineId,
|
||||||
|
std::span<const std::string_view>(kChannelStripInputChannels),
|
||||||
|
kChannelStripMLConfig.input_size,
|
||||||
|
std::span<const std::size_t>(kChannelStripHiddenLayers),
|
||||||
|
kChannelStripMLConfig.output_size,
|
||||||
|
kChannelStripMLConfig.default_spread,
|
||||||
|
kChannelStripMLConfig.default_learning_rate,
|
||||||
|
kChannelStripMLConfig.default_max_iterations,
|
||||||
|
std::span<const Param>(kChannelStripParams),
|
||||||
|
std::span<const std::string_view>(kChannelStripVoiceSpaces),
|
||||||
|
kChannelStripUI,
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace nisps::modes::generated
|
} // namespace nisps::modes::generated
|
||||||
|
|
||||||
#endif // NISPS_GENERATED_CHANNEL_STRIP_SCHEMA_HPP
|
#endif // NISPS_GENERATED_CHANNEL_STRIP_SCHEMA_HPP
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#define NISPS_GENERATED_ELYSIAMORF_SCHEMA_HPP
|
#define NISPS_GENERATED_ELYSIAMORF_SCHEMA_HPP
|
||||||
|
|
||||||
#include "schema_types.hpp"
|
#include "schema_types.hpp"
|
||||||
|
#include "../../ml/mlp.hpp"
|
||||||
|
|
||||||
namespace nisps::modes::generated {
|
namespace nisps::modes::generated {
|
||||||
|
|
||||||
|
|
@ -403,6 +404,23 @@ inline constexpr UIConfig kElysiamorfUI = {
|
||||||
false,
|
false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using ElysiamorfMLP = ::nisps::ml::MLP<kElysiamorfMLConfig.input_size, kElysiamorfHiddenLayers[0], kElysiamorfHiddenLayers[1], kElysiamorfHiddenLayers[2], kElysiamorfMLConfig.output_size>;
|
||||||
|
|
||||||
|
inline constexpr ::nisps::ParamSchema kElysiamorfSchema = {
|
||||||
|
kElysiamorfModeId,
|
||||||
|
kElysiamorfEngineId,
|
||||||
|
std::span<const std::string_view>(kElysiamorfInputChannels),
|
||||||
|
kElysiamorfMLConfig.input_size,
|
||||||
|
std::span<const std::size_t>(kElysiamorfHiddenLayers),
|
||||||
|
kElysiamorfMLConfig.output_size,
|
||||||
|
kElysiamorfMLConfig.default_spread,
|
||||||
|
kElysiamorfMLConfig.default_learning_rate,
|
||||||
|
kElysiamorfMLConfig.default_max_iterations,
|
||||||
|
std::span<const Param>(kElysiamorfParams),
|
||||||
|
std::span<const std::string_view>(kElysiamorfVoiceSpaces),
|
||||||
|
kElysiamorfUI,
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace nisps::modes::generated
|
} // namespace nisps::modes::generated
|
||||||
|
|
||||||
#endif // NISPS_GENERATED_ELYSIAMORF_SCHEMA_HPP
|
#endif // NISPS_GENERATED_ELYSIAMORF_SCHEMA_HPP
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#define NISPS_GENERATED_MEMLCELIUM_SCHEMA_HPP
|
#define NISPS_GENERATED_MEMLCELIUM_SCHEMA_HPP
|
||||||
|
|
||||||
#include "schema_types.hpp"
|
#include "schema_types.hpp"
|
||||||
|
#include "../../ml/mlp.hpp"
|
||||||
|
|
||||||
namespace nisps::modes::generated {
|
namespace nisps::modes::generated {
|
||||||
|
|
||||||
|
|
@ -549,6 +550,23 @@ inline constexpr UIConfig kMemlceliumUI = {
|
||||||
true,
|
true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using MemlceliumMLP = ::nisps::ml::MLP<kMemlceliumMLConfig.input_size, kMemlceliumHiddenLayers[0], kMemlceliumHiddenLayers[1], kMemlceliumHiddenLayers[2], kMemlceliumMLConfig.output_size>;
|
||||||
|
|
||||||
|
inline constexpr ::nisps::ParamSchema kMemlceliumSchema = {
|
||||||
|
kMemlceliumModeId,
|
||||||
|
kMemlceliumEngineId,
|
||||||
|
std::span<const std::string_view>(kMemlceliumInputChannels),
|
||||||
|
kMemlceliumMLConfig.input_size,
|
||||||
|
std::span<const std::size_t>(kMemlceliumHiddenLayers),
|
||||||
|
kMemlceliumMLConfig.output_size,
|
||||||
|
kMemlceliumMLConfig.default_spread,
|
||||||
|
kMemlceliumMLConfig.default_learning_rate,
|
||||||
|
kMemlceliumMLConfig.default_max_iterations,
|
||||||
|
std::span<const Param>(kMemlceliumParams),
|
||||||
|
std::span<const std::string_view>(kMemlceliumVoiceSpaces),
|
||||||
|
kMemlceliumUI,
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace nisps::modes::generated
|
} // namespace nisps::modes::generated
|
||||||
|
|
||||||
#endif // NISPS_GENERATED_MEMLCELIUM_SCHEMA_HPP
|
#endif // NISPS_GENERATED_MEMLCELIUM_SCHEMA_HPP
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#define NISPS_GENERATED_PAF_SYNTH_SCHEMA_HPP
|
#define NISPS_GENERATED_PAF_SYNTH_SCHEMA_HPP
|
||||||
|
|
||||||
#include "schema_types.hpp"
|
#include "schema_types.hpp"
|
||||||
|
#include "../../ml/mlp.hpp"
|
||||||
|
|
||||||
namespace nisps::modes::generated {
|
namespace nisps::modes::generated {
|
||||||
|
|
||||||
|
|
@ -348,6 +349,23 @@ inline constexpr UIConfig kPafSynthUI = {
|
||||||
true,
|
true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using PafSynthMLP = ::nisps::ml::MLP<kPafSynthMLConfig.input_size, kPafSynthHiddenLayers[0], kPafSynthHiddenLayers[1], kPafSynthHiddenLayers[2], kPafSynthMLConfig.output_size>;
|
||||||
|
|
||||||
|
inline constexpr ::nisps::ParamSchema kPafSynthSchema = {
|
||||||
|
kPafSynthModeId,
|
||||||
|
kPafSynthEngineId,
|
||||||
|
std::span<const std::string_view>(kPafSynthInputChannels),
|
||||||
|
kPafSynthMLConfig.input_size,
|
||||||
|
std::span<const std::size_t>(kPafSynthHiddenLayers),
|
||||||
|
kPafSynthMLConfig.output_size,
|
||||||
|
kPafSynthMLConfig.default_spread,
|
||||||
|
kPafSynthMLConfig.default_learning_rate,
|
||||||
|
kPafSynthMLConfig.default_max_iterations,
|
||||||
|
std::span<const Param>(kPafSynthParams),
|
||||||
|
std::span<const std::string_view>(kPafSynthVoiceSpaces),
|
||||||
|
kPafSynthUI,
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace nisps::modes::generated
|
} // namespace nisps::modes::generated
|
||||||
|
|
||||||
#endif // NISPS_GENERATED_PAF_SYNTH_SCHEMA_HPP
|
#endif // NISPS_GENERATED_PAF_SYNTH_SCHEMA_HPP
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,18 @@
|
||||||
//
|
//
|
||||||
// `Curve` is the authoritative enum from nisps/core/math.hpp; we re-export it
|
// `Curve` is the authoritative enum from nisps/core/math.hpp; we re-export it
|
||||||
// into this namespace so generated headers can refer to plain `Curve::linear`.
|
// into this namespace so generated headers can refer to plain `Curve::linear`.
|
||||||
|
//
|
||||||
|
// `ParamSchema` lives in the top-level `nisps` namespace, not
|
||||||
|
// `nisps::modes::generated`: nisps/core/concepts.hpp forward-declares
|
||||||
|
// `nisps::ParamSchema` and requires `T::param_schema()` to return
|
||||||
|
// `const nisps::ParamSchema&`, so the definition has to match that
|
||||||
|
// forward declaration exactly (S5, one-core simplification 2026-07).
|
||||||
#ifndef NISPS_GENERATED_SCHEMA_TYPES_HPP
|
#ifndef NISPS_GENERATED_SCHEMA_TYPES_HPP
|
||||||
#define NISPS_GENERATED_SCHEMA_TYPES_HPP
|
#define NISPS_GENERATED_SCHEMA_TYPES_HPP
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <span>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include "../../core/math.hpp"
|
#include "../../core/math.hpp"
|
||||||
|
|
@ -51,4 +58,28 @@ struct UIConfig {
|
||||||
|
|
||||||
} // namespace nisps::modes::generated
|
} // namespace nisps::modes::generated
|
||||||
|
|
||||||
|
namespace nisps {
|
||||||
|
|
||||||
|
// View-style aggregate satisfying the `nisps::Mode` concept's
|
||||||
|
// `param_schema()` requirement. All members are spans/views into
|
||||||
|
// compile-time generated arrays; codegen emits one
|
||||||
|
// `inline constexpr ParamSchema k<Mode>Schema` per mode (see the
|
||||||
|
// per-mode <mode_id>_schema.hpp in this directory).
|
||||||
|
struct ParamSchema {
|
||||||
|
std::string_view mode_id;
|
||||||
|
std::string_view engine_id;
|
||||||
|
std::span<const std::string_view> input_channels;
|
||||||
|
std::size_t input_size;
|
||||||
|
std::span<const std::size_t> hidden_layers;
|
||||||
|
std::size_t output_size;
|
||||||
|
float default_spread;
|
||||||
|
float default_learning_rate;
|
||||||
|
std::size_t default_max_iterations;
|
||||||
|
std::span<const ::nisps::modes::generated::Param> params;
|
||||||
|
std::span<const std::string_view> voice_spaces;
|
||||||
|
::nisps::modes::generated::UIConfig ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace nisps
|
||||||
|
|
||||||
#endif // NISPS_GENERATED_SCHEMA_TYPES_HPP
|
#endif // NISPS_GENERATED_SCHEMA_TYPES_HPP
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#define NISPS_GENERATED_SLP_WORKSHOP_SCHEMA_HPP
|
#define NISPS_GENERATED_SLP_WORKSHOP_SCHEMA_HPP
|
||||||
|
|
||||||
#include "schema_types.hpp"
|
#include "schema_types.hpp"
|
||||||
|
#include "../../ml/mlp.hpp"
|
||||||
|
|
||||||
namespace nisps::modes::generated {
|
namespace nisps::modes::generated {
|
||||||
|
|
||||||
|
|
@ -549,6 +550,23 @@ inline constexpr UIConfig kSlpWorkshopUI = {
|
||||||
true,
|
true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using SlpWorkshopMLP = ::nisps::ml::MLP<kSlpWorkshopMLConfig.input_size, kSlpWorkshopHiddenLayers[0], kSlpWorkshopHiddenLayers[1], kSlpWorkshopHiddenLayers[2], kSlpWorkshopMLConfig.output_size>;
|
||||||
|
|
||||||
|
inline constexpr ::nisps::ParamSchema kSlpWorkshopSchema = {
|
||||||
|
kSlpWorkshopModeId,
|
||||||
|
kSlpWorkshopEngineId,
|
||||||
|
std::span<const std::string_view>(kSlpWorkshopInputChannels),
|
||||||
|
kSlpWorkshopMLConfig.input_size,
|
||||||
|
std::span<const std::size_t>(kSlpWorkshopHiddenLayers),
|
||||||
|
kSlpWorkshopMLConfig.output_size,
|
||||||
|
kSlpWorkshopMLConfig.default_spread,
|
||||||
|
kSlpWorkshopMLConfig.default_learning_rate,
|
||||||
|
kSlpWorkshopMLConfig.default_max_iterations,
|
||||||
|
std::span<const Param>(kSlpWorkshopParams),
|
||||||
|
std::span<const std::string_view>(kSlpWorkshopVoiceSpaces),
|
||||||
|
kSlpWorkshopUI,
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace nisps::modes::generated
|
} // namespace nisps::modes::generated
|
||||||
|
|
||||||
#endif // NISPS_GENERATED_SLP_WORKSHOP_SCHEMA_HPP
|
#endif // NISPS_GENERATED_SLP_WORKSHOP_SCHEMA_HPP
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#define NISPS_GENERATED_SOUND_ANALYSIS_MIDI_SCHEMA_HPP
|
#define NISPS_GENERATED_SOUND_ANALYSIS_MIDI_SCHEMA_HPP
|
||||||
|
|
||||||
#include "schema_types.hpp"
|
#include "schema_types.hpp"
|
||||||
|
#include "../../ml/mlp.hpp"
|
||||||
|
|
||||||
namespace nisps::modes::generated {
|
namespace nisps::modes::generated {
|
||||||
|
|
||||||
|
|
@ -121,6 +122,23 @@ inline constexpr UIConfig kSoundAnalysisMidiUI = {
|
||||||
false,
|
false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using SoundAnalysisMidiMLP = ::nisps::ml::MLP<kSoundAnalysisMidiMLConfig.input_size, kSoundAnalysisMidiHiddenLayers[0], kSoundAnalysisMidiHiddenLayers[1], kSoundAnalysisMidiHiddenLayers[2], kSoundAnalysisMidiMLConfig.output_size>;
|
||||||
|
|
||||||
|
inline constexpr ::nisps::ParamSchema kSoundAnalysisMidiSchema = {
|
||||||
|
kSoundAnalysisMidiModeId,
|
||||||
|
kSoundAnalysisMidiEngineId,
|
||||||
|
std::span<const std::string_view>(kSoundAnalysisMidiInputChannels),
|
||||||
|
kSoundAnalysisMidiMLConfig.input_size,
|
||||||
|
std::span<const std::size_t>(kSoundAnalysisMidiHiddenLayers),
|
||||||
|
kSoundAnalysisMidiMLConfig.output_size,
|
||||||
|
kSoundAnalysisMidiMLConfig.default_spread,
|
||||||
|
kSoundAnalysisMidiMLConfig.default_learning_rate,
|
||||||
|
kSoundAnalysisMidiMLConfig.default_max_iterations,
|
||||||
|
std::span<const Param>(kSoundAnalysisMidiParams),
|
||||||
|
std::span<const std::string_view>(kSoundAnalysisMidiVoiceSpaces),
|
||||||
|
kSoundAnalysisMidiUI,
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace nisps::modes::generated
|
} // namespace nisps::modes::generated
|
||||||
|
|
||||||
#endif // NISPS_GENERATED_SOUND_ANALYSIS_MIDI_SCHEMA_HPP
|
#endif // NISPS_GENERATED_SOUND_ANALYSIS_MIDI_SCHEMA_HPP
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#define NISPS_GENERATED_VERB_FX_SCHEMA_HPP
|
#define NISPS_GENERATED_VERB_FX_SCHEMA_HPP
|
||||||
|
|
||||||
#include "schema_types.hpp"
|
#include "schema_types.hpp"
|
||||||
|
#include "../../ml/mlp.hpp"
|
||||||
|
|
||||||
namespace nisps::modes::generated {
|
namespace nisps::modes::generated {
|
||||||
|
|
||||||
|
|
@ -479,6 +480,23 @@ inline constexpr UIConfig kVerbFxUI = {
|
||||||
false,
|
false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using VerbFxMLP = ::nisps::ml::MLP<kVerbFxMLConfig.input_size, kVerbFxHiddenLayers[0], kVerbFxHiddenLayers[1], kVerbFxHiddenLayers[2], kVerbFxMLConfig.output_size>;
|
||||||
|
|
||||||
|
inline constexpr ::nisps::ParamSchema kVerbFxSchema = {
|
||||||
|
kVerbFxModeId,
|
||||||
|
kVerbFxEngineId,
|
||||||
|
std::span<const std::string_view>(kVerbFxInputChannels),
|
||||||
|
kVerbFxMLConfig.input_size,
|
||||||
|
std::span<const std::size_t>(kVerbFxHiddenLayers),
|
||||||
|
kVerbFxMLConfig.output_size,
|
||||||
|
kVerbFxMLConfig.default_spread,
|
||||||
|
kVerbFxMLConfig.default_learning_rate,
|
||||||
|
kVerbFxMLConfig.default_max_iterations,
|
||||||
|
std::span<const Param>(kVerbFxParams),
|
||||||
|
std::span<const std::string_view>(kVerbFxVoiceSpaces),
|
||||||
|
kVerbFxUI,
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace nisps::modes::generated
|
} // namespace nisps::modes::generated
|
||||||
|
|
||||||
#endif // NISPS_GENERATED_VERB_FX_SCHEMA_HPP
|
#endif // NISPS_GENERATED_VERB_FX_SCHEMA_HPP
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#define NISPS_GENERATED_XIASRI_SCHEMA_HPP
|
#define NISPS_GENERATED_XIASRI_SCHEMA_HPP
|
||||||
|
|
||||||
#include "schema_types.hpp"
|
#include "schema_types.hpp"
|
||||||
|
#include "../../ml/mlp.hpp"
|
||||||
|
|
||||||
namespace nisps::modes::generated {
|
namespace nisps::modes::generated {
|
||||||
|
|
||||||
|
|
@ -261,6 +262,23 @@ inline constexpr UIConfig kXiasriUI = {
|
||||||
false,
|
false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using XiasriMLP = ::nisps::ml::MLP<kXiasriMLConfig.input_size, kXiasriHiddenLayers[0], kXiasriHiddenLayers[1], kXiasriHiddenLayers[2], kXiasriMLConfig.output_size>;
|
||||||
|
|
||||||
|
inline constexpr ::nisps::ParamSchema kXiasriSchema = {
|
||||||
|
kXiasriModeId,
|
||||||
|
kXiasriEngineId,
|
||||||
|
std::span<const std::string_view>(kXiasriInputChannels),
|
||||||
|
kXiasriMLConfig.input_size,
|
||||||
|
std::span<const std::size_t>(kXiasriHiddenLayers),
|
||||||
|
kXiasriMLConfig.output_size,
|
||||||
|
kXiasriMLConfig.default_spread,
|
||||||
|
kXiasriMLConfig.default_learning_rate,
|
||||||
|
kXiasriMLConfig.default_max_iterations,
|
||||||
|
std::span<const Param>(kXiasriParams),
|
||||||
|
std::span<const std::string_view>(kXiasriVoiceSpaces),
|
||||||
|
kXiasriUI,
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace nisps::modes::generated
|
} // namespace nisps::modes::generated
|
||||||
|
|
||||||
#endif // NISPS_GENERATED_XIASRI_SCHEMA_HPP
|
#endif // NISPS_GENERATED_XIASRI_SCHEMA_HPP
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
#include "../core/perf.hpp"
|
#include "../core/perf.hpp"
|
||||||
#include "../core/types.hpp"
|
#include "../core/types.hpp"
|
||||||
#include "../engines/memlcelium.hpp"
|
#include "../engines/memlcelium.hpp"
|
||||||
#include "../ml/mlp.hpp"
|
|
||||||
#include "base.hpp"
|
#include "base.hpp"
|
||||||
#include "generated/memlcelium_schema.hpp"
|
#include "generated/memlcelium_schema.hpp"
|
||||||
|
|
||||||
|
|
@ -25,17 +24,19 @@ namespace nisps::modes {
|
||||||
class MEMLCeliumMode : public ModeBase<
|
class MEMLCeliumMode : public ModeBase<
|
||||||
MEMLCeliumMode,
|
MEMLCeliumMode,
|
||||||
MEMLCeliumEngine,
|
MEMLCeliumEngine,
|
||||||
ml::MLP<4u, 10u, 14u, 18u, 56u>,
|
generated::MemlceliumMLP,
|
||||||
4u> {
|
4u> {
|
||||||
public:
|
public:
|
||||||
using Base = ModeBase<MEMLCeliumMode, MEMLCeliumEngine,
|
using Base = ModeBase<MEMLCeliumMode, MEMLCeliumEngine,
|
||||||
ml::MLP<4u, 10u, 14u, 18u, 56u>, 4u>;
|
generated::MemlceliumMLP, 4u>;
|
||||||
using Base::Base;
|
using Base::Base;
|
||||||
|
|
||||||
static constexpr std::string_view mode_id() noexcept {
|
static constexpr std::string_view mode_id() noexcept {
|
||||||
return generated::kMemlceliumModeId;
|
return generated::kMemlceliumModeId;
|
||||||
}
|
}
|
||||||
static constexpr const ParamSchema& param_schema() noexcept { return kSchema; }
|
static constexpr const ParamSchema& param_schema() noexcept {
|
||||||
|
return generated::kMemlceliumSchema;
|
||||||
|
}
|
||||||
|
|
||||||
NISPS_FORCE_INLINE void set_playing(bool playing) noexcept {
|
NISPS_FORCE_INLINE void set_playing(bool playing) noexcept {
|
||||||
engine_.set_playing(playing);
|
engine_.set_playing(playing);
|
||||||
|
|
@ -43,22 +44,6 @@ class MEMLCeliumMode : public ModeBase<
|
||||||
NISPS_FORCE_INLINE void update_bpm(float bpm) noexcept {
|
NISPS_FORCE_INLINE void update_bpm(float bpm) noexcept {
|
||||||
engine_.update_bpm(bpm);
|
engine_.update_bpm(bpm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
static inline constexpr ParamSchema kSchema = ParamSchema{
|
|
||||||
generated::kMemlceliumModeId,
|
|
||||||
generated::kMemlceliumEngineId,
|
|
||||||
std::span<const std::string_view>(generated::kMemlceliumInputChannels),
|
|
||||||
generated::kMemlceliumMLConfig.input_size,
|
|
||||||
std::span<const std::size_t>(generated::kMemlceliumHiddenLayers),
|
|
||||||
generated::kMemlceliumMLConfig.output_size,
|
|
||||||
generated::kMemlceliumMLConfig.default_spread,
|
|
||||||
generated::kMemlceliumMLConfig.default_learning_rate,
|
|
||||||
generated::kMemlceliumMLConfig.default_max_iterations,
|
|
||||||
std::span<const generated::Param>(generated::kMemlceliumParams),
|
|
||||||
std::span<const std::string_view>(generated::kMemlceliumVoiceSpaces),
|
|
||||||
generated::kMemlceliumUI,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(Mode<MEMLCeliumMode>, "MEMLCeliumMode must satisfy nisps::Mode");
|
static_assert(Mode<MEMLCeliumMode>, "MEMLCeliumMode must satisfy nisps::Mode");
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@
|
||||||
#include "../core/perf.hpp"
|
#include "../core/perf.hpp"
|
||||||
#include "../core/types.hpp"
|
#include "../core/types.hpp"
|
||||||
#include "../engines/paf_synth.hpp"
|
#include "../engines/paf_synth.hpp"
|
||||||
#include "../ml/mlp.hpp"
|
|
||||||
#include "base.hpp"
|
#include "base.hpp"
|
||||||
#include "generated/paf_synth_schema.hpp"
|
#include "generated/paf_synth_schema.hpp"
|
||||||
|
|
||||||
|
|
@ -28,18 +27,20 @@ namespace nisps::modes {
|
||||||
class PAFSynthMode : public ModeBase<
|
class PAFSynthMode : public ModeBase<
|
||||||
PAFSynthMode,
|
PAFSynthMode,
|
||||||
PAFSynthEngine,
|
PAFSynthEngine,
|
||||||
ml::MLP<4u, 10u, 10u, 14u, 33u>,
|
generated::PafSynthMLP,
|
||||||
4u> {
|
4u> {
|
||||||
public:
|
public:
|
||||||
using Base = ModeBase<PAFSynthMode, PAFSynthEngine,
|
using Base = ModeBase<PAFSynthMode, PAFSynthEngine,
|
||||||
ml::MLP<4u, 10u, 10u, 14u, 33u>, 4u>;
|
generated::PafSynthMLP, 4u>;
|
||||||
using Base::Base;
|
using Base::Base;
|
||||||
|
|
||||||
// ---- Concept-required statics ----
|
// ---- Concept-required statics ----
|
||||||
static constexpr std::string_view mode_id() noexcept {
|
static constexpr std::string_view mode_id() noexcept {
|
||||||
return generated::kPafSynthModeId;
|
return generated::kPafSynthModeId;
|
||||||
}
|
}
|
||||||
static constexpr const ParamSchema& param_schema() noexcept { return kSchema; }
|
static constexpr const ParamSchema& param_schema() noexcept {
|
||||||
|
return generated::kPafSynthSchema;
|
||||||
|
}
|
||||||
|
|
||||||
// ---- Mode-specific control glue ----
|
// ---- Mode-specific control glue ----
|
||||||
NISPS_FORCE_INLINE void note_on(std::uint8_t note, std::uint8_t velocity) noexcept {
|
NISPS_FORCE_INLINE void note_on(std::uint8_t note, std::uint8_t velocity) noexcept {
|
||||||
|
|
@ -48,22 +49,6 @@ class PAFSynthMode : public ModeBase<
|
||||||
NISPS_FORCE_INLINE void note_off(std::uint8_t note) noexcept {
|
NISPS_FORCE_INLINE void note_off(std::uint8_t note) noexcept {
|
||||||
engine_.note_off(note);
|
engine_.note_off(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
static inline constexpr ParamSchema kSchema = ParamSchema{
|
|
||||||
generated::kPafSynthModeId,
|
|
||||||
generated::kPafSynthEngineId,
|
|
||||||
std::span<const std::string_view>(generated::kPafSynthInputChannels),
|
|
||||||
generated::kPafSynthMLConfig.input_size,
|
|
||||||
std::span<const std::size_t>(generated::kPafSynthHiddenLayers),
|
|
||||||
generated::kPafSynthMLConfig.output_size,
|
|
||||||
generated::kPafSynthMLConfig.default_spread,
|
|
||||||
generated::kPafSynthMLConfig.default_learning_rate,
|
|
||||||
generated::kPafSynthMLConfig.default_max_iterations,
|
|
||||||
std::span<const generated::Param>(generated::kPafSynthParams),
|
|
||||||
std::span<const std::string_view>(generated::kPafSynthVoiceSpaces),
|
|
||||||
generated::kPafSynthUI,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(Mode<PAFSynthMode>, "PAFSynthMode must satisfy nisps::Mode");
|
static_assert(Mode<PAFSynthMode>, "PAFSynthMode must satisfy nisps::Mode");
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@
|
||||||
#include "../core/perf.hpp"
|
#include "../core/perf.hpp"
|
||||||
#include "../core/types.hpp"
|
#include "../core/types.hpp"
|
||||||
#include "../engines/memlcelium.hpp"
|
#include "../engines/memlcelium.hpp"
|
||||||
#include "../ml/mlp.hpp"
|
|
||||||
#include "base.hpp"
|
#include "base.hpp"
|
||||||
#include "generated/slp_workshop_schema.hpp"
|
#include "generated/slp_workshop_schema.hpp"
|
||||||
|
|
||||||
|
|
@ -37,17 +36,19 @@ namespace nisps::modes {
|
||||||
class SLPWorkshopMode : public ModeBase<
|
class SLPWorkshopMode : public ModeBase<
|
||||||
SLPWorkshopMode,
|
SLPWorkshopMode,
|
||||||
MEMLCeliumEngine,
|
MEMLCeliumEngine,
|
||||||
ml::MLP<4u, 10u, 14u, 18u, 56u>,
|
generated::SlpWorkshopMLP,
|
||||||
4u> {
|
4u> {
|
||||||
public:
|
public:
|
||||||
using Base = ModeBase<SLPWorkshopMode, MEMLCeliumEngine,
|
using Base = ModeBase<SLPWorkshopMode, MEMLCeliumEngine,
|
||||||
ml::MLP<4u, 10u, 14u, 18u, 56u>, 4u>;
|
generated::SlpWorkshopMLP, 4u>;
|
||||||
using Base::Base;
|
using Base::Base;
|
||||||
|
|
||||||
static constexpr std::string_view mode_id() noexcept {
|
static constexpr std::string_view mode_id() noexcept {
|
||||||
return generated::kSlpWorkshopModeId;
|
return generated::kSlpWorkshopModeId;
|
||||||
}
|
}
|
||||||
static constexpr const ParamSchema& param_schema() noexcept { return kSchema; }
|
static constexpr const ParamSchema& param_schema() noexcept {
|
||||||
|
return generated::kSlpWorkshopSchema;
|
||||||
|
}
|
||||||
|
|
||||||
NISPS_FORCE_INLINE void set_playing(bool playing) noexcept {
|
NISPS_FORCE_INLINE void set_playing(bool playing) noexcept {
|
||||||
engine_.set_playing(playing);
|
engine_.set_playing(playing);
|
||||||
|
|
@ -55,22 +56,6 @@ class SLPWorkshopMode : public ModeBase<
|
||||||
NISPS_FORCE_INLINE void update_bpm(float bpm) noexcept {
|
NISPS_FORCE_INLINE void update_bpm(float bpm) noexcept {
|
||||||
engine_.update_bpm(bpm);
|
engine_.update_bpm(bpm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
static inline constexpr ParamSchema kSchema = ParamSchema{
|
|
||||||
generated::kSlpWorkshopModeId,
|
|
||||||
generated::kSlpWorkshopEngineId,
|
|
||||||
std::span<const std::string_view>(generated::kSlpWorkshopInputChannels),
|
|
||||||
generated::kSlpWorkshopMLConfig.input_size,
|
|
||||||
std::span<const std::size_t>(generated::kSlpWorkshopHiddenLayers),
|
|
||||||
generated::kSlpWorkshopMLConfig.output_size,
|
|
||||||
generated::kSlpWorkshopMLConfig.default_spread,
|
|
||||||
generated::kSlpWorkshopMLConfig.default_learning_rate,
|
|
||||||
generated::kSlpWorkshopMLConfig.default_max_iterations,
|
|
||||||
std::span<const generated::Param>(generated::kSlpWorkshopParams),
|
|
||||||
std::span<const std::string_view>(generated::kSlpWorkshopVoiceSpaces),
|
|
||||||
generated::kSlpWorkshopUI,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(Mode<SLPWorkshopMode>, "SLPWorkshopMode must satisfy nisps::Mode");
|
static_assert(Mode<SLPWorkshopMode>, "SLPWorkshopMode must satisfy nisps::Mode");
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@
|
||||||
#include "../core/types.hpp"
|
#include "../core/types.hpp"
|
||||||
#include "../engines/analysis.hpp"
|
#include "../engines/analysis.hpp"
|
||||||
#include "../engines/base.hpp" // NoOpEngine
|
#include "../engines/base.hpp" // NoOpEngine
|
||||||
#include "../ml/mlp.hpp"
|
|
||||||
#include "base.hpp"
|
#include "base.hpp"
|
||||||
#include "generated/sound_analysis_midi_schema.hpp"
|
#include "generated/sound_analysis_midi_schema.hpp"
|
||||||
|
|
||||||
|
|
@ -48,17 +47,19 @@ namespace nisps::modes {
|
||||||
class SoundAnalysisMIDIMode : public ModeBase<
|
class SoundAnalysisMIDIMode : public ModeBase<
|
||||||
SoundAnalysisMIDIMode,
|
SoundAnalysisMIDIMode,
|
||||||
NoOpEngine,
|
NoOpEngine,
|
||||||
ml::MLP<10u, 10u, 10u, 14u, 8u>,
|
generated::SoundAnalysisMidiMLP,
|
||||||
10u> {
|
10u> {
|
||||||
public:
|
public:
|
||||||
using Base = ModeBase<SoundAnalysisMIDIMode, NoOpEngine,
|
using Base = ModeBase<SoundAnalysisMIDIMode, NoOpEngine,
|
||||||
ml::MLP<10u, 10u, 10u, 14u, 8u>, 10u>;
|
generated::SoundAnalysisMidiMLP, 10u>;
|
||||||
using Base::Base;
|
using Base::Base;
|
||||||
|
|
||||||
static constexpr std::string_view mode_id() noexcept {
|
static constexpr std::string_view mode_id() noexcept {
|
||||||
return generated::kSoundAnalysisMidiModeId;
|
return generated::kSoundAnalysisMidiModeId;
|
||||||
}
|
}
|
||||||
static constexpr const ParamSchema& param_schema() noexcept { return kSchema; }
|
static constexpr const ParamSchema& param_schema() noexcept {
|
||||||
|
return generated::kSoundAnalysisMidiSchema;
|
||||||
|
}
|
||||||
|
|
||||||
void on_setup(float sample_rate) noexcept {
|
void on_setup(float sample_rate) noexcept {
|
||||||
analysis_.setup(sample_rate);
|
analysis_.setup(sample_rate);
|
||||||
|
|
@ -107,21 +108,6 @@ class SoundAnalysisMIDIMode : public ModeBase<
|
||||||
static constexpr std::size_t kCCCount = 8u;
|
static constexpr std::size_t kCCCount = 8u;
|
||||||
|
|
||||||
AnalysisEngine analysis_{};
|
AnalysisEngine analysis_{};
|
||||||
|
|
||||||
static inline constexpr ParamSchema kSchema = ParamSchema{
|
|
||||||
generated::kSoundAnalysisMidiModeId,
|
|
||||||
generated::kSoundAnalysisMidiEngineId,
|
|
||||||
std::span<const std::string_view>(generated::kSoundAnalysisMidiInputChannels),
|
|
||||||
generated::kSoundAnalysisMidiMLConfig.input_size,
|
|
||||||
std::span<const std::size_t>(generated::kSoundAnalysisMidiHiddenLayers),
|
|
||||||
generated::kSoundAnalysisMidiMLConfig.output_size,
|
|
||||||
generated::kSoundAnalysisMidiMLConfig.default_spread,
|
|
||||||
generated::kSoundAnalysisMidiMLConfig.default_learning_rate,
|
|
||||||
generated::kSoundAnalysisMidiMLConfig.default_max_iterations,
|
|
||||||
std::span<const generated::Param>(generated::kSoundAnalysisMidiParams),
|
|
||||||
std::span<const std::string_view>(generated::kSoundAnalysisMidiVoiceSpaces),
|
|
||||||
generated::kSoundAnalysisMidiUI,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(Mode<SoundAnalysisMIDIMode>,
|
static_assert(Mode<SoundAnalysisMIDIMode>,
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@
|
||||||
#include "../core/concepts.hpp"
|
#include "../core/concepts.hpp"
|
||||||
#include "../core/types.hpp"
|
#include "../core/types.hpp"
|
||||||
#include "../engines/verb_fx.hpp"
|
#include "../engines/verb_fx.hpp"
|
||||||
#include "../ml/mlp.hpp"
|
|
||||||
#include "base.hpp"
|
#include "base.hpp"
|
||||||
#include "generated/verb_fx_schema.hpp"
|
#include "generated/verb_fx_schema.hpp"
|
||||||
|
|
||||||
|
|
@ -21,33 +20,19 @@ namespace nisps::modes {
|
||||||
class VerbFXMode : public ModeBase<
|
class VerbFXMode : public ModeBase<
|
||||||
VerbFXMode,
|
VerbFXMode,
|
||||||
VerbFXEngine,
|
VerbFXEngine,
|
||||||
ml::MLP<4u, 10u, 14u, 18u, 47u>,
|
generated::VerbFxMLP,
|
||||||
4u> {
|
4u> {
|
||||||
public:
|
public:
|
||||||
using Base = ModeBase<VerbFXMode, VerbFXEngine,
|
using Base = ModeBase<VerbFXMode, VerbFXEngine,
|
||||||
ml::MLP<4u, 10u, 14u, 18u, 47u>, 4u>;
|
generated::VerbFxMLP, 4u>;
|
||||||
using Base::Base;
|
using Base::Base;
|
||||||
|
|
||||||
static constexpr std::string_view mode_id() noexcept {
|
static constexpr std::string_view mode_id() noexcept {
|
||||||
return generated::kVerbFxModeId;
|
return generated::kVerbFxModeId;
|
||||||
}
|
}
|
||||||
static constexpr const ParamSchema& param_schema() noexcept { return kSchema; }
|
static constexpr const ParamSchema& param_schema() noexcept {
|
||||||
|
return generated::kVerbFxSchema;
|
||||||
private:
|
}
|
||||||
static inline constexpr ParamSchema kSchema = ParamSchema{
|
|
||||||
generated::kVerbFxModeId,
|
|
||||||
generated::kVerbFxEngineId,
|
|
||||||
std::span<const std::string_view>(generated::kVerbFxInputChannels),
|
|
||||||
generated::kVerbFxMLConfig.input_size,
|
|
||||||
std::span<const std::size_t>(generated::kVerbFxHiddenLayers),
|
|
||||||
generated::kVerbFxMLConfig.output_size,
|
|
||||||
generated::kVerbFxMLConfig.default_spread,
|
|
||||||
generated::kVerbFxMLConfig.default_learning_rate,
|
|
||||||
generated::kVerbFxMLConfig.default_max_iterations,
|
|
||||||
std::span<const generated::Param>(generated::kVerbFxParams),
|
|
||||||
std::span<const std::string_view>(generated::kVerbFxVoiceSpaces),
|
|
||||||
generated::kVerbFxUI,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(Mode<VerbFXMode>, "VerbFXMode must satisfy nisps::Mode");
|
static_assert(Mode<VerbFXMode>, "VerbFXMode must satisfy nisps::Mode");
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
#include "../core/concepts.hpp"
|
#include "../core/concepts.hpp"
|
||||||
#include "../core/types.hpp"
|
#include "../core/types.hpp"
|
||||||
#include "../engines/xiasri.hpp"
|
#include "../engines/xiasri.hpp"
|
||||||
#include "../ml/mlp.hpp"
|
|
||||||
#include "base.hpp"
|
#include "base.hpp"
|
||||||
#include "generated/xiasri_schema.hpp"
|
#include "generated/xiasri_schema.hpp"
|
||||||
|
|
||||||
|
|
@ -22,33 +21,19 @@ namespace nisps::modes {
|
||||||
class XIASRIMode : public ModeBase<
|
class XIASRIMode : public ModeBase<
|
||||||
XIASRIMode,
|
XIASRIMode,
|
||||||
XIASRIEngine,
|
XIASRIEngine,
|
||||||
ml::MLP<4u, 10u, 10u, 14u, 24u>,
|
generated::XiasriMLP,
|
||||||
4u> {
|
4u> {
|
||||||
public:
|
public:
|
||||||
using Base = ModeBase<XIASRIMode, XIASRIEngine,
|
using Base = ModeBase<XIASRIMode, XIASRIEngine,
|
||||||
ml::MLP<4u, 10u, 10u, 14u, 24u>, 4u>;
|
generated::XiasriMLP, 4u>;
|
||||||
using Base::Base;
|
using Base::Base;
|
||||||
|
|
||||||
static constexpr std::string_view mode_id() noexcept {
|
static constexpr std::string_view mode_id() noexcept {
|
||||||
return generated::kXiasriModeId;
|
return generated::kXiasriModeId;
|
||||||
}
|
}
|
||||||
static constexpr const ParamSchema& param_schema() noexcept { return kSchema; }
|
static constexpr const ParamSchema& param_schema() noexcept {
|
||||||
|
return generated::kXiasriSchema;
|
||||||
private:
|
}
|
||||||
static inline constexpr ParamSchema kSchema = ParamSchema{
|
|
||||||
generated::kXiasriModeId,
|
|
||||||
generated::kXiasriEngineId,
|
|
||||||
std::span<const std::string_view>(generated::kXiasriInputChannels),
|
|
||||||
generated::kXiasriMLConfig.input_size,
|
|
||||||
std::span<const std::size_t>(generated::kXiasriHiddenLayers),
|
|
||||||
generated::kXiasriMLConfig.output_size,
|
|
||||||
generated::kXiasriMLConfig.default_spread,
|
|
||||||
generated::kXiasriMLConfig.default_learning_rate,
|
|
||||||
generated::kXiasriMLConfig.default_max_iterations,
|
|
||||||
std::span<const generated::Param>(generated::kXiasriParams),
|
|
||||||
std::span<const std::string_view>(generated::kXiasriVoiceSpaces),
|
|
||||||
generated::kXiasriUI,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(Mode<XIASRIMode>, "XIASRIMode must satisfy nisps::Mode");
|
static_assert(Mode<XIASRIMode>, "XIASRIMode must satisfy nisps::Mode");
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue