feat(control): global settings state + persistence

This commit is contained in:
L'électron rare
2026-06-30 13:40:19 +02:00
parent 8bead14e23
commit 64348aa90d
2 changed files with 41 additions and 1 deletions
+19 -1
View File
@@ -79,6 +79,22 @@ export function resetGlobalActions() {
matGlobalActions = ["fill", "drop", "evolve", "breakdown"];
}
export let matGlobalSettings = { openThresh: 0.65, closeThresh: 0.30, transientBars: 1, breakdownKeep: ["kick", "sub"] };
export function setGlobalSetting(key, value) { matGlobalSettings[key] = value; }
export function resetGlobalSettings() {
matGlobalSettings = { openThresh: 0.65, closeThresh: 0.30, transientBars: 1, breakdownKeep: ["kick", "sub"] };
}
// Decode /matrix/globalsettings args: [openThresh, closeThresh, transientBars, keepN, keep0..]
export function parseGlobalSettings(args) {
const openThresh = Number(args[0]);
const closeThresh = Number(args[1]);
const transientBars = Math.round(Number(args[2]));
const keepN = Math.round(Number(args[3])) || 0;
const breakdownKeep = [];
for (let k = 0; k < keepN; k++) breakdownKeep.push(String(args[4 + k]));
return { openThresh, closeThresh, transientBars, breakdownKeep };
}
export const MATRIX_MOD_TARGETS = {
kick:["none","amp","pan","rev"], hats:["none","amp","pan","rev"], clap:["none","amp","pan","rev"], perc:["none","amp","cutoff","pan","rev","pitch"],
sub:["none","amp","pan","rev","res","pitch"], acid:["none","amp","cutoff","pan","rev","res","pitch"], arp:["none","amp","cutoff","pan","rev","res","pitch"],
@@ -172,7 +188,7 @@ export function saveMatState() {
try { localStorage.setItem(MATRIX_STORAGE_KEY,
JSON.stringify({ grid: matGrid, inst: matInst, cdef: matColorDefs,
vmod: matVoiceMods, vpose: matVoicePoses,
gact: matGlobalActions })); } catch (_e) {}
gact: matGlobalActions, gset: matGlobalSettings })); } catch (_e) {}
}
export function loadMatState() {
@@ -199,6 +215,8 @@ export function loadMatState() {
if (Array.isArray(raw.vmod) && raw.vmod.length === MATRIX_VOICES.length) matVoiceMods = raw.vmod;
if (Array.isArray(raw.vpose) && raw.vpose.length === MATRIX_VOICES.length) matVoicePoses = raw.vpose;
if (Array.isArray(raw.gact) && raw.gact.length === 4) matGlobalActions = raw.gact;
if (raw.gset && typeof raw.gset === "object" && Array.isArray(raw.gset.breakdownKeep))
matGlobalSettings = raw.gset;
return; }
if (Array.isArray(raw) && raw.length === MATRIX_VOICES.length) { matGrid = raw; return; } // legacy: bare grid
} catch (_e) {}
+22
View File
@@ -118,3 +118,25 @@ test("setGlobalAction mutates a slot", () => {
assert.equal(matGlobalActions[2], "fill");
setGlobalAction(2, "evolve"); // restore default
});
import { matGlobalSettings, setGlobalSetting, parseGlobalSettings }
from "../public/control/js/matrix-state.js";
test("default global settings", () => {
assert.equal(matGlobalSettings.openThresh, 0.65);
assert.equal(matGlobalSettings.closeThresh, 0.30);
assert.equal(matGlobalSettings.transientBars, 1);
assert.deepEqual(matGlobalSettings.breakdownKeep, ["kick", "sub"]);
});
test("setGlobalSetting mutates one key", () => {
setGlobalSetting("closeThresh", 0.4);
assert.equal(matGlobalSettings.closeThresh, 0.4);
setGlobalSetting("closeThresh", 0.30);
});
test("parseGlobalSettings decodes the OSC arg layout", () => {
const s = parseGlobalSettings([0.7, 0.2, 3, 2, "kick", "snare"]);
assert.equal(s.openThresh, 0.7);
assert.equal(s.closeThresh, 0.2);
assert.equal(s.transientBars, 3);
assert.deepEqual(s.breakdownKeep, ["kick", "snare"]);
});