Generated API reference
This reference describes the current build, including unreleased checkout additions; it does not retroactively change historical release archives.
Generated from the compiler-emitted declarations for every package export. Export tables identify the public import surfaces; the complete declaration files below include their supporting types, comments, overloads and private-member markers. Supporting modules are not additional public import promises. No signatures are handwritten or abridged.
opm.js/voices/normalize.js
| Export | Kind | Declaration |
|---|
normalizeVoice | value / type where applicable | voices/normalize.d.ts |
|---|
prepareVoice | value / type where applicable | voices/normalize.d.ts |
|---|
opm.js/voices/brass.js
| Export | Kind | Declaration |
|---|
brass | value / type where applicable | voices/brass.d.ts |
|---|
opm.js/voices/examples.js
| Export | Kind | Declaration |
|---|
examples | value / type where applicable | voices/examples.d.ts |
|---|
opm.js/voices/gm-map.js
| Export | Kind | Declaration |
|---|
gmDrumVoices | value / type where applicable | voices/gm-map.d.ts |
|---|
gmProgramVoices | value / type where applicable | voices/gm-map.d.ts |
|---|
opm.js/voices/original.js
| Export | Kind | Declaration |
|---|
originalPresets | value / type where applicable | voices/original.d.ts |
|---|
opm.js/voices/voice.schema.js
| Export | Kind | Declaration |
|---|
voiceSchema | value / type where applicable | voices/voice.schema.d.ts |
|---|
api/arrangement.d.ts
import type { OPM } from './index.js';
import type { ArrangementDefinition } from '../core/arrangement-definition.js';
export type { ArrangementLayer, ArrangementSection } from '../core/arrangement-definition.js';
import type { BarBeat, TempoPoint } from '../core/transport.js';
export interface ArrangementOptions extends ArrangementDefinition {
bpm?: number;
horizon?: number;
interval?: number;
onError?: (error: Error) => void;
}
export interface ArrangementChangeOptions {
/** Boundary in quarter notes, or the meter-defined beat/bar; default bar. Never earlier than already admitted notes. */
quantize?: 'beat' | 'bar' | number;
/** Removed layers may finish naturally instead of being released at the boundary. Default false. */
preserveNotes?: boolean;
/** Linear gain fade in seconds, 0..10; default 0. Shared layers remain continuous. */
fade?: number;
}
export interface ArrangementGainOptions {
quantize?: 'beat' | 'bar' | number;
fade?: number;
}
export type ArrangementState = 'stopped' | 'starting' | 'running' | 'paused' | 'disposed';
export interface ArrangementSnapshot {
readonly state: ArrangementState;
/** Global quarter-note position; a paused arrangement reports where it will resume. */
readonly position: number;
readonly musicalPosition: Readonly<BarBeat>;
readonly section: string;
/** Layers effective at position. */
readonly layers: readonly string[];
/** Committed changes after the current position. */
readonly pending: readonly Readonly<{
beat: number;
section: string;
layers: readonly string[];
}>[];
/** Notes refused by voice-priority admission; they are not an arrangement failure. */
readonly priorityDrops: number;
readonly tempoMap: readonly Readonly<TempoPoint>[];
}
export interface Arrangement {
readonly state: ArrangementState;
readonly snapshot: ArrangementSnapshot;
start(): Promise<void>;
resume(): Promise<void>;
/** Releases owned notes. Resume restarts musically at the paused beat; no DSP checkpoint is restored. */
pause(): void;
/** Releases owned notes and rewinds to beat 0. */
stop(): void;
switchSection(name: string, options?: ArrangementChangeOptions): number;
setLayer(name: string, enabled: boolean, options?: ArrangementChangeOptions): number;
setLayerGain(name: string, gain: number, options?: ArrangementGainOptions): number;
/** Replaces tempo from the current beat onward; notes already admitted keep their admitted audio times. */
setTempo(bpm: number): void;
setTempoMap(map: readonly TempoPoint[]): void;
pump(): void;
dispose(): void;
}
/**
* Looping, quantized adaptive music for one OPM instance. Layers are aligned to the global beat grid, so a layer
* shared by two sections is one continuous schedule: its sounding gates are neither retriggered nor stopped when
* unrelated layers change. Changes are committed at a boundary no earlier than the notes already admitted.
*/
export declare function createArrangement(opm: OPM, options: ArrangementOptions): Arrangement;
api/fx.d.ts
import type { StereoEffectsOptions } from '../core/fx.js';
export interface EffectsEvent {
type: 'error';
error: Error;
}
export interface EffectsOptions {
workletUrl?: string | URL;
params?: StereoEffectsOptions;
onEvent?: (event: EffectsEvent) => void;
}
export interface OpmEffects {
readonly input: AudioNode;
readonly output: AudioNode;
/** Resolves once the module/node have been created; context playback is host-owned. */
readonly ready: Promise<void>;
update(params: StereoEffectsOptions): void;
reset(): void;
dispose(): void;
}
/** Optional stereo effect insert. Does not connect, resume, suspend or close the host context. */
export declare function createEffects(context: BaseAudioContext, options?: EffectsOptions): Promise<OpmEffects>;
api/index.d.ts
import type { CompleteVoiceInput, NormalizedVoice, VoiceInput } from '../voices/schema.js';
import type { NoteControls, QualityProfile, SynthOptions } from '../core/synth.js';
import type { TuningOptions } from '../core/tuning.js';
export type { ADSR, LFO, LFOInput, LegacyLFO, LegacyLFOV5, LFOTargets, LFOTargetsInput, KeyScale, Operator, OperatorWaveform, Voice, VoiceInput, FrozenVoice, FrozenOperator, NormalizedVoice, PreparedVoice, PitchEnvelope, LegacyVoiceV3, LegacyVoiceV4, LegacyVoiceV5, LegacyVoiceV6 } from '../voices/schema.js';
export type { NoteControls, SynthOptions, QualityProfile } from '../core/synth.js';
export type { TuningOptions, NormalizedTuning } from '../core/tuning.js';
export { createEffects } from './fx.js';
export type { OpmEffects, EffectsOptions, EffectsEvent } from './fx.js';
export { createStereoEffects, applyEffects } from '../core/fx.js';
export type { StereoEffects, StereoEffectsOptions, ChorusOptions, ReverbOptions } from '../core/fx.js';
export { playSequence, streamSequence } from './sequence.js';
export type { PlaySequenceOptions, SequencePlayback, SequenceStreamOptions, SequenceStream } from './sequence.js';
export type { SequenceEvent, SequenceNoteEvent, SequenceStopEvent, SequenceControlEvent } from '../core/sequence.js';
export { createTransport, beatsToSeconds, secondsToBeats, beatToBarBeat, barBeatToBeat, normalizeTempoMap, quantizeBeat, swingBeat, swingBeatEvents } from './transport.js';
export type { BeatSequenceEvent, TransportLoop, TransportState, TransportOptions, TransportSnapshot, MusicalTransport, TempoPoint, TimeSignature, BarBeat, BeatQuantization } from './transport.js';
export { createArrangement } from './arrangement.js';
export type { Arrangement, ArrangementLayer, ArrangementSection, ArrangementOptions, ArrangementChangeOptions, ArrangementGainOptions, ArrangementState, ArrangementSnapshot } from './arrangement.js';
export { createMidiAdapter, requestMidiAccess } from './midi.js';
export type { MidiAdapter, MidiAdapterOptions, MidiAdapterSnapshot, MidiAccessLike, MidiInputLike, MidiMessageEventLike, MidiNavigatorLike, MidiControllerMapping, MidiScalarControl, MidiOperatorControl } from './midi.js';
export { importMidiFile, exportMidiFile, MAX_MIDI_FILE_BYTES, MAX_MIDI_FILE_TRACKS, MAX_MIDI_FILE_EVENTS } from '../core/midi-file.js';
export type { MidiFileWarningCode, MidiFileWarning, MidiImportOptions, MidiImportResult, MidiExportOptions, MidiFileControlKind, MidiFilePreservedControl, MidiFileLossSummary } from '../core/midi-file.js';
export type { MidiVoiceMap } from '../core/midi-state.js';
export { gmProgramVoices, gmDrumVoices } from '../voices/gm-map.js';
export { parseScoreProject, serializeScoreProject, compileBeatSequence, MAX_SCORE_PROJECT_BYTES, MAX_SCORE_PROJECT_VOICES, parseArrangementProject, serializeArrangementProject, MAX_ARRANGEMENT_PROJECT_BYTES, MAX_ARRANGEMENT_PROJECT_VOICES } from '../core/project.js';
export type { ScoreProject, ScoreProjectSettings, BeatSequenceOptions, ArrangementProject } from '../core/project.js';
export type { ArrangementDefinition } from '../core/arrangement-definition.js';
export { VERSION } from '../version.js';
export { createPerformance } from './performance.js';
export type { Performance, PerformanceOptions, PerformancePartOptions, PerformancePartControls, PerformanceNoteOptions, PerformanceNoteOffOptions, PerformanceKeySnapshot, PerformancePartSnapshot } from './performance.js';
export { renderSequenceInWorker } from './render-worker.js';
export type { WavSink, WorkerRenderOptions, WorkerRenderProgress, WorkerRenderResult, WorkerRenderPhase, WorkerRenderPhaseStatus, WorkerRenderPhaseDiagnostics } from './render-worker.js';
export type NoteState = 'accepted' | 'started' | 'released' | 'ended' | 'stolen' | 'cancelled' | 'rejected';
export interface NoteEvent {
type: 'note';
id: number;
state: NoteState;
reason?: string;
/** Actual AudioContext sample frame and seconds at admission, dispatch or completion. */
frame: number;
time: number;
}
export interface DiagnosticsEvent {
type: 'diagnostics';
requestId: number;
activeVoices: number;
pendingEvents: number;
errors: number;
rejectedNotes: number;
}
export interface ErrorEvent {
type: 'error';
error: Error;
}
export type CommandName = 'stop' | 'updateNote' | 'allNotesOff' | 'panic' | 'setMixGain' | 'setTuning';
export interface CommandEvent {
type: 'command';
command: CommandName;
commandId?: number;
id?: number;
/** Accepted means admitted or immediately applied, not a future execution guarantee. */
state: 'accepted' | 'rejected';
reason?: string;
frame: number;
time: number;
}
export type ContextState = AudioContextState | 'interrupted';
export interface ContextEvent {
type: 'context';
state: ContextState;
frame: number;
time: number;
}
export interface ResetEvent {
type: 'reset';
reason: 'close' | 'failure' | 'panic' | 'interruption';
frame: number;
time: number;
/** Initiating panic command, when available; independent of receipt-cache eviction. */
commandId?: number;
}
export type OPMEvent = NoteEvent | DiagnosticsEvent | CommandEvent | ContextEvent | ResetEvent | ErrorEvent;
export interface CommandWaitOptions {
/** Milliseconds, default 5000; an integer in 1..60000. */
timeout?: number;
signal?: AbortSignal;
}
/** Admission rejection, not an audio execution/completion result. */
export declare class CommandRejectedError extends Error {
readonly event: Readonly<CommandEvent>;
constructor(event: CommandEvent);
}
export interface OPMOptions {
sampleRate?: number;
/** Borrowed context: OPM never closes or suspends it. */
context?: AudioContext;
/** Omit to connect to context.destination; null disables automatic connection. */
destination?: AudioNode | null;
/** Same-origin HTTPS (or secure loopback HTTP) module; default stays relative to this API module. */
workletUrl?: string | URL;
mixGain?: number;
tuning?: TuningOptions;
stealing?: SynthOptions['stealing'];
/** Immutable synthesis profile; standard preserves the default sound. */
quality?: QualityProfile;
/** Logical polyphony, an integer in 1..32; default 8. Release tails occupy voices. */
maxVoices?: number;
/** Cancel all voices/events on interruption, or preserve direct-note state until resume. */
interruption?: 'cancel' | 'preserve';
onEvent?: (event: OPMEvent) => void;
}
interface PlayNoteBase {
voice?: string | VoiceInput;
note: number;
/** A late start keeps its full duration; drop rejects even if processing is delayed. */
late?: 'start' | 'drop';
/** null (the default) holds until stop; a number sets a duration before release. */
duration?: number | null;
velocity?: number;
pan?: number;
/** Admission importance, integer 0..127; larger values cannot be stolen by lower-priority notes. Default 0. */
voicePriority?: number;
}
export type PlayNoteOptions = PlayNoteBase & (
/** Relative delay in seconds; cannot be combined with at. */
{
time?: number;
at?: never;
} |
/** Absolute AudioContext seconds, at most 60 seconds ahead. Past times are allowed. */
{
at: number;
time?: never;
});
export interface ScheduledNoteOptions {
/** Absolute AudioContext seconds. Stop without at is immediate, including cancellation. */
at?: number;
}
/** Explicit cancellation is immediate-only; ordinary stops preserve tail automation. */
export type StopOptions = ScheduledNoteOptions & {
cancelControls?: never;
} | {
at?: never;
cancelControls?: boolean;
};
/** Browser-facing facade. Import Synth from ../core/synth.js for offline rendering. */
export declare class OPM {
readonly sampleRate: number | undefined;
get quality(): QualityProfile;
get maxVoices(): number;
/** Defensive map snapshot; loaded patches are deeply frozen. Use loadVoice to replace one. */
get voices(): ReadonlyMap<string, NormalizedVoice>;
readonly context: AudioContext | null;
readonly node: AudioWorkletNode | null;
onEvent?: (event: OPMEvent) => void;
constructor(options?: OPMOptions);
loadVoice(name: string, voice: VoiceInput): void;
/** Atomically replaces the registry. Only an empty plain array (not JSON "[]") clears it. */
replaceVoiceBank(source: string | readonly CompleteVoiceInput[]): void;
removeVoice(name: string): boolean;
/** Canonical versioned entries, detached from the immutable registry and UTF-8 bounded. */
exportVoiceBank(): string;
/** Independent subscription; close preserves it for restart, dispose removes it permanently. */
subscribe(listener: (event: OPMEvent) => void): () => void;
start(): Promise<void>;
resume(): Promise<void>;
connect(destination: AudioNode): this;
disconnect(destination?: AudioNode): this;
playNote(options: PlayNoteOptions): number;
stop(id: number, options?: StopOptions): number;
/** Pending updates apply at onset. At equal frames stop precedes onset, then controls. */
updateNote(id: number, controls: NoteControls, options?: ScheduledNoteOptions): number;
/** Cancel all pending events and release all active gates, preserving release tails. */
allNotesOff(): number;
/** Immediate silence, including release/stealing tails; routing and patch cache survive. */
panic(): number;
setMixGain(gain: number): number;
setTuning(tuning: TuningOptions): number;
/** Wait for admission only. At most 128 receipts and 64 live waits; live waits prevent eviction. */
waitForCommand(commandId: number, options?: CommandWaitOptions): Promise<CommandEvent>;
getDiagnostics(): Promise<DiagnosticsEvent>;
close(): Promise<void>;
/** Permanently closes OPM and releases host callbacks; never closes a borrowed context. */
dispose(): Promise<void>;
}
export interface LookaheadWindow {
/** Half-open absolute AudioContext time window. Missed windows are skipped after a stall. */
from: number;
to: number;
/** Maximum notes the callback may return in this batch. */
maxNotes: number;
}
export type LookaheadNote = PlayNoteOptions & {
at: number;
duration: number;
};
export interface LookaheadOptions {
/** Seconds, default 0.2; bounded to 0.02..10 and greater than interval. */
horizon?: number;
/** Seconds between pumps, default 0.025; bounded to 0.005..1. */
interval?: number;
/** Maximum batch size, default 32; bounded to 1..128. */
maxNotes?: number;
/** Timer/callback failures stop scheduling and are delivered here. */
onError: (error: Error) => void;
}
export interface LookaheadScheduler {
readonly running: boolean;
/** Call from a user gesture; initializes/resumes OPM, then fills the first window. */
start(): Promise<void>;
/** Cancels pending notes and releases this scheduler's active gates, not other notes. */
stop(): void;
/** Stops and permanently prevents restart; does not close OPM. */
dispose(): void;
}
/** Bounded timer-driven admission, not timer-driven note release. Audio frames own all gates. */
export declare function createLookaheadScheduler(opm: OPM, schedule: (window: LookaheadWindow) => readonly LookaheadNote[], options: LookaheadOptions): LookaheadScheduler;
api/midi.d.ts
import type { Performance } from './performance.js';
import type { MidiVoiceMap } from '../core/midi-state.js';
export type MidiScalarControl = 'pitch' | 'expression' | 'gain' | 'pan' | 'modulation' | 'feedback' | 'lfoRate' | 'amDepth' | 'pmDepth';
export type MidiOperatorControl = 'operatorLevels' | 'operatorRatios' | 'operatorFrequencies';
interface MidiControllerRange {
/** CC number 0..127, excluding RPN selection/pedal/reset/panic CC64/100/101/120/121/123. */
controller: number;
/** CC0 maps to min and CC127 to max; both endpoints must be valid engine controls. */
min: number;
max: number;
/** Seconds 0..10; pitch uses glide, other fields use the engine control ramp. */
ramp: number;
}
/** One CC targets one scalar or one operator element; no executable callbacks are accepted. */
export type MidiControllerMapping = MidiControllerRange & ({
field: MidiScalarControl;
reset?: number;
} | {
field: MidiOperatorControl;
operator: 0 | 1 | 2 | 3;
reset?: number | null;
});
/** Structural subset of Web MIDI, so hosts and tests can inject a real or simulated access object. */
export interface MidiMessageEventLike {
readonly data: Uint8Array | null;
}
export interface MidiInputLike {
readonly id: string;
readonly name?: string | null;
readonly state?: string;
readonly connection?: string;
open?(): Promise<unknown>;
addEventListener(type: 'midimessage', listener: (event: MidiMessageEventLike) => void): void;
removeEventListener(type: 'midimessage', listener: (event: MidiMessageEventLike) => void): void;
}
export interface MidiAccessLike {
readonly inputs: ReadonlyMap<string, MidiInputLike>;
addEventListener(type: 'statechange', listener: () => void): void;
removeEventListener(type: 'statechange', listener: () => void): void;
}
export interface MidiNavigatorLike {
requestMIDIAccess?(options?: {
sysex?: boolean;
software?: boolean;
}): Promise<MidiAccessLike>;
}
export interface MidiAdapterOptions {
/** Channels 1..16 map to zero-based Performance parts below this count; default 16. */
parts?: number;
/** Semitones for full pitch-bend deflection, 0..48; default 2. */
pitchBendRange?: number;
/** Opt-in program 0..127 to named voice selection for later note onsets. */
programVoices?: MidiVoiceMap;
/** Restrict to these stable port IDs; default every currently and subsequently connected input. */
inputIds?: readonly string[];
/** At most 128 own-data mappings. Ordinary CC defaults are overridden only for listed CCs. */
controllerMap?: readonly MidiControllerMapping[];
onError?: (error: Error) => void;
}
export interface MidiAdapterSnapshot {
readonly inputs: readonly string[];
readonly heldKeys: number;
/** Messages outside the supported channel-voice subset or malformed packets. */
readonly ignoredMessages: number;
readonly disposed: boolean;
}
export interface MidiAdapter {
readonly snapshot: MidiAdapterSnapshot;
/** Releases only keys owned by this adapter; unrelated Performance parts and host notes stay untouched. */
releaseAll(): void;
dispose(): void;
}
/**
* Request MIDI access without SysEx. Call from an explicit user action; browsers may show a permission prompt.
* Importing this module never requests access.
*/
export declare function requestMidiAccess(host?: MidiNavigatorLike | undefined): Promise<MidiAccessLike>;
/**
* Map channel-voice MIDI from user-granted inputs onto Performance parts. It is an adapter, not a MIDI driver:
* no SysEx, clock or hardware-specific behavior is implemented.
*
* Note-off releases the oldest still-held key of the same input/channel/pitch. CC1, channel pressure and polyphonic
* pressure all scale LFO depth 1x..2x (never below the patch default). CC7/CC11 multiply into part expression, CC10 pans,
* CC64 is sustain, CC120/123 release only this adapter's keys for the channel, and CC121 resets its controllers.
*/
export declare function createMidiAdapter(performance: Performance, access: MidiAccessLike, options?: MidiAdapterOptions): MidiAdapter;
export {};
import type { OPM } from './index.js';
import type { PreparedVoice, VoiceInput } from '../voices/schema.js';
import type { NoteControls } from '../core/synth.js';
export interface PerformanceOptions {
/** Zero-based part count, 1..16; default 16. */
parts?: number;
/** Total physical/pedal key records, 1..128; default 128. */
maxKeys?: number;
/** Per-part key records, 1..128; default 128, also subject to maxKeys. */
maxKeysPerPart?: number;
/** Event-driven cleanup failures; synchronous operation failures still throw. */
onError?: (error: Error) => void;
}
export interface PerformancePartControls {
glide?: number;
pan?: number;
expression?: number;
}
export interface PerformancePartOptions extends PerformancePartControls {
voice: string | VoiceInput;
mode: 'poly' | 'mono';
legato: boolean;
priority: 'last' | 'high' | 'low';
/** Optional owned-voice budget, including audible release tails, 1..32. */
voiceLimit?: number;
/** Admission importance, 0..127; larger values protect against lower-priority notes. */
voicePriority?: number;
}
export interface PerformanceNoteOptions {
velocity?: number;
}
export interface PerformanceNoteOffOptions {
force?: boolean;
}
export interface PerformanceKeySnapshot {
readonly key: number;
readonly note: number;
readonly velocity: number;
readonly held: boolean;
/** Only the currently sounding mono key owns its shared gate. */
readonly gateId: number | null;
}
export interface PerformancePartSnapshot {
readonly voice: string | PreparedVoice;
readonly mode: 'poly' | 'mono';
readonly legato: boolean;
readonly priority: 'last' | 'high' | 'low';
readonly glide: number;
readonly pan: number;
readonly expression: number;
readonly sustain: boolean;
readonly voiceLimit: number | undefined;
readonly voicePriority: number;
readonly selectedKey: number | null;
readonly keys: readonly PerformanceKeySnapshot[];
}
export interface Performance {
/** preserveNotes keeps existing gates when only the voice changes; default false. */
configurePart(part: number, options: Partial<PerformancePartOptions>, policy?: {
preserveNotes?: boolean;
}): void;
updatePart(part: number, controls: PerformancePartControls): void;
/** Update one physical key; inactive mono keys store controls without touching the selected gate. */
updateKey(part: number, key: number, controls: NoteControls): boolean;
/** Update owned sounding notes and defaults for future notes, including release tails. */
updatePartNotes(part: number, controls: NoteControls): void;
/** Independent key identity, not an OPM admission receipt. OPM must already be started. */
noteOn(part: number, note: number, options?: PerformanceNoteOptions): number;
noteOff(part: number, key: number, options?: PerformanceNoteOffOptions): boolean;
sustain(part: number, on: boolean): void;
allNotesOff(part?: number): void;
getPart(part: number): PerformancePartSnapshot;
/** Detached effective part defaults, including resolved voice operator controls (not per-key overrides). */
getPartControls(part: number): Readonly<NoteControls>;
dispose(): void;
}
/** Device-agnostic key policy. No context, timers, MIDI driver or global panic is created. */
export declare function createPerformance(opm: OPM, options?: PerformanceOptions): Performance;
api/render-worker.d.ts
import type { ChunkedSequenceOptions, SequenceCapacity, SequenceEvent } from '../core/sequence.js';
import type { WavFormat } from '../core/wav.js';
export interface WavSink {
/** Takes ownership of bytes; transferring/detaching their buffer is supported. */
write(bytes: Uint8Array): Promise<void> | void;
close?(): Promise<void> | void;
/** Must invalidate outstanding writes. Called once on failure, without waiting for them. */
abort?(reason: unknown): Promise<void> | void;
}
export interface WorkerRenderProgress {
readonly frames: number;
readonly totalFrames: number;
readonly bytesWritten: number;
readonly errors: number;
}
export type WorkerRenderPhase = 'initializing' | 'rendering' | 'writing' | 'closing' | 'completed' | 'cancelled' | 'failed';
export interface WorkerRenderPhaseStatus {
readonly phase: WorkerRenderPhase;
/** Host-local monotonic wall time, not a DSP benchmark or network trace. */
readonly elapsedMs: number;
readonly phaseElapsedMs: number;
readonly frames: number;
readonly totalFrames: number;
readonly bytesWritten: number;
readonly errors: number;
}
export interface WorkerRenderPhaseDiagnostics {
readonly status: 'completed' | 'cancelled' | 'failed';
readonly initializingMs: number;
readonly renderingMs: number;
readonly writingMs: number;
readonly closingMs: number;
readonly totalMs: number;
}
export interface WorkerRenderOptions extends ChunkedSequenceOptions {
format?: WavFormat;
sink: WavSink;
onProgress?: (progress: WorkerRenderProgress) => void;
/** Optional module-ready deadline only; integer milliseconds in 1..2147483647. */
startupTimeoutMs?: number;
/** Retain four bounded host-local phase totals in the successful result. */
phaseDiagnostics?: boolean;
/** Synchronous observer. Throwing fails the render and invalidates the sink. */
onPhase?: (status: WorkerRenderPhaseStatus) => void;
/** Reviewed same-origin secure HTTP(S) static module, never a blob/data URL. */
workerUrl?: string | URL;
}
export interface WorkerRenderResult {
readonly capacity: SequenceCapacity;
readonly format: WavFormat;
readonly bytesWritten: number;
readonly diagnostics: Readonly<{
errors: number;
processedEvents: number;
renderedFrames: number;
phases?: WorkerRenderPhaseDiagnostics;
}>;
}
/** Browser-only, backpressured offline rendering; importing this module allocates nothing. */
export declare function renderSequenceInWorker(events: readonly SequenceEvent[], options: WorkerRenderOptions): Promise<WorkerRenderResult>;
api/sequence.d.ts
import type { OPM } from './index.js';
import type { SequenceEvent } from '../core/sequence.js';
export interface PlaySequenceOptions {
/** Absolute AudioContext origin; omitted means currentTime at submission. */
at?: number;
}
export interface SequencePlayback {
/** Score IDs mapped to submitted OPM IDs, not an acknowledgement of admission. */
readonly ids: ReadonlyMap<number, number>;
/** Release started notes and immediately cancel pending onsets. Idempotent. */
stop(): void;
}
/** Submit one bounded, wholly validated score; lifecycle acknowledgements remain OPM events. */
export declare function playSequence(opm: OPM, events: readonly SequenceEvent[], options?: PlaySequenceOptions): SequencePlayback;
export interface SequenceStreamOptions {
/** Absolute origin, at most60 seconds ahead; defaults to currentTime at start. */
at?: number;
/** Lookahead seconds in0.01..10, default0.2. */
horizon?: number;
/** Timer interval seconds in0.001..horizon/2, default0.025 (or horizon/2). */
interval?: number;
/** Maximum own queued commands, integer1..256; default256. */
maxSlots?: number;
signal?: AbortSignal;
onError?: (error: Error) => void;
}
export interface SequenceStream {
readonly running: boolean;
/** Live/pending owned score IDs only; terminal IDs are pruned. Detached snapshot. */
readonly ids: ReadonlyMap<number, number>;
/** One-shot start. stop/dispose/reset/interruption permanently cancel this score. */
start(): Promise<void>;
/** Optional explicit pump for hosts driving their own clock; timers still run. */
pump(): void;
stop(): void;
dispose(): void;
}
/**
* Stream a fully validated long score in bounded mixed-event windows.
* A missed onset/window or rejected command stops the stream instead of silently retiming.
*/
export declare function streamSequence(opm: OPM, events: readonly SequenceEvent[], options?: SequenceStreamOptions): SequenceStream;
api/transport.d.ts
import type { OPM } from './index.js';
import type { BeatSequenceEvent } from '../core/sequence.js';
import type { TempoPoint, TimeSignature, BarBeat } from '../core/transport.js';
export { beatsToSeconds, secondsToBeats, beatToBarBeat, barBeatToBeat, normalizeTempoMap, quantizeBeat, swingBeat } from '../core/transport.js';
export type { TempoPoint, TimeSignature, BarBeat, BeatQuantization } from '../core/transport.js';
export type { BeatSequenceEvent } from '../core/sequence.js';
export interface TransportLoop {
enabled: boolean;
from: number;
to: number;
}
export type TransportState = 'stopped' | 'starting' | 'running' | 'paused' | 'disposed';
export interface TransportOptions {
bpm?: number;
tempoMap?: readonly TempoPoint[];
timeSignature?: TimeSignature;
loop?: TransportLoop;
horizon?: number;
interval?: number;
/** Future audio anchor in seconds for start and reconstruction; default min(0.05, horizon / 2), range 0..10. */
startupLead?: number;
maxSlots?: number;
onError?: (error: Error) => void;
}
export interface TransportSnapshot {
readonly position: number;
readonly musicalPosition: Readonly<BarBeat>;
readonly state: TransportState;
readonly running: boolean;
readonly tempoMap: readonly Readonly<TempoPoint>[];
readonly timeSignature: Readonly<TimeSignature>;
readonly loop: Readonly<TransportLoop>;
}
export interface MusicalTransport {
readonly position: number;
readonly running: boolean;
readonly state: TransportState;
readonly snapshot: TransportSnapshot;
readonly ids: ReadonlyMap<number, number>;
start(): Promise<void>;
resume(): Promise<void>;
pause(): void;
stop(): void;
seek(beat: number): void;
/** Replace the tempo from the current musical position onward; retain preceding points. */
setTempo(bpm: number): void;
setTempoMap(map: readonly TempoPoint[]): void;
setLoop(loop: TransportLoop): void;
pump(): void;
dispose(): void;
}
/** Internal shared preparation: beat durations remain beats until admitted to the audio clock. */
export declare function prepareBeatEvents(opm: OPM, beatEvents: readonly BeatSequenceEvent[]): import("../core/sequence.js").SequenceSnapshot;
/** Swing note starts AND ends, so adjacent gates retain their musical ordering. */
export declare function swingBeatEvents(events: readonly BeatSequenceEvent[], subdivision?: number, ratio?: number): BeatSequenceEvent[];
/** Restartable beat transport. Only owned IDs are ever stopped; the shared engine is not closed. */
export declare function createTransport(opm: OPM, beatEvents: readonly BeatSequenceEvent[], options?: TransportOptions): MusicalTransport;
core/algorithms.d.ts
export interface AlgorithmGraph {
readonly inputs: readonly (readonly number[])[];
readonly carriers: readonly number[];
}
export declare const ALGORITHMS: readonly [AlgorithmGraph, AlgorithmGraph, AlgorithmGraph, AlgorithmGraph, AlgorithmGraph, AlgorithmGraph, AlgorithmGraph, AlgorithmGraph];
export declare function feedbackPhase(previous: number, older: number, amount: number): number;
core/arrangement-definition.d.ts
import type { BeatSequenceEvent, SequenceSnapshot, SequenceVoices } from './sequence.js';
import type { TempoPoint, TimeSignature } from './transport.js';
export interface ArrangementLayer {
name: string;
/** Loop length in quarter notes, 1/1024 <= length <= 256; aligned to the global beat grid. */
length: number;
/** Note onsets lie inside [0, length). Durations and owned controls may cross a loop boundary. */
events: readonly BeatSequenceEvent[];
/** Admission importance 0..127, combined with each note's value by taking the maximum. */
voicePriority?: number;
/** Per-layer gain 0..1, default 1; independent of authored note expression. */
gain?: number;
}
export interface ArrangementSection {
name: string;
layers: readonly string[];
}
/** Musical definition shared by projects and live options, without scheduler callbacks or audio state. */
export interface ArrangementDefinition {
readonly layers: readonly ArrangementLayer[];
readonly sections: readonly ArrangementSection[];
readonly initialSection: string;
readonly tempoMap?: readonly TempoPoint[];
readonly timeSignature?: TimeSignature;
}
interface NormalizedArrangementDefinition extends ArrangementDefinition {
readonly layers: readonly Readonly<Required<ArrangementLayer>>[];
readonly sections: readonly Readonly<ArrangementSection>[];
readonly tempoMap: readonly Readonly<TempoPoint>[];
readonly timeSignature: Readonly<TimeSignature>;
}
export declare const MAX_ARRANGEMENT_LAYERS = 16;
export declare const MAX_ARRANGEMENT_SECTIONS = 32;
export declare const MAX_ARRANGEMENT_LAYER_LENGTH = 256;
export declare function arrangementName(value: unknown, label: string): string;
/** One beat-event boundary for portable projects and live arrangements. */
export declare function prepareBeatSequence(events: readonly BeatSequenceEvent[], voices?: SequenceVoices): {
events: readonly BeatSequenceEvent[];
score: SequenceSnapshot;
};
/** Reject definitions that cannot be converted through their complete tempo map. */
export declare function validateBeatHorizon(events: readonly BeatSequenceEvent[], map: readonly Readonly<TempoPoint>[]): void;
/** Validate all references and resource bounds before a scheduler can own any notes. */
export declare function prepareArrangementDefinition(input: unknown, voices?: SequenceVoices): {
definition: NormalizedArrangementDefinition;
scores: readonly SequenceSnapshot[];
};
export {};
core/decimator.d.ts
export type QualityProfile = 'eco' | 'standard' | 'high';
export declare const DECIMATOR_STATE_SIZE = 8;
export declare function qualityOversample(quality: QualityProfile): number;
export declare function createDecimatorCoefficients(sampleRate: number, quality?: QualityProfile): Float64Array;
export declare function decimateSample(input: number, state: Float64Array, coefficients: Float64Array): number;
core/envelope.d.ts
import type { ADSR } from '../voices/schema.js';
export interface PreparedEnvelope extends ADSR {
sustainDB: number;
sustainGain: number;
decayEnd: number;
releaseEnd: number;
releaseDB: number;
releaseSpanDB: number;
}
export declare const FLOOR_DB = -96;
export declare function prepareEnvelope(a: number, d: number, s: number, r: number, gate: number): PreparedEnvelope;
export declare function preparedEnvelopeAt(time: number, gate: number, envelope: PreparedEnvelope): number;
export declare function envelopeAt(time: number, gate: number, adsr: ADSR): number;
core/fx.d.ts
export interface ChorusOptions {
rate: number;
depth: number;
mix: number;
feedback?: number;
voices?: number;
}
export interface ReverbOptions {
size: number;
damping: number;
mix: number;
preDelay?: number;
width?: number;
}
export interface StereoEffectsOptions {
chorus?: ChorusOptions;
reverb?: ReverbOptions;
order?: 'chorus-reverb' | 'reverb-chorus';
}
export interface StereoEffects {
process(left: Float32Array, right: Float32Array, offset?: number, length?: number): void;
/** Replaces the complete configuration; omitted sections fade to bypass. */
update(params: StereoEffectsOptions): void;
reset(): void;
readonly tailSeconds: number;
readonly params: Readonly<StereoEffectsOptions>;
}
/** Internal trust-boundary helper, also used by the worklet protocol. */
export declare function effectsData(input: unknown, keys: readonly string[], label: string): Record<string, unknown>;
export declare function normalizeEffectsOptions(input?: StereoEffectsOptions): Readonly<StereoEffectsOptions>;
export declare function createStereoEffects(sampleRate: number, options?: StereoEffectsOptions): StereoEffects;
export declare function applyEffects(left: Float32Array, right: Float32Array, sampleRate: number, params: StereoEffectsOptions): {
left: Float32Array;
right: Float32Array;
};
core/index.d.ts
import type { CompleteVoiceInput, FrozenVoice } from '../voices/schema.js';
import type { SynthOptions } from './synth.js';
export type { ADSR, PitchEnvelope, LFO, LFOInput, LegacyLFO, LegacyLFOV5, LFOTargets, LFOTargetsInput, KeyScale, Operator, OperatorWaveform, Voice, LegacyVoice, LegacyVoiceV2, LegacyVoiceV3, LegacyVoiceV4, LegacyVoiceV5, LegacyVoiceV6, VoiceInput, FrozenVoice, PreparedVoice } from '../voices/schema.js';
export type { NoteOptions, NoteControls, VoiceEndReason, SynthOptions, QualityProfile } from './synth.js';
export type { TuningOptions, NormalizedTuning } from './tuning.js';
export { createStereoEffects, applyEffects } from './fx.js';
export type { StereoEffects, StereoEffectsOptions, ChorusOptions, ReverbOptions } from './fx.js';
export { normalizeTuning, tuningFrequency } from './tuning.js';
export { lfoValue } from './lfo.js';
export type { BeatSequenceEvent, SequenceEvent, SequenceNoteEvent, SequenceStopEvent, SequenceControlEvent, SequenceVoices, SequenceOptions, PreparedSequenceEvent, SequenceSnapshot, SequenceCapacity, ChunkedSequenceOptions, SequenceChunk, ChunkedSequenceRender } from './sequence.js';
export { prepareSequence, renderSequence, prepareLongSequence, estimateSequenceCapacity, renderSequenceChunks, MAX_SEQUENCE_NOTES, MAX_SEQUENCE_SLOTS, MAX_SEQUENCE_SECONDS, MAX_RENDER_SAMPLES, MAX_LONG_SEQUENCE_SECONDS, MAX_LONG_SEQUENCE_EVENTS, MAX_SEQUENCE_CHUNK_FRAMES, sampleRateValue } from './sequence.js';
export type { WavOptions, WavFormat, WavEncoderOptions, WavEncoder, WavChunk } from './wav.js';
export type { TempoPoint, TimeSignature, BarBeat } from './transport.js';
export { beatsToSeconds, secondsToBeats, beatToBarBeat, barBeatToBeat, normalizeTempoMap } from './transport.js';
export { importMidiFile, exportMidiFile, MAX_MIDI_FILE_BYTES, MAX_MIDI_FILE_TRACKS, MAX_MIDI_FILE_EVENTS } from './midi-file.js';
export type { MidiFileWarningCode, MidiFileWarning, MidiImportOptions, MidiImportResult, MidiExportOptions, MidiFileControlKind, MidiFilePreservedControl, MidiFileLossSummary } from './midi-file.js';
export type { MidiVoiceMap } from './midi-state.js';
export { gmProgramVoices, gmDrumVoices } from '../voices/gm-map.js';
export { parseScoreProject, serializeScoreProject, compileBeatSequence, MAX_SCORE_PROJECT_BYTES, MAX_SCORE_PROJECT_VOICES, parseArrangementProject, serializeArrangementProject, MAX_ARRANGEMENT_PROJECT_BYTES, MAX_ARRANGEMENT_PROJECT_VOICES } from './project.js';
export type { ScoreProject, ScoreProjectSettings, BeatSequenceOptions, ArrangementProject } from './project.js';
export type { ArrangementLayer, ArrangementSection, ArrangementDefinition } from './arrangement-definition.js';
export interface RenderNoteOptions extends SynthOptions {
voice: CompleteVoiceInput | FrozenVoice;
note?: number;
duration?: number;
velocity?: number;
pan?: number;
voicePriority?: number;
sampleRate?: number;
}
export interface RenderResult {
/** Same buffer as left, retained for compatibility. */
samples: Float32Array;
left: Float32Array;
right: Float32Array;
sampleRate: number;
diagnostics: {
errors: number;
};
}
export { envelopeAt } from './envelope.js';
export { ALGORITHMS } from './algorithms.js';
export { Synth, VoiceAdmissionError, normalizeVoice, prepareVoice, validateMaxVoices, validateNoteControls, validateVoicePriority } from './synth.js';
export { encodeWav, createWavEncoder } from './wav.js';
export declare const HEADROOM = 0.7;
export declare const OVERSAMPLE = 4;
export declare function renderNote(options: RenderNoteOptions): RenderResult;
core/lfo.d.ts
import type { LFO } from '../voices/schema.js';
/** Radian phase; sine and triangle start at zero rising, saw at -1, square at +1. */
export declare function lfoValue(phase: number, waveform: LFO['waveform']): number;
core/midi-file.d.ts
import type { BeatSequenceEvent } from './sequence.js';
import type { TempoPoint, TimeSignature } from './transport.js';
import type { MidiVoiceMap } from './midi-state.js';
export declare const MAX_MIDI_FILE_BYTES: number;
export declare const MAX_MIDI_FILE_TRACKS = 128;
/** Counts all wire events, including skipped messages and end-of-track markers. */
export declare const MAX_MIDI_FILE_EVENTS = 65536;
export type MidiFileWarningCode = 'header-extension' | 'ignored-meta' | 'ignored-sysex' | 'ignored-channel' | 'ignored-program' | 'release-velocity' | 'default-voice' | 'sustain-applied' | 'tempo-conflict' | 'meter-detail' | 'unclosed-notes' | 'release-tail-controls';
export interface MidiFileWarning {
code: MidiFileWarningCode;
message: string;
count: number;
}
export type MidiFileControlKind = 'pitch-bend' | 'expression' | 'pan' | 'modulation' | 'channel-pressure' | 'poly-pressure' | 'program-change' | 'pitch-bend-range';
export interface MidiFilePreservedControl {
kind: MidiFileControlKind;
count: number;
}
/** Counts source messages, not the number of per-note events generated by fanout. */
export interface MidiFileLossSummary {
omissions: readonly Readonly<MidiFileWarning>[];
approximations: readonly Readonly<MidiFileWarning>[];
preservedControls: readonly Readonly<MidiFilePreservedControl>[];
}
export interface MidiImportOptions {
/** Zero-based MIDI channels, written as decimal object keys, to OPM voice names. */
channelVoices?: Readonly<Record<string, string>>;
defaultVoice?: string;
programVoices?: MidiVoiceMap;
drumVoices?: MidiVoiceMap;
/** Unsupported musical/metadata content is reported, or rejects the entire file. */
unsupported?: 'warn' | 'reject';
/** Includes keys held by sustain at the final end-of-track tick. */
unclosedNotes?: 'reject' | 'close-at-end';
sustain?: 'apply' | 'reject';
/** Legacy note-only conversion is the default. */
controls?: 'preserve' | 'omit';
/** Initial bend range; preserve mode honors RPN 0. Finite semitones in 0..48, default 2. */
pitchBendRange?: number;
}
export interface MidiImportResult {
events: BeatSequenceEvent[];
tempoMap: readonly Readonly<TempoPoint>[];
timeSignature: Readonly<TimeSignature>;
warnings: readonly Readonly<MidiFileWarning>[];
lossSummary: Readonly<MidiFileLossSummary>;
}
export interface MidiExportOptions {
format?: 0 | 1;
ppqn?: number;
tempoMap?: readonly TempoPoint[];
bpm?: number;
timeSignature?: TimeSignature;
/** Named voices to zero-based MIDI channels. Only brass -> channel 0 is implicit. */
voiceChannels?: Readonly<Record<string, number>>;
controls?: 'preserve' | 'omit';
/** Must match the import/receiver policy; no RPN is emitted. */
pitchBendRange?: number;
}
/** Strict SMF 0/1 PPQN adapter, not a General MIDI synthesizer or device driver. */
export declare function importMidiFile(source: Uint8Array, options?: MidiImportOptions): MidiImportResult;
/** Deterministic SMF 0/1; expressive conversion is explicit and rejects ambiguous channel ownership. */
export declare function exportMidiFile(events: readonly BeatSequenceEvent[], options?: MidiExportOptions): Uint8Array;
core/midi-state.d.ts
/** Program/drum note numbers 0..127 mapped to named FM voices. */
export type MidiVoiceMap = Readonly<Record<number, string>> | ReadonlyMap<number, string>;
export declare function midiVoiceName(value: unknown): string;
export declare function midiVoiceMap(input: unknown): ReadonlyMap<number, string>;
export interface MidiRpnState {
msb: number;
lsb: number;
semitones: number;
cents: number;
range: number;
}
export declare function midiRpnState(range: number): MidiRpnState;
/** Selection wins over CC mappings; data entry wins only while RPN 0 is selected. */
export declare function midiRpnControl(state: MidiRpnState, controller: number, value: number): boolean;
core/project.d.ts
import type { PreparedVoice } from '../voices/schema.js';
import type { BeatSequenceEvent, SequenceEvent, SequenceVoices } from './sequence.js';
import type { ArrangementDefinition, ArrangementLayer, ArrangementSection } from './arrangement-definition.js';
import type { QualityProfile, SynthOptions } from './synth.js';
import type { NormalizedTuning } from './tuning.js';
import type { TempoPoint, TimeSignature } from './transport.js';
export declare const MAX_SCORE_PROJECT_BYTES: number;
export declare const MAX_SCORE_PROJECT_VOICES = 128;
export declare const MAX_ARRANGEMENT_PROJECT_BYTES: number;
export declare const MAX_ARRANGEMENT_PROJECT_VOICES = 128;
export interface BeatSequenceOptions {
tempoMap?: readonly TempoPoint[];
bpm?: number;
voices?: SequenceVoices;
}
export interface ScoreProjectSettings {
readonly sampleRate: number;
readonly quality: QualityProfile;
readonly maxVoices: number;
readonly mixGain: number;
readonly tuning: NormalizedTuning;
readonly stealing: NonNullable<SynthOptions['stealing']>;
}
/** Version 1 is self-contained: every note names a patch stored in voices. */
export interface ScoreProject {
readonly version: 1;
readonly events: readonly BeatSequenceEvent[];
readonly tempoMap: readonly Readonly<TempoPoint>[];
readonly timeSignature: Readonly<TimeSignature>;
readonly voices: Readonly<Record<string, PreparedVoice>>;
readonly settings: ScoreProjectSettings;
}
/** Version 1 stores a replayable definition; no live cursor, pending commands or DSP state. */
export interface ArrangementProject extends ArrangementDefinition {
readonly version: 1;
readonly layers: readonly Readonly<Required<ArrangementLayer>>[];
readonly sections: readonly Readonly<ArrangementSection>[];
readonly tempoMap: readonly Readonly<TempoPoint>[];
readonly timeSignature: Readonly<TimeSignature>;
readonly voices: Readonly<Record<string, PreparedVoice>>;
readonly settings: ScoreProjectSettings;
}
/** Compile musical gates by integrating both endpoints; control ramp/glide remain seconds. */
export declare function compileBeatSequence(events: readonly BeatSequenceEvent[], options?: BeatSequenceOptions): SequenceEvent[];
/** Parse strict versioned own-data input, detach all nested data and freeze the snapshot. */
export declare function parseScoreProject(source: string | object): ScoreProject;
/** Canonical compact JSON: stable field order, sorted patch names, normalized defaults. */
export declare function serializeScoreProject(project: ScoreProject): string;
/** Parse a self-contained arrangement using the same definition boundary as createArrangement. */
export declare function parseArrangementProject(source: string | object): ArrangementProject;
/** Canonical compact JSON for a definition, never a live Arrangement object. */
export declare function serializeArrangementProject(project: ArrangementProject): string;
core/sequence.d.ts
import type { PreparedVoice, VoiceInput } from '../voices/schema.js';
import type { NoteControls, SynthOptions } from './synth.js';
import type { RenderResult } from './index.js';
export interface SequenceNoteEvent {
type: 'note';
id: number;
time: number;
duration: number;
voice?: string | VoiceInput;
note: number;
velocity?: number;
pan?: number;
voicePriority?: number;
}
export interface SequenceStopEvent {
type: 'stop';
id: number;
time: number;
}
export interface SequenceControlEvent {
type: 'control';
id: number;
time: number;
controls: NoteControls;
}
export type SequenceEvent = SequenceNoteEvent | SequenceStopEvent | SequenceControlEvent;
export type BeatSequenceEvent = SequenceEvent extends infer E ? E extends SequenceEvent ? Omit<E, 'time'> & {
beat: number;
} : never : never;
export type SequenceVoices = ReadonlyMap<string, VoiceInput>;
export interface SequenceOptions extends SynthOptions {
voices?: SequenceVoices;
sampleRate?: number;
/** Logical polyphony, integer1..32; default8. Stolen fades remain bounded to eight. */
maxVoices?: number;
}
export type PreparedSequenceEvent = Readonly<Omit<SequenceNoteEvent, 'voice' | 'velocity' | 'pan' | 'voicePriority'> & {
voice: PreparedVoice;
velocity: number;
pan: number;
voicePriority: number;
}> | Readonly<SequenceStopEvent> | Readonly<Omit<SequenceControlEvent, 'controls'> & {
controls: Readonly<NoteControls>;
}>;
export interface SequenceSnapshot {
readonly events: readonly PreparedSequenceEvent[];
readonly noteCount: number;
/** Notes reserve both onset and automatic release, even if explicitly cancelled. */
readonly reservedSlots: number;
readonly endTime: number;
}
export declare const MAX_SEQUENCE_NOTES = 128;
export declare const MAX_SEQUENCE_SLOTS = 256;
export declare const MAX_SEQUENCE_SECONDS = 60;
export declare const MAX_RENDER_SAMPLES = 4000000;
export declare const MAX_LONG_SEQUENCE_SECONDS: number;
export declare const MAX_LONG_SEQUENCE_EVENTS = 65536;
export declare const MAX_SEQUENCE_CHUNK_FRAMES = 65536;
export declare function sampleRateValue(value: number): number;
export declare function sequenceOwnData(input: unknown, allowed: readonly string[], required: readonly string[], label: string): Record<string, unknown>;
/** Validate the entire score without invoking accessors, and detach every patch/control. */
export declare function prepareSequence(events: readonly SequenceEvent[], options?: Pick<SequenceOptions, 'voices'>): SequenceSnapshot;
/** Long scores have a separate input budget; this does not enlarge worklet queues. */
export declare function prepareLongSequence(events: readonly SequenceEvent[], options?: Pick<SequenceOptions, 'voices'>): SequenceSnapshot;
export type SequenceFrameEvent = {
frame: number;
order: number;
event: PreparedSequenceEvent;
};
/** Shared sample-frame ordering, including automatic releases and pending controls. */
export declare function sequenceFrameEvents(score: SequenceSnapshot, sampleRate: number, origin?: number): {
queue: SequenceFrameEvent[];
length: number;
};
/** Peak submissions in any half-open window; includes automatic releases. */
export declare function sequenceWindowCapacity(queue: readonly SequenceFrameEvent[], sampleRate: number, horizon: number): {
peakWindowSlots: number;
peakWindowNotes: number;
};
export interface ChunkedSequenceOptions extends SequenceOptions {
/** Integer 1..65536; default4096. Two buffers are reused for the entire render. */
chunkFrames?: number;
/** Optional hard cumulative frame budget, checked before allocation/advancement. */
maxFrames?: number;
signal?: AbortSignal;
}
export interface SequenceCapacity {
readonly sampleRate: number;
readonly frames: number;
readonly pcmBytes: number;
readonly chunkFrames: number;
readonly chunkBytes: number;
readonly eventCount: number;
readonly noteCount: number;
readonly reservedSlots: number;
readonly fullBufferAllowed: boolean;
readonly singleBatchAllowed: boolean;
/** Default0.2s-window preflight eligibility, not guaranteed live worklet admission. */
readonly streamAllowed: boolean;
readonly peakWindowSlots: number;
readonly peakWindowNotes: number;
readonly limits: Readonly<{
fullBufferFrames: number;
batchNotes: number;
batchSlots: number;
longEvents: number;
longSeconds: number;
chunkFrames: number;
streamHorizonSeconds: number;
streamSlots: number;
streamNotes: number;
}>;
}
export interface SequenceChunk {
/** Borrowed arrays, overwritten by the next next(). Copy only if retention is required. */
readonly left: Float32Array;
readonly right: Float32Array;
readonly offset: number;
readonly frames: number;
readonly sampleRate: number;
readonly diagnostics: Readonly<{
errors: number;
processedEvents: number;
renderedFrames: number;
}>;
}
export interface ChunkedSequenceRender extends IterableIterator<SequenceChunk> {
readonly capacity: SequenceCapacity;
readonly diagnostics: Readonly<{
errors: number;
processedEvents: number;
renderedFrames: number;
}>;
/** Idempotent. Subsequent next() returns done without advancing the synth. */
cancel(): void;
}
/** Validate and estimate without allocating any PCM or advancing a synth. */
export declare function estimateSequenceCapacity(events: readonly SequenceEvent[], options?: ChunkedSequenceOptions): SequenceCapacity;
/** Fully validate first; each next() advances at most chunkFrames, never allocates full PCM. */
export declare function renderSequenceChunks(events: readonly SequenceEvent[], options?: ChunkedSequenceOptions): ChunkedSequenceRender;
/** Convenience full-buffer rendering retains the original score and allocation budgets. */
export declare function renderSequence(events: readonly SequenceEvent[], options?: SequenceOptions): RenderResult;
core/synth.d.ts
import type { ADSR, PreparedVoice, VoiceInput } from '../voices/schema.js';
import type { TuningOptions } from './tuning.js';
import type { QualityProfile } from './decimator.js';
export type { QualityProfile } from './decimator.js';
export type VoiceEndReason = 'stolen' | 'ended' | 'error' | 'cancelled';
export interface NoteOptions {
velocity?: number;
pan?: number;
voicePriority?: number;
}
export interface NoteControls {
pitch?: number;
glide?: number;
expression?: number;
pan?: number;
modulation?: number;
ramp?: number;
/** Independent per-note amplitude, 0..1 (default 1), multiplied with expression before mix saturation. */
gain?: number;
operatorLevels?: readonly [number, number, number, number];
feedback?: number;
lfoRate?: number;
amDepth?: number;
pmDepth?: number;
operatorRatios?: readonly [number, number, number, number];
/** A number enables fixed Hz; null restores the operator's live ratio. Pitch still applies. */
operatorFrequencies?: readonly [number | null, number | null, number | null, number | null];
operatorADSR?: readonly [ADSR, ADSR, ADSR, ADSR];
}
export interface SynthOptions {
mixGain?: number;
tuning?: TuningOptions;
stealing?: 'oldest' | 'release-first' | 'quietest';
quality?: QualityProfile;
}
/** A valid note could not displace any higher-priority logical voice. */
export declare class VoiceAdmissionError extends Error {
constructor();
}
export declare function validateMaxVoices(value: unknown): number;
export declare function validateVoicePriority(value: unknown): number;
/** Copy strict own-data controls at the API/dispatch boundary without invoking getters. */
export declare function validateNoteControls(input: NoteControls): NoteControls;
export { normalizeVoice, prepareVoice } from '../voices/normalize.js';
export declare class Synth {
readonly sampleRate: number;
readonly maxVoices: number;
readonly quality: QualityProfile;
readonly currentFrame: number;
readonly errorCount: number;
readonly lastStolenId: number | null;
onVoiceEnded?: ((id: number, reason: VoiceEndReason) => void) | null;
constructor(sampleRate: number, maxVoices?: number, options?: SynthOptions);
setMixGain(gain: number): void;
setTuning(tuning: TuningOptions): void;
noteOn(input: VoiceInput | PreparedVoice, note: number, id?: number, options?: NoteOptions): number;
noteOff(id: number): boolean;
allNotesOff(): void;
panic(): void;
updateNote(id: number, input: NoteControls): boolean;
render(left: Float32Array, right: Float32Array, offset?: number, length?: number): void;
}
core/transport.d.ts
export interface TempoPoint {
beat: number;
bpm: number;
curve?: 'step' | 'linear';
endBpm?: number;
}
export interface TimeSignature {
numerator: number;
denominator: number;
}
/** One-based bars and beats; beat may contain a fractional subdivision. */
export interface BarBeat {
bar: number;
beat: number;
}
export declare const MAX_TRANSPORT_BEATS = 86400;
export declare const MAX_TEMPO_POINTS = 1024;
export declare function transportNumber(value: unknown, min: number, max: number, label: string): number;
/** Read dense own-data arrays without executing element getters or iteration overrides. */
export declare function transportArray(input: unknown, max: number, label: string): unknown[];
/** Strictly increasing quarter-note tempo; linear curves interpolate BPM in beat space. */
export declare function normalizeTempoMap(input?: readonly TempoPoint[], bpm?: number): readonly Readonly<TempoPoint>[];
export declare function normalizeTimeSignature(input?: TimeSignature): Readonly<TimeSignature>;
/** BPM at a beat in an already validated map. */
export declare function tempoBPM(beat: number, map: readonly Readonly<TempoPoint>[]): number;
/** Insert a step without changing the elapsed portion of a linear ramp. */
export declare function replaceTempoFrom(beat: number, bpm: number, map: readonly Readonly<TempoPoint>[]): readonly Readonly<TempoPoint>[];
/** Integral of 60/BPM across tempo boundaries. */
export declare function beatsToSeconds(beat: number, tempoMap?: readonly TempoPoint[]): number;
/** Internal validated-map form avoids recopying a map on each scheduler tick. */
export declare function tempoSeconds(beat: number, map: readonly Readonly<TempoPoint>[]): number;
export declare function secondsToBeats(seconds: number, tempoMap?: readonly TempoPoint[]): number;
export declare function tempoBeat(seconds: number, map: readonly Readonly<TempoPoint>[]): number;
export declare function beatToBarBeat(beat: number, signature?: TimeSignature): Readonly<BarBeat>;
export declare function barBeatToBeat(position: BarBeat, signature?: TimeSignature): number;
export type BeatQuantization = 'floor' | 'ceil' | 'nearest' | 'next';
/** Grid in quarter-note beats; next is strictly later even at an exact boundary. */
export declare function quantizeBeat(beat: number, quantum?: number, mode?: BeatQuantization): number;
/** Warp each pair of subdivisions; ratio .5 is straight, 2/3 is triplet swing. */
export declare function swingBeat(beat: number, subdivision?: number, ratio?: number): number;
core/tuning.d.ts
export interface TuningOptions {
referenceHz?: number;
offsets?: readonly number[];
}
export interface NormalizedTuning {
readonly referenceHz: number;
readonly offsets: readonly number[];
}
/** Validate own data only and detach the cents table from its caller. */
export declare function normalizeTuning(input: TuningOptions): NormalizedTuning;
/** Fractional MIDI notes interpolate cents, not frequencies, between adjacent keys. */
export declare function tuningFrequency(note: number, tuning: NormalizedTuning): number;
core/wav.d.ts
export type WavFormat = 'pcm16' | 'pcm24' | 'float32';
export interface WavOptions {
left: Float32Array;
right?: Float32Array;
sampleRate: number;
format?: WavFormat;
}
export interface WavEncoderOptions {
sampleRate: number;
channels: 1 | 2;
format?: WavFormat;
totalFrames: number;
}
export interface WavChunk {
left: Float32Array;
right?: Float32Array;
}
export interface WavEncoder {
readonly totalFrames: number;
readonly framesEncoded: number;
/** Entire file length, including the header and any RIFF alignment byte. */
readonly byteLength: number;
readonly finished: boolean;
/** Emit exactly once, before encoding PCM. */
header(): Uint8Array;
/** Atomic accounting: invalid chunks never consume frames. Maximum65536 frames per call. */
encode(chunk: WavChunk): Uint8Array;
/** Require exact totalFrames; returns the RIFF alignment byte, or an empty array. */
finalize(): Uint8Array;
}
/** Streaming RIFF32 output with known length; retains no PCM or emitted bytes. */
export declare function createWavEncoder(options: WavEncoderOptions): WavEncoder;
/** Full-buffer WAV convenience export; defaultPCM16, at most4000000 frames. */
export declare function encodeWav(input: WavOptions): Uint8Array;
export interface CopyAssetsOptions {
destination: string;
/** Advanced: deploy this installed opm.js package directory instead of the one containing this module. */
packageRoot?: string;
}
export interface AssetDeployment {
readonly version: string;
readonly destination: string;
readonly files: number;
readonly bytes: number;
readonly reused: boolean;
}
export interface CheckDeploymentOptions {
/** Overall deadline, integer milliseconds in 1..60000; default 15000. */
timeoutMs?: number;
/** Require production X-Content-Type-Options: nosniff; default true. */
requireNosniff?: boolean;
/** Advanced: compare with this installed opm.js package directory instead of the one containing this module. */
packageRoot?: string;
}
export interface DeploymentCheck {
readonly version: string;
readonly baseUrl: string;
readonly files: number;
readonly bytes: number;
readonly limitations: readonly string[];
}
/** Node-only. Atomically create a complete release-specific directory; never overwrite host files. */
export declare function copyAssets(options: CopyAssetsOptions): Promise<AssetDeployment>;
/** Fetch and hash the complete installed release; this does not certify page CSP or audible playback. */
export declare function checkDeployment(baseUrl: string | URL, options?: CheckDeploymentOptions): Promise<DeploymentCheck>;
version.d.ts
/** Package version; scripts/security-check.ts fails if it differs from package.json. */
export declare const VERSION = "1.11.1";
voices/brass.d.ts
import type { Voice } from './schema.js';
export declare const brass: Voice;
voices/dx7.d.ts
import type { Algorithm, Voice } from './schema.js';
export interface DX7ImportDescription {
name: string;
/** Original DX7 algorithm, 1..32. */
sourceAlgorithm: number;
algorithm: Algorithm;
/** DX7 operator numbers 1..6 in converted OPM signal order. */
selectedOperators: number[];
droppedOperators: number[];
warnings: string[];
}
/** Import exactly one standard DX7 single/bank dump as approximate four-op voices. */
export declare function importDX7(input: Uint8Array): Voice[];
/** Report losses separately so imported voices retain the strict normal voice shape. */
export declare function describeDX7(input: Uint8Array): DX7ImportDescription[];
voices/examples.d.ts
import type { Voice } from './schema.js';
export declare const examples: readonly Voice[];
voices/gm-map.d.ts
/** Artistic GM-family starter mappings, not a General MIDI sound set. */
export declare const gmProgramVoices: Readonly<Record<number, string>>;
/** Partial GM percussion starter; unmapped notes retain the caller fallback. */
export declare const gmDrumVoices: Readonly<Record<number, string>>;
voices/normalize.d.ts
import type { NormalizedVoice, PreparedVoice, VoiceInput } from './schema.js';
export declare function normalizeVoice(source: VoiceInput): NormalizedVoice;
/** Validate once and retain a deeply immutable, caller-independent snapshot. */
export declare function prepareVoice(input: VoiceInput): PreparedVoice;
voices/opm.d.ts
import type { Algorithm, Voice } from './schema.js';
export interface OPMImportDescription {
name: string;
program: number;
algorithm: Algorithm;
/** Source labels in destination operator order. */
operators: readonly string[];
warnings: string[];
}
/** Import bounded decimal VOPM/MXDRV-family text patches as approximate v7 voices. */
export declare function importOPM(source: string | Uint8Array): Voice[];
/** Report source program metadata and bounded, de-duplicated conversion losses. */
export declare function describeOPM(source: string | Uint8Array): OPMImportDescription[];
voices/original.d.ts
import type { Voice } from './schema.js';
export declare const originalPresets: readonly Voice[];
export interface PresetMetadata {
readonly family: 'bell' | 'brass' | 'bass' | 'keys' | 'organ' | 'lead' | 'strings' | 'mallet' | 'pluck' | 'reed' | 'pad' | 'metallic' | 'percussion' | 'inharmonic';
readonly provenance: {
readonly kind: 'repository-recipe' | 'original-recipe';
readonly source: string;
readonly license: 'Apache-2.0';
readonly copiedEmulatorPatch: false;
};
readonly intendedMidi: readonly [number, number];
readonly intendedVelocity: readonly [number, number];
/** Extra attenuation before the common audition gain; never an operator-level compensation. */
readonly hostTrimDb: number;
readonly purpose: string;
readonly suggestedPolyphony: number;
readonly designRationale: string;
/** Authoring intent and numerical checks are not a listener verdict. */
readonly listeningStatus: 'unverified';
}
export declare const presetMetadata: Readonly<Record<string, PresetMetadata>>;
/** The separate default brass export is not the bank brass recipe. */
export declare const defaultBrassMetadata: PresetMetadata;
voices/schema.d.ts
export type Algorithm = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
export interface ADSR {
a: number;
d: number;
s: number;
r: number;
}
export type LFOTargets = readonly [number, number, number, number];
export type LFOTargetsInput = readonly [number | boolean, number | boolean, number | boolean, number | boolean];
export interface LegacyLFO {
rate: number;
amDepth: number;
pmDepth: number;
waveform?: never;
delay?: never;
sync?: never;
phase?: never;
amTargets?: never;
pmTargets?: never;
}
export interface LegacyLFOV4 extends Omit<LegacyLFO, 'waveform'> {
waveform: 'sine' | 'triangle' | 'saw' | 'square';
}
export interface LegacyLFOV5 extends Omit<LegacyLFOV4, 'delay' | 'sync' | 'phase'> {
delay?: number;
sync?: 'note' | 'global';
phase?: number;
}
export interface LFO extends Omit<LegacyLFOV5, 'amTargets' | 'pmTargets'> {
amTargets?: LFOTargets;
pmTargets?: LFOTargets;
}
export type LFOInput = Omit<LFO, 'waveform' | 'amTargets' | 'pmTargets'> & {
waveform?: LFO['waveform'];
amTargets?: LFOTargetsInput;
pmTargets?: LFOTargetsInput;
};
export interface PitchEnvelope {
a: number;
d: number;
r: number;
initial: number;
peak: number;
sustain: number;
final: number;
}
export interface KeyScale {
breakpoint: number;
leftDbPerOctave: number;
rightDbPerOctave: number;
}
export type OperatorWaveform = 'sine' | 'half' | 'abs' | 'quarter' | 'alternating' | 'camel' | 'square' | 'saw' | 'noise';
export interface LegacyOperator {
ratio: number;
level: number;
detune: number;
adsr: ADSR;
keyScale?: never;
velocitySensitivity?: never;
frequency?: never;
rateKeyScale?: never;
waveform?: never;
noiseRate?: never;
}
export interface LegacyOperatorV2 extends Omit<LegacyOperator, 'keyScale'> {
keyScale?: KeyScale;
}
export interface LegacyOperatorV3 extends Omit<LegacyOperatorV2, 'velocitySensitivity'> {
velocitySensitivity?: number;
}
export interface LegacyOperatorV6 extends Omit<LegacyOperatorV3, 'frequency' | 'rateKeyScale'> {
frequency?: number;
rateKeyScale?: number;
}
export interface Operator extends Omit<LegacyOperatorV6, 'waveform' | 'noiseRate'> {
waveform?: OperatorWaveform;
noiseRate?: number;
}
export type FourOperators<T = Operator> = [T, T, T, T];
interface VoiceBase {
name?: string;
algorithm: Algorithm;
feedback: Algorithm;
modIndex?: number;
}
/** Strict single-voice input; omitted version uses the current shape. */
export type VoiceInput = (VoiceBase & {
version?: 7;
lfo?: LFOInput;
pitchEnvelope?: PitchEnvelope;
ops: readonly [Operator, Operator, Operator, Operator];
}) | (VoiceBase & {
version: 6;
lfo?: LFOInput;
pitchEnvelope?: PitchEnvelope;
ops: readonly [LegacyOperatorV6, LegacyOperatorV6, LegacyOperatorV6, LegacyOperatorV6];
}) | (VoiceBase & {
version: 5;
lfo?: Omit<LegacyLFOV5, 'waveform'> & {
waveform?: LFO['waveform'];
};
pitchEnvelope?: PitchEnvelope;
ops: readonly [LegacyOperatorV6, LegacyOperatorV6, LegacyOperatorV6, LegacyOperatorV6];
}) | (VoiceBase & {
version: 4;
lfo?: Omit<LegacyLFOV4, 'waveform'> & {
waveform?: LFO['waveform'];
};
pitchEnvelope?: never;
ops: readonly [LegacyOperatorV3, LegacyOperatorV3, LegacyOperatorV3, LegacyOperatorV3];
}) | (VoiceBase & {
version: 3;
lfo?: LegacyLFO;
pitchEnvelope?: never;
ops: readonly [LegacyOperatorV3, LegacyOperatorV3, LegacyOperatorV3, LegacyOperatorV3];
}) | (VoiceBase & {
version: 2;
lfo?: LegacyLFO;
pitchEnvelope?: never;
ops: readonly [LegacyOperatorV2, LegacyOperatorV2, LegacyOperatorV2, LegacyOperatorV2];
}) | (VoiceBase & {
version: 1;
lfo?: LegacyLFO;
pitchEnvelope?: never;
ops: readonly [LegacyOperator, LegacyOperator, LegacyOperator, LegacyOperator];
});
export interface Voice {
version: 7;
name: string;
algorithm: Algorithm;
feedback: Algorithm;
modIndex: number;
lfo: LFO;
pitchEnvelope?: PitchEnvelope;
ops: FourOperators;
}
export interface LegacyVoice {
version: 1;
name: string;
algorithm: Algorithm;
feedback: Algorithm;
modIndex: number;
lfo: LegacyLFO;
pitchEnvelope?: never;
ops: FourOperators<LegacyOperator>;
}
export interface LegacyVoiceV2 extends Omit<LegacyVoice, 'version' | 'ops'> {
version: 2;
ops: FourOperators<LegacyOperatorV2>;
}
export interface LegacyVoiceV3 extends Omit<LegacyVoice, 'version' | 'ops'> {
version: 3;
ops: FourOperators<LegacyOperatorV3>;
}
export interface LegacyVoiceV4 extends Omit<LegacyVoiceV3, 'version' | 'lfo'> {
version: 4;
lfo: LegacyLFOV4;
}
export interface LegacyVoiceV6 extends Omit<Voice, 'version' | 'ops'> {
version: 6;
ops: FourOperators<LegacyOperatorV6>;
}
export interface LegacyVoiceV5 extends Omit<LegacyVoiceV6, 'version' | 'lfo'> {
version: 5;
lfo: LegacyLFOV5;
}
export interface NormalizedVoice {
version: 7;
name?: string;
algorithm: Algorithm;
feedback: Algorithm;
modIndex: number;
lfo: LFO;
pitchEnvelope?: PitchEnvelope;
ops: FourOperators;
}
export type CompleteVoiceInput = Voice | LegacyVoice | LegacyVoiceV2 | LegacyVoiceV3 | LegacyVoiceV4 | LegacyVoiceV5 | LegacyVoiceV6;
export type FrozenVoice = Readonly<Omit<Voice, 'lfo' | 'ops' | 'pitchEnvelope'>> & {
readonly lfo: Readonly<LFO>;
readonly pitchEnvelope?: Readonly<PitchEnvelope>;
readonly ops: readonly [FrozenOperator, FrozenOperator, FrozenOperator, FrozenOperator];
};
export type FrozenOperator = Readonly<Omit<Operator, 'adsr' | 'keyScale'>> & {
readonly adsr: Readonly<ADSR>;
readonly keyScale?: Readonly<KeyScale>;
};
declare const preparedVoiceBrand: unique symbol;
/** Immutable validated snapshot. Only prepareVoice can create the trusted identity. */
export type PreparedVoice = Readonly<Omit<NormalizedVoice, 'lfo' | 'ops' | 'pitchEnvelope'>> & {
readonly lfo: Readonly<LFO>;
readonly pitchEnvelope?: Readonly<PitchEnvelope>;
readonly ops: readonly [FrozenOperator, FrozenOperator, FrozenOperator, FrozenOperator];
readonly [preparedVoiceBrand]: true;
};
export { prepareVoice } from './normalize.js';
export declare const MAX_BANK_BYTES = 262144;
export declare const MAX_BANK_VOICES = 128;
type LimitKey = 'noiseRate' | 'ratio' | 'level' | 'detune' | 'velocitySensitivity' | 'frequency' | 'rateKeyScale' | 'a' | 'd' | 's' | 'r' | 'modIndex' | 'rate' | 'amDepth' | 'pmDepth' | 'delay' | 'phase' | 'initial' | 'peak' | 'sustain' | 'final' | 'breakpoint' | 'leftDbPerOctave' | 'rightDbPerOctave';
export declare const LIMITS: Readonly<Record<LimitKey, readonly [number, number]>>;
export declare function bounded(value: unknown, min: number, max: number, label?: string): number;
export declare function lfoWaveform(value: unknown): LFO['waveform'];
export declare function lfoSync(value: unknown): NonNullable<LFO['sync']>;
export declare function operatorWaveform(value: unknown): OperatorWaveform;
export declare function validateVoice(input: unknown): FrozenVoice;
export declare function parseVoiceBank(source: string | readonly unknown[]): Map<string, FrozenVoice>;
voices/voice.schema.d.ts
export declare const voiceSchema: {
$schema: string;
title: string;
type: string;
additionalProperties: boolean;
required: string[];
properties: {
version: {
const: number;
};
name: {
type: string;
pattern: string;
};
algorithm: {
type: string;
minimum: number;
maximum: number;
};
feedback: {
type: string;
minimum: number;
maximum: number;
};
modIndex: {
type: string;
minimum: number;
maximum: number;
};
pitchEnvelope: {
type: string;
additionalProperties: boolean;
required: string[];
properties: {
a: {
type: string;
minimum: number;
maximum: number;
};
d: {
type: string;
minimum: number;
maximum: number;
};
r: {
type: string;
minimum: number;
maximum: number;
};
initial: {
type: string;
minimum: number;
maximum: number;
};
peak: {
type: string;
minimum: number;
maximum: number;
};
sustain: {
type: string;
minimum: number;
maximum: number;
};
final: {
type: string;
minimum: number;
maximum: number;
};
};
};
lfo: {
type: string;
additionalProperties: boolean;
required: string[];
properties: {
delay: {
type: string;
minimum: number;
maximum: number;
default: number;
};
sync: {
type: string;
enum: string[];
default: string;
};
phase: {
type: string;
minimum: number;
maximum: number;
default: number;
};
amTargets: {
type: string;
minItems: number;
maxItems: number;
items: {
type: string;
minimum: number;
maximum: number;
};
description: string;
};
pmTargets: {
type: string;
minItems: number;
maxItems: number;
items: {
type: string;
minimum: number;
maximum: number;
};
description: string;
};
waveform: {
type: string;
enum: string[];
};
rate: {
type: string;
minimum: number;
maximum: number;
};
amDepth: {
type: string;
minimum: number;
maximum: number;
};
pmDepth: {
type: string;
minimum: number;
maximum: number;
};
};
};
ops: {
type: string;
minItems: number;
maxItems: number;
items: {
type: string;
additionalProperties: boolean;
required: string[];
properties: {
waveform: {
type: string;
enum: string[];
default: string;
};
noiseRate: {
type: string;
minimum: number;
maximum: number;
default: number;
description: string;
};
frequency: {
type: string;
minimum: number;
maximum: number;
description: string;
};
rateKeyScale: {
type: string;
minimum: number;
maximum: number;
description: string;
};
velocitySensitivity: {
type: string;
minimum: number;
maximum: number;
description: string;
};
keyScale: {
type: string;
additionalProperties: boolean;
required: string[];
properties: {
breakpoint: {
type: string;
minimum: number;
maximum: number;
};
leftDbPerOctave: {
type: string;
minimum: number;
maximum: number;
};
rightDbPerOctave: {
type: string;
minimum: number;
maximum: number;
};
};
};
ratio: {
type: string;
minimum: number;
maximum: number;
};
level: {
type: string;
minimum: number;
maximum: number;
};
detune: {
type: string;
minimum: number;
maximum: number;
};
adsr: {
type: string;
additionalProperties: boolean;
required: string[];
properties: {
a: {
type: string;
minimum: number;
maximum: number;
};
d: {
type: string;
minimum: number;
maximum: number;
};
s: {
type: string;
minimum: number;
maximum: number;
};
r: {
type: string;
minimum: number;
maximum: number;
};
};
};
};
};
};
};
};