import { PARAM_GROUPS, type ParamSpec, type BassParams } from '../params'; interface Props { params: BassParams; onChange: (key: keyof BassParams, value: number | boolean) => void; } const SLIDER_STEPS = 1000; function sliderFromValue(spec: ParamSpec, v: number): number { if (spec.log) { const t = (Math.log(v) - Math.log(spec.min)) / (Math.log(spec.max) - Math.log(spec.min)); return Math.round(t * SLIDER_STEPS); } return Math.round(((v - spec.min) / (spec.max - spec.min)) * SLIDER_STEPS); } function valueFromSlider(spec: ParamSpec, s: number): number { const t = s / SLIDER_STEPS; let v: number; if (spec.log) { v = Math.exp(Math.log(spec.min) + t * (Math.log(spec.max) - Math.log(spec.min))); // keep three significant digits so the displayed number stays readable const mag = 10 ** Math.floor(Math.log10(Math.abs(v))); v = Math.round((v / mag) * 100) / 100 * mag; } else { v = spec.min + t * (spec.max - spec.min); if (spec.step) v = Math.round(v / spec.step) * spec.step; } if (spec.integer) v = Math.round(v); return Math.min(spec.max, Math.max(spec.min, v)); } function formatValue(v: number): string { if (v === 0) return '0'; const a = Math.abs(v); if (a >= 1e5 || a < 1e-3) return v.toExponential(2); return String(Math.round(v * 1e6) / 1e6); } function ParamRow({ spec, params, onChange }: Props & { spec: ParamSpec }) { const v = params[spec.key] as number; return (