K

Parameters

The ParamDef shape, control modifiers, factories, and how values are read.

Params are declared in describe with m.addParam(def) or m.addSetting(def). Both take a ParamDef. A param renders as an on-brand control and reads back in process by its declaration index.

ParamDef

new ParamDef(id, name, shortName, min, max, default, modulatable)
ArgumentTypeMeaning
idstringStable key, used to resolve the param by name.
namestringFull display label.
shortNamestringCompact label for tight layouts.
min, maxnumberRange.
defaultnumberInitial value.
modulatableboolWhether it can be a modulation target. Defaults to false.

Params vs settings

Same ParamDef, two manifest calls:

CallModulatableUse for
m.addParam(def)Yes (if modulatable: true)A continuous control: cutoff, gain, depth. Gets a depth wheel and per-sample modulation.
m.addSetting(def)No (forced off)A mode, a count, an on/off. Never a modulation target.

A setting is still a param. Bind it with param("id") in ui.ts and read it with ctx.param(idx). The setting("id") binding is for built-in node settings, not devices.

Control modifiers

Chain these on a ParamDef to change how it renders or feels. A bare param is a knob.

ModifierEffect
.asDragNumber()A draggable number.
.asToggle()An on/off toggle. Use min 0, max 1.
.asToggleGroup([...])A segmented button bar. Value is the option index (min + i).
.asSelect([...])A dropdown. Value is the option index (min 0, max length - 1).
.unit(UNIT_HZ)Show and parse a unit. Also UNIT_DB, UNIT_SECONDS, UNIT_PERCENT, UNIT_SEMITONES, UNIT_CENTS, UNIT_DEGREES, UNIT_DB_GAIN, UNIT_RAW.
.logarithmic()True logarithmic sweep (equal octave spacing). For frequency; needs min > 0.
.skew(exponent)Power-curve skew. exponent < 1 biases resolution to the low end (time, depth).
.precision(digits)Fix the readout to digits decimal places. Default derives from the range.
.step(size)Quantize the knob to detents size apart (must be positive and no larger than the range).
.integer()Quantize to whole numbers. Shorthand for .step(1).

Modifiers chain and return the ParamDef:

m.addParam(
  new ParamDef("cutoff", "Cutoff", "Cut", 20, 20000, 1000, true)
    .unit(UNIT_HZ)
    .logarithmic(),
);

Static factories

Less boilerplate for common shapes. The harmony selects read the catalog index straight into ScaleType / ChordQuality.

FactoryBuilds
ParamDef.freq(id, name, short, min, max, def)A modulatable Hz knob, log-skewed.
ParamDef.time(id, name, short, min, max, def)A modulatable seconds knob, low-end-biased skew.
ParamDef.scaleSelect(id, name, short, def?)A select over every scale (value = ScaleType index).
ParamDef.rootSelect(id, name, short, def?)A key/root select (value = pitch class 0-11).
ParamDef.chordSelect(id, name, short, def?)A chord-quality select (value = ChordQuality index).

The three selects are non-modulatable by design. Pair them with m.addSetting(...). See Harmony.

Reading values

Inside process, params are read by their declaration order (0, 1, 2...):

const cutoff = ctx.modulatedParam(0, i); // first param, with modulation
const mode = ctx.param(1); // second param, plain value

Don't hardcode the index. Resolve it by name once in prepare and cache it:

let cutoffIdx: i32 = -1;
prepare(sampleRate: f64, maxBlock: i32): void {
  cutoffIdx = ctx.paramIndex("cutoff"); // -1 if the id is missing
}
process(ctx: Ctx): void {
  const cutoff = ctx.modulatedParam(cutoffIdx, i);
}

Use modulatedParam for anything modulatable, and param for a value you read once per block or for a setting. Modulation is additive on the host side, so multiplying by mod(...) is wrong: read modulatedParam and use it directly.