memlnaut-nisps/playground/js/midi/midi-cc-presets.js
w1n5t0n 0a112f2d84 feat(playground): MIDI CC device presets + bug fixes
Add MIDI CC preset system for bundled device configurations:
- midi-cc-presets.js: listPresets/loadPreset/loadPresetFromFile API
- presets/polybrute.json: Arturia PolyBrute CC map
- Preset selector in quick controls bar and MIDI CC drawer
- File import button for loading JSON presets from disk

Bug fixes in a-app.js:
- Destroy IML instances before resizeMLP() to free WASM memory
- Fix randomiseWeights() call (was drawWeights())
- Fix thumbs-up to store rawParamValues instead of post-pipeline outputs
2026-04-02 20:35:38 +01:00

60 lines
1.6 KiB
JavaScript

// MIDI CC Presets — bundled device configurations
// Each preset is a JSON file with { name, description, channel, params[] }
const PRESET_URLS = {
'polybrute': './js/midi/presets/polybrute.json',
};
// In-memory cache
const _cache = new Map();
/**
* Get list of available preset IDs and names.
* @returns {Array<{id: string, name: string}>}
*/
export function listPresets() {
return [
{ id: 'polybrute', name: 'Arturia PolyBrute' },
];
}
/**
* Load a preset by ID. Returns the parsed preset object.
* @param {string} id — preset identifier
* @returns {Promise<{name: string, description: string, channel: number, params: Array}>}
*/
export async function loadPreset(id) {
if (_cache.has(id)) return _cache.get(id);
const url = PRESET_URLS[id];
if (!url) throw new Error(`Unknown MIDI CC preset: ${id}`);
const resp = await fetch(url);
if (!resp.ok) throw new Error(`Failed to load preset ${id}: ${resp.status}`);
const preset = await resp.json();
_cache.set(id, preset);
return preset;
}
/**
* Load a preset from a user-provided JSON file (File object).
* @param {File} file
* @returns {Promise<{name: string, description: string, channel: number, params: Array}|null>}
*/
export async function loadPresetFromFile(file) {
try {
const text = await file.text();
const preset = JSON.parse(text);
if (!preset.params || !Array.isArray(preset.params) || preset.params.length === 0) {
return null;
}
// Validate param shape
for (const p of preset.params) {
if (typeof p.cc !== 'number' || typeof p.channel !== 'number') return null;
}
return preset;
} catch (e) {
return null;
}
}