feat(playground): add tiered synth parameter preset system
4 tiers of progressive complexity (Beginner 15 params → Expert 126), 13 presets total with per-param min/max/curve overrides that bias distributions without clamping extremes. Preset dropdown in UI, persisted to localStorage, supports ?preset= URL param.
This commit is contained in:
parent
4e32919494
commit
8a550361ea
5 changed files with 844 additions and 2 deletions
16
CLAUDE.md
16
CLAUDE.md
|
|
@ -44,6 +44,7 @@ Key files: `js/nisps/` (ML core port), `js/ui/` (visualizer, joystick, controls)
|
|||
|-------|-------|---------|--------|
|
||||
| `tame` | 0–1 | 1 | Constrains synth output ranges toward safe limits |
|
||||
| `spread` | 0–1 | 0.6 | Controls weight initialization, RL noise scaling, and weight decay (see below) |
|
||||
| `preset` | preset id | _(none)_ | Auto-loads a synth parameter preset on first visit (e.g. `?preset=beginner-1`) |
|
||||
|
||||
#### `spread` — sigmoid saturation control
|
||||
|
||||
|
|
@ -76,6 +77,21 @@ The 126 synth parameters in `js/synth/param-map.js` were curated from the C15's
|
|||
| PM shaper blend | 4 | Secondary routing params |
|
||||
| FB Mix source selects | 4 | Discrete A/B selectors |
|
||||
|
||||
### Synth Presets
|
||||
|
||||
Presets (`js/synth/presets.js`) control which parameters the ML engine can modify, with unselected params muted at safe defaults. Each preset defines per-param `{ muted, fixedValue, min, max, curve }` — no training examples or model weights.
|
||||
|
||||
4 tiers of progressive complexity:
|
||||
|
||||
| Tier | Presets | Active params | What's exposed |
|
||||
|------|---------|---------------|----------------|
|
||||
| 1 (Beginner) | 1.1–1.4 | 15 | Basic ADSR, SVF cutoff/res, Shaper A drive/fold, output levels, reverb mix |
|
||||
| 2 (Intermediate) | 2.1–2.4 | 40 | + Env B/C, filter FM, effects (reverb/echo/flanger), cabinet, stereo panning |
|
||||
| 3 (Advanced) | 3.1–3.3 | ~95 | + Cross-oscillator PM, feedback mixer, dual shapers, comb/gap filters, ring mod |
|
||||
| 4 (Expert) | 4.1–4.2 | 126 | Full engine |
|
||||
|
||||
Presets use `curve` values to bias parameter distributions (< 0.5 = spend more time low, > 0.5 = bias high) without clamping extremes. Users can tweak any preset via the group drawer after loading.
|
||||
|
||||
## Build System
|
||||
|
||||
This is an Arduino project targeting Raspberry Pi Pico. Build and upload using Arduino IDE or arduino-cli with the earlephilhower/pico board package.
|
||||
|
|
|
|||
|
|
@ -28,6 +28,30 @@
|
|||
<label>Vol <input type="range" id="quick-vol" min="0" max="1" step="0.01" value="0.5"></label>
|
||||
<label>BPM <input type="range" id="quick-bpm" min="40" max="240" step="1" value="120"><span id="quick-bpm-val">120</span></label>
|
||||
</div>
|
||||
<select class="preset-select" id="synth-preset-select" title="Synth preset">
|
||||
<option value="">Manual</option>
|
||||
<optgroup label="Beginner">
|
||||
<option value="beginner-1">1.1</option>
|
||||
<option value="beginner-2">1.2</option>
|
||||
<option value="beginner-3">1.3</option>
|
||||
<option value="beginner-4">1.4</option>
|
||||
</optgroup>
|
||||
<optgroup label="Intermediate">
|
||||
<option value="intermediate-1">2.1</option>
|
||||
<option value="intermediate-2">2.2</option>
|
||||
<option value="intermediate-3">2.3</option>
|
||||
<option value="intermediate-4">2.4</option>
|
||||
</optgroup>
|
||||
<optgroup label="Advanced">
|
||||
<option value="advanced-1">3.1</option>
|
||||
<option value="advanced-2">3.2</option>
|
||||
<option value="advanced-3">3.3</option>
|
||||
</optgroup>
|
||||
<optgroup label="Expert">
|
||||
<option value="expert-1">4.1</option>
|
||||
<option value="expert-2">4.2</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Fullscreen flow field canvas -->
|
||||
|
|
@ -226,6 +250,7 @@
|
|||
<div class="help-section">
|
||||
<h3>Synth Controls</h3>
|
||||
<ul>
|
||||
<li><strong>Presets</strong> — use the dropdown (top left, next to play) to choose a parameter preset. Lower tiers (1.x) expose fewer parameters for simpler exploration; higher tiers (3.x, 4.x) unlock cross-modulation, feedback, and the full engine. You can tweak any preset afterwards using the controls below.</li>
|
||||
<li><strong>Hover any bar</strong> in the synth visualizer to see parameter name, current value, range, and curve</li>
|
||||
<li><strong>Hover a group name</strong> (e.g. "Env A", "Osc B") at the top to open its control drawer:</li>
|
||||
<ul>
|
||||
|
|
|
|||
|
|
@ -822,6 +822,45 @@ html, body {
|
|||
display: flex;
|
||||
}
|
||||
|
||||
/* Synth preset dropdown */
|
||||
.preset-select {
|
||||
margin-left: 8px;
|
||||
height: 36px;
|
||||
padding: 0 10px;
|
||||
border-radius: 18px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
background: rgba(13, 13, 13, 0.65);
|
||||
backdrop-filter: blur(16px);
|
||||
-webkit-backdrop-filter: blur(16px);
|
||||
color: var(--text);
|
||||
font-family: inherit;
|
||||
font-size: 11px;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s, border-color 0.15s;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23888'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 8px center;
|
||||
padding-right: 24px;
|
||||
min-width: 0;
|
||||
max-width: 160px;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.preset-select:hover,
|
||||
.preset-select:focus {
|
||||
border-color: rgba(255, 255, 255, 0.15);
|
||||
background-color: rgba(255, 255, 255, 0.06);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.preset-select option,
|
||||
.preset-select optgroup {
|
||||
background: #1a1a1a;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
/* ---- Utility ---- */
|
||||
.hidden {
|
||||
display: none !important;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { Arpeggiator } from './synth/arpeggiator.js';
|
|||
import { MIDIInput } from './synth/midi-input.js';
|
||||
import { SYNTH_PARAM_MAP, SYNTH_PARAM_NAMES, SYNTH_PARAM_COLORS, applyCurve, applyGroupOverride } from './synth/param-map.js';
|
||||
import { GamepadInput } from './ui/gamepad.js';
|
||||
import { SYNTH_PRESETS, PRESET_TIERS } from './synth/presets.js';
|
||||
|
||||
// ---- Constants ----
|
||||
const N_INPUTS = 2;
|
||||
|
|
@ -128,9 +129,13 @@ const SYNTH_SECTIONS = [
|
|||
// Defaults are seeded from safeMin/safeMax in SYNTH_PARAM_MAP, scaled by the
|
||||
// ?tame URL parameter (0 = unconstrained, 1 = full safe limits).
|
||||
// localStorage overrides on load.
|
||||
|
||||
// Module-level tame so applyPreset() can use it
|
||||
const _urlTame = parseFloat(new URLSearchParams(window.location.search).get('tame') ?? '1');
|
||||
const tameLevel = isNaN(_urlTame) ? 1 : Math.max(0, Math.min(1, _urlTame));
|
||||
|
||||
const groupOverrides = (() => {
|
||||
const urlTame = parseFloat(new URLSearchParams(window.location.search).get('tame') ?? '1');
|
||||
const t = isNaN(urlTame) ? 1 : Math.max(0, Math.min(1, urlTame));
|
||||
const t = tameLevel;
|
||||
let flatIdx = 0;
|
||||
return SYNTH_SECTIONS.map(sec => ({
|
||||
curve: 0.5,
|
||||
|
|
@ -150,6 +155,13 @@ const groupOverrides = (() => {
|
|||
}));
|
||||
})();
|
||||
|
||||
// Lookup: param name -> flat index (for preset application)
|
||||
const paramNameToIndex = new Map();
|
||||
SYNTH_PARAM_MAP.forEach((p, i) => paramNameToIndex.set(p.name, i));
|
||||
|
||||
// Currently active synth preset id (null = no preset / manual)
|
||||
let activeSynthPresetId = null;
|
||||
|
||||
// Build a flat lookup: paramIndex -> { sectionIndex, localIndex }
|
||||
const paramToSection = [];
|
||||
{
|
||||
|
|
@ -188,6 +200,93 @@ function isParamMuted(paramIndex) {
|
|||
return groupOverrides[mapping.si].params[mapping.li].muted;
|
||||
}
|
||||
|
||||
// ---- Synth Preset Application ----
|
||||
|
||||
/**
|
||||
* Apply a synth preset by id.
|
||||
* Sets groupOverrides (muted/active, min/max/curve/fixedValue) for all 126 params,
|
||||
* re-routes outputs, saves state, and updates the UI dropdown.
|
||||
*/
|
||||
function applyPreset(presetId) {
|
||||
const preset = SYNTH_PRESETS.find(p => p.id === presetId);
|
||||
if (!preset) {
|
||||
console.warn(`[NISPS] Unknown preset: ${presetId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const t = tameLevel;
|
||||
const allActive = preset.active === null; // null = all params active (Tier 4)
|
||||
const activeSet = allActive ? null : new Set(preset.active);
|
||||
const overrides = preset.overrides || {};
|
||||
const mutedOv = preset.mutedOverrides || {};
|
||||
|
||||
for (let i = 0; i < N_SYNTH_OUTPUTS; i++) {
|
||||
const param = SYNTH_PARAM_MAP[i];
|
||||
const mapping = paramToSection[i];
|
||||
if (!mapping) continue;
|
||||
const gp = groupOverrides[mapping.si].params[mapping.li];
|
||||
const paramName = param.name;
|
||||
|
||||
// Tame-derived defaults for this param
|
||||
const safeMin = param.safeMin ?? 0;
|
||||
const safeMax = param.safeMax ?? 1;
|
||||
const tameMin = safeMin * t;
|
||||
const tameMax = 1 - (1 - safeMax) * t;
|
||||
|
||||
const isActive = allActive || activeSet.has(paramName);
|
||||
|
||||
if (isActive) {
|
||||
gp.muted = false;
|
||||
const ov = overrides[paramName];
|
||||
if (ov) {
|
||||
gp.min = ov.min !== undefined ? ov.min : tameMin;
|
||||
gp.max = ov.max !== undefined ? ov.max : tameMax;
|
||||
gp.curve = ov.curve !== undefined ? ov.curve : 0.5;
|
||||
gp.fixedValue = ov.fixedValue !== undefined ? ov.fixedValue : param.defaultValue;
|
||||
} else {
|
||||
gp.min = tameMin;
|
||||
gp.max = tameMax;
|
||||
gp.curve = 0.5;
|
||||
gp.fixedValue = param.defaultValue;
|
||||
}
|
||||
} else {
|
||||
gp.muted = true;
|
||||
const mov = mutedOv[paramName];
|
||||
gp.fixedValue = (mov && mov.fixedValue !== undefined) ? mov.fixedValue : param.defaultValue;
|
||||
// Keep tame-derived ranges for manual unmuting
|
||||
gp.min = tameMin;
|
||||
gp.max = tameMax;
|
||||
gp.curve = 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply group curves
|
||||
for (let si = 0; si < SYNTH_SECTIONS.length; si++) {
|
||||
const gc = preset.groupCurves || {};
|
||||
const secName = SYNTH_SECTIONS[si].name;
|
||||
groupOverrides[si].curve = (gc[secName] !== undefined) ? gc[secName] : 0.5;
|
||||
}
|
||||
|
||||
activeSynthPresetId = presetId;
|
||||
|
||||
// Close the group drawer if open
|
||||
hideGroupDrawer();
|
||||
|
||||
// Re-route outputs through updated overrides
|
||||
if (iml) {
|
||||
routeOutputs(iml.getOutputs());
|
||||
}
|
||||
|
||||
// Update the preset dropdown
|
||||
const $presetSelect = document.getElementById('synth-preset-select');
|
||||
if ($presetSelect) $presetSelect.value = presetId;
|
||||
|
||||
// Save to storage
|
||||
saveState();
|
||||
|
||||
console.log(`[NISPS] Applied synth preset: ${preset.name}`);
|
||||
}
|
||||
|
||||
// ---- SynthVisualizer class ----
|
||||
class SynthVisualizer {
|
||||
constructor(canvas) {
|
||||
|
|
@ -648,6 +747,19 @@ function init() {
|
|||
// Restore saved state (if any)
|
||||
loadState();
|
||||
|
||||
// Wire synth preset selector
|
||||
wireSynthPresets();
|
||||
|
||||
// Check URL ?preset param (overrides localStorage)
|
||||
const urlPreset = urlParams.get('preset');
|
||||
if (urlPreset && SYNTH_PRESETS.some(p => p.id === urlPreset)) {
|
||||
applyPreset(urlPreset);
|
||||
} else if (activeSynthPresetId) {
|
||||
// Restored from localStorage — sync the dropdown
|
||||
const $ps = document.getElementById('synth-preset-select');
|
||||
if ($ps) $ps.value = activeSynthPresetId;
|
||||
}
|
||||
|
||||
// Initial inference
|
||||
iml.setInput(0, joyX);
|
||||
iml.setInput(1, joyY);
|
||||
|
|
@ -1438,6 +1550,22 @@ function wireKeyboard() {
|
|||
}
|
||||
|
||||
// ---- Quick play controls ----
|
||||
// ---- Synth Preset Selector ----
|
||||
function wireSynthPresets() {
|
||||
const $select = document.getElementById('synth-preset-select');
|
||||
if (!$select) return;
|
||||
$select.addEventListener('change', () => {
|
||||
const val = $select.value;
|
||||
if (val === '') {
|
||||
// "Manual" selected — clear preset tracking but don't change overrides
|
||||
activeSynthPresetId = null;
|
||||
saveState();
|
||||
} else {
|
||||
applyPreset(val);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function wireQuickPlayControls() {
|
||||
const quickPlay = document.getElementById('quick-play');
|
||||
const quickPlayIcon = document.getElementById('quick-play-icon');
|
||||
|
|
@ -1879,6 +2007,7 @@ function saveState() {
|
|||
joyX,
|
||||
joyY,
|
||||
groupOverrides,
|
||||
synthPresetId: activeSynthPresetId,
|
||||
};
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
|
||||
} catch (e) {
|
||||
|
|
@ -1924,6 +2053,11 @@ function loadState() {
|
|||
}
|
||||
}
|
||||
|
||||
// Restore synth preset id (just track it, don't re-apply — groupOverrides already restored above)
|
||||
if (typeof state.synthPresetId === 'string') {
|
||||
activeSynthPresetId = state.synthPresetId;
|
||||
}
|
||||
|
||||
// Restore output mode
|
||||
if (state.outputMode && state.outputMode !== outputMode) {
|
||||
setOutputMode(state.outputMode);
|
||||
|
|
|
|||
628
playground/js/synth/presets.js
Normal file
628
playground/js/synth/presets.js
Normal file
|
|
@ -0,0 +1,628 @@
|
|||
// Synth presets for NISPS playground
|
||||
// Each preset defines which of the 126 C15 params are active (ML-controlled)
|
||||
// and which are muted at safe defaults. Organized in 4 tiers of complexity.
|
||||
|
||||
export const SYNTH_PRESETS = [
|
||||
// ======================================================================
|
||||
// TIER 1 — Beginner (15 active params)
|
||||
// ======================================================================
|
||||
{
|
||||
id: 'beginner-1',
|
||||
name: '1.1',
|
||||
tier: 1,
|
||||
description: 'Mellow filtered tones with slow attack and long reverb tail',
|
||||
active: [
|
||||
'Env_A_Att', 'Env_A_Dec_1', 'Env_A_Sus', 'Env_A_Rel',
|
||||
'Osc_A_Fluct', 'Osc_B_Fluct',
|
||||
'Shp_A_Drive', 'Shp_A_Fold',
|
||||
'SV_Flt_Cut', 'SV_Flt_Res', 'SV_Flt_LBH',
|
||||
'Out_Mix_A_Lvl', 'Out_Mix_SVF_Lvl', 'Out_Mix_Lvl',
|
||||
'Reverb_Mix',
|
||||
],
|
||||
overrides: {
|
||||
'Env_A_Att': { min: 0.2, max: 0.7, curve: 0.6 },
|
||||
'Env_A_Dec_1': { min: 0.3, max: 0.8, curve: 0.55 },
|
||||
'Env_A_Sus': { min: 0.3, max: 0.8, curve: 0.6 },
|
||||
'Env_A_Rel': { min: 0.3, max: 0.65, curve: 0.55 },
|
||||
'Osc_A_Fluct': { min: 0.0, max: 0.3, curve: 0.35 },
|
||||
'Osc_B_Fluct': { min: 0.0, max: 0.3, curve: 0.35 },
|
||||
'Shp_A_Drive': { min: 0.05, max: 0.35, curve: 0.35 },
|
||||
'Shp_A_Fold': { min: 0.3, max: 0.7, curve: 0.45 },
|
||||
'SV_Flt_Cut': { min: 0.15, max: 0.55, curve: 0.35 },
|
||||
'SV_Flt_Res': { min: 0.2, max: 0.6, curve: 0.4 },
|
||||
'SV_Flt_LBH': { min: 0.0, max: 0.4, curve: 0.35 },
|
||||
'Out_Mix_A_Lvl': { min: 0.4, max: 0.85, curve: 0.55 },
|
||||
'Out_Mix_SVF_Lvl': { min: 0.3, max: 0.8, curve: 0.55 },
|
||||
'Out_Mix_Lvl': { min: 0.25, max: 0.6, curve: 0.45 },
|
||||
'Reverb_Mix': { min: 0.15, max: 0.55, curve: 0.4 },
|
||||
},
|
||||
mutedOverrides: {},
|
||||
groupCurves: {},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'beginner-2',
|
||||
name: '1.2',
|
||||
tier: 1,
|
||||
description: 'Snappy attack, crisp shaper, filter biased high',
|
||||
active: [
|
||||
'Env_A_Att', 'Env_A_Dec_1', 'Env_A_Sus', 'Env_A_Rel',
|
||||
'Osc_A_Fluct', 'Osc_B_Fluct',
|
||||
'Shp_A_Drive', 'Shp_A_Fold',
|
||||
'SV_Flt_Cut', 'SV_Flt_Res', 'SV_Flt_LBH',
|
||||
'Out_Mix_A_Lvl', 'Out_Mix_SVF_Lvl', 'Out_Mix_Lvl',
|
||||
'Reverb_Mix',
|
||||
],
|
||||
overrides: {
|
||||
'Env_A_Att': { min: 0.0, max: 0.1, curve: 0.3 },
|
||||
'Env_A_Dec_1': { min: 0.15, max: 0.5, curve: 0.35 },
|
||||
'Env_A_Sus': { min: 0.0, max: 0.4, curve: 0.4 },
|
||||
'Env_A_Rel': { min: 0.15, max: 0.45, curve: 0.4 },
|
||||
'Osc_A_Fluct': { min: 0.0, max: 0.2, curve: 0.35 },
|
||||
'Osc_B_Fluct': { min: 0.0, max: 0.2, curve: 0.35 },
|
||||
'Shp_A_Drive': { min: 0.15, max: 0.55, curve: 0.6 },
|
||||
'Shp_A_Fold': { min: 0.2, max: 0.8, curve: 0.55 },
|
||||
'SV_Flt_Cut': { min: 0.5, max: 0.95, curve: 0.65 },
|
||||
'SV_Flt_Res': { min: 0.3, max: 0.7, curve: 0.55 },
|
||||
'SV_Flt_LBH': { min: 0.4, max: 1.0, curve: 0.6 },
|
||||
'Out_Mix_A_Lvl': { min: 0.4, max: 0.85, curve: 0.55 },
|
||||
'Out_Mix_SVF_Lvl': { min: 0.35, max: 0.8, curve: 0.55 },
|
||||
'Out_Mix_Lvl': { min: 0.2, max: 0.55, curve: 0.45 },
|
||||
'Reverb_Mix': { min: 0.0, max: 0.25, curve: 0.35 },
|
||||
},
|
||||
mutedOverrides: {},
|
||||
groupCurves: {},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'beginner-3',
|
||||
name: '1.3',
|
||||
tier: 1,
|
||||
description: 'Slow attack, high sustain, wide filter sweep, deep reverb',
|
||||
active: [
|
||||
'Env_A_Att', 'Env_A_Dec_1', 'Env_A_Sus', 'Env_A_Rel',
|
||||
'Osc_A_Fluct', 'Osc_B_Fluct',
|
||||
'Shp_A_Drive', 'Shp_A_Fold',
|
||||
'SV_Flt_Cut', 'SV_Flt_Res', 'SV_Flt_LBH',
|
||||
'Out_Mix_A_Lvl', 'Out_Mix_SVF_Lvl', 'Out_Mix_Lvl',
|
||||
'Reverb_Mix',
|
||||
],
|
||||
overrides: {
|
||||
'Env_A_Att': { min: 0.3, max: 0.85, curve: 0.6 },
|
||||
'Env_A_Dec_1': { min: 0.4, max: 0.9, curve: 0.6 },
|
||||
'Env_A_Sus': { min: 0.5, max: 1.0, curve: 0.6 },
|
||||
'Env_A_Rel': { min: 0.35, max: 0.7, curve: 0.55 },
|
||||
'Osc_A_Fluct': { min: 0.0, max: 0.4, curve: 0.35 },
|
||||
'Osc_B_Fluct': { min: 0.0, max: 0.4, curve: 0.35 },
|
||||
'Shp_A_Drive': { min: 0.0, max: 0.25, curve: 0.3 },
|
||||
'Shp_A_Fold': { min: 0.4, max: 0.65, curve: 0.45 },
|
||||
'SV_Flt_Cut': { min: 0.1, max: 0.85, curve: 0.45 },
|
||||
'SV_Flt_Res': { min: 0.15, max: 0.55, curve: 0.4 },
|
||||
'SV_Flt_LBH': { min: 0.0, max: 0.6, curve: 0.4 },
|
||||
'Out_Mix_A_Lvl': { min: 0.45, max: 0.85, curve: 0.55 },
|
||||
'Out_Mix_SVF_Lvl': { min: 0.4, max: 0.85, curve: 0.55 },
|
||||
'Out_Mix_Lvl': { min: 0.2, max: 0.55, curve: 0.45 },
|
||||
'Reverb_Mix': { min: 0.2, max: 0.65, curve: 0.45 },
|
||||
},
|
||||
mutedOverrides: {},
|
||||
groupCurves: {},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'beginner-4',
|
||||
name: '1.4',
|
||||
tier: 1,
|
||||
description: 'Zero attack, fast decay, low sustain, bright filter with steep curve',
|
||||
active: [
|
||||
'Env_A_Att', 'Env_A_Dec_1', 'Env_A_Sus', 'Env_A_Rel',
|
||||
'Osc_A_Fluct', 'Osc_B_Fluct',
|
||||
'Shp_A_Drive', 'Shp_A_Fold',
|
||||
'SV_Flt_Cut', 'SV_Flt_Res', 'SV_Flt_LBH',
|
||||
'Out_Mix_A_Lvl', 'Out_Mix_SVF_Lvl', 'Out_Mix_Lvl',
|
||||
'Reverb_Mix',
|
||||
],
|
||||
overrides: {
|
||||
'Env_A_Att': { min: 0.0, max: 0.02, curve: 0.3 },
|
||||
'Env_A_Dec_1': { min: 0.1, max: 0.4, curve: 0.35 },
|
||||
'Env_A_Sus': { min: 0.0, max: 0.15, curve: 0.3 },
|
||||
'Env_A_Rel': { min: 0.1, max: 0.35, curve: 0.4 },
|
||||
'Osc_A_Fluct': { min: 0.0, max: 0.15, curve: 0.3 },
|
||||
'Osc_B_Fluct': { min: 0.0, max: 0.15, curve: 0.3 },
|
||||
'Shp_A_Drive': { min: 0.1, max: 0.45, curve: 0.55 },
|
||||
'Shp_A_Fold': { min: 0.3, max: 0.75, curve: 0.55 },
|
||||
'SV_Flt_Cut': { min: 0.55, max: 1.0, curve: 0.65 },
|
||||
'SV_Flt_Res': { min: 0.25, max: 0.65, curve: 0.6 },
|
||||
'SV_Flt_LBH': { min: 0.3, max: 0.8, curve: 0.55 },
|
||||
'Out_Mix_A_Lvl': { min: 0.4, max: 0.85, curve: 0.55 },
|
||||
'Out_Mix_SVF_Lvl': { min: 0.35, max: 0.8, curve: 0.55 },
|
||||
'Out_Mix_Lvl': { min: 0.2, max: 0.55, curve: 0.45 },
|
||||
'Reverb_Mix': { min: 0.0, max: 0.3, curve: 0.3 },
|
||||
},
|
||||
mutedOverrides: {},
|
||||
groupCurves: {},
|
||||
},
|
||||
|
||||
// ======================================================================
|
||||
// TIER 2 — Intermediate (adds 25 params → 40 total)
|
||||
// ======================================================================
|
||||
{
|
||||
id: 'intermediate-1',
|
||||
name: '2.1',
|
||||
tier: 2,
|
||||
description: 'Lush reverb and echo, wide stereo spread, gentle cabinet warmth',
|
||||
active: [
|
||||
// Tier 1 base
|
||||
'Env_A_Att', 'Env_A_Dec_1', 'Env_A_Sus', 'Env_A_Rel',
|
||||
'Osc_A_Fluct', 'Osc_B_Fluct',
|
||||
'Shp_A_Drive', 'Shp_A_Fold',
|
||||
'SV_Flt_Cut', 'SV_Flt_Res', 'SV_Flt_LBH',
|
||||
'Out_Mix_A_Lvl', 'Out_Mix_SVF_Lvl', 'Out_Mix_Lvl',
|
||||
'Reverb_Mix',
|
||||
// Tier 2 additions
|
||||
'Env_A_BP', 'Env_A_Dec_2', 'Env_A_Gain',
|
||||
'Env_B_Att', 'Env_B_Dec_1', 'Env_B_Sus', 'Env_B_Rel',
|
||||
'Env_C_Att', 'Env_C_Dec_1',
|
||||
'Shp_A_Asym', 'Shp_A_Mix',
|
||||
'SV_Flt_FM', 'SV_Flt_Spread',
|
||||
'Out_Mix_A_Pan', 'Out_Mix_To_FX',
|
||||
'Reverb_Size', 'Reverb_Color',
|
||||
'Echo_Mix', 'Echo_Time',
|
||||
'Flanger_Mix', 'Flanger_Time', 'Flanger_Rate',
|
||||
'Cabinet_Drive', 'Cabinet_Tilt', 'Cabinet_Mix',
|
||||
],
|
||||
overrides: {
|
||||
'Env_A_Att': { min: 0.15, max: 0.6, curve: 0.55 },
|
||||
'Env_A_Dec_1': { min: 0.3, max: 0.8, curve: 0.55 },
|
||||
'Env_A_Sus': { min: 0.3, max: 0.8, curve: 0.6 },
|
||||
'Env_A_Rel': { min: 0.3, max: 0.65, curve: 0.55 },
|
||||
'SV_Flt_Cut': { min: 0.2, max: 0.75, curve: 0.45 },
|
||||
'SV_Flt_Spread': { min: 0.2, max: 0.8, curve: 0.6 },
|
||||
'Out_Mix_A_Pan': { min: 0.2, max: 0.8, curve: 0.5 },
|
||||
'Out_Mix_To_FX': { min: 0.2, max: 0.7, curve: 0.55 },
|
||||
'Reverb_Size': { min: 0.25, max: 0.65, curve: 0.6 },
|
||||
'Reverb_Color': { min: 0.3, max: 0.7, curve: 0.45 },
|
||||
'Reverb_Mix': { min: 0.15, max: 0.6, curve: 0.45 },
|
||||
'Echo_Mix': { min: 0.1, max: 0.5, curve: 0.4 },
|
||||
'Echo_Time': { min: 0.2, max: 0.7, curve: 0.55 },
|
||||
'Flanger_Mix': { min: 0.0, max: 0.3, curve: 0.35 },
|
||||
'Flanger_Time': { min: 0.2, max: 0.6, curve: 0.45 },
|
||||
'Flanger_Rate': { min: 0.1, max: 0.4, curve: 0.4 },
|
||||
'Cabinet_Drive': { min: 0.1, max: 0.35, curve: 0.35 },
|
||||
'Cabinet_Tilt': { min: 0.3, max: 0.7, curve: 0.45 },
|
||||
'Cabinet_Mix': { min: 0.1, max: 0.5, curve: 0.4 },
|
||||
'Out_Mix_Lvl': { min: 0.2, max: 0.55, curve: 0.45 },
|
||||
},
|
||||
mutedOverrides: {},
|
||||
groupCurves: {},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'intermediate-2',
|
||||
name: '2.2',
|
||||
tier: 2,
|
||||
description: 'Short envelopes, echo with rhythmic timing, flanger movement',
|
||||
active: [
|
||||
'Env_A_Att', 'Env_A_Dec_1', 'Env_A_Sus', 'Env_A_Rel',
|
||||
'Osc_A_Fluct', 'Osc_B_Fluct',
|
||||
'Shp_A_Drive', 'Shp_A_Fold',
|
||||
'SV_Flt_Cut', 'SV_Flt_Res', 'SV_Flt_LBH',
|
||||
'Out_Mix_A_Lvl', 'Out_Mix_SVF_Lvl', 'Out_Mix_Lvl',
|
||||
'Reverb_Mix',
|
||||
'Env_A_BP', 'Env_A_Dec_2', 'Env_A_Gain',
|
||||
'Env_B_Att', 'Env_B_Dec_1', 'Env_B_Sus', 'Env_B_Rel',
|
||||
'Env_C_Att', 'Env_C_Dec_1',
|
||||
'Shp_A_Asym', 'Shp_A_Mix',
|
||||
'SV_Flt_FM', 'SV_Flt_Spread',
|
||||
'Out_Mix_A_Pan', 'Out_Mix_To_FX',
|
||||
'Reverb_Size', 'Reverb_Color',
|
||||
'Echo_Mix', 'Echo_Time',
|
||||
'Flanger_Mix', 'Flanger_Time', 'Flanger_Rate',
|
||||
'Cabinet_Drive', 'Cabinet_Tilt', 'Cabinet_Mix',
|
||||
],
|
||||
overrides: {
|
||||
'Env_A_Att': { min: 0.0, max: 0.08, curve: 0.3 },
|
||||
'Env_A_Dec_1': { min: 0.1, max: 0.4, curve: 0.35 },
|
||||
'Env_A_Sus': { min: 0.0, max: 0.25, curve: 0.3 },
|
||||
'Env_A_Rel': { min: 0.1, max: 0.35, curve: 0.35 },
|
||||
'Env_B_Att': { min: 0.0, max: 0.05, curve: 0.3 },
|
||||
'Env_B_Dec_1': { min: 0.1, max: 0.35, curve: 0.35 },
|
||||
'SV_Flt_Cut': { min: 0.3, max: 0.9, curve: 0.55 },
|
||||
'SV_Flt_FM': { min: 0.3, max: 0.7, curve: 0.45 },
|
||||
'Echo_Mix': { min: 0.15, max: 0.55, curve: 0.45 },
|
||||
'Echo_Time': { min: 0.15, max: 0.6, curve: 0.35 },
|
||||
'Flanger_Mix': { min: 0.1, max: 0.5, curve: 0.4 },
|
||||
'Flanger_Time': { min: 0.1, max: 0.5, curve: 0.45 },
|
||||
'Flanger_Rate': { min: 0.2, max: 0.7, curve: 0.45 },
|
||||
'Cabinet_Drive': { min: 0.15, max: 0.45, curve: 0.55 },
|
||||
'Out_Mix_To_FX': { min: 0.25, max: 0.7, curve: 0.55 },
|
||||
'Out_Mix_Lvl': { min: 0.2, max: 0.55, curve: 0.45 },
|
||||
'Reverb_Mix': { min: 0.0, max: 0.2, curve: 0.3 },
|
||||
},
|
||||
mutedOverrides: {},
|
||||
groupCurves: {},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'intermediate-3',
|
||||
name: '2.3',
|
||||
tier: 2,
|
||||
description: 'Long envelope times, filter FM, slow flanger, lush reverb',
|
||||
active: [
|
||||
'Env_A_Att', 'Env_A_Dec_1', 'Env_A_Sus', 'Env_A_Rel',
|
||||
'Osc_A_Fluct', 'Osc_B_Fluct',
|
||||
'Shp_A_Drive', 'Shp_A_Fold',
|
||||
'SV_Flt_Cut', 'SV_Flt_Res', 'SV_Flt_LBH',
|
||||
'Out_Mix_A_Lvl', 'Out_Mix_SVF_Lvl', 'Out_Mix_Lvl',
|
||||
'Reverb_Mix',
|
||||
'Env_A_BP', 'Env_A_Dec_2', 'Env_A_Gain',
|
||||
'Env_B_Att', 'Env_B_Dec_1', 'Env_B_Sus', 'Env_B_Rel',
|
||||
'Env_C_Att', 'Env_C_Dec_1',
|
||||
'Shp_A_Asym', 'Shp_A_Mix',
|
||||
'SV_Flt_FM', 'SV_Flt_Spread',
|
||||
'Out_Mix_A_Pan', 'Out_Mix_To_FX',
|
||||
'Reverb_Size', 'Reverb_Color',
|
||||
'Echo_Mix', 'Echo_Time',
|
||||
'Flanger_Mix', 'Flanger_Time', 'Flanger_Rate',
|
||||
'Cabinet_Drive', 'Cabinet_Tilt', 'Cabinet_Mix',
|
||||
],
|
||||
overrides: {
|
||||
'Env_A_Att': { min: 0.3, max: 0.85, curve: 0.6 },
|
||||
'Env_A_Dec_1': { min: 0.5, max: 0.9, curve: 0.6 },
|
||||
'Env_A_Dec_2': { min: 0.5, max: 0.85, curve: 0.6 },
|
||||
'Env_A_Sus': { min: 0.4, max: 0.9, curve: 0.6 },
|
||||
'Env_A_Rel': { min: 0.35, max: 0.65, curve: 0.55 },
|
||||
'Env_B_Att': { min: 0.2, max: 0.7, curve: 0.6 },
|
||||
'Env_B_Dec_1': { min: 0.4, max: 0.85, curve: 0.6 },
|
||||
'Env_B_Sus': { min: 0.3, max: 0.8, curve: 0.55 },
|
||||
'Env_C_Att': { min: 0.2, max: 0.6, curve: 0.55 },
|
||||
'SV_Flt_Cut': { min: 0.15, max: 0.8, curve: 0.4 },
|
||||
'SV_Flt_FM': { min: 0.25, max: 0.75, curve: 0.45 },
|
||||
'SV_Flt_Spread': { min: 0.2, max: 0.7, curve: 0.55 },
|
||||
'Reverb_Size': { min: 0.3, max: 0.65, curve: 0.55 },
|
||||
'Reverb_Color': { min: 0.3, max: 0.7, curve: 0.45 },
|
||||
'Reverb_Mix': { min: 0.2, max: 0.6, curve: 0.45 },
|
||||
'Echo_Mix': { min: 0.05, max: 0.35, curve: 0.35 },
|
||||
'Flanger_Mix': { min: 0.05, max: 0.35, curve: 0.35 },
|
||||
'Flanger_Rate': { min: 0.05, max: 0.25, curve: 0.35 },
|
||||
'Flanger_Time': { min: 0.2, max: 0.6, curve: 0.45 },
|
||||
'Out_Mix_To_FX': { min: 0.2, max: 0.6, curve: 0.5 },
|
||||
'Out_Mix_Lvl': { min: 0.2, max: 0.55, curve: 0.45 },
|
||||
'Cabinet_Mix': { min: 0.1, max: 0.4, curve: 0.35 },
|
||||
},
|
||||
mutedOverrides: {},
|
||||
groupCurves: {},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'intermediate-4',
|
||||
name: '2.4',
|
||||
tier: 2,
|
||||
description: 'Cabinet drive pushed, asymmetric shaper, compressed envelope, dry',
|
||||
active: [
|
||||
'Env_A_Att', 'Env_A_Dec_1', 'Env_A_Sus', 'Env_A_Rel',
|
||||
'Osc_A_Fluct', 'Osc_B_Fluct',
|
||||
'Shp_A_Drive', 'Shp_A_Fold',
|
||||
'SV_Flt_Cut', 'SV_Flt_Res', 'SV_Flt_LBH',
|
||||
'Out_Mix_A_Lvl', 'Out_Mix_SVF_Lvl', 'Out_Mix_Lvl',
|
||||
'Reverb_Mix',
|
||||
'Env_A_BP', 'Env_A_Dec_2', 'Env_A_Gain',
|
||||
'Env_B_Att', 'Env_B_Dec_1', 'Env_B_Sus', 'Env_B_Rel',
|
||||
'Env_C_Att', 'Env_C_Dec_1',
|
||||
'Shp_A_Asym', 'Shp_A_Mix',
|
||||
'SV_Flt_FM', 'SV_Flt_Spread',
|
||||
'Out_Mix_A_Pan', 'Out_Mix_To_FX',
|
||||
'Reverb_Size', 'Reverb_Color',
|
||||
'Echo_Mix', 'Echo_Time',
|
||||
'Flanger_Mix', 'Flanger_Time', 'Flanger_Rate',
|
||||
'Cabinet_Drive', 'Cabinet_Tilt', 'Cabinet_Mix',
|
||||
],
|
||||
overrides: {
|
||||
'Env_A_Att': { min: 0.0, max: 0.1, curve: 0.3 },
|
||||
'Env_A_Dec_1': { min: 0.15, max: 0.5, curve: 0.4 },
|
||||
'Env_A_Sus': { min: 0.1, max: 0.5, curve: 0.45 },
|
||||
'Env_A_Rel': { min: 0.15, max: 0.4, curve: 0.4 },
|
||||
'Shp_A_Drive': { min: 0.2, max: 0.55, curve: 0.6 },
|
||||
'Shp_A_Fold': { min: 0.2, max: 0.8, curve: 0.55 },
|
||||
'Shp_A_Asym': { min: 0.1, max: 0.7, curve: 0.6 },
|
||||
'Shp_A_Mix': { min: 0.2, max: 0.8, curve: 0.55 },
|
||||
'SV_Flt_Cut': { min: 0.25, max: 0.8, curve: 0.55 },
|
||||
'SV_Flt_Res': { min: 0.3, max: 0.75, curve: 0.55 },
|
||||
'Cabinet_Drive': { min: 0.3, max: 0.58, curve: 0.6 },
|
||||
'Cabinet_Tilt': { min: 0.2, max: 0.65, curve: 0.55 },
|
||||
'Cabinet_Mix': { min: 0.3, max: 0.8, curve: 0.6 },
|
||||
'Out_Mix_Lvl': { min: 0.2, max: 0.5, curve: 0.45 },
|
||||
'Reverb_Mix': { min: 0.0, max: 0.15, curve: 0.3 },
|
||||
'Echo_Mix': { min: 0.0, max: 0.15, curve: 0.3 },
|
||||
'Flanger_Mix': { min: 0.0, max: 0.1, curve: 0.3 },
|
||||
},
|
||||
mutedOverrides: {},
|
||||
groupCurves: {},
|
||||
},
|
||||
|
||||
// ======================================================================
|
||||
// TIER 3 — Advanced (adds 55 params → 95 total)
|
||||
// ======================================================================
|
||||
{
|
||||
id: 'advanced-1',
|
||||
name: '3.1',
|
||||
tier: 3,
|
||||
description: 'Cross-oscillator PM, ring modulation, comb filter resonance, clean effects',
|
||||
active: [
|
||||
// Tier 1
|
||||
'Env_A_Att', 'Env_A_Dec_1', 'Env_A_Sus', 'Env_A_Rel',
|
||||
'Osc_A_Fluct', 'Osc_B_Fluct',
|
||||
'Shp_A_Drive', 'Shp_A_Fold',
|
||||
'SV_Flt_Cut', 'SV_Flt_Res', 'SV_Flt_LBH',
|
||||
'Out_Mix_A_Lvl', 'Out_Mix_SVF_Lvl', 'Out_Mix_Lvl',
|
||||
'Reverb_Mix',
|
||||
// Tier 2
|
||||
'Env_A_BP', 'Env_A_Dec_2', 'Env_A_Gain',
|
||||
'Env_B_Att', 'Env_B_Dec_1', 'Env_B_Sus', 'Env_B_Rel',
|
||||
'Env_C_Att', 'Env_C_Dec_1',
|
||||
'Shp_A_Asym', 'Shp_A_Mix',
|
||||
'SV_Flt_FM', 'SV_Flt_Spread',
|
||||
'Out_Mix_A_Pan', 'Out_Mix_To_FX',
|
||||
'Reverb_Size', 'Reverb_Color',
|
||||
'Echo_Mix', 'Echo_Time',
|
||||
'Flanger_Mix', 'Flanger_Time', 'Flanger_Rate',
|
||||
'Cabinet_Drive', 'Cabinet_Tilt', 'Cabinet_Mix',
|
||||
// Tier 3 additions
|
||||
'Env_B_BP', 'Env_B_Dec_2', 'Env_B_Gain',
|
||||
'Env_C_BP', 'Env_C_Dec_2', 'Env_C_Rel', 'Env_C_Sus',
|
||||
'Osc_A_PM_Self', 'Osc_A_PM_B', 'Osc_A_PM_FB', 'Osc_A_Phase',
|
||||
'Osc_B_PM_Self', 'Osc_B_PM_A', 'Osc_B_PM_FB', 'Osc_B_Phase',
|
||||
'Shp_A_FB_Mix', 'Shp_A_Ring_Mod',
|
||||
'Shp_B_Drive', 'Shp_B_Fold', 'Shp_B_Asym', 'Shp_B_Mix', 'Shp_B_FB_Mix', 'Shp_B_Ring_Mod',
|
||||
'Comb_Flt_Pitch', 'Comb_Flt_Decay', 'Comb_Flt_In_A_B', 'Comb_Flt_AP_Res', 'Comb_Flt_PM',
|
||||
'SV_Flt_In_A_B', 'SV_Flt_Comb_Mix', 'SV_Flt_Par', 'SV_Flt_FM_A_B',
|
||||
'Gap_Flt_Center', 'Gap_Flt_Gap', 'Gap_Flt_Res', 'Gap_Flt_Mix',
|
||||
'FB_Mix_Comb', 'FB_Mix_SVF', 'FB_Mix_FX', 'FB_Mix_Osc', 'FB_Mix_Lvl', 'FB_Mix_Drive',
|
||||
'Out_Mix_B_Lvl', 'Out_Mix_B_Pan', 'Out_Mix_Comb_Lvl',
|
||||
'Flanger_Feedback', 'Flanger_Stereo', 'Flanger_Phase',
|
||||
'Echo_Feedback', 'Echo_Stereo',
|
||||
'Reverb_Pre_Dly', 'Reverb_Chorus',
|
||||
'Cabinet_Fold', 'Cabinet_Asym', 'Cabinet_Hi_Cut', 'Cabinet_Lo_Cut', 'Cabinet_Cab_Lvl',
|
||||
'Unison_Detune',
|
||||
],
|
||||
overrides: {
|
||||
'Env_A_Att': { min: 0.0, max: 0.05, curve: 0.3 },
|
||||
'Env_A_Dec_1': { min: 0.2, max: 0.6, curve: 0.35 },
|
||||
'Env_A_Sus': { min: 0.0, max: 0.2, curve: 0.3 },
|
||||
'Env_A_Rel': { min: 0.2, max: 0.55, curve: 0.4 },
|
||||
'Osc_A_PM_Self': { min: 0.3, max: 0.7, curve: 0.4 },
|
||||
'Osc_A_PM_B': { min: 0.25, max: 0.7, curve: 0.4 },
|
||||
'Osc_A_PM_FB': { min: 0.3, max: 0.65, curve: 0.4 },
|
||||
'Osc_B_PM_Self': { min: 0.3, max: 0.7, curve: 0.4 },
|
||||
'Osc_B_PM_A': { min: 0.25, max: 0.7, curve: 0.4 },
|
||||
'Osc_B_PM_FB': { min: 0.3, max: 0.65, curve: 0.4 },
|
||||
'Shp_A_Ring_Mod': { min: 0.0, max: 0.5, curve: 0.35 },
|
||||
'Shp_B_Ring_Mod': { min: 0.0, max: 0.5, curve: 0.35 },
|
||||
'Comb_Flt_Pitch': { min: 0.3, max: 0.7, curve: 0.45 },
|
||||
'Comb_Flt_Decay': { min: 0.3, max: 0.7, curve: 0.4 },
|
||||
'Comb_Flt_AP_Res': { min: 0.2, max: 0.65, curve: 0.4 },
|
||||
'SV_Flt_Cut': { min: 0.3, max: 0.85, curve: 0.55 },
|
||||
'Reverb_Mix': { min: 0.15, max: 0.5, curve: 0.4 },
|
||||
'Reverb_Size': { min: 0.2, max: 0.55, curve: 0.45 },
|
||||
'Reverb_Chorus': { min: 0.1, max: 0.5, curve: 0.4 },
|
||||
'Echo_Mix': { min: 0.0, max: 0.25, curve: 0.35 },
|
||||
'Flanger_Mix': { min: 0.0, max: 0.2, curve: 0.3 },
|
||||
'FB_Mix_Lvl': { min: 0.1, max: 0.4, curve: 0.4 },
|
||||
'FB_Mix_Drive': { min: 0.1, max: 0.3, curve: 0.35 },
|
||||
'Out_Mix_Lvl': { min: 0.2, max: 0.55, curve: 0.45 },
|
||||
'Out_Mix_B_Lvl': { min: 0.15, max: 0.6, curve: 0.45 },
|
||||
},
|
||||
mutedOverrides: {},
|
||||
groupCurves: {},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'advanced-2',
|
||||
name: '3.2',
|
||||
tier: 3,
|
||||
description: 'Feedback mixer active, dual shapers, gap filter, gritty cabinet',
|
||||
active: [
|
||||
// Tier 1
|
||||
'Env_A_Att', 'Env_A_Dec_1', 'Env_A_Sus', 'Env_A_Rel',
|
||||
'Osc_A_Fluct', 'Osc_B_Fluct',
|
||||
'Shp_A_Drive', 'Shp_A_Fold',
|
||||
'SV_Flt_Cut', 'SV_Flt_Res', 'SV_Flt_LBH',
|
||||
'Out_Mix_A_Lvl', 'Out_Mix_SVF_Lvl', 'Out_Mix_Lvl',
|
||||
'Reverb_Mix',
|
||||
// Tier 2
|
||||
'Env_A_BP', 'Env_A_Dec_2', 'Env_A_Gain',
|
||||
'Env_B_Att', 'Env_B_Dec_1', 'Env_B_Sus', 'Env_B_Rel',
|
||||
'Env_C_Att', 'Env_C_Dec_1',
|
||||
'Shp_A_Asym', 'Shp_A_Mix',
|
||||
'SV_Flt_FM', 'SV_Flt_Spread',
|
||||
'Out_Mix_A_Pan', 'Out_Mix_To_FX',
|
||||
'Reverb_Size', 'Reverb_Color',
|
||||
'Echo_Mix', 'Echo_Time',
|
||||
'Flanger_Mix', 'Flanger_Time', 'Flanger_Rate',
|
||||
'Cabinet_Drive', 'Cabinet_Tilt', 'Cabinet_Mix',
|
||||
// Tier 3 additions
|
||||
'Env_B_BP', 'Env_B_Dec_2', 'Env_B_Gain',
|
||||
'Env_C_BP', 'Env_C_Dec_2', 'Env_C_Rel', 'Env_C_Sus',
|
||||
'Osc_A_PM_Self', 'Osc_A_PM_B', 'Osc_A_PM_FB', 'Osc_A_Phase',
|
||||
'Osc_B_PM_Self', 'Osc_B_PM_A', 'Osc_B_PM_FB', 'Osc_B_Phase',
|
||||
'Shp_A_FB_Mix', 'Shp_A_Ring_Mod',
|
||||
'Shp_B_Drive', 'Shp_B_Fold', 'Shp_B_Asym', 'Shp_B_Mix', 'Shp_B_FB_Mix', 'Shp_B_Ring_Mod',
|
||||
'Comb_Flt_Pitch', 'Comb_Flt_Decay', 'Comb_Flt_In_A_B', 'Comb_Flt_AP_Res', 'Comb_Flt_PM',
|
||||
'SV_Flt_In_A_B', 'SV_Flt_Comb_Mix', 'SV_Flt_Par', 'SV_Flt_FM_A_B',
|
||||
'Gap_Flt_Center', 'Gap_Flt_Gap', 'Gap_Flt_Res', 'Gap_Flt_Mix',
|
||||
'FB_Mix_Comb', 'FB_Mix_SVF', 'FB_Mix_FX', 'FB_Mix_Osc', 'FB_Mix_Lvl', 'FB_Mix_Drive',
|
||||
'Out_Mix_B_Lvl', 'Out_Mix_B_Pan', 'Out_Mix_Comb_Lvl',
|
||||
'Flanger_Feedback', 'Flanger_Stereo', 'Flanger_Phase',
|
||||
'Echo_Feedback', 'Echo_Stereo',
|
||||
'Reverb_Pre_Dly', 'Reverb_Chorus',
|
||||
'Cabinet_Fold', 'Cabinet_Asym', 'Cabinet_Hi_Cut', 'Cabinet_Lo_Cut', 'Cabinet_Cab_Lvl',
|
||||
'Unison_Detune',
|
||||
],
|
||||
overrides: {
|
||||
'Env_A_Att': { min: 0.0, max: 0.15, curve: 0.3 },
|
||||
'Env_A_Dec_1': { min: 0.2, max: 0.6, curve: 0.4 },
|
||||
'Env_A_Sus': { min: 0.1, max: 0.5, curve: 0.45 },
|
||||
'Shp_A_Drive': { min: 0.2, max: 0.55, curve: 0.6 },
|
||||
'Shp_A_Asym': { min: 0.1, max: 0.65, curve: 0.6 },
|
||||
'Shp_B_Drive': { min: 0.15, max: 0.55, curve: 0.6 },
|
||||
'Shp_B_Asym': { min: 0.1, max: 0.6, curve: 0.55 },
|
||||
'Shp_B_FB_Mix': { min: 0.1, max: 0.5, curve: 0.4 },
|
||||
'Gap_Flt_Center': { min: 0.2, max: 0.8, curve: 0.45 },
|
||||
'Gap_Flt_Gap': { min: 0.05, max: 0.4, curve: 0.35 },
|
||||
'Gap_Flt_Res': { min: 0.2, max: 0.7, curve: 0.45 },
|
||||
'Gap_Flt_Mix': { min: 0.2, max: 0.7, curve: 0.45 },
|
||||
'FB_Mix_Comb': { min: 0.3, max: 0.65, curve: 0.45 },
|
||||
'FB_Mix_SVF': { min: 0.3, max: 0.65, curve: 0.45 },
|
||||
'FB_Mix_FX': { min: 0.3, max: 0.6, curve: 0.4 },
|
||||
'FB_Mix_Osc': { min: 0.3, max: 0.6, curve: 0.4 },
|
||||
'FB_Mix_Lvl': { min: 0.2, max: 0.5, curve: 0.4 },
|
||||
'FB_Mix_Drive': { min: 0.15, max: 0.38, curve: 0.4 },
|
||||
'Cabinet_Drive': { min: 0.3, max: 0.58, curve: 0.6 },
|
||||
'Cabinet_Fold': { min: 0.15, max: 0.5, curve: 0.55 },
|
||||
'Cabinet_Asym': { min: 0.1, max: 0.5, curve: 0.55 },
|
||||
'Cabinet_Mix': { min: 0.3, max: 0.75, curve: 0.6 },
|
||||
'Out_Mix_Lvl': { min: 0.18, max: 0.5, curve: 0.45 },
|
||||
'Reverb_Mix': { min: 0.0, max: 0.25, curve: 0.3 },
|
||||
'Echo_Mix': { min: 0.0, max: 0.2, curve: 0.3 },
|
||||
},
|
||||
mutedOverrides: {},
|
||||
groupCurves: {},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'advanced-3',
|
||||
name: '3.3',
|
||||
tier: 3,
|
||||
description: 'Both oscillators through both filters, stereo panning, full effects',
|
||||
active: [
|
||||
// Tier 1
|
||||
'Env_A_Att', 'Env_A_Dec_1', 'Env_A_Sus', 'Env_A_Rel',
|
||||
'Osc_A_Fluct', 'Osc_B_Fluct',
|
||||
'Shp_A_Drive', 'Shp_A_Fold',
|
||||
'SV_Flt_Cut', 'SV_Flt_Res', 'SV_Flt_LBH',
|
||||
'Out_Mix_A_Lvl', 'Out_Mix_SVF_Lvl', 'Out_Mix_Lvl',
|
||||
'Reverb_Mix',
|
||||
// Tier 2
|
||||
'Env_A_BP', 'Env_A_Dec_2', 'Env_A_Gain',
|
||||
'Env_B_Att', 'Env_B_Dec_1', 'Env_B_Sus', 'Env_B_Rel',
|
||||
'Env_C_Att', 'Env_C_Dec_1',
|
||||
'Shp_A_Asym', 'Shp_A_Mix',
|
||||
'SV_Flt_FM', 'SV_Flt_Spread',
|
||||
'Out_Mix_A_Pan', 'Out_Mix_To_FX',
|
||||
'Reverb_Size', 'Reverb_Color',
|
||||
'Echo_Mix', 'Echo_Time',
|
||||
'Flanger_Mix', 'Flanger_Time', 'Flanger_Rate',
|
||||
'Cabinet_Drive', 'Cabinet_Tilt', 'Cabinet_Mix',
|
||||
// Tier 3 additions
|
||||
'Env_B_BP', 'Env_B_Dec_2', 'Env_B_Gain',
|
||||
'Env_C_BP', 'Env_C_Dec_2', 'Env_C_Rel', 'Env_C_Sus',
|
||||
'Osc_A_PM_Self', 'Osc_A_PM_B', 'Osc_A_PM_FB', 'Osc_A_Phase',
|
||||
'Osc_B_PM_Self', 'Osc_B_PM_A', 'Osc_B_PM_FB', 'Osc_B_Phase',
|
||||
'Shp_A_FB_Mix', 'Shp_A_Ring_Mod',
|
||||
'Shp_B_Drive', 'Shp_B_Fold', 'Shp_B_Asym', 'Shp_B_Mix', 'Shp_B_FB_Mix', 'Shp_B_Ring_Mod',
|
||||
'Comb_Flt_Pitch', 'Comb_Flt_Decay', 'Comb_Flt_In_A_B', 'Comb_Flt_AP_Res', 'Comb_Flt_PM',
|
||||
'SV_Flt_In_A_B', 'SV_Flt_Comb_Mix', 'SV_Flt_Par', 'SV_Flt_FM_A_B',
|
||||
'Gap_Flt_Center', 'Gap_Flt_Gap', 'Gap_Flt_Res', 'Gap_Flt_Mix',
|
||||
'FB_Mix_Comb', 'FB_Mix_SVF', 'FB_Mix_FX', 'FB_Mix_Osc', 'FB_Mix_Lvl', 'FB_Mix_Drive',
|
||||
'Out_Mix_B_Lvl', 'Out_Mix_B_Pan', 'Out_Mix_Comb_Lvl',
|
||||
'Flanger_Feedback', 'Flanger_Stereo', 'Flanger_Phase',
|
||||
'Echo_Feedback', 'Echo_Stereo',
|
||||
'Reverb_Pre_Dly', 'Reverb_Chorus',
|
||||
'Cabinet_Fold', 'Cabinet_Asym', 'Cabinet_Hi_Cut', 'Cabinet_Lo_Cut', 'Cabinet_Cab_Lvl',
|
||||
'Unison_Detune',
|
||||
],
|
||||
overrides: {
|
||||
'Env_A_Att': { min: 0.05, max: 0.5, curve: 0.45 },
|
||||
'Env_B_Att': { min: 0.05, max: 0.5, curve: 0.45 },
|
||||
'Osc_A_PM_B': { min: 0.2, max: 0.65, curve: 0.45 },
|
||||
'Osc_B_PM_A': { min: 0.2, max: 0.65, curve: 0.45 },
|
||||
'SV_Flt_In_A_B': { min: 0.2, max: 0.8, curve: 0.5 },
|
||||
'Comb_Flt_In_A_B': { min: 0.2, max: 0.8, curve: 0.5 },
|
||||
'Out_Mix_A_Lvl': { min: 0.3, max: 0.8, curve: 0.55 },
|
||||
'Out_Mix_B_Lvl': { min: 0.3, max: 0.8, curve: 0.55 },
|
||||
'Out_Mix_A_Pan': { min: 0.15, max: 0.45, curve: 0.4 },
|
||||
'Out_Mix_B_Pan': { min: 0.55, max: 0.85, curve: 0.6 },
|
||||
'Out_Mix_Comb_Lvl': { min: 0.15, max: 0.6, curve: 0.45 },
|
||||
'Out_Mix_Lvl': { min: 0.18, max: 0.5, curve: 0.45 },
|
||||
'SV_Flt_Cut': { min: 0.15, max: 0.85, curve: 0.45 },
|
||||
'SV_Flt_Spread': { min: 0.15, max: 0.75, curve: 0.55 },
|
||||
'Flanger_Stereo': { min: 0.2, max: 0.8, curve: 0.6 },
|
||||
'Echo_Stereo': { min: 0.2, max: 0.8, curve: 0.6 },
|
||||
'Reverb_Mix': { min: 0.1, max: 0.5, curve: 0.4 },
|
||||
'Echo_Mix': { min: 0.05, max: 0.4, curve: 0.4 },
|
||||
'Flanger_Mix': { min: 0.05, max: 0.35, curve: 0.35 },
|
||||
'Unison_Detune': { min: 0.0, max: 0.3, curve: 0.3 },
|
||||
'FB_Mix_Lvl': { min: 0.15, max: 0.45, curve: 0.4 },
|
||||
},
|
||||
mutedOverrides: {},
|
||||
groupCurves: {},
|
||||
},
|
||||
|
||||
// ======================================================================
|
||||
// TIER 4 — Expert (all 126 params active)
|
||||
// ======================================================================
|
||||
{
|
||||
id: 'expert-1',
|
||||
name: '4.1',
|
||||
tier: 4,
|
||||
description: 'All parameters active with conservative tame-derived ranges',
|
||||
active: null, // null means ALL params active
|
||||
overrides: {
|
||||
// Use tame-derived defaults for everything (no per-param overrides)
|
||||
},
|
||||
mutedOverrides: {},
|
||||
groupCurves: {},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'expert-2',
|
||||
name: '4.2',
|
||||
tier: 4,
|
||||
description: 'All parameters active with wider ranges for extreme exploration',
|
||||
active: null, // all active
|
||||
overrides: {
|
||||
// Push ranges wider than tame defaults — halve the tame constraint
|
||||
'Osc_A_PM_Self': { min: 0.1, max: 0.9, curve: 0.45 },
|
||||
'Osc_A_PM_B': { min: 0.1, max: 0.9, curve: 0.45 },
|
||||
'Osc_A_PM_FB': { min: 0.15, max: 0.85, curve: 0.45 },
|
||||
'Osc_B_PM_Self': { min: 0.1, max: 0.9, curve: 0.45 },
|
||||
'Osc_B_PM_A': { min: 0.1, max: 0.9, curve: 0.45 },
|
||||
'Osc_B_PM_FB': { min: 0.15, max: 0.85, curve: 0.45 },
|
||||
'Shp_A_Drive': { min: 0.0, max: 0.8, curve: 0.55 },
|
||||
'Shp_B_Drive': { min: 0.0, max: 0.8, curve: 0.55 },
|
||||
'Shp_A_FB_Mix': { min: 0.0, max: 0.85, curve: 0.45 },
|
||||
'Shp_B_FB_Mix': { min: 0.0, max: 0.85, curve: 0.45 },
|
||||
'Comb_Flt_Decay': { min: 0.15, max: 0.85, curve: 0.45 },
|
||||
'Comb_Flt_AP_Res': { min: 0.0, max: 0.9, curve: 0.4 },
|
||||
'Comb_Flt_PM': { min: 0.15, max: 0.85, curve: 0.45 },
|
||||
'SV_Flt_Res': { min: 0.0, max: 0.9, curve: 0.4 },
|
||||
'SV_Flt_FM': { min: 0.1, max: 0.9, curve: 0.45 },
|
||||
'Gap_Flt_Res': { min: 0.0, max: 0.9, curve: 0.4 },
|
||||
'FB_Mix_Comb': { min: 0.15, max: 0.85, curve: 0.45 },
|
||||
'FB_Mix_SVF': { min: 0.15, max: 0.85, curve: 0.45 },
|
||||
'FB_Mix_FX': { min: 0.15, max: 0.85, curve: 0.45 },
|
||||
'FB_Mix_Osc': { min: 0.15, max: 0.85, curve: 0.45 },
|
||||
'FB_Mix_Lvl': { min: 0.0, max: 0.65, curve: 0.4 },
|
||||
'FB_Mix_Drive': { min: 0.0, max: 0.5, curve: 0.4 },
|
||||
'Out_Mix_Lvl': { min: 0.1, max: 0.8, curve: 0.45 },
|
||||
'Out_Mix_Drive': { min: 0.0, max: 0.65, curve: 0.55 },
|
||||
'Cabinet_Drive': { min: 0.0, max: 0.75, curve: 0.55 },
|
||||
'Flanger_Feedback':{ min: 0.1, max: 0.9, curve: 0.45 },
|
||||
'Flanger_Cross_FB':{ min: 0.15, max: 0.85, curve: 0.45 },
|
||||
'Echo_Feedback': { min: 0.0, max: 0.85, curve: 0.4 },
|
||||
'Echo_Mix': { min: 0.0, max: 0.8, curve: 0.4 },
|
||||
'Reverb_Size': { min: 0.0, max: 0.8, curve: 0.45 },
|
||||
'Reverb_Mix': { min: 0.0, max: 0.8, curve: 0.4 },
|
||||
'Reverb_Send': { min: 0.0, max: 1.0, curve: 0.5 },
|
||||
},
|
||||
mutedOverrides: {},
|
||||
groupCurves: {},
|
||||
},
|
||||
];
|
||||
|
||||
// Tier metadata for UI grouping
|
||||
export const PRESET_TIERS = [
|
||||
{ tier: 1, label: 'Beginner' },
|
||||
{ tier: 2, label: 'Intermediate' },
|
||||
{ tier: 3, label: 'Advanced' },
|
||||
{ tier: 4, label: 'Expert' },
|
||||
];
|
||||
Loading…
Reference in a new issue