@map-audio/pam-mcp-server 1.22.0 → 1.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ export declare const MIDI_PPQ = 480;
2
+ /** Must match syncUtils::patternSpeedMultipliers (modules/dsp-core/SyncUtils.h). */
3
+ export declare const PATTERN_SPEED_MULTIPLIERS: readonly [number, number, number, number, number, number, number, number, number, 1, 1.33, 1.5, 1.66, 2, 3, 4, 5, 6, 8, 12];
4
+ export declare const patternSpeedMultiplier: (index: unknown) => number;
5
+ export interface MidiNoteEvent {
6
+ channel: number;
7
+ note: number;
8
+ velocity: number;
9
+ startBeats: number;
10
+ durationBeats: number;
11
+ }
12
+ /**
13
+ * Tile one cell's drawn pattern across `totalBeats` host beats. Event times are
14
+ * in pattern units; the speed multiplier converts them to host beats.
15
+ */
16
+ export declare function tilePatternEvents(sequence: unknown, patternLength: unknown, speedIndex: unknown, totalBeats: number, channel: number): MidiNoteEvent[];
17
+ /** A type-1 SMF: one tempo track plus one named track per entry. */
18
+ export declare function buildMidiFile(bpm: number, tracks: {
19
+ name: string;
20
+ events: MidiNoteEvent[];
21
+ }[], title?: string): Buffer;
@@ -0,0 +1,108 @@
1
+ // Standard MIDI File (type 1) writer for export_midi — pure Node over the
2
+ // pattern state, mirroring PAMPluginProcessor::exportMidi's tiling and channel rule.
3
+ export const MIDI_PPQ = 480;
4
+ /** Must match syncUtils::patternSpeedMultipliers (modules/dsp-core/SyncUtils.h). */
5
+ export const PATTERN_SPEED_MULTIPLIERS = [
6
+ 1 / 32, 1 / 16, 1 / 12, 1 / 8, 1 / 6, 1 / 5, 1 / 4, 1 / 3, 1 / 2, 1,
7
+ 1.33, 1.5, 1.66, 2, 3, 4, 5, 6, 8, 12,
8
+ ];
9
+ export const patternSpeedMultiplier = (index) => {
10
+ const i = Math.round(Number(index));
11
+ return PATTERN_SPEED_MULTIPLIERS[Number.isFinite(i) ? Math.max(0, Math.min(PATTERN_SPEED_MULTIPLIERS.length - 1, i)) : 9];
12
+ };
13
+ /**
14
+ * Tile one cell's drawn pattern across `totalBeats` host beats. Event times are
15
+ * in pattern units; the speed multiplier converts them to host beats.
16
+ */
17
+ export function tilePatternEvents(sequence, patternLength, speedIndex, totalBeats, channel) {
18
+ const events = [];
19
+ if (!Array.isArray(sequence) || sequence.length === 0)
20
+ return events;
21
+ const speedMul = patternSpeedMultiplier(speedIndex);
22
+ const length = Number(patternLength);
23
+ const cycleBeats = (Number.isFinite(length) && length > 0 ? length : 4) / speedMul;
24
+ if (!(cycleBeats > 0) || !(totalBeats > 0))
25
+ return events;
26
+ // Velocities are 0..127 in state; a pattern written in 0..1 is rescaled.
27
+ const raw = sequence;
28
+ const maxVelocity = raw.reduce((max, e) => Math.max(max, Number(e?.velocity) || 0), 0);
29
+ const velocityScale = maxVelocity > 0 && maxVelocity <= 1 ? 127 : 1;
30
+ for (let loop = 0; loop * cycleBeats < totalBeats; loop++) {
31
+ const loopStart = loop * cycleBeats;
32
+ for (const e of raw) {
33
+ const note = Math.round(Number(e?.note));
34
+ const time = Number(e?.time);
35
+ if (!Number.isFinite(note) || note < 0 || note > 127 || !Number.isFinite(time) || time < 0)
36
+ continue;
37
+ const startBeats = loopStart + time / speedMul;
38
+ if (startBeats >= totalBeats)
39
+ continue;
40
+ const duration = Number(e?.duration);
41
+ const durationBeats = Math.max(1 / 64, (Number.isFinite(duration) && duration > 0 ? duration : 0.25) / speedMul);
42
+ const velocity = Math.max(1, Math.min(127, Math.round((Number(e?.velocity) || 100) * velocityScale)));
43
+ events.push({ channel, note, velocity, startBeats, durationBeats: Math.min(durationBeats, totalBeats - startBeats) });
44
+ }
45
+ }
46
+ return events;
47
+ }
48
+ function varLen(value) {
49
+ let v = Math.max(0, Math.round(value));
50
+ const bytes = [v & 0x7f];
51
+ v >>= 7;
52
+ while (v > 0) {
53
+ bytes.unshift((v & 0x7f) | 0x80);
54
+ v >>= 7;
55
+ }
56
+ return bytes;
57
+ }
58
+ function chunk(type, body) {
59
+ const header = Buffer.alloc(8);
60
+ header.write(type, 0, "ascii");
61
+ header.writeUInt32BE(body.length, 4);
62
+ return Buffer.concat([header, Buffer.from(body)]);
63
+ }
64
+ function metaTrack(bpm, name) {
65
+ const usPerQuarter = Math.round(60_000_000 / Math.max(1, bpm));
66
+ const nameBytes = [...Buffer.from(name, "utf8")];
67
+ const body = [
68
+ ...varLen(0), 0xff, 0x03, ...varLen(nameBytes.length), ...nameBytes,
69
+ ...varLen(0), 0xff, 0x51, 0x03, (usPerQuarter >> 16) & 0xff, (usPerQuarter >> 8) & 0xff, usPerQuarter & 0xff,
70
+ ...varLen(0), 0xff, 0x58, 0x04, 4, 2, 24, 8,
71
+ ...varLen(0), 0xff, 0x2f, 0x00,
72
+ ];
73
+ return chunk("MTrk", body);
74
+ }
75
+ function noteTrack(name, events) {
76
+ const messages = [];
77
+ for (const e of events) {
78
+ const status = Math.max(0, Math.min(15, e.channel - 1));
79
+ const on = Math.round(e.startBeats * MIDI_PPQ);
80
+ const off = Math.max(on + 1, Math.round((e.startBeats + e.durationBeats) * MIDI_PPQ));
81
+ // Note-offs sort before note-ons at the same tick so a retrigger is not swallowed.
82
+ messages.push({ tick: off, order: 0, bytes: [0x80 | status, e.note, 0] });
83
+ messages.push({ tick: on, order: 1, bytes: [0x90 | status, e.note, e.velocity] });
84
+ }
85
+ messages.sort((a, b) => a.tick - b.tick || a.order - b.order);
86
+ const nameBytes = [...Buffer.from(name, "utf8")];
87
+ const body = [...varLen(0), 0xff, 0x03, ...varLen(nameBytes.length), ...nameBytes];
88
+ let last = 0;
89
+ for (const m of messages) {
90
+ body.push(...varLen(m.tick - last), ...m.bytes);
91
+ last = m.tick;
92
+ }
93
+ body.push(...varLen(0), 0xff, 0x2f, 0x00);
94
+ return chunk("MTrk", body);
95
+ }
96
+ /** A type-1 SMF: one tempo track plus one named track per entry. */
97
+ export function buildMidiFile(bpm, tracks, title = "PAM") {
98
+ const header = Buffer.alloc(6);
99
+ header.writeUInt16BE(1, 0);
100
+ header.writeUInt16BE(tracks.length + 1, 2);
101
+ header.writeUInt16BE(MIDI_PPQ, 4);
102
+ return Buffer.concat([
103
+ chunk("MThd", [...header]),
104
+ metaTrack(bpm, title),
105
+ ...tracks.map((track) => noteTrack(track.name, track.events)),
106
+ ]);
107
+ }
108
+ //# sourceMappingURL=midiFile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"midiFile.js","sourceRoot":"","sources":["../src/midiFile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ export interface PlayerSlotSpec {
2
+ label: string;
3
+ default: number;
4
+ steps?: number;
5
+ stepLabels?: string[];
6
+ hint?: string;
7
+ center?: boolean;
8
+ }
9
+ export interface PlayerSpec {
10
+ id: number;
11
+ name: string;
12
+ tag: "drum" | "melodic" | "both";
13
+ replay: boolean;
14
+ blurb: string;
15
+ defaults: {
16
+ density: number;
17
+ mutate: number;
18
+ };
19
+ slots: PlayerSlotSpec[];
20
+ }
21
+ export interface PlayerPreset {
22
+ name: string;
23
+ density: number;
24
+ mutate: number;
25
+ p: number[];
26
+ }
27
+ export declare const PLAYER_SLOT_FIELDS: readonly ["playerP1", "playerP2", "playerP3", "playerP4", "playerP5"];
28
+ export type PlayerSlotField = (typeof PLAYER_SLOT_FIELDS)[number];
29
+ export type PlayerField = "playerDensity" | "playerMutate" | PlayerSlotField;
30
+ /** The seven fields that are ALSO manifest params: every write must reach both. */
31
+ export declare const MODULATABLE_PLAYER_FIELDS: readonly PlayerField[];
32
+ export declare const LISTEN_MODES: readonly ["off", "complement", "answer", "harmonic"];
33
+ export type ListenModeName = (typeof LISTEN_MODES)[number];
34
+ export declare const PATTERN_MODES: readonly ["mask", "keep"];
35
+ export type PatternModeName = (typeof PATTERN_MODES)[number];
36
+ /** "No arm on record" in the persisted poly ledger (interface/src/utils/playerPolyArm.ts). */
37
+ export declare const NO_POLY_ARM = -1;
38
+ export declare const PLAYER_GENRES: readonly ["boom_bap", "trap", "drill", "house", "techno", "dnb", "idm"];
39
+ export type PlayerGenre = (typeof PLAYER_GENRES)[number];
40
+ export declare const GENERATIVE_PLAYERS: PlayerSpec[];
41
+ export declare const PLAYER_NAMES: string[];
42
+ export declare const getPlayerSpec: (type: number) => PlayerSpec | undefined;
43
+ /** A roster name (any case) or a numeric id; undefined for anything else. */
44
+ export declare function resolvePlayerSpec(ref: string | number): PlayerSpec | undefined;
45
+ export declare const playerPresetsFor: (type: number) => PlayerPreset[];
46
+ export declare function resolvePlayerPreset(spec: PlayerSpec, name: string): PlayerPreset | undefined;
47
+ /** The roster's own voicing for a type pick — what setCellPlayer seeds before the caller's fields. */
48
+ export declare function playerDefaultsFor(type: number): Record<string, number>;
49
+ export declare function presetConfig(preset: PlayerPreset): Record<string, number>;
50
+ /** A detented field writes exactly i/(steps-1); continuous is the clamped identity. */
51
+ export declare function snapPlayerValue(steps: number | undefined, value: number): number;
52
+ export declare function playerSlotStepIndex(slot: PlayerSlotSpec, value: number): number;
53
+ export declare function playerSlotDisplay(slot: PlayerSlotSpec, value: number): string;
54
+ export declare const playerDensityDisplay: (value: number) => string;
55
+ export declare const playerMutateDisplay: (value: number) => string;
56
+ /**
57
+ * A slot write from an agent: a 0..1 position (snapped to the slot's detents) or,
58
+ * on a labelled slot, one of its step labels. Returns an error string on a miss.
59
+ */
60
+ export declare function resolveSlotValue(slot: PlayerSlotSpec, input: number | string): number | string;
61
+ export interface PlayerGenreSlot {
62
+ index: number;
63
+ genres: PlayerGenre[];
64
+ }
65
+ /** The slot whose detents all name randomizer genres — found from the registry, never hardcoded. */
66
+ export declare function playerGenreSlot(spec: PlayerSpec | undefined): PlayerGenreSlot | undefined;
67
+ export declare function playerGenreConfig(spec: PlayerSpec | undefined, genre: string | undefined): Record<string, number>;
68
+ export interface RolePlayerConfig {
69
+ playerType: number;
70
+ playerP1?: number;
71
+ playerP5?: number;
72
+ isPoly?: number;
73
+ }
74
+ export declare const DEFAULT_PLAYER_TYPE = 2;
75
+ export declare const rolePlayerConfigFor: (cellId: number) => RolePlayerConfig;
76
+ export declare const roleSpreadSummary: () => Record<number, string>;
77
+ export declare const isMelodicPlayer: (spec: PlayerSpec | undefined) => boolean;
78
+ /** uint31 so the seed round-trips through every JSON/number layer intact. */
79
+ export declare const randomPlayerSeed: () => number;
80
+ export declare const cellPlayerType: (cell: Record<string, unknown> | undefined) => number;
81
+ /**
82
+ * Human-readable summary of a cell's running player. The seven modulatable
83
+ * fields are read from the PARAMS (`cell{N}_player*`) with the config as the
84
+ * fallback, because only a UI write mirrors the two and an automated move
85
+ * leaves the config behind.
86
+ */
87
+ export declare function describeCellPlayer(cellId: number, cell: Record<string, unknown> | undefined, state: Record<string, unknown>): Record<string, unknown> | undefined;
88
+ /** The roster as an agent-facing catalogue: one entry per player, presets attached. */
89
+ export declare function describePlayerSpec(spec: PlayerSpec, includePresets: boolean): Record<string, unknown>;
@@ -0,0 +1,235 @@
1
+ // Generative Players (per-cell PLAYER mode) for the MCP server, read from the
2
+ // two shared registries build.js and the UI consume; vendored into dist/ by
3
+ // scripts/build-postprocess.mjs.
4
+ import { existsSync, readFileSync } from "node:fs";
5
+ import { dirname, resolve } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+ export const PLAYER_SLOT_FIELDS = ["playerP1", "playerP2", "playerP3", "playerP4", "playerP5"];
8
+ /** The seven fields that are ALSO manifest params: every write must reach both. */
9
+ export const MODULATABLE_PLAYER_FIELDS = ["playerDensity", "playerMutate", ...PLAYER_SLOT_FIELDS];
10
+ export const LISTEN_MODES = ["off", "complement", "answer", "harmonic"];
11
+ export const PATTERN_MODES = ["mask", "keep"];
12
+ /** "No arm on record" in the persisted poly ledger (interface/src/utils/playerPolyArm.ts). */
13
+ export const NO_POLY_ARM = -1;
14
+ export const PLAYER_GENRES = ["boom_bap", "trap", "drill", "house", "techno", "dnb", "idm"];
15
+ function readRegistry(fileName, valid) {
16
+ const here = dirname(fileURLToPath(import.meta.url));
17
+ const candidates = [
18
+ resolve(here, "..", "..", "..", "shared", fileName), // repo checkout
19
+ resolve(here, fileName), // published dist/
20
+ ];
21
+ for (const file of candidates) {
22
+ if (!existsSync(file))
23
+ continue;
24
+ const parsed = JSON.parse(readFileSync(file, "utf8"));
25
+ if (valid(parsed))
26
+ return parsed;
27
+ }
28
+ throw new Error(`pam-mcp: ${fileName} not found. Rebuild the package (scripts/build-postprocess.mjs vendors it into dist/) — ` +
29
+ "arming a player without it would write values that disagree with the plugin.");
30
+ }
31
+ const REGISTRY = readRegistry("generativePlayers.json", (parsed) => !!parsed.players && Object.keys(parsed.players).length > 0);
32
+ const PRESETS = readRegistry("generativePlayerPresets.json", (parsed) => !!parsed.presets);
33
+ export const GENERATIVE_PLAYERS = Object.keys(REGISTRY.players)
34
+ .map(Number)
35
+ .sort((a, b) => a - b)
36
+ .map((id) => ({ id, ...REGISTRY.players[String(id)] }));
37
+ const BY_ID = new Map(GENERATIVE_PLAYERS.map((spec) => [spec.id, spec]));
38
+ const BY_NAME = new Map(GENERATIVE_PLAYERS.map((spec) => [spec.name.toLowerCase(), spec]));
39
+ export const PLAYER_NAMES = GENERATIVE_PLAYERS.map((spec) => spec.name);
40
+ export const getPlayerSpec = (type) => BY_ID.get(Math.round(type));
41
+ /** A roster name (any case) or a numeric id; undefined for anything else. */
42
+ export function resolvePlayerSpec(ref) {
43
+ if (typeof ref === "number")
44
+ return getPlayerSpec(ref);
45
+ const trimmed = ref.trim();
46
+ if (/^\d+$/.test(trimmed))
47
+ return getPlayerSpec(Number(trimmed));
48
+ return BY_NAME.get(trimmed.toLowerCase());
49
+ }
50
+ export const playerPresetsFor = (type) => PRESETS.presets[String(Math.round(type))] ?? [];
51
+ export function resolvePlayerPreset(spec, name) {
52
+ const wanted = name.trim().toLowerCase();
53
+ return playerPresetsFor(spec.id).find((preset) => preset.name.toLowerCase() === wanted);
54
+ }
55
+ /** The roster's own voicing for a type pick — what setCellPlayer seeds before the caller's fields. */
56
+ export function playerDefaultsFor(type) {
57
+ const spec = getPlayerSpec(type);
58
+ const out = {
59
+ playerType: type,
60
+ playerDensity: spec?.defaults.density ?? 0.5,
61
+ playerMutate: spec?.defaults.mutate ?? 0.25,
62
+ };
63
+ PLAYER_SLOT_FIELDS.forEach((field, i) => {
64
+ out[field] = spec?.slots[i]?.default ?? 0.5;
65
+ });
66
+ return out;
67
+ }
68
+ export function presetConfig(preset) {
69
+ const out = { playerDensity: preset.density, playerMutate: preset.mutate };
70
+ preset.p.forEach((value, i) => {
71
+ const field = PLAYER_SLOT_FIELDS[i];
72
+ if (field)
73
+ out[field] = value;
74
+ });
75
+ return out;
76
+ }
77
+ /** A detented field writes exactly i/(steps-1); continuous is the clamped identity. */
78
+ export function snapPlayerValue(steps, value) {
79
+ const clamped = Math.max(0, Math.min(1, value));
80
+ if (!steps || steps < 2)
81
+ return clamped;
82
+ return Math.round(clamped * (steps - 1)) / (steps - 1);
83
+ }
84
+ export function playerSlotStepIndex(slot, value) {
85
+ if (!slot.steps || slot.steps < 2)
86
+ return 0;
87
+ const clamped = Math.max(0, Math.min(1, value));
88
+ return Math.max(0, Math.min(slot.steps - 1, Math.round(clamped * (slot.steps - 1))));
89
+ }
90
+ export function playerSlotDisplay(slot, value) {
91
+ if (slot.steps && slot.stepLabels)
92
+ return slot.stepLabels[playerSlotStepIndex(slot, value)] ?? "";
93
+ if (slot.steps && slot.steps >= 2)
94
+ return String(playerSlotStepIndex(slot, value));
95
+ const clamped = Math.max(0, Math.min(1, value));
96
+ if (slot.center) {
97
+ const signed = Math.round((clamped - 0.5) * 200);
98
+ return signed > 0 ? `+${signed}%` : `${signed}%`;
99
+ }
100
+ return `${Math.round(clamped * 100)}%`;
101
+ }
102
+ export const playerDensityDisplay = (value) => `${Math.round(value * 100)}%`;
103
+ export const playerMutateDisplay = (value) => (value < 0.02 ? "Lock" : `${Math.round(value * 100)}%`);
104
+ /**
105
+ * A slot write from an agent: a 0..1 position (snapped to the slot's detents) or,
106
+ * on a labelled slot, one of its step labels. Returns an error string on a miss.
107
+ */
108
+ export function resolveSlotValue(slot, input) {
109
+ if (typeof input === "number")
110
+ return snapPlayerValue(slot.steps, input);
111
+ const wanted = input.trim().toLowerCase();
112
+ if (slot.stepLabels && slot.steps) {
113
+ const index = slot.stepLabels.findIndex((label) => label.toLowerCase() === wanted);
114
+ if (index >= 0)
115
+ return index / (slot.steps - 1);
116
+ return `'${input}' is not a ${slot.label} position — one of: ${slot.stepLabels.join(", ")}.`;
117
+ }
118
+ const numeric = Number(wanted.replace(/%$/, ""));
119
+ if (Number.isFinite(numeric))
120
+ return snapPlayerValue(slot.steps, wanted.endsWith("%") ? numeric / 100 : numeric);
121
+ return `${slot.label} takes a 0..1 value${slot.steps ? ` (${slot.steps} detents)` : ""}, not '${input}'.`;
122
+ }
123
+ const normalizeGenre = (label) => {
124
+ const lowered = label.toLowerCase().trim().replace(/-/g, "_").replace(/\s+/g, "_");
125
+ return PLAYER_GENRES.includes(lowered) ? lowered : undefined;
126
+ };
127
+ /** The slot whose detents all name randomizer genres — found from the registry, never hardcoded. */
128
+ export function playerGenreSlot(spec) {
129
+ if (!spec)
130
+ return undefined;
131
+ for (let index = 0; index < spec.slots.length; index++) {
132
+ const labels = spec.slots[index].stepLabels;
133
+ if (!labels || labels.length === 0)
134
+ continue;
135
+ const genres = labels.map(normalizeGenre);
136
+ if (genres.every((genre) => genre !== undefined))
137
+ return { index, genres };
138
+ }
139
+ return undefined;
140
+ }
141
+ export function playerGenreConfig(spec, genre) {
142
+ const slot = spec ? playerGenreSlot(spec) : undefined;
143
+ const wanted = genre ? normalizeGenre(genre) : undefined;
144
+ if (!spec || !slot || !wanted)
145
+ return {};
146
+ const position = slot.genres.indexOf(wanted);
147
+ if (position < 0)
148
+ return {};
149
+ const steps = spec.slots[slot.index].steps ?? 1;
150
+ return { [PLAYER_SLOT_FIELDS[slot.index]]: position / (steps - 1) };
151
+ }
152
+ // Twin of ROLE_PLAYER_CONFIGS in interface/src/utils/generativePlayers.ts
153
+ // (KIT's positional cellId → role table); scripts/check-parity.mjs diffs them.
154
+ const ROLE_PLAYER_CONFIGS = {
155
+ 1: { playerType: 2 },
156
+ 2: { playerType: 6, playerP1: 1 / 3 },
157
+ 3: { playerType: 1 },
158
+ 4: { playerType: 7 },
159
+ 5: { playerType: 4, isPoly: 1 },
160
+ 6: { playerType: 3 },
161
+ 7: { playerType: 5, playerP5: 2 / 5, isPoly: 1 },
162
+ 8: { playerType: 8, playerP5: 3 / 5, isPoly: 1 },
163
+ };
164
+ export const DEFAULT_PLAYER_TYPE = 2;
165
+ export const rolePlayerConfigFor = (cellId) => ROLE_PLAYER_CONFIGS[cellId] ?? { playerType: DEFAULT_PLAYER_TYPE };
166
+ export const roleSpreadSummary = () => Object.fromEntries(Object.entries(ROLE_PLAYER_CONFIGS).map(([cellId, config]) => [
167
+ Number(cellId),
168
+ getPlayerSpec(config.playerType)?.name ?? String(config.playerType),
169
+ ]));
170
+ export const isMelodicPlayer = (spec) => spec?.tag === "melodic";
171
+ /** uint31 so the seed round-trips through every JSON/number layer intact. */
172
+ export const randomPlayerSeed = () => Math.floor(Math.random() * 0x7fffffff);
173
+ export const cellPlayerType = (cell) => Math.round(Number(cell?.playerType ?? 0));
174
+ const numberOr = (value, fallback) => {
175
+ const n = Number(value);
176
+ return Number.isFinite(n) ? n : fallback;
177
+ };
178
+ /**
179
+ * Human-readable summary of a cell's running player. The seven modulatable
180
+ * fields are read from the PARAMS (`cell{N}_player*`) with the config as the
181
+ * fallback, because only a UI write mirrors the two and an automated move
182
+ * leaves the config behind.
183
+ */
184
+ export function describeCellPlayer(cellId, cell, state) {
185
+ const type = cellPlayerType(cell);
186
+ const spec = getPlayerSpec(type);
187
+ if (!spec)
188
+ return undefined;
189
+ const readField = (field, fallback) => numberOr(state[`cell${cellId}_${field}`], numberOr(cell?.[field], fallback));
190
+ const slots = {};
191
+ spec.slots.forEach((slot, i) => {
192
+ const field = PLAYER_SLOT_FIELDS[i];
193
+ slots[slot.label] = playerSlotDisplay(slot, readField(field, slot.default));
194
+ });
195
+ const density = readField("playerDensity", spec.defaults.density);
196
+ const mutate = readField("playerMutate", spec.defaults.mutate);
197
+ const listenMode = Math.round(numberOr(cell?.playerListenMode, 0));
198
+ return {
199
+ id: spec.id,
200
+ name: spec.name,
201
+ density: playerDensityDisplay(density),
202
+ mutate: playerMutateDisplay(mutate),
203
+ slots,
204
+ seed: Math.round(numberOr(cell?.playerSeed, 0)),
205
+ patternMode: PATTERN_MODES[Math.round(numberOr(cell?.playerPatternMode, 0))] ?? "mask",
206
+ listen: listenMode > 0
207
+ ? {
208
+ mode: LISTEN_MODES[listenMode] ?? "off",
209
+ source: Math.round(numberOr(cell?.playerListenSource, 0)),
210
+ amount: numberOr(cell?.playerListenAmount, 0.5),
211
+ }
212
+ : undefined,
213
+ };
214
+ }
215
+ /** The roster as an agent-facing catalogue: one entry per player, presets attached. */
216
+ export function describePlayerSpec(spec, includePresets) {
217
+ return {
218
+ id: spec.id,
219
+ name: spec.name,
220
+ tag: spec.tag,
221
+ blurb: spec.blurb,
222
+ defaults: spec.defaults,
223
+ slots: spec.slots.map((slot, i) => ({
224
+ arg: `p${i + 1}`,
225
+ label: slot.label,
226
+ default: slot.default,
227
+ ...(slot.steps && slot.steps >= 2
228
+ ? { detents: slot.steps, ...(slot.stepLabels ? { positions: slot.stepLabels } : {}) }
229
+ : { range: slot.center ? "bipolar 0..1, centre 0.5" : "0..1" }),
230
+ ...(slot.hint ? { hint: slot.hint } : {}),
231
+ })),
232
+ ...(includePresets ? { presets: playerPresetsFor(spec.id).map((preset) => preset.name) } : {}),
233
+ };
234
+ }
235
+ //# sourceMappingURL=players.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"players.js","sourceRoot":"","sources":["../src/players.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { Buffer } from "node:buffer";
1
2
  /** Strip the library prefix accepted by MCP tools before resolving a preset on disk. */
2
3
  export declare function normalizePresetLookupPath(presetPath: string): string;
3
4
  /**
@@ -8,3 +9,7 @@ export declare function normalizePresetLookupPath(presetPath: string): string;
8
9
  * destination remains the only useful source (for explicit-path overwrites).
9
10
  */
10
11
  export declare function selectSaveVariationSourcePath(activePresetPath: unknown, destinationPath: string): string;
12
+ export declare function parsePresetFile(raw: string | Buffer): {
13
+ metadata: Record<string, unknown>;
14
+ data: Record<string, unknown>;
15
+ };
@@ -1,3 +1,4 @@
1
+ import { Buffer } from "node:buffer";
1
2
  /** Strip the library prefix accepted by MCP tools before resolving a preset on disk. */
2
3
  export function normalizePresetLookupPath(presetPath) {
3
4
  return presetPath.startsWith("Presets/")
@@ -19,4 +20,25 @@ export function selectSaveVariationSourcePath(activePresetPath, destinationPath)
19
20
  }
20
21
  return normalizePresetLookupPath(destinationPath);
21
22
  }
23
+ export function parsePresetFile(raw) {
24
+ const bytes = typeof raw === "string" ? Buffer.from(raw, "utf8") : raw;
25
+ let prefixLength = 0;
26
+ while (bytes[prefixLength] >= 48 && bytes[prefixLength] <= 57)
27
+ prefixLength++;
28
+ if (prefixLength === 0)
29
+ throw new Error("invalid format (no metadata size prefix)");
30
+ const metadataSize = Number(bytes.toString("ascii", 0, prefixLength));
31
+ const dataOffset = prefixLength + metadataSize;
32
+ if (!Number.isSafeInteger(metadataSize) || metadataSize <= 0 || dataOffset >= bytes.length) {
33
+ throw new Error("invalid format (metadata size out of bounds)");
34
+ }
35
+ const metadata = JSON.parse(bytes.toString("utf8", prefixLength, dataOffset));
36
+ const data = JSON.parse(bytes.toString("utf8", dataOffset));
37
+ for (const value of [metadata, data]) {
38
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
39
+ throw new Error("invalid format (metadata and data must be objects)");
40
+ }
41
+ }
42
+ return { metadata, data };
43
+ }
22
44
  //# sourceMappingURL=presetSave.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"presetSave.js","sourceRoot":"","sources":["../src/presetSave.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,MAAM,UAAU,yBAAyB,CAAC,UAAkB;IAC1D,OAAO,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC;QACtC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC;QACrC,CAAC,CAAC,UAAU,CAAC;AACjB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,6BAA6B,CAC3C,gBAAyB,EACzB,eAAuB;IAEvB,IACE,OAAO,gBAAgB,KAAK,QAAQ;QACpC,gBAAgB,CAAC,MAAM,GAAG,CAAC;QAC3B,gBAAgB,KAAK,MAAM,EAC3B,CAAC;QACD,OAAO,yBAAyB,CAAC,gBAAgB,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,yBAAyB,CAAC,eAAe,CAAC,CAAC;AACpD,CAAC"}
1
+ {"version":3,"file":"presetSave.js","sourceRoot":"","sources":["../src/presetSave.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,wFAAwF;AACxF,MAAM,UAAU,yBAAyB,CAAC,UAAkB;IAC1D,OAAO,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC;QACtC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC;QACrC,CAAC,CAAC,UAAU,CAAC;AACjB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,6BAA6B,CAC3C,gBAAyB,EACzB,eAAuB;IAEvB,IACE,OAAO,gBAAgB,KAAK,QAAQ;QACpC,gBAAgB,CAAC,MAAM,GAAG,CAAC;QAC3B,gBAAgB,KAAK,MAAM,EAC3B,CAAC;QACD,OAAO,yBAAyB,CAAC,gBAAgB,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,yBAAyB,CAAC,eAAe,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAoB;IAIlD,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACvE,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,OAAO,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE;QAAE,YAAY,EAAE,CAAC;IAC9E,IAAI,YAAY,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IACpF,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC;IACtE,MAAM,UAAU,GAAG,YAAY,GAAG,YAAY,CAAC;IAC/C,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,IAAI,YAAY,IAAI,CAAC,IAAI,UAAU,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAC3F,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC;IAC9E,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC5D,KAAK,MAAM,KAAK,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC;QACrC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACxE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { WavData } from "./audioAnalysis.js";
2
+ /** interface/src/stores/SliceProperties.ts MAX_SLICES */
3
+ export declare const MAX_SLICES = 64;
4
+ /** Sorted, clamped, deduplicated 0..1 boundaries that always start at 0 and end at 1. */
5
+ export declare function normalizeBoundaries(input: number[]): number[];
6
+ export declare function equalBoundaries(count: number): number[];
7
+ /**
8
+ * Onset positions (0..1 of the file) from half-wave-rectified log-energy
9
+ * flux, peak-picked with a 40 ms refractory window. `sensitivity` 0..1 lowers
10
+ * the threshold; at most `maxSlices - 1` onsets survive, strongest first.
11
+ */
12
+ export declare function detectOnsetBoundaries(wav: WavData, sensitivity?: number, maxSlices?: number): number[];
@@ -0,0 +1,78 @@
1
+ // Slice-boundary helpers for set_slices: boundary normalisation, equal division
2
+ // and a plain energy-onset detector over a decoded WAV (no plugin round trip).
3
+ /** interface/src/stores/SliceProperties.ts MAX_SLICES */
4
+ export const MAX_SLICES = 64;
5
+ /** Sorted, clamped, deduplicated 0..1 boundaries that always start at 0 and end at 1. */
6
+ export function normalizeBoundaries(input) {
7
+ const points = input
8
+ .map((v) => Math.max(0, Math.min(1, Number(v))))
9
+ .filter((v) => Number.isFinite(v))
10
+ .sort((a, b) => a - b);
11
+ const out = [0];
12
+ for (const p of points) {
13
+ if (p - out[out.length - 1] > 1e-4 && p < 1 - 1e-4)
14
+ out.push(p);
15
+ }
16
+ out.push(1);
17
+ return out;
18
+ }
19
+ export function equalBoundaries(count) {
20
+ const n = Math.max(1, Math.min(MAX_SLICES, Math.round(count)));
21
+ return Array.from({ length: n + 1 }, (_, i) => i / n);
22
+ }
23
+ /**
24
+ * Onset positions (0..1 of the file) from half-wave-rectified log-energy
25
+ * flux, peak-picked with a 40 ms refractory window. `sensitivity` 0..1 lowers
26
+ * the threshold; at most `maxSlices - 1` onsets survive, strongest first.
27
+ */
28
+ export function detectOnsetBoundaries(wav, sensitivity = 0.5, maxSlices = 32) {
29
+ const { samples, sampleRate } = wav;
30
+ const hop = Math.max(64, Math.round(sampleRate * 0.0058));
31
+ const frames = Math.floor(samples.length / hop);
32
+ if (frames < 4)
33
+ return [0, 1];
34
+ const energy = new Float64Array(frames);
35
+ for (let f = 0; f < frames; f++) {
36
+ let sum = 0;
37
+ const start = f * hop;
38
+ for (let i = 0; i < hop; i++) {
39
+ const s = samples[start + i];
40
+ sum += s * s;
41
+ }
42
+ energy[f] = 10 * Math.log10(sum / hop + 1e-10);
43
+ }
44
+ const flux = new Float64Array(frames);
45
+ let mean = 0;
46
+ for (let f = 1; f < frames; f++) {
47
+ flux[f] = Math.max(0, energy[f] - energy[f - 1]);
48
+ mean += flux[f];
49
+ }
50
+ mean /= frames - 1;
51
+ let variance = 0;
52
+ for (let f = 1; f < frames; f++)
53
+ variance += (flux[f] - mean) ** 2;
54
+ const std = Math.sqrt(variance / Math.max(1, frames - 2));
55
+ const clampedSensitivity = Math.max(0, Math.min(1, sensitivity));
56
+ const threshold = mean + (2.5 - 2.0 * clampedSensitivity) * std;
57
+ const floorDb = -60;
58
+ const refractory = Math.max(1, Math.round((sampleRate * 0.04) / hop));
59
+ const peaks = [];
60
+ let lastPeak = -refractory;
61
+ for (let f = 2; f < frames - 1; f++) {
62
+ if (flux[f] < threshold || energy[f] < floorDb)
63
+ continue;
64
+ if (flux[f] < flux[f - 1] || flux[f] < flux[f + 1])
65
+ continue;
66
+ if (f - lastPeak < refractory)
67
+ continue;
68
+ peaks.push({ frame: f - 1, strength: flux[f] });
69
+ lastPeak = f;
70
+ }
71
+ const keep = Math.max(0, Math.min(MAX_SLICES, Math.round(maxSlices)) - 1);
72
+ const chosen = peaks
73
+ .sort((a, b) => b.strength - a.strength)
74
+ .slice(0, keep)
75
+ .map((p) => (p.frame * hop) / samples.length);
76
+ return normalizeBoundaries(chosen);
77
+ }
78
+ //# sourceMappingURL=sampleSlicing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sampleSlicing.js","sourceRoot":"","sources":["../src/sampleSlicing.ts"],"names":[],"mappings":"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"}