Contracts

The shared contracts every surface agrees on: parameter descriptors and their normalization, timed events, and the module face props.

Contracts are the small, dependency-free types that the module, the browser runtime, the native shell and the interface all share. They do no audio work. Their value is that every surface reads them the same way. They are exported from maruaudio/contracts, and most authors meet them through the Audio SDK rather than importing them directly.

This page explains the ideas. The exported types in your installed version are the exact reference.

Parameters

A module's parameter schema is an ordered list of descriptors. Each descriptor has a dotted path, which is also its stable automation id, plus a label, a group, a type (float, enum or bool) and, where relevant, a range, step, default, units, options and a response curve (taper).

Order matters to hosts: it is the order parameters are registered in. Treat a schema's paths and order as part of the module's identity.

A descriptor can also carry optional hints, such as a default MIDI controller or a role a host may act on (for example, where to write the host tempo). These never change what the parameter means.

One normalization for every surface

Hosts and controllers speak in positions from 0 to 1, while your DSP speaks in engine values such as hertz or decibels. normalize and denormalize convert between the two, applying the parameter's range, step and taper:

ts
import { denormalize, normalize } from "maruaudio/contracts"

const value = denormalize(descriptor, 0.5)
const position = normalize(descriptor, value)

Every surface uses this one conversion: host automation, MIDI CC, faces and the native plugin shell, where the same algorithm is generated for C. A knob, a controller and an automation lane therefore land on the same value. Shape a parameter's feel with its taper, not with a face-level curve.

Events

Events are timed by sample frame within the current render block, never by seconds, so every host computes the same timing. They cover parameter changes, note on and off with optional note identity, and per-note expression.

sortEvents puts events in delivery order: by frame, with parameter changes before notes on the same frame, and expression after the note it applies to. A note that starts on the frame its cutoff changes hears the new cutoff.

Faces

A face receives AudioModuleFaceProps: parameter values and setters, host facts and optional host capabilities such as generation or license state. It presents and edits; it never generates audio or opens devices. See Module UI.

Further reading