@libraz/libsonare 1.7.1 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/opfs_clip_pages.ts","../src/clip_page_streamer.ts","../src/errors.ts","../src/module_state.ts","../src/codes.ts","../src/realtime_engine.ts","../src/mixer.ts","../src/realtime_voice_changer.ts","../src/index.ts","../src/worklet/engine-sync.ts","../src/worklet/engine-automation.ts","../src/worklet/engine-offline.ts","../src/worklet/protocol.ts","../src/worklet/engine-capture-facade.ts","../src/worklet/engine-clips.ts","../src/worklet/engine-markers.ts","../src/worklet/engine-mixer-facade.ts","../src/worklet/guards.ts","../src/worklet/engine-node.ts","../src/worklet/engine-parameter-facade.ts","../src/worklet/engine-strips.ts","../src/worklet/engine-tempo-facade.ts","../src/worklet/engine.ts","../src/worklet/messages.ts","../src/worklet/engine-processor.ts","../src/worklet/engine-register.ts","../src/worklet/mixer-processor.ts","../src/worklet/voice-changer-processor.ts"],"sourcesContent":["import type { ClipPageProvider, ClipPageRequest, RealtimeEngine } from './realtime_engine';\n\nexport interface OpfsClipPageProviderOptions {\n path: string;\n numChannels: number;\n numSamples: number;\n pageFrames: number;\n dataOffsetBytes?: number;\n worker?: Worker;\n terminateWorkerOnClose?: boolean;\n /** Internal bridge hook used to mirror a supplied page into an AudioWorklet. */\n onPageSupplied?: (pageIndex: number, channels: Float32Array[]) => void;\n /** Internal bridge hook used to mirror an eviction into an AudioWorklet. */\n onPageCleared?: (pageIndex: number) => void;\n /** Internal bridge hook called after the local provider is destroyed. */\n onClose?: () => void;\n}\n\nexport interface OpfsClipPageProviderBinding {\n provider: ClipPageProvider;\n supplyPage(pageIndex: number): Promise<boolean>;\n supplyRequest(request: ClipPageRequest): Promise<boolean>;\n /** Evict one resident page from every configured consumer. */\n clearPage?(pageIndex: number): void;\n close(): void;\n}\n\ninterface PageResponse {\n type: 'sonare:clip-page';\n requestId: number;\n pageIndex: number;\n ok: boolean;\n frames?: number;\n channels?: Float32Array[];\n channelBuffers?: ArrayBufferLike[];\n error?: string;\n}\n\nexport const opfsClipPageWorkerSource = `\nconst sonareClipPageReadQueues = new Map();\n\nfunction sonareEnqueueClipPageRead(key, task) {\n const previous = sonareClipPageReadQueues.get(key) || Promise.resolve();\n const next = previous.catch(() => undefined).then(task);\n const queued = next.finally(() => {\n if (sonareClipPageReadQueues.get(key) === queued) {\n sonareClipPageReadQueues.delete(key);\n }\n });\n sonareClipPageReadQueues.set(key, queued);\n return next;\n}\n\nself.onmessage = async (event) => {\n const message = event.data;\n if (!message || message.type !== 'sonare:read-clip-page') return;\n const { requestId, path, pageIndex, numChannels, numSamples, pageFrames, dataOffsetBytes = 0 } = message;\n await sonareEnqueueClipPageRead(String(path), async () => {\n try {\n if (pageIndex < 0) {\n self.postMessage({ type: 'sonare:clip-page', requestId, pageIndex, ok: false });\n return;\n }\n const startFrame = pageIndex * pageFrames;\n if (startFrame >= numSamples) {\n self.postMessage({ type: 'sonare:clip-page', requestId, pageIndex, ok: false });\n return;\n }\n const root = await self.navigator.storage.getDirectory();\n let dir = root;\n const parts = String(path).split('/').filter(Boolean);\n for (let i = 0; i < parts.length - 1; ++i) {\n dir = await dir.getDirectoryHandle(parts[i]);\n }\n const fileHandle = await dir.getFileHandle(parts[parts.length - 1]);\n const access = await fileHandle.createSyncAccessHandle();\n try {\n const frames = Math.min(pageFrames, numSamples - startFrame);\n const frameBytes = numChannels * 4;\n const bytes = new Uint8Array(frames * frameBytes);\n let bytesReadTotal = 0;\n const readOffset = dataOffsetBytes + startFrame * frameBytes;\n while (bytesReadTotal < bytes.byteLength) {\n const bytesRead = access.read(bytes.subarray(bytesReadTotal), {\n at: readOffset + bytesReadTotal,\n });\n if (bytesRead <= 0) {\n break;\n }\n bytesReadTotal += bytesRead;\n }\n if (bytesReadTotal !== bytes.byteLength || bytesReadTotal % frameBytes !== 0) {\n self.postMessage({ type: 'sonare:clip-page', requestId, pageIndex, ok: false });\n return;\n }\n const framesRead = bytesReadTotal / frameBytes;\n const view = new DataView(bytes.buffer, 0, framesRead * frameBytes);\n const channelBuffers = Array.from({ length: numChannels }, () => new ArrayBuffer(framesRead * 4));\n for (let ch = 0; ch < numChannels; ++ch) {\n const channel = new Float32Array(channelBuffers[ch]);\n for (let frame = 0; frame < framesRead; ++frame) {\n channel[frame] = view.getFloat32((frame * numChannels + ch) * 4, true);\n }\n }\n self.postMessage(\n { type: 'sonare:clip-page', requestId, pageIndex, ok: true, frames: framesRead, channelBuffers },\n channelBuffers,\n );\n } finally {\n access.close();\n }\n } catch (error) {\n self.postMessage({\n type: 'sonare:clip-page',\n requestId,\n pageIndex,\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n });\n};\n`;\n\nexport function createOpfsClipPageWorker(): Worker {\n const blob = new Blob([opfsClipPageWorkerSource], { type: 'text/javascript' });\n const url = URL.createObjectURL(blob);\n try {\n return new Worker(url);\n } finally {\n // Worker construction retains the script URL internally; keeping this\n // object URL alive after construction leaks one browser registration per\n // attach/close cycle.\n URL.revokeObjectURL(url);\n }\n}\n\nexport function createOpfsClipPageProvider(\n engine: RealtimeEngine,\n options: OpfsClipPageProviderOptions,\n): OpfsClipPageProviderBinding {\n if (options.numChannels <= 0 || options.numSamples <= 0 || options.pageFrames <= 0) {\n throw new Error('numChannels, numSamples, and pageFrames must be positive');\n }\n const provider = engine.createClipPageProvider(\n options.numChannels,\n options.numSamples,\n options.pageFrames,\n );\n const worker = options.worker ?? createOpfsClipPageWorker();\n const ownsWorker = options.worker === undefined || options.terminateWorkerOnClose === true;\n let nextRequestId = 1;\n let closed = false;\n let readQueue: Promise<void> = Promise.resolve();\n const pending = new Map<\n number,\n { resolve: (value: boolean) => void; reject: (reason: unknown) => void }\n >();\n\n const onMessage = (event: MessageEvent<PageResponse>) => {\n const response = event.data;\n if (response?.type !== 'sonare:clip-page') {\n return;\n }\n const entry = pending.get(response.requestId);\n if (!entry) {\n return;\n }\n pending.delete(response.requestId);\n if (!response.ok) {\n entry.resolve(false);\n return;\n }\n const channels =\n response.channels ??\n response.channelBuffers?.map(\n (buffer) => new Float32Array(buffer, 0, response.frames ?? buffer.byteLength / 4),\n );\n if (!channels || channels.length === 0) {\n entry.resolve(false);\n return;\n }\n try {\n provider.supply(response.pageIndex, channels);\n options.onPageSupplied?.(response.pageIndex, channels);\n } catch {\n entry.resolve(false);\n return;\n }\n entry.resolve(true);\n };\n worker.addEventListener('message', onMessage as EventListener);\n\n const supplyPage = (pageIndex: number): Promise<boolean> => {\n if (closed) {\n return Promise.reject(new Error('OpfsClipPageProvider is closed'));\n }\n const requestId = nextRequestId++;\n const promise = new Promise<boolean>((resolve, reject) => {\n pending.set(requestId, { resolve, reject });\n });\n readQueue = readQueue\n .catch(() => undefined)\n .then(() => {\n if (closed) {\n const entry = pending.get(requestId);\n pending.delete(requestId);\n entry?.reject(new Error('OpfsClipPageProvider is closed'));\n return;\n }\n worker.postMessage({\n type: 'sonare:read-clip-page',\n requestId,\n path: options.path,\n pageIndex,\n numChannels: options.numChannels,\n numSamples: options.numSamples,\n pageFrames: options.pageFrames,\n dataOffsetBytes: options.dataOffsetBytes ?? 0,\n });\n return promise.then(\n () => undefined,\n () => undefined,\n );\n });\n readQueue.catch(() => {\n // The per-request promise carries the user-visible failure.\n });\n return promise;\n };\n\n return {\n provider,\n supplyPage,\n supplyRequest(request: ClipPageRequest) {\n return supplyPage(Math.floor(request.sample / options.pageFrames));\n },\n clearPage(pageIndex: number) {\n if (closed) {\n return;\n }\n provider.clear(pageIndex);\n options.onPageCleared?.(pageIndex);\n },\n close() {\n if (closed) {\n return;\n }\n closed = true;\n worker.removeEventListener('message', onMessage as EventListener);\n for (const entry of pending.values()) {\n entry.reject(new Error('OpfsClipPageProvider is closed'));\n }\n pending.clear();\n provider.destroy();\n options.onClose?.();\n if (ownsWorker) {\n worker.terminate();\n }\n },\n };\n}\n","import {\n createOpfsClipPageProvider,\n type OpfsClipPageProviderBinding,\n type OpfsClipPageProviderOptions,\n} from './opfs_clip_pages';\nimport type { ClipPageProvider, ClipPageRequest, RealtimeEngine } from './realtime_engine';\n\n/**\n * Minimal engine surface the streamer drives. {@link RealtimeEngine} satisfies\n * this structurally; tests can supply a lightweight stand-in.\n */\nexport interface ClipPageStreamerEngine {\n /** Drain one pending audio-thread page-miss request, or `null` when empty. */\n popClipPageRequest(): ClipPageStreamerRequest | null;\n}\n\n/**\n * A page miss reported by either a direct engine (`sample`) or the worklet\n * bridge (`pageIndex`). Exactly one position form is required.\n */\nexport interface ClipPageStreamerRequest {\n clipId: number;\n sample?: number;\n pageIndex?: number;\n}\n\n/** A paged clip the streamer keeps fed from its backing store. */\nexport interface ClipPageStreamSource {\n /** Clip schedule id passed to `setClips` (matches {@link ClipPageRequest.clipId}). */\n clipId: number;\n /** OPFS-backed page provider binding for this clip. */\n binding: OpfsClipPageProviderBinding;\n /** Page size in frames (must equal the provider's `pageFrames`). */\n pageFrames: number;\n /** Total sample count of the clip source. */\n numSamples: number;\n}\n\nexport interface ClipPageStreamerOptions {\n /**\n * Pages to prefetch ahead of the page a miss was reported for. Larger values\n * hide fetch latency at the cost of more resident memory. Default 2.\n */\n readAheadPages?: number;\n /**\n * Pages to retain behind the playback frontier before eviction, so a small\n * backward seek does not immediately miss. Default 1.\n */\n retainBehindPages?: number;\n /**\n * Upper bound on requests drained per {@link ClipPageStreamer.pump} call, so a\n * burst of misses cannot spin unbounded. Default 256.\n */\n maxRequestsPerPump?: number;\n}\n\ninterface SourceState {\n source: ClipPageStreamSource;\n lastPage: number;\n /** Playback-window generation; advanced on reset or backward discontinuity. */\n generation: number;\n /** Most recently serviced playback frontier, or null before the first miss. */\n lastFrontier: number | null;\n /** Resident page -> generation, so in-flight stale fetches cannot alias. */\n resident: Map<number, number>;\n}\n\n/**\n * Keeps OPFS-paged clips fed within a bounded sliding window around the live\n * playback position, so a multitrack arrangement never holds its full PCM in\n * WASM memory.\n *\n * The audio thread reports a page miss whenever the {@link ClipPlayer} reads a\n * sample whose page is not resident. {@link pump} drains those requests, fetches\n * the missing page plus a read-ahead window from each clip's backing store, and\n * evicts pages that fall outside the window via the provider's `clear`. The\n * resident set per clip is therefore bounded to\n * `retainBehindPages + readAheadPages + 1` pages regardless of clip length.\n *\n * Call {@link pump} on a cadence that keeps up with playback — typically once\n * per animation frame or per worklet control tick on the main/control thread\n * (never the audio thread; fetches are asynchronous).\n */\nexport class ClipPageStreamer {\n private readonly engine: ClipPageStreamerEngine;\n private readonly readAheadPages: number;\n private readonly retainBehindPages: number;\n private readonly maxRequestsPerPump: number;\n private readonly sources = new Map<number, SourceState>();\n private closed = false;\n\n constructor(engine: ClipPageStreamerEngine, options: ClipPageStreamerOptions = {}) {\n this.engine = engine;\n this.readAheadPages = Math.max(0, Math.floor(options.readAheadPages ?? 2));\n this.retainBehindPages = Math.max(0, Math.floor(options.retainBehindPages ?? 1));\n this.maxRequestsPerPump = Math.max(1, Math.floor(options.maxRequestsPerPump ?? 256));\n }\n\n /**\n * Register a paged clip. Pages already supplied to the provider before\n * registration (for example a primed first page) should be passed in\n * `initialResidentPages` so they participate in eviction.\n */\n addSource(source: ClipPageStreamSource, initialResidentPages: Iterable<number> = []): void {\n if (source.pageFrames <= 0 || source.numSamples <= 0) {\n throw new Error('pageFrames and numSamples must be positive');\n }\n const lastPage = Math.ceil(source.numSamples / source.pageFrames) - 1;\n const previous = this.sources.get(source.clipId);\n if (previous) {\n this.resetState(previous);\n }\n this.sources.set(source.clipId, {\n source,\n lastPage,\n generation: 0,\n lastFrontier: null,\n resident: new Map(Array.from(initialResidentPages, (page) => [page, 0])),\n });\n }\n\n /** Stop tracking a clip. Does not close its binding (the caller owns that). */\n removeSource(clipId: number): void {\n const state = this.sources.get(clipId);\n if (state) {\n this.resetState(state);\n }\n this.sources.delete(clipId);\n }\n\n /**\n * Explicitly start a new playback generation after a host seek/loop. Resident\n * pages are evicted and any older in-flight fetch is cleared when it settles.\n * The next miss establishes the new bounded window.\n */\n resetSource(clipId: number): void {\n const state = this.sources.get(clipId);\n if (state) {\n this.resetState(state);\n }\n }\n\n /**\n * Drain pending page-miss requests, fetch the missing pages plus their\n * read-ahead window, and evict out-of-window pages. Resolves once this round's\n * fetches settle. Concurrent fetches are serialized inside each binding.\n */\n async pump(): Promise<void> {\n if (this.closed) {\n return;\n }\n // Collapse this round's misses to the latest observed frontier per clip.\n // Queue order reflects playback order, so a backward seek/loop request that\n // follows a stale high-page miss must win even though its page index is\n // smaller. Multiple channel misses still collapse to one service window.\n const frontiers = new Map<number, number>();\n for (let drained = 0; drained < this.maxRequestsPerPump; ++drained) {\n const request = this.engine.popClipPageRequest();\n if (!request) {\n break;\n }\n const state = this.sources.get(request.clipId);\n if (!state) {\n continue;\n }\n const page =\n request.pageIndex !== undefined\n ? request.pageIndex\n : Math.floor((request.sample ?? Number.NaN) / state.source.pageFrames);\n if (!Number.isInteger(page) || page < 0 || page > state.lastPage) {\n continue;\n }\n frontiers.set(request.clipId, page);\n }\n\n const fetches: Promise<unknown>[] = [];\n for (const [clipId, frontier] of frontiers) {\n const state = this.sources.get(clipId);\n if (!state) {\n continue;\n }\n fetches.push(...this.serviceFrontier(state, frontier));\n }\n await Promise.all(fetches);\n }\n\n /** Close every registered clip's binding and stop tracking. */\n close(): void {\n if (this.closed) {\n return;\n }\n this.closed = true;\n for (const state of this.sources.values()) {\n this.resetState(state);\n state.source.binding.close();\n }\n this.sources.clear();\n }\n\n private serviceFrontier(state: SourceState, frontier: number): Promise<unknown>[] {\n // A lower frontier after a previously serviced high page is a seek/loop\n // discontinuity. Advance generation before scheduling its new window so an\n // older asynchronous fetch can never become resident in the new window.\n if (state.lastFrontier !== null && frontier < state.lastFrontier) {\n this.resetState(state);\n }\n state.lastFrontier = frontier;\n const generation = state.generation;\n const low = Math.max(0, frontier - this.retainBehindPages);\n const high = Math.min(state.lastPage, frontier + this.readAheadPages);\n\n // Evict pages outside the window first so a burst of fetches never exceeds\n // the bound by transiently holding old pages alongside new ones.\n for (const page of state.resident.keys()) {\n if (page < low || page > high) {\n this.clearPage(state, page);\n state.resident.delete(page);\n }\n }\n\n const fetches: Promise<unknown>[] = [];\n for (let page = low; page <= high; ++page) {\n if (state.resident.get(page) === generation) {\n continue;\n }\n // Mark resident eagerly so the same page is not fetched twice across\n // overlapping windows; drop it again if the fetch reports a miss.\n state.resident.set(page, generation);\n const pageIndex = page;\n fetches.push(\n state.source.binding.supplyPage(pageIndex).then(\n (ok) => {\n if (state.generation !== generation) {\n // The fetch crossed a seek/reset boundary. supplyPage may have\n // installed it after resetState's clear pass, so clear it again.\n this.clearPage(state, pageIndex);\n } else if (!ok && state.resident.get(pageIndex) === generation) {\n state.resident.delete(pageIndex);\n }\n return ok;\n },\n (error) => {\n if (state.resident.get(pageIndex) === generation) {\n state.resident.delete(pageIndex);\n }\n throw error;\n },\n ),\n );\n }\n return fetches;\n }\n\n private resetState(state: SourceState): void {\n state.generation += 1;\n state.lastFrontier = null;\n for (const page of state.resident.keys()) {\n this.clearPage(state, page);\n }\n state.resident.clear();\n }\n\n private clearPage(state: SourceState, pageIndex: number): void {\n // `clearPage` mirrors eviction into the AudioWorklet. Keep the older\n // provider-only form working for direct-engine callers and test doubles.\n if (state.source.binding.clearPage) {\n state.source.binding.clearPage(pageIndex);\n } else {\n state.source.binding.provider.clear(pageIndex);\n }\n }\n}\n\nexport interface OpfsClipStreamOptions extends OpfsClipPageProviderOptions {\n /** Clip schedule id used in `setClips` (matches the page-miss request clipId). */\n clipId: number;\n /**\n * Leading pages fetched synchronously before returning, so playback can start\n * without an immediate miss. Default 1.\n */\n primePages?: number;\n}\n\nexport interface OpfsClipStream {\n binding: OpfsClipPageProviderBinding;\n /** Pass as `addClip`'s buffer argument to schedule the streaming clip. */\n provider: ClipPageProvider;\n}\n\n/** Structural seam implemented by the AudioWorklet-backed `SonareEngine`. */\nexport interface WorkletOpfsClipStreamHost {\n attachOpfsClipStream(options: OpfsClipStreamOptions): Promise<OpfsClipStream>;\n}\n\n/**\n * One-call wiring of an OPFS-backed streaming clip: creates the page provider,\n * primes the leading pages, and registers it with `streamer` so later misses are\n * serviced within the bounded window. Returns the binding (for `close`) and the\n * provider to schedule via `addClip(trackId, provider, startPpq, { id: clipId })`.\n *\n * @param streamer Shared streamer pumped on the control thread.\n * @param engine Engine the provider is created on (the same one `streamer` drives).\n * @param options Provider options plus `clipId` and optional `primePages`.\n */\nexport function attachOpfsClipStream(\n streamer: ClipPageStreamer,\n engine: RealtimeEngine,\n options: OpfsClipStreamOptions,\n): Promise<OpfsClipStream>;\n/**\n * Worklet overload: delegates to `SonareEngine.attachOpfsClipStream`, which\n * creates the remote provider and drives this same sliding-window policy from\n * worklet page-miss messages.\n */\nexport function attachOpfsClipStream(\n engine: WorkletOpfsClipStreamHost,\n options: OpfsClipStreamOptions,\n): Promise<OpfsClipStream>;\nexport async function attachOpfsClipStream(\n streamerOrEngine: ClipPageStreamer | WorkletOpfsClipStreamHost,\n engineOrOptions: RealtimeEngine | OpfsClipStreamOptions,\n maybeOptions?: OpfsClipStreamOptions,\n): Promise<OpfsClipStream> {\n if (!(streamerOrEngine instanceof ClipPageStreamer)) {\n return streamerOrEngine.attachOpfsClipStream(engineOrOptions as OpfsClipStreamOptions);\n }\n const streamer = streamerOrEngine;\n const engine = engineOrOptions as RealtimeEngine;\n const options = maybeOptions;\n if (!options) {\n throw new Error('attachOpfsClipStream requires options.');\n }\n const { clipId, primePages = 1, ...providerOptions } = options;\n const binding = createOpfsClipPageProvider(engine, providerOptions);\n const lastPage = Math.ceil(providerOptions.numSamples / providerOptions.pageFrames) - 1;\n const primed: number[] = [];\n for (let page = 0; page < primePages && page <= lastPage; ++page) {\n if (await binding.supplyPage(page)) {\n primed.push(page);\n }\n }\n streamer.addSource(\n {\n clipId,\n binding,\n pageFrames: providerOptions.pageFrames,\n numSamples: providerOptions.numSamples,\n },\n primed,\n );\n return { binding, provider: binding.provider };\n}\n","/**\n * Numeric error codes carried by a {@link SonareError}. Mirrors the C ABI\n * `SonareError` enum (and the Node / Python surfaces), so the same failure\n * reports the same numeric code on every binding.\n */\nexport enum ErrorCode {\n Ok = 0,\n FileNotFound = 1,\n InvalidFormat = 2,\n DecodeFailed = 3,\n InvalidParameter = 4,\n OutOfMemory = 5,\n NotSupported = 6,\n InvalidState = 7,\n Cancelled = 8,\n Unknown = 99,\n}\n\n/**\n * Error thrown by libsonare on a native (C++) failure. Carries a numeric\n * {@link ErrorCode} `code` plus its canonical `codeName`, so callers can branch\n * on the cause instead of matching message text.\n */\nexport class SonareError extends Error {\n /** Numeric error code, equal to an {@link ErrorCode} value. */\n readonly code: number;\n /** Canonical name of `code`, e.g. `'InvalidParameter'`. */\n readonly codeName: string;\n\n constructor(code: number, codeName: string, message: string) {\n super(message);\n this.name = 'SonareError';\n this.code = code;\n this.codeName = codeName;\n }\n}\n\n/** Type guard: whether a caught value is a libsonare {@link SonareError}. */\nexport function isSonareError(value: unknown): value is SonareError {\n return (\n value instanceof Error &&\n (value as { name?: unknown }).name === 'SonareError' &&\n typeof (value as { code?: unknown }).code === 'number'\n );\n}\n","import { ErrorCode, SonareError } from './errors';\nimport type { SonareModule } from './sonare.js';\n\nlet wrappedModule: SonareModule | null = null;\n\n/**\n * Shape of the structured info the native `sonareExceptionInfo(ptr)` returns.\n */\ninterface NativeExceptionInfo {\n code: number;\n codeName: string;\n message: string;\n}\n\n/**\n * Recover the native exception-object pointer from a value thrown across the\n * WASM boundary. emscripten surfaces a C++ throw in two shapes depending on the\n * toolchain/exception mode:\n * - a raw pointer number (older / classic surfacing), or\n * - a `CppException` object exposing the pointer as `excPtr` (emscripten with\n * `-fexceptions`).\n * Returns null when the thrown value is neither (a genuine JS error), so the\n * caller rethrows it unchanged.\n */\nfunction nativeExceptionPtr(error: unknown): number | null {\n if (typeof error === 'number') {\n return error;\n }\n if (error !== null && typeof error === 'object') {\n const ptr = (error as { excPtr?: unknown }).excPtr;\n if (typeof ptr === 'number') {\n return ptr;\n }\n }\n return null;\n}\n\n/**\n * Turn a thrown native exception pointer into a {@link SonareError}. The bound\n * `sonareExceptionInfo` decodes the pointer back into { code, codeName,\n * message }.\n */\nfunction makeSonareError(raw: SonareModule, thrown: number): SonareError {\n let code: number = ErrorCode.Unknown;\n let codeName = 'Unknown';\n let message = `libsonare native exception (${thrown})`;\n try {\n const info = (\n raw as unknown as { sonareExceptionInfo?: (ptr: number) => NativeExceptionInfo }\n ).sonareExceptionInfo?.(thrown);\n if (info) {\n code = info.code ?? code;\n codeName = info.codeName ?? codeName;\n message = info.message || message;\n }\n } catch {\n // Fall back to the generic message if decoding fails.\n }\n return new SonareError(code, codeName, message);\n}\n\n/**\n * Wrap the embind module so a native C++ exception (which surfaces as a raw\n * pointer number or a `CppException` carrying one) is rethrown as a\n * {@link SonareError}. Only function-valued\n * members are wrapped, and the wrapper is cached per member so repeated access\n * stays cheap; non-function members (typed-array heap views, etc.) pass through\n * unchanged.\n */\nfunction wrapModuleErrors(raw: SonareModule): SonareModule {\n const cache = new Map<PropertyKey, unknown>();\n const objectCache = new WeakMap<object, unknown>();\n const convert = (error: unknown): never => {\n const ptr = nativeExceptionPtr(error);\n if (ptr !== null) {\n throw makeSonareError(raw, ptr);\n }\n throw error;\n };\n\n const wrapNativeObject = (value: unknown): unknown => {\n if (value === null || typeof value !== 'object') {\n return value;\n }\n if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer || value instanceof Promise) {\n return value;\n }\n const objectValue = value as object;\n const cached = objectCache.get(objectValue);\n if (cached) {\n return cached;\n }\n const methodCache = new Map<PropertyKey, unknown>();\n const wrapped = new Proxy(objectValue, {\n get(target, prop, receiver) {\n const member = Reflect.get(target, prop, receiver);\n if (typeof member !== 'function') {\n return member;\n }\n const cachedMethod = methodCache.get(prop);\n if (cachedMethod) {\n return cachedMethod;\n }\n const method = member as (...a: unknown[]) => unknown;\n const wrappedMethod = (...args: unknown[]) => {\n try {\n return wrapNativeObject(Reflect.apply(method, target, args));\n } catch (error) {\n return convert(error);\n }\n };\n methodCache.set(prop, wrappedMethod);\n return wrappedMethod;\n },\n });\n objectCache.set(objectValue, wrapped);\n return wrapped;\n };\n\n const wrapFunction = (value: (...a: unknown[]) => unknown): unknown => {\n const fnCache = new Map<PropertyKey, unknown>();\n return new Proxy(value, {\n get(target, prop, receiver) {\n const member = Reflect.get(target, prop, receiver);\n if (typeof member !== 'function') {\n return member;\n }\n const cachedMember = fnCache.get(prop);\n if (cachedMember) {\n return cachedMember;\n }\n const fn = member as (...a: unknown[]) => unknown;\n const wrappedMember = (...args: unknown[]) => {\n try {\n return wrapNativeObject(Reflect.apply(fn, target, args));\n } catch (error) {\n return convert(error);\n }\n };\n fnCache.set(prop, wrappedMember);\n return wrappedMember;\n },\n apply(t, thisArg, args) {\n try {\n return wrapNativeObject(Reflect.apply(t, thisArg, args as unknown[]));\n } catch (error) {\n return convert(error);\n }\n },\n construct(t, args, newTarget) {\n try {\n return wrapNativeObject(Reflect.construct(t, args as unknown[], newTarget)) as object;\n } catch (error) {\n return convert(error) as object;\n }\n },\n });\n };\n\n return new Proxy(raw, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (typeof value !== 'function') {\n return value;\n }\n const cached = cache.get(prop);\n if (cached) {\n return cached;\n }\n // Wrap as a Proxy (not a plain function) so embind class constructors\n // invoked via `new module.Foo(...)` keep their `[[Construct]]` behaviour\n // and prototype while still converting thrown native pointers.\n const wrapped = wrapFunction(value as (...a: unknown[]) => unknown);\n cache.set(prop, wrapped);\n return wrapped;\n },\n }) as SonareModule;\n}\n\nexport function setSonareModule(module: SonareModule): void {\n wrappedModule = wrapModuleErrors(module);\n}\n\nexport function getSonareModule(): SonareModule {\n if (!wrappedModule) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return wrappedModule;\n}\n","import type { AutomationCurve, MeterTap, PanLawInput, PanMode, SendTiming } from './public_types';\n\n/** Resolve a numeric ordinal in an inclusive range without coercion. */\nexport function resolveOrdinalInRange(\n value: unknown,\n min: number,\n max: number,\n enumName: string,\n): number {\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < min || value > max) {\n throw new RangeError(`Invalid ${enumName}: ${String(value)}`);\n }\n return value;\n}\n\n/** Resolve a public enum spelling or ordinal without permitting unknown values. */\nexport function resolveEnumOrdinal(\n value: unknown,\n values: Readonly<Record<string, number>>,\n enumName: string,\n): number {\n if (typeof value === 'number') {\n const ordinals = Object.values(values);\n const ordinal = resolveOrdinalInRange(\n value,\n Math.min(...ordinals),\n Math.max(...ordinals),\n enumName,\n );\n if (!ordinals.includes(ordinal)) {\n throw new RangeError(`Invalid ${enumName}: ${String(value)}`);\n }\n return ordinal;\n }\n if (typeof value === 'string') {\n const ordinal = values[value];\n if (ordinal !== undefined) {\n return ordinal;\n }\n }\n throw new RangeError(`Invalid ${enumName}: ${String(value)}`);\n}\n\nconst AUTOMATION_CURVE_VALUES = {\n linear: 0,\n exponential: 1,\n hold: 2,\n 's-curve': 3,\n} as const;\nconst PAN_LAW_VALUES: Readonly<Record<string, number>> = {\n const3db: 0,\n 'const-3db': 0,\n '-3db': 0,\n 'const4.5db': 1,\n 'const-4.5db': 1,\n '-4.5db': 1,\n const6db: 2,\n 'const-6db': 2,\n '-6db': 2,\n linear0db: 3,\n 'linear-0db': 3,\n linear: 3,\n '0db': 3,\n} as const;\nconst PAN_MODE_VALUES = {\n balance: 0,\n pan: 1,\n stereopan: 1,\n 'stereo-pan': 1,\n dualpan: 2,\n 'dual-pan': 2,\n} as const;\nconst METER_TAP_VALUES = { preFader: 0, postFader: 1 } as const;\nconst SEND_TIMING_VALUES = { postFader: 0, preFader: 1 } as const;\nconst TRACK_MONITOR_MODE_VALUES = { off: 0, pfl: 1, afl: 2 } as const;\n\nexport function automationCurveCode(curve: AutomationCurve): number {\n return resolveEnumOrdinal(curve, AUTOMATION_CURVE_VALUES, 'automation curve');\n}\n\nexport function panLawCode(panLaw: PanLawInput): number {\n const normalized = typeof panLaw === 'string' ? panLaw.toLowerCase().replace(/_/g, '-') : panLaw;\n return resolveEnumOrdinal(normalized, PAN_LAW_VALUES, 'pan law');\n}\n\nexport function panModeCode(panMode: PanMode | number): number {\n const normalized =\n typeof panMode === 'string' ? panMode.replace(/_/g, '-').toLowerCase() : panMode;\n return resolveEnumOrdinal(normalized, PAN_MODE_VALUES, 'pan mode');\n}\n\nexport function meterTapCode(tap: MeterTap | number): number {\n return resolveEnumOrdinal(tap, METER_TAP_VALUES, 'meter tap');\n}\n\nexport function sendTimingCode(timing: SendTiming | number): number {\n // Mirrors SonareSendTiming: post-fader is 0 (so an omitted/zeroed value is\n // post-fader), pre-fader is 1. A raw number is passed through as the C ABI int.\n // An unknown string is rejected rather than silently routed to post-fader,\n // matching the sibling enum-code helpers and Node's sendTimingValue.\n return resolveEnumOrdinal(timing, SEND_TIMING_VALUES, 'send timing');\n}\n\n/** Resolve a per-track PFL/AFL monitor mode to its C-ABI ordinal. */\nexport function trackMonitorModeCode(mode: unknown): number {\n return resolveEnumOrdinal(mode, TRACK_MONITOR_MODE_VALUES, 'track monitor mode');\n}\n","import { panLawCode, panModeCode, sendTimingCode, trackMonitorModeCode } from './codes';\nimport { ErrorCode, SonareError } from './errors';\nimport { getSonareModule } from './module_state';\nimport type { ProjectMidiCcBinding, SynthPatch } from './project';\nimport type { EqBand, PanLawInput, PanMode, SendTiming } from './public_types';\nimport type {\n WasmClipPageRequest,\n WasmEngineAutomationPoint,\n WasmEngineBounceOptions,\n WasmEngineBounceResult,\n WasmEngineCaptureStatus,\n WasmEngineClip,\n WasmEngineFreezeOptions,\n WasmEngineFreezeResult,\n WasmEngineGraphSpec,\n WasmEngineMarker,\n WasmEngineMeterTelemetry,\n WasmEngineMeterTelemetryWide,\n WasmEngineMetronomeConfig,\n WasmEngineParameterInfo,\n WasmEngineProcessWithMonitorResult,\n WasmEngineScopeTelemetry,\n WasmEngineTelemetry,\n WasmEngineTempoSegment,\n WasmEngineTimeSignatureSegment,\n WasmEngineTransportState,\n WasmExternalMidiEvent,\n WasmRealtimeEngine,\n} from './sonare.js';\n\nexport type ExternalMidiEvent = WasmExternalMidiEvent;\n\nexport type EngineClip = WasmEngineClip;\nexport type ClipPageRequest = WasmClipPageRequest;\nexport type EngineParameterInfo = WasmEngineParameterInfo;\nexport type EngineAutomationPoint = WasmEngineAutomationPoint;\nexport type EngineMarker = WasmEngineMarker;\nexport type EngineMetronomeConfig = WasmEngineMetronomeConfig;\nexport type EngineGraphSpec = WasmEngineGraphSpec;\nexport type EngineCaptureStatus = WasmEngineCaptureStatus;\nexport type EngineCaptureSource = EngineCaptureStatus['source'] | number;\nexport type EngineBounceOptions = WasmEngineBounceOptions;\nexport type EngineBounceResult = WasmEngineBounceResult;\nexport type EngineFreezeOptions = WasmEngineFreezeOptions;\nexport type EngineFreezeResult = WasmEngineFreezeResult;\nexport type EngineTelemetry = WasmEngineTelemetry;\nexport type EngineMeterTelemetry = WasmEngineMeterTelemetry;\nexport type EngineMeterTelemetryWide = WasmEngineMeterTelemetryWide;\nexport type EngineScopeTelemetry = WasmEngineScopeTelemetry;\nexport type EngineTransportState = WasmEngineTransportState;\nexport type EngineTempoSegment = WasmEngineTempoSegment;\nexport type EngineTimeSignatureSegment = WasmEngineTimeSignatureSegment;\n\nexport interface EngineTrackSend {\n busId: number;\n levelDb?: number;\n enabled?: boolean;\n /**\n * Pre/post-fader tap point. Defaults to post-fader when omitted, matching the\n * historical lane-send behavior and the scene-JSON default.\n */\n sendTiming?: SendTiming | number;\n}\n\nexport interface EngineTrackLane {\n trackId: number;\n sends?: EngineTrackSend[];\n /**\n * Bus the lane's post-fader output sums into instead of the master mix\n * (group/folder routing); 0 or absent keeps the lane on the master mix.\n */\n outputBusId?: number;\n /**\n * Input channel layout of the source feeding this lane (`SonareChannelLayout`:\n * 0 mono, 1 stereo, 2 5.1, 3 7.1). Absent defaults to stereo. Stored but inert\n * until the surround DSP path lands.\n */\n sourceChannelLayout?: number;\n}\n\n/** Per-track cue/monitor tap mode: off, pre-fader listen, or after-fader listen. */\nexport type EngineTrackMonitorMode = 'off' | 'pfl' | 'afl' | 0 | 1 | 2;\n\n/** Short alias for {@link EngineTrackMonitorMode}. */\nexport type TrackMonitorMode = EngineTrackMonitorMode;\n\nexport interface EngineBus {\n busId: number;\n gainDb?: number;\n /**\n * Channel layout of the bus (`SonareChannelLayout`: 0 mono, 1 stereo, 2 5.1,\n * 3 7.1). A surround layout makes this a surround group bus: lanes routed to\n * it are surround-panned and it sums into the master plane-by-plane. Defaults\n * to stereo.\n */\n channelLayout?: number;\n}\n\nexport interface EngineMidiEvent {\n renderFrame: number;\n word0?: number;\n word1?: number;\n word2?: number;\n word3?: number;\n wordCount?: number;\n group?: number;\n sysexHandle?: number;\n data0?: number;\n data1?: number;\n}\n\nexport interface EngineMidiClipSchedule {\n id?: number;\n trackId?: number;\n destinationId?: number;\n startSample?: number;\n startPpq?: number;\n lengthSamples?: number;\n loop?: boolean;\n loopLengthSamples?: number;\n events: EngineMidiEvent[];\n}\n\nexport const EXPECTED_ENGINE_ABI_VERSION = 3;\n\n/** Options for {@link RealtimeEngine.bindMidiCc}. All fields are optional. */\nexport interface MidiCcBindOptions {\n /** Lower end of the mapped parameter range. Default `0`. */\n minValue?: number;\n /** Upper end of the mapped parameter range. Default `1`. */\n maxValue?: number;\n}\n\nexport interface EngineCapabilities {\n engineAbiVersion: number;\n expectedEngineAbiVersion: number;\n abiCompatible: boolean;\n sharedArrayBuffer: boolean;\n atomics: boolean;\n audioWorklet: boolean;\n mode: 'sab' | 'postMessage';\n}\n\nexport function engineCapabilities(): EngineCapabilities {\n const abiVersion = getSonareModule().engineAbiVersion();\n const sharedArrayBuffer = typeof globalThis.SharedArrayBuffer === 'function';\n const atomics = typeof globalThis.Atomics === 'object';\n const audioWorklet =\n typeof AudioWorkletNode !== 'undefined' ||\n typeof (globalThis as typeof globalThis & { AudioWorkletProcessor?: unknown })\n .AudioWorkletProcessor !== 'undefined';\n return {\n engineAbiVersion: abiVersion,\n expectedEngineAbiVersion: EXPECTED_ENGINE_ABI_VERSION,\n abiCompatible: abiVersion === EXPECTED_ENGINE_ABI_VERSION,\n sharedArrayBuffer,\n atomics,\n audioWorklet,\n mode: sharedArrayBuffer && atomics ? 'sab' : 'postMessage',\n };\n}\n\nexport class RealtimeEngine {\n private native: WasmRealtimeEngine;\n\n constructor(\n sampleRate = 48000,\n maxBlockSize = 128,\n commandCapacity = 1024,\n telemetryCapacity = 1024,\n maxChannels = 64,\n ) {\n const module = getSonareModule();\n const capabilities = engineCapabilities();\n if (!capabilities.abiCompatible) {\n throw new Error(\n `Engine ABI mismatch: wasm=${capabilities.engineAbiVersion}, expected=${capabilities.expectedEngineAbiVersion}`,\n );\n }\n this.native = new module.RealtimeEngine(\n sampleRate,\n maxBlockSize,\n commandCapacity,\n telemetryCapacity,\n maxChannels,\n );\n }\n\n prepare(\n sampleRate: number,\n maxBlockSize: number,\n commandCapacity = 1024,\n telemetryCapacity = 1024,\n maxChannels = 64,\n ): void {\n this.native.prepareWithChannels(\n sampleRate,\n maxBlockSize,\n commandCapacity,\n telemetryCapacity,\n maxChannels,\n );\n }\n\n /** Queue a sample-accurate parameter change (engine kSetParam). */\n setParameter(paramId: number, value: number, renderFrame = -1): void {\n this.native.setParameter(paramId, value, renderFrame);\n }\n\n /** Queue a smoothed parameter change (engine kSetParamSmoothed). */\n setParameterSmoothed(paramId: number, value: number, renderFrame = -1): void {\n this.native.setParameterSmoothed(paramId, value, renderFrame);\n }\n\n /**\n * Set the default ramp time (ms) for engine-level smoothed parameters —\n * fader/pan glides, insert-parameter automation, and MIDI-CC mappings. The\n * default is 20 ms; pass `0` for instant (un-ramped) changes.\n */\n setParamSmoothingMs(smoothingMs: number): void {\n this.native.setParamSmoothingMs(smoothingMs);\n }\n\n setSoloMute(laneIndex: number, solo: boolean, mute: boolean, renderFrame = -1): void {\n this.native.setSoloMute(laneIndex, solo, mute, renderFrame);\n }\n\n /** Queue a per-track PFL/AFL monitor tap mode change. */\n setTrackMonitorMode(laneIndex: number, mode: EngineTrackMonitorMode, renderFrame = -1): void {\n this.native.setTrackMonitorMode(laneIndex, trackMonitorModeCode(mode), renderFrame);\n }\n\n setMidiClips(clips: readonly EngineMidiClipSchedule[]): void {\n this.native.setMidiClips(clips);\n }\n\n setBuiltinInstrument(\n config: { destinationId?: number } & Record<string, unknown> = {},\n destinationId = config.destinationId ?? 0,\n ): void {\n this.native.setBuiltinInstrument(destinationId, config);\n }\n\n /**\n * Bind the patch-driven NativeSynth to a realtime MIDI destination. `patch`\n * is a {@link SynthPatch} or a preset-name string (`'saw-lead'` /\n * `'va:saw-lead'`; see {@link synthPresetNames}), resolving exactly like\n * {@link Project.bounceWithSynthInstrument}. Live note/CC commands and\n * scheduled MIDI clips routed to that destination render through the synth.\n * Unknown preset names throw. An object patch's `destinationId` is a JS\n * binding convenience, not part of the NativeSynth patch itself.\n */\n setSynthInstrument(\n patch: SynthPatch | string = {},\n destinationId = (typeof patch === 'object' ? patch.destinationId : undefined) ?? 0,\n ): void {\n this.native.setSynthInstrument(destinationId, patch);\n }\n\n /**\n * Load (parse) SoundFont 2 bytes into the engine so SF2 instruments can be\n * bound with {@link setSf2Instrument}. The host fetches the `.sf2` and\n * passes the raw bytes; they are copied into linear memory for the call and\n * not referenced afterwards. Replaces any previously loaded SoundFont.\n */\n loadSoundFont(data: Uint8Array): void {\n this.native.loadSoundFont(data);\n }\n\n /**\n * Bind a GS-compatible SoundFont player to a realtime MIDI destination, fed\n * by the engine's loaded SoundFont ({@link loadSoundFont}). Live note/CC\n * commands and scheduled MIDI clips routed to that destination render\n * through the player (16 MIDI channels, channel 10 drums, GS NRPN part\n * edits, GS/GM SysEx resets). Without a loaded SoundFont — or for programs\n * the SoundFont does not cover — notes play through the built-in\n * synthesizer GM fallback bank (the data-free floor).\n */\n setSf2Instrument(\n config: {\n destinationId?: number;\n gain?: number;\n polyphony?: number;\n preferModelForModeledFamilies?: boolean;\n } = {},\n destinationId = config.destinationId ?? 0,\n ): void {\n this.native.setSf2Instrument(destinationId, config);\n }\n\n clearMidiInstrument(destinationId = 0): void {\n this.native.clearMidiInstrument(destinationId);\n }\n\n midiInstrumentCount(): number {\n return this.native.midiInstrumentCount();\n }\n\n /**\n * Bind a live MIDI CC to an engine automation parameter. The MIDI event still\n * reaches the destination instrument; when bound, its 7-bit value is also\n * mapped into [minValue, maxValue] for `paramId`.\n */\n bindMidiCc(\n channel: number,\n controller: number,\n paramId: number,\n options: MidiCcBindOptions = {},\n ): void {\n this.native.bindMidiCc(\n channel,\n controller,\n paramId,\n options.minValue ?? 0,\n options.maxValue ?? 1,\n );\n }\n\n /** Bind a 7/14-bit CC, RPN, or NRPN descriptor to a live parameter. */\n bindMidiCcBinding(binding: ProjectMidiCcBinding): void {\n this.native.bindMidiCcBinding(binding);\n }\n\n clearMidiCcBindings(): void {\n this.native.clearMidiCcBindings();\n }\n\n midiCcBindingCount(): number {\n return this.native.midiCcBindingCount();\n }\n\n /** Install/replace a live non-destructive MIDI-FX insert for one destination. */\n setMidiFx(destinationId: number, configJson: string): void {\n this.native.setMidiFx(destinationId, configJson);\n }\n\n clearMidiFx(destinationId = 0): void {\n this.native.clearMidiFx(destinationId);\n }\n\n /** Enable the engine-owned live MIDI input source for a destination. */\n setMidiInputSource(destinationId = 0): void {\n this.native.setMidiInputSource(destinationId);\n }\n\n clearMidiInputSource(): void {\n this.native.clearMidiInputSource();\n }\n\n midiInputPendingCount(): number {\n return this.native.midiInputPendingCount();\n }\n\n /**\n * Route a destination's (track lane's) MIDI to the external output queue\n * instead of the internal instrument rack, so the track plays an external\n * device. Clearing it restores internal-synth playback.\n */\n setMidiDestinationExternal(destinationId: number, external: boolean): void {\n this.native.setMidiDestinationExternal(destinationId, external);\n }\n\n /**\n * Enable/disable forwarding MIDI clock + transport (start/continue/stop) to\n * the external output queue so external gear tracks the transport tempo.\n */\n setExternalMidiClockEnabled(enabled: boolean): void {\n this.native.setExternalMidiClockEnabled(enabled);\n }\n\n /** Count of external-MIDI events dropped because the output queue was full. */\n externalMidiDroppedCount(): number {\n return this.native.externalMidiDroppedCount();\n }\n\n externalMidiPendingCount(): number {\n return this.native.externalMidiPendingCount();\n }\n\n /**\n * Drain queued external-MIDI events, already lowered to MIDI 1.0 byte\n * messages ready to write to a Web MIDI output port. Call once per audio\n * block / animation frame. `maxRecords` caps the number of output events\n * returned — the shared unit across every surface. Events past the cap stay\n * queued for the next call (lossless); call again to drain the rest.\n */\n drainExternalMidi(maxRecords = 1024): WasmExternalMidiEvent[] {\n return this.native.drainExternalMidi(maxRecords);\n }\n\n /** Scalar, allocation-free external-MIDI drain for AudioWorklet SAB output. */\n popExternalMidiToScratch(): boolean {\n return this.native.popExternalMidiToScratch();\n }\n\n externalMidiScratchDestinationId(): number {\n return this.native.externalMidiScratchDestinationId();\n }\n\n externalMidiScratchRenderFrame(): number {\n return this.native.externalMidiScratchRenderFrame();\n }\n\n externalMidiScratchByteWord(): number {\n return this.native.externalMidiScratchByteWord();\n }\n\n externalMidiScratchByteCount(): number {\n return this.native.externalMidiScratchByteCount();\n }\n\n consumeExternalMidiScratch(): void {\n this.native.consumeExternalMidiScratch();\n }\n\n pushMidiInputNoteOn(\n group: number,\n channel: number,\n note: number,\n velocity: number,\n portTimeSamples = 0,\n ): void {\n this.native.pushMidiInputNoteOn(group, channel, note, velocity, portTimeSamples);\n }\n\n pushMidiInputNoteOff(\n group: number,\n channel: number,\n note: number,\n velocity = 0,\n portTimeSamples = 0,\n ): void {\n this.native.pushMidiInputNoteOff(group, channel, note, velocity, portTimeSamples);\n }\n\n pushMidiInputCc(\n group: number,\n channel: number,\n controller: number,\n value: number,\n portTimeSamples = 0,\n ): void {\n this.native.pushMidiInputCc(group, channel, controller, value, portTimeSamples);\n }\n\n pushMidiNoteOn(\n destinationId: number,\n group: number,\n channel: number,\n note: number,\n velocity: number,\n renderFrame = -1,\n ): void {\n this.native.pushMidiNoteOn(destinationId, group, channel, note, velocity, renderFrame);\n }\n\n pushMidiNoteOff(\n destinationId: number,\n group: number,\n channel: number,\n note: number,\n velocity = 0,\n renderFrame = -1,\n ): void {\n this.native.pushMidiNoteOff(destinationId, group, channel, note, velocity, renderFrame);\n }\n\n /**\n * Queue an immediate (live) MIDI control change to a MIDI destination\n * (engine kMidiCcImmediate). `group`/`channel` are 0..15; `controller`/`value`\n * are 7-bit (0..127). `renderFrame` is the frame to fire at, or -1 for\n * immediate. Mirrors the Node/Python/C-ABI `pushMidiCc`.\n */\n pushMidiCc(\n destinationId: number,\n group: number,\n channel: number,\n controller: number,\n value: number,\n renderFrame = -1,\n ): void {\n this.native.pushMidiCc(destinationId, group, channel, controller, value, renderFrame);\n }\n\n /** Queue one immediate MIDI 1.0 channel-voice UMP word for a destination. */\n pushMidiUmp(destinationId: number, word0: number, renderFrame = -1): void {\n this.native.pushMidiUmp(destinationId, word0, renderFrame);\n }\n\n /**\n * Queue an immediate (live) MIDI SysEx frame to a MIDI destination. `data` is\n * the full message including the leading 0xF0 and trailing 0xF7 (1..512\n * bytes). `renderFrame` is the frame to fire at, or -1 for immediate. Mirrors\n * the Node/Python/C-ABI `pushMidiSysex`.\n */\n pushMidiSysex(destinationId: number, data: Uint8Array, renderFrame = -1): void {\n this.native.pushMidiSysex(destinationId, data, renderFrame);\n }\n\n /**\n * Queue a MIDI panic (all-notes-off) releasing every sounding note at\n * `renderFrame` (-1 = immediate). Mirrors the C-ABI `pushMidiPanic`.\n */\n pushMidiPanic(renderFrame = -1): void {\n this.native.pushMidiPanic(renderFrame);\n }\n\n /**\n * Remove all registered parameters (and their automation lanes). Control-thread\n * only; not realtime-safe. Mirrors the C-ABI `clearParameters`.\n */\n clearParameters(): void {\n this.native.clearParameters();\n }\n\n /** Read back the current transport state snapshot. */\n getTransportState(): EngineTransportState {\n return this.native.getTransportState();\n }\n\n play(renderFrame = -1): void {\n this.native.play(renderFrame);\n }\n\n stop(renderFrame = -1): void {\n this.native.stop(renderFrame);\n }\n\n seekSample(timelineSample: number, renderFrame = -1): void {\n this.native.seekSample(timelineSample, renderFrame);\n }\n\n /**\n * Snaps every in-flight parameter ramp (engine-level smoothed params, mixer\n * lane fader/pan/gate, bus gains) to its target value. Offline renders call\n * this after a priming process() block so the first audible block renders at\n * settled values instead of ramping in from defaults.\n */\n settleParameters(): void {\n this.native.settleParameters();\n }\n\n /** Drains queued commands on an offline/control-only engine immediately. */\n flushControlCommands(): void {\n this.native.flushControlCommands();\n }\n\n seekPpq(ppq: number, renderFrame = -1): void {\n this.native.seekPpq(ppq, renderFrame);\n }\n\n /** Set a finite tempo in the range (0, 100000] BPM. */\n setTempo(bpm: number): void {\n this.native.setTempo(bpm);\n }\n\n setTempoSegments(segments: readonly EngineTempoSegment[]): void {\n this.native.setTempoSegments([...segments]);\n }\n\n setTimeSignature(numerator: number, denominator: number): void {\n this.native.setTimeSignature(numerator, denominator);\n }\n\n setTimeSignatureSegments(segments: readonly EngineTimeSignatureSegment[]): void {\n this.native.setTimeSignatureSegments([...segments]);\n }\n\n sampleAtPpq(ppq: number): number {\n return Number(this.native.sampleAtPpq(ppq));\n }\n\n setLoop(startPpq: number, endPpq: number, enabled = true): void {\n this.native.setLoop(startPpq, endPpq, enabled);\n }\n\n addParameter(info: EngineParameterInfo): void {\n this.native.addParameter(info);\n }\n\n parameterCount(): number {\n return this.native.parameterCount();\n }\n\n parameterInfoByIndex(index: number): EngineParameterInfo {\n return this.native.parameterInfoByIndex(index);\n }\n\n parameterInfo(id: number): EngineParameterInfo {\n return this.native.parameterInfo(id);\n }\n\n setAutomationLane(paramId: number, points: EngineAutomationPoint[]): void {\n this.native.setAutomationLane(paramId, points);\n }\n\n automationLaneCount(): number {\n return this.native.automationLaneCount();\n }\n\n setMarkers(markers: EngineMarker[]): void {\n this.native.setMarkers(markers);\n }\n\n markerCount(): number {\n return this.native.markerCount();\n }\n\n markerByIndex(index: number): EngineMarker {\n return this.native.markerByIndex(index);\n }\n\n marker(id: number): EngineMarker {\n return this.native.marker(id);\n }\n\n seekMarker(markerId: number, renderFrame = -1): void {\n this.native.seekMarker(markerId, renderFrame);\n }\n\n setLoopFromMarkers(startMarkerId: number, endMarkerId: number): void {\n this.native.setLoopFromMarkers(startMarkerId, endMarkerId);\n }\n\n /** Set a metronome config; click lengths are limited to one second. */\n setMetronome(config: EngineMetronomeConfig): void {\n this.native.setMetronome(config);\n }\n\n metronome(): Required<EngineMetronomeConfig> {\n return this.native.metronome();\n }\n\n countInEndSample(startSample: number, bars: number): number {\n return Number(this.native.countInEndSample(startSample, bars));\n }\n\n setGraph(spec: EngineGraphSpec): void {\n this.native.setGraph(spec);\n }\n\n graphNodeCount(): number {\n return this.native.graphNodeCount();\n }\n\n graphConnectionCount(): number {\n return this.native.graphConnectionCount();\n }\n\n setClips(clips: EngineClip[]): void {\n this.native.setClips(\n clips.map((clip) => ({\n ...clip,\n pageProvider:\n typeof clip.pageProvider === 'object' && clip.pageProvider !== null\n ? clip.pageProvider.id\n : clip.pageProvider,\n })),\n );\n }\n\n /**\n * Returns the PCM generated for a tempo-sync clip by the control-thread\n * setter, or `null` when the clip did not require a tempo-sync bake.\n */\n prebakedClipChannels(clipId: number): Float32Array[] | null {\n return this.native.prebakedClipChannels(clipId);\n }\n\n clipCount(): number {\n return this.native.clipCount();\n }\n\n setTrackLanes(lanes: Array<number | EngineTrackLane>): void {\n this.native.setTrackLanes(\n lanes.map((lane) => {\n if (typeof lane === 'number') {\n return { trackId: lane };\n }\n if (!lane.sends) {\n return lane;\n }\n // Normalize each send's pre/post tap point to the integer the native\n // layer reads (defaults to post-fader when omitted).\n return {\n ...lane,\n sends: lane.sends.map((send) => ({\n ...send,\n // Post-fader (0) is the default for an omitted sendTiming.\n sendTiming: send.sendTiming === undefined ? 0 : sendTimingCode(send.sendTiming),\n })),\n };\n }),\n );\n }\n\n /**\n * Keys one insert of a lane strip from another lane's post-strip audio\n * (ducking/sidechainRouter inserts). sourceTrackId 0 removes the binding.\n */\n setLaneSidechain(trackId: number, insertIndex: number, sourceTrackId: number): void {\n this.native.setLaneSidechain(trackId, insertIndex, sourceTrackId);\n }\n\n setTrackBuses(buses: EngineBus[]): void {\n this.native.setTrackBuses(buses);\n }\n\n setBusStripJson(busId: number, sceneJson: string): void {\n try {\n JSON.parse(sceneJson);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'invalid bus strip JSON';\n throw new SonareError(ErrorCode.InvalidFormat, 'InvalidFormat', message);\n }\n this.native.setBusStripJson(busId, sceneJson);\n }\n\n setTrackStripJson(trackId: number, sceneJson: string): void {\n try {\n JSON.parse(sceneJson);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'invalid track strip JSON';\n throw new SonareError(ErrorCode.InvalidFormat, 'InvalidFormat', message);\n }\n this.native.setTrackStripJson(trackId, sceneJson);\n }\n\n setTrackStripEqBand(trackId: number, bandIndex: number, band: EqBand | string): void {\n this.native.setTrackStripEqBandJson(\n trackId,\n bandIndex,\n typeof band === 'string' ? band : JSON.stringify(band),\n );\n }\n\n setTrackStripEqBandJson(trackId: number, bandIndex: number, bandJson: string): void {\n this.native.setTrackStripEqBandJson(trackId, bandIndex, bandJson);\n }\n\n setTrackStripInsertBypassed(\n trackId: number,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n this.native.setTrackStripInsertBypassed(trackId, insertIndex, bypassed, resetOnBypass);\n }\n\n setMasterStripJson(sceneJson: string): void {\n try {\n JSON.parse(sceneJson);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'invalid master strip JSON';\n throw new SonareError(ErrorCode.InvalidFormat, 'InvalidFormat', message);\n }\n this.native.setMasterStripJson(sceneJson);\n }\n\n setMasterStripEqBand(bandIndex: number, band: EqBand | string): void {\n this.native.setMasterStripEqBandJson(\n bandIndex,\n typeof band === 'string' ? band : JSON.stringify(band),\n );\n }\n\n setMasterStripEqBandJson(bandIndex: number, bandJson: string): void {\n this.native.setMasterStripEqBandJson(bandIndex, bandJson);\n }\n\n setMasterStripInsertBypassed(\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n this.native.setMasterStripInsertBypassed(insertIndex, bypassed, resetOnBypass);\n }\n\n /**\n * Changes one track-strip insert parameter in realtime, addressed by the\n * processor's JSON-key parameter name (see {@link masteringInsertParamInfo}).\n * Applied at the next block head via the engine command queue; safe during\n * playback. Throws if the track, insert, or name is unknown, the param is not\n * realtime-safe, or the command queue is full.\n */\n setTrackStripInsertParamByName(\n trackId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n this.native.setTrackStripInsertParamByName(trackId, insertIndex, paramName, value);\n }\n\n /** Master-strip counterpart of {@link setTrackStripInsertParamByName}. */\n setMasterStripInsertParamByName(insertIndex: number, paramName: string, value: number): void {\n this.native.setMasterStripInsertParamByName(insertIndex, paramName, value);\n }\n\n /** Bus-strip counterpart of {@link setTrackStripInsertParamByName}. */\n setBusStripInsertParamByName(\n busId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n this.native.setBusStripInsertParamByName(busId, insertIndex, paramName, value);\n }\n\n /** Bus-strip counterpart of {@link setTrackStripInsertBypassed}. */\n setBusStripInsertBypassed(\n busId: number,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n this.native.setBusStripInsertBypassed(busId, insertIndex, bypassed, resetOnBypass);\n }\n\n /**\n * Resolves a track-lane insert parameter (by its JSON-key name) to the\n * reserved automation id usable with `setAutomationLane` / `setParameter`.\n * Returns `-1` when the track, insert, or name is unknown. (The Python binding\n * raises a `SonareError` for an unknown id where Node/WASM return the `-1`\n * sentinel.)\n */\n resolveTrackInsertAutomationId(trackId: number, insertIndex: number, paramName: string): number {\n return this.native.resolveTrackInsertAutomationId(trackId, insertIndex, paramName);\n }\n\n resolveMasterInsertAutomationId(insertIndex: number, paramName: string): number {\n return this.native.resolveMasterInsertAutomationId(insertIndex, paramName);\n }\n\n resolveBusInsertAutomationId(busId: number, insertIndex: number, paramName: string): number {\n return this.native.resolveBusInsertAutomationId(busId, insertIndex, paramName);\n }\n\n /** Sets a track lane strip's pan position in realtime (glitch-free). */\n setTrackStripPan(trackId: number, pan: number): void {\n this.native.setTrackStripPan(trackId, pan);\n }\n\n /** Sets a track lane strip's pan law in realtime. */\n setTrackStripPanLaw(trackId: number, panLaw: PanLawInput): void {\n this.native.setTrackStripPanLaw(trackId, panLawCode(panLaw));\n }\n\n /** Sets a track lane strip's pan mode in realtime. */\n setTrackStripPanMode(trackId: number, panMode: PanMode | number): void {\n this.native.setTrackStripPanMode(trackId, panModeCode(panMode));\n }\n\n /** Sets a track lane strip's dual-pan left/right positions in realtime. */\n setTrackStripDualPan(trackId: number, leftPan: number, rightPan: number): void {\n this.native.setTrackStripDualPan(trackId, leftPan, rightPan);\n }\n\n /**\n * Sets a track lane strip's inter-channel alignment delay (whole samples).\n * Adjusts strip latency, so PDC and reported graph latency are refreshed.\n */\n setTrackStripChannelDelaySamples(trackId: number, delaySamples: number): void {\n this.native.setTrackStripChannelDelaySamples(trackId, delaySamples);\n }\n\n createClipPageProvider(\n numChannels: number,\n numSamples: number,\n pageFrames: number,\n ): ClipPageProvider {\n const id = this.native.createClipPageProvider(numChannels, numSamples, pageFrames);\n return new ClipPageProvider(this, id);\n }\n\n supplyClipPage(providerId: number, pageIndex: number, channels: Float32Array[]): void {\n this.native.supplyClipPage(providerId, pageIndex, channels);\n }\n\n clearClipPage(providerId: number, pageIndex: number): void {\n this.native.clearClipPage(providerId, pageIndex);\n }\n\n destroyClipPageProvider(providerId: number): void {\n this.native.destroyClipPageProvider(providerId);\n }\n\n popClipPageRequest(): ClipPageRequest | null {\n return this.native.popClipPageRequest();\n }\n\n /**\n * Moves one native request into the binding's persistent scalar scratch.\n * This avoids creating an embind JS object in AudioWorklet process().\n */\n popClipPageRequestToScratch(): boolean {\n return this.native.popClipPageRequestToScratch();\n }\n\n clipPageRequestScratchClipId(): number {\n return this.native.clipPageRequestScratchClipId();\n }\n\n clipPageRequestScratchSample(): number {\n return this.native.clipPageRequestScratchSample();\n }\n\n /** Cumulative page misses dropped because the native bounded request queue was full. */\n clipPageRequestOverflowCount(): number {\n return this.native.clipPageRequestOverflowCount();\n }\n\n setCaptureBuffer(numChannels: number, capacityFrames: number): void {\n this.native.setCaptureBuffer(numChannels, capacityFrames);\n }\n\n armCapture(armed = true): void {\n this.native.armCapture(armed);\n }\n\n setCapturePunch(startSample: number, endSample: number, enabled = true): void {\n this.native.setCapturePunch(startSample, endSample, enabled);\n }\n\n setCaptureSource(source: EngineCaptureSource): void {\n this.native.setCaptureSource(source);\n }\n\n /** Positive values delay capture relative to the punch window. */\n setRecordOffsetSamples(offsetSamples: number): void {\n this.native.setRecordOffsetSamples(offsetSamples);\n }\n\n setInputMonitor(enabled: boolean, gain = 1): void {\n this.native.setInputMonitor(enabled, gain);\n }\n\n resetCapture(): void {\n this.native.resetCapture();\n }\n\n captureStatus(): EngineCaptureStatus {\n return this.native.captureStatus();\n }\n\n capturedAudio(): Float32Array[] {\n return this.native.capturedAudio();\n }\n\n /**\n * Renders in place, adding engine output to `channels`. Zero each plane first\n * when it contains no upstream input.\n */\n process(channels: Float32Array[]): Float32Array[] {\n return this.native.process(channels);\n }\n\n /**\n * Allocates persistent per-channel WASM-heap scratch for the zero-copy\n * `getChannelBuffer` / `processPrepared` realtime path. Call once (off the\n * audio thread) before driving `processPrepared` from an AudioWorklet so the\n * render callback never allocates on the C++/JS heap.\n */\n prepareChannels(numChannels: number, maxFrames: number): void {\n this.native.prepareChannels(numChannels, maxFrames);\n }\n\n /**\n * Returns a Float32Array view onto the persistent WASM-heap scratch for one\n * channel (valid for up to `numFrames`). Fill it, call `processPrepared`, then\n * read the same view back. Re-acquire after WASM memory growth.\n */\n getChannelBuffer(channel: number, numFrames: number): Float32Array {\n return this.native.getChannelBuffer(channel, numFrames);\n }\n\n /**\n * Runs the engine in place over the prepared per-channel scratch buffers.\n * Zero each active span first when it contains no upstream input.\n * Allocation-free: safe to call on the AudioWorklet render thread after\n * `prepareChannels`.\n */\n processPrepared(numFrames: number): void {\n this.native.processPrepared(numFrames);\n }\n\n processWithMonitor(channels: Float32Array[]): WasmEngineProcessWithMonitorResult {\n return this.native.processWithMonitor(channels);\n }\n\n renderOffline(channels: Float32Array[], blockSize = 128): Float32Array[] {\n return this.native.renderOffline(channels, blockSize);\n }\n\n bounceOffline(options: EngineBounceOptions): EngineBounceResult {\n return this.native.bounceOffline(options);\n }\n\n freezeOffline(options: EngineFreezeOptions): EngineFreezeResult {\n return this.native.freezeOffline(options);\n }\n\n drainTelemetry(maxRecords = 1024): EngineTelemetry[] {\n return this.native.drainTelemetry(maxRecords);\n }\n\n popTelemetryToScratch(): boolean {\n return this.native.popTelemetryToScratch();\n }\n\n telemetryScratchType(): number {\n return this.native.telemetryScratchType();\n }\n\n telemetryScratchError(): number {\n return this.native.telemetryScratchError();\n }\n\n telemetryScratchRenderFrame(): number {\n return Number(this.native.telemetryScratchRenderFrame());\n }\n\n telemetryScratchTimelineSample(): number {\n return Number(this.native.telemetryScratchTimelineSample());\n }\n\n telemetryScratchAudibleTimelineSample(): number {\n return Number(this.native.telemetryScratchAudibleTimelineSample());\n }\n\n telemetryScratchGraphLatencySamplesQ8(): number {\n return this.native.telemetryScratchGraphLatencySamplesQ8();\n }\n\n telemetryScratchValue(): number {\n return this.native.telemetryScratchValue();\n }\n\n popMeterTelemetryToScratch(): boolean {\n return this.native.popMeterTelemetryToScratch();\n }\n meterScratchTargetId(): number {\n return this.native.meterScratchTargetId();\n }\n meterScratchRenderFrame(): number {\n return Number(this.native.meterScratchRenderFrame());\n }\n meterScratchValue(field: number): number {\n return this.native.meterScratchValue(field);\n }\n\n drainMeterTelemetry(maxRecords = 1024): EngineMeterTelemetry[] {\n return this.native.drainMeterTelemetry(maxRecords);\n }\n\n /**\n * Drains pending meter telemetry as per-plane (wide) records for a surround\n * target. Use this for a surround mix target; {@link drainMeterTelemetry}\n * stays the stereo fast path. The two share one queue — call only one per\n * target. The live AudioWorklet path owns the queue via the stereo drain, so\n * this wide drain is for an offline (non-worklet) engine instance; per-plane\n * surround meters are not delivered over the live worklet meter ring.\n */\n drainMeterTelemetryWide(maxRecords = 1024): EngineMeterTelemetryWide[] {\n return this.native.drainMeterTelemetryWide(maxRecords);\n }\n\n /**\n * Enables per-target spectrum + vectorscope capture. @param intervalFrames is\n * the minimum render-frame gap between snapshots (0 disables). @param bandCount\n * is the FFT band resolution (1..64); changing it re-prepares the tap. Returns\n * the band count actually applied.\n */\n configureScopeTelemetry(intervalFrames: number, bandCount: number): number {\n return this.native.configureScopeTelemetry(intervalFrames, bandCount);\n }\n\n /** Drains pending spectrum + vectorscope snapshots (per mix target). */\n drainScopeTelemetry(maxRecords = 1024): EngineScopeTelemetry[] {\n return this.native.drainScopeTelemetry(maxRecords);\n }\n\n popScopeTelemetryToScratch(): boolean {\n return this.native.popScopeTelemetryToScratch();\n }\n scopeScratchTargetId(): number {\n return this.native.scopeScratchTargetId();\n }\n scopeScratchRenderFrame(): number {\n return Number(this.native.scopeScratchRenderFrame());\n }\n scopeScratchBandCount(): number {\n return this.native.scopeScratchBandCount();\n }\n scopeScratchBand(index: number): number {\n return this.native.scopeScratchBand(index);\n }\n scopeScratchPointCount(): number {\n return this.native.scopeScratchPointCount();\n }\n scopeScratchPointLeft(index: number): number {\n return this.native.scopeScratchPointLeft(index);\n }\n scopeScratchPointRight(index: number): number {\n return this.native.scopeScratchPointRight(index);\n }\n\n destroy(): void {\n this.native.delete();\n }\n}\n\nexport class ClipPageProvider {\n private disposed = false;\n\n constructor(\n private readonly engine: RealtimeEngine,\n readonly id: number,\n ) {}\n\n supply(pageIndex: number, channels: Float32Array[]): void {\n if (this.disposed) {\n throw new Error('ClipPageProvider is destroyed');\n }\n this.engine.supplyClipPage(this.id, pageIndex, channels);\n }\n\n clear(pageIndex: number): void {\n if (this.disposed) {\n return;\n }\n this.engine.clearClipPage(this.id, pageIndex);\n }\n\n destroy(): void {\n if (this.disposed) {\n return;\n }\n this.disposed = true;\n this.engine.destroyClipPageProvider(this.id);\n }\n}\n","import {\n automationCurveCode,\n meterTapCode,\n panLawCode,\n panModeCode,\n sendTimingCode,\n} from './codes';\nimport { getSonareModule } from './module_state';\nimport type {\n AutomationCurve,\n GoniometerPoint,\n MeterTap,\n MixerProcessResult,\n MixMeterSnapshot,\n PanLawInput,\n PanMode,\n SendTiming,\n SurroundPan,\n} from './public_types';\n\nexport interface MixerRealtimeBuffer {\n leftInputs: Float32Array[];\n rightInputs: Float32Array[];\n outLeft: Float32Array;\n outRight: Float32Array;\n process: (numSamples?: number) => void;\n}\n\n// ============================================================================\n// Mixer Class (scene-based persistent mixer)\n// ============================================================================\n\n/**\n * Persistent, scene-based stereo mixer.\n *\n * Build one from a scene JSON string (e.g. {@link mixingScenePresetJson} or a\n * hand-authored scene), then feed per-strip stereo blocks through\n * {@link processStereo} to get the routed stereo master. Strips, sends, buses,\n * and inserts are described entirely by the scene; the routing graph is\n * compiled lazily on the first {@link processStereo} call (or eagerly via\n * {@link compile}).\n *\n * Call {@link delete} (or use a `try/finally`) to release the underlying WASM\n * object — the embind handle is not garbage-collected automatically.\n *\n * @example\n * ```typescript\n * const mixer = Mixer.fromSceneJson(mixingScenePresetJson('basicStereo'), 48000, 512);\n * try {\n * const out = mixer.processStereo([stripL], [stripR]);\n * } finally {\n * mixer.delete();\n * }\n * ```\n */\nexport class Mixer {\n private mixer: import('./sonare.js').WasmMixer;\n private readonly blockSize: number;\n\n private constructor(mixer: import('./sonare.js').WasmMixer, blockSize: number) {\n this.mixer = mixer;\n this.blockSize = blockSize;\n }\n\n /**\n * Build a mixer from a scene JSON string.\n *\n * @param json - Scene JSON (strips, buses, sends, connections, inserts)\n * @param sampleRate - Sample rate in Hz (default: 48000)\n * @param blockSize - Maximum block size per {@link processStereo} call (default: 512)\n */\n static fromSceneJson(json: string, sampleRate = 48000, blockSize = 512): Mixer {\n const module = getSonareModule();\n return new Mixer(module.createMixerFromSceneJson(json, sampleRate, blockSize), blockSize);\n }\n\n /**\n * Rebuild and compile the routing graph without resetting its absolute\n * automation sample position or queued strip automation.\n */\n compile(): void {\n this.mixer.compile();\n }\n\n /**\n * Non-fatal warnings captured when this mixer was built from scene JSON: one\n * entry per channel-strip insert that was handed param keys it does not read\n * (a likely typo, or a key meant for a different processor). The scene still\n * loaded; these keys simply took no effect. Empty when every key was consumed.\n * Use {@link masteringInsertParamNames} to discover the keys an insert accepts.\n */\n sceneWarnings(): string[] {\n return this.mixer.sceneWarnings();\n }\n\n /**\n * Mix one block of per-strip stereo audio into the stereo master.\n *\n * @param leftChannels - `leftChannels[i]` is the left channel of strip `i`\n * @param rightChannels - `rightChannels[i]` is the right channel of strip `i`\n * @returns Mixed stereo master (`left`, `right`, `sampleRate`)\n */\n processStereo(leftChannels: Float32Array[], rightChannels: Float32Array[]): MixerProcessResult {\n if (leftChannels.length !== rightChannels.length) {\n throw new Error('leftChannels and rightChannels must have the same length.');\n }\n return this.mixer.processStereo(leftChannels, rightChannels);\n }\n\n /**\n * Mix one block into caller-owned output arrays.\n *\n * This avoids allocating the result object and result `Float32Array`s. It is\n * intended for realtime bridges such as AudioWorklet; the input channel count\n * must match the scene strip count and all arrays must have the same length.\n */\n processStereoInto(\n leftChannels: Float32Array[],\n rightChannels: Float32Array[],\n outLeft: Float32Array,\n outRight: Float32Array,\n ): void {\n if (leftChannels.length !== rightChannels.length) {\n throw new Error('leftChannels and rightChannels must have the same length.');\n }\n if (outLeft.length !== outRight.length) {\n throw new Error('outLeft and outRight must have the same length.');\n }\n this.mixer.processStereoInto(leftChannels, rightChannels, outLeft, outRight);\n }\n\n /**\n * Create reusable WASM-heap input/output views for realtime-style processing.\n *\n * Fill `leftInputs[i]` / `rightInputs[i]`, call `process()`, then read\n * `outLeft` / `outRight`. The views are owned by this mixer and become invalid\n * after {@link delete}.\n */\n createRealtimeBuffer(): MixerRealtimeBuffer {\n const stripCount = this.stripCount();\n let leftInputs: Float32Array[] = [];\n let rightInputs: Float32Array[] = [];\n let outLeft = this.mixer.outputLeftView();\n let outRight = this.mixer.outputRightView();\n const acquire = (): void => {\n leftInputs = [];\n rightInputs = [];\n for (let index = 0; index < stripCount; index++) {\n leftInputs.push(this.mixer.inputLeftView(index));\n rightInputs.push(this.mixer.inputRightView(index));\n }\n outLeft = this.mixer.outputLeftView();\n outRight = this.mixer.outputRightView();\n };\n acquire();\n // The cached heap views can detach if WASM linear memory grows (the embind\n // module is built ALLOW_MEMORY_GROWTH). Re-acquire them if detached\n // (byteLength === 0) before use, mirroring the worklet RT path.\n const reacquireIfDetached = (): void => {\n if (outLeft.byteLength === 0 || (leftInputs[0]?.byteLength ?? 1) === 0) {\n acquire();\n }\n };\n return {\n get leftInputs(): Float32Array[] {\n reacquireIfDetached();\n return leftInputs;\n },\n get rightInputs(): Float32Array[] {\n reacquireIfDetached();\n return rightInputs;\n },\n get outLeft(): Float32Array {\n reacquireIfDetached();\n return outLeft;\n },\n get outRight(): Float32Array {\n reacquireIfDetached();\n return outRight;\n },\n process: (numSamples = outLeft.length) => {\n reacquireIfDetached();\n this.mixer.processPreparedStereo(numSamples);\n },\n };\n }\n\n /** Number of strips in the mixer (e.g. strips loaded from the scene). */\n stripCount(): number {\n return this.mixer.stripCount();\n }\n\n /**\n * Schedule sample-accurate insert-parameter automation on a strip's insert.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param insertIndex - Index into the strip's combined insert sequence\n * (`[pre-inserts... post-inserts...]`)\n * @param paramId - Processor-specific parameter id\n * @param samplePos - Absolute samples from the start of processing (the mixer\n * advances an internal position from 0 on the first {@link processStereo}\n * call; recompiling resets it to 0)\n * @param value - Target parameter value\n * @param curve - Interpolation curve (default: `'linear'`)\n * @throws If the strip index is out of range or the schedule call fails\n * (unknown curve, out-of-range insert index, or full event lane)\n */\n scheduleInsertAutomation(\n stripIndex: number,\n insertIndex: number,\n paramId: number,\n samplePos: number,\n value: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleInsertAutomation(\n stripIndex,\n insertIndex,\n paramId,\n samplePos,\n value,\n automationCurveCode(curve),\n );\n }\n\n /**\n * Resolve a strip's index in `[0, stripCount())` from its scene id, or `null`\n * when no strip with that id exists (matches the Node binding's `number | null`).\n */\n stripById(id: string): number | null {\n const index = this.mixer.stripById(id);\n return index < 0 ? null : index;\n }\n\n /**\n * Add a bus to the mixer topology. `role` is one of `'master'`, `'aux'`, or\n * `'submix'` (defaults to `'aux'`). Marks the routing graph dirty; call\n * {@link compile} (or {@link processStereo}) to rebuild.\n */\n addBus(id: string, role = 'aux'): void {\n this.mixer.addBus(id, role);\n }\n\n /** Remove a bus by id. Marks the routing graph dirty. */\n removeBus(id: string): void {\n this.mixer.removeBus(id);\n }\n\n /** Number of buses in the mixer topology. */\n busCount(): number {\n return this.mixer.busCount();\n }\n\n /**\n * Add a VCA group with the given gain offset (dB). `members` is a list of\n * strip ids governed by the group (may be empty).\n */\n addVcaGroup(id: string, gainDb = 0.0, members: string[] = []): void {\n this.mixer.addVcaGroup(id, gainDb, members);\n }\n\n /** Set an existing VCA group's gain in dB. */\n setVcaGroupGainDb(id: string, gainDb: number): void {\n this.mixer.setVcaGroupGainDb(id, gainDb);\n }\n\n /** Replace an existing VCA group's strip membership. */\n setVcaGroupMembers(id: string, members: string[]): void {\n this.mixer.setVcaGroupMembers(id, members);\n }\n\n /** Remove a VCA group by id. */\n removeVcaGroup(id: string): void {\n this.mixer.removeVcaGroup(id);\n }\n\n /** Number of VCA groups in the mixer topology. */\n vcaGroupCount(): number {\n return this.mixer.vcaGroupCount();\n }\n\n /** Set the strip's input trim in dB. */\n setInputTrimDb(stripIndex: number, db: number): void {\n this.mixer.setInputTrimDb(stripIndex, db);\n }\n\n /** Set the strip's fader level in dB. */\n setFaderDb(stripIndex: number, db: number): void {\n this.mixer.setFaderDb(stripIndex, db);\n }\n\n /**\n * Set the strip's pan position.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param pan - Pan position in `[-1, 1]`\n * @param panMode - Optional pan mode. When omitted the strip's current pan\n * mode is kept (passes `SONARE_PAN_MODE_KEEP`), so a plain pan nudge does\n * not reset a scene-defined `'stereoPan'` / `'dualPan'` mode back to\n * balance. Pass `'balance'` (or `0`) explicitly to force balance mode.\n */\n setPan(stripIndex: number, pan: number, panMode?: PanMode | number): void {\n // SONARE_PAN_MODE_KEEP (-1) = keep the strip's current pan mode.\n const mode = panMode === undefined ? -1 : panModeCode(panMode);\n this.mixer.setPan(stripIndex, pan, mode);\n }\n\n /** Set the strip's stereo width. */\n setWidth(stripIndex: number, width: number): void {\n this.mixer.setWidth(stripIndex, width);\n }\n\n /** Set the strip's mute state. */\n setMuted(stripIndex: number, muted: boolean): void {\n this.mixer.setMuted(stripIndex, muted);\n }\n\n /**\n * Set a strip's solo state. Takes effect on the next process without a\n * graph recompile.\n */\n setSoloed(stripIndex: number, soloed: boolean): void {\n this.mixer.setSoloed(stripIndex, soloed);\n }\n\n /**\n * Mark a strip solo-safe so it is never implied-muted by another strip's\n * solo. Takes effect on the next process without a graph recompile.\n */\n setSoloSafe(stripIndex: number, soloSafe: boolean): void {\n this.mixer.setSoloSafe(stripIndex, soloSafe);\n }\n\n /** Invert the polarity of the left and/or right channel of a strip. */\n setPolarityInvert(stripIndex: number, invertLeft: boolean, invertRight: boolean): void {\n this.mixer.setPolarityInvert(stripIndex, invertLeft, invertRight);\n }\n\n /** Set the strip's pan law (a {@link PanLawName} alias or raw C ABI ordinal). */\n setPanLaw(stripIndex: number, panLaw: PanLawInput): void {\n this.mixer.setPanLaw(stripIndex, panLawCode(panLaw));\n }\n\n /**\n * Set a per-strip channel delay in samples. This changes the strip's reported\n * latency; recompile to re-run latency compensation.\n */\n setChannelDelaySamples(stripIndex: number, delaySamples: number): void {\n this.mixer.setChannelDelaySamples(stripIndex, delaySamples);\n }\n\n /** Set the strip's live VCA gain offset in dB (not persisted to the scene). */\n setVcaOffsetDb(stripIndex: number, offsetDb: number): void {\n this.mixer.setVcaOffsetDb(stripIndex, offsetDb);\n }\n\n /** Set independent left/right pan positions (dual-pan mode). */\n setDualPan(stripIndex: number, leftPan: number, rightPan: number): void {\n this.mixer.setDualPan(stripIndex, leftPan, rightPan);\n }\n\n /**\n * Set the strip's surround pan position, used when it feeds a >2-channel bus.\n * Stored on the scene; inert until the surround DSP path applies it.\n */\n setSurroundPan(stripIndex: number, pan: SurroundPan): void {\n this.mixer.setSurroundPan(stripIndex, pan);\n }\n\n /**\n * Add a send to a strip after construction.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param id - Send id\n * @param destinationBusId - Destination bus id\n * @param sendDb - Initial send level in dB\n * @param timing - `'preFader'` or `'postFader'` (default: `'postFader'`)\n * @returns The new send's index\n */\n addSend(\n stripIndex: number,\n id: string,\n destinationBusId: string,\n sendDb = 0.0,\n timing: SendTiming | number = 'postFader',\n ): number {\n return this.mixer.addSend(stripIndex, id, destinationBusId, sendDb, sendTimingCode(timing));\n }\n\n /** Set the send level (in dB) for an existing send by index. */\n setSendDb(stripIndex: number, sendIndex: number, sendDb: number): void {\n this.mixer.setSendDb(stripIndex, sendIndex, sendDb);\n }\n\n /**\n * Remove an existing send from a strip by index.\n *\n * Sends are addressed in add order. After removal, sends with a higher index\n * than `sendIndex` shift down by one. Recompile (or process) before reading\n * results so the routing graph rebuilds.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param sendIndex - Send index in add order\n */\n removeSend(stripIndex: number, sendIndex: number): void {\n this.mixer.removeSend(stripIndex, sendIndex);\n }\n\n /**\n * Read a strip's meter snapshot at the given tap point.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param tap - `'preFader'` or `'postFader'` (default: `'postFader'`)\n */\n meterTap(stripIndex: number, tap: MeterTap = 'postFader'): MixMeterSnapshot {\n return this.mixer.meterTap(stripIndex, meterTapCode(tap));\n }\n\n /**\n * Read a strip's meter snapshot.\n *\n * With no `tap` argument this reads the strip's own (post-fader) meter,\n * matching the Node/Python tap-less `stripMeter` contract. Pass an optional\n * `tap` (`'preFader'` / `'postFader'`) to read the tap-selectable snapshot\n * instead — the same backing call as {@link meterTap}.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param tap - Optional tap point (`'preFader'` / `'postFader'`); when omitted\n * the tap-less post-fader strip meter is read.\n */\n stripMeter(stripIndex: number, tap?: MeterTap | number): MixMeterSnapshot {\n if (tap === undefined) {\n return this.mixer.stripMeter(stripIndex);\n }\n return this.mixer.meterTap(stripIndex, meterTapCode(tap));\n }\n\n /** Read the post-insert meter for a compiled bus, including master. */\n busMeter(busId: string): MixMeterSnapshot {\n return this.mixer.busMeter(busId);\n }\n\n /**\n * Schedule sample-accurate fader automation on a strip.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param samplePos - Absolute samples from the start of processing\n * @param faderDb - Target fader level in dB\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n scheduleFaderAutomation(\n stripIndex: number,\n samplePos: number,\n faderDb: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleFaderAutomation(stripIndex, samplePos, faderDb, automationCurveCode(curve));\n }\n\n /**\n * Schedule sample-accurate pan automation on a strip.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param samplePos - Absolute samples from the start of processing\n * @param pan - Target pan position\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n schedulePanAutomation(\n stripIndex: number,\n samplePos: number,\n pan: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.schedulePanAutomation(stripIndex, samplePos, pan, automationCurveCode(curve));\n }\n\n /**\n * Schedule sample-accurate width automation on a strip.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param samplePos - Absolute samples from the start of processing\n * @param width - Target stereo width\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n scheduleWidthAutomation(\n stripIndex: number,\n samplePos: number,\n width: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleWidthAutomation(stripIndex, samplePos, width, automationCurveCode(curve));\n }\n\n /**\n * Schedule sample-accurate send-level automation on a strip's send.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param sendIndex - Send index in the strip's add order\n * @param samplePos - Absolute samples from the start of processing\n * @param db - Target send level in dB\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n scheduleSendAutomation(\n stripIndex: number,\n sendIndex: number,\n samplePos: number,\n db: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleSendAutomation(\n stripIndex,\n sendIndex,\n samplePos,\n db,\n automationCurveCode(curve),\n );\n }\n\n /**\n * Read up to `maxPoints` of a strip's most recent goniometer samples\n * (oldest to newest).\n */\n readGoniometerLatest(stripIndex: number, maxPoints: number): GoniometerPoint[] {\n return this.mixer.readGoniometerLatest(stripIndex, maxPoints);\n }\n\n /** Serialize the current scene (strips, buses, sends, connections) to JSON. */\n toSceneJson(): string {\n return this.mixer.toSceneJson();\n }\n\n /**\n * Longest audible serial processor-tail path to the master, in samples. Lazily\n * compiles the routing graph if the topology is dirty.\n */\n tailSamples(): number {\n return this.mixer.tailSamples();\n }\n\n /**\n * Reported latency (samples) of the compiled mixer graph, for aligning\n * dry/wet material. Lazily compiles the routing graph if the topology is dirty.\n */\n latencySamples(): number {\n return this.mixer.latencySamples();\n }\n\n /**\n * Drain delayed / tail audio by processing a zero-input block of `numSamples`\n * frames after the host stops feeding strip inputs. Returns the mixed stereo\n * master (`left`, `right`, `sampleRate`).\n */\n drainTailStereo(numSamples: number): MixerProcessResult {\n if (!Number.isSafeInteger(numSamples) || numSamples <= 0 || numSamples > this.blockSize) {\n throw new RangeError(\n `Mixer.drainTailStereo: numSamples must be an integer in [1, ${this.blockSize}]`,\n );\n }\n return this.mixer.drainTailStereo(numSamples);\n }\n\n /** Release the underlying WASM object. Safe to call only once. */\n delete(): void {\n this.mixer.delete();\n }\n\n /** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n}\n","import { getSonareModule } from './module_state';\nimport type {\n RealtimeVoiceChangerConfigInput,\n RealtimeVoiceChangerPodConfig,\n VoicePresetId,\n} from './public_types';\n\n/**\n * Zero-copy realtime buffer pair for {@link RealtimeVoiceChanger} mono\n * processing. The `input` / `output` `Float32Array`s are typed-memory views\n * onto the WASM heap — write samples into `input`, call `process()`, then\n * read from `output`. The views are owned by the {@link RealtimeVoiceChanger}\n * and remain valid until `delete()` is called on it.\n */\nexport interface RealtimeVoiceChangerMonoBuffer {\n input: Float32Array;\n output: Float32Array;\n process: () => void;\n}\n\n/**\n * Zero-copy realtime buffer pair for {@link RealtimeVoiceChanger} interleaved\n * multi-channel processing. Layout is L0,R0,L1,R1,... for stereo. The views\n * are owned by the {@link RealtimeVoiceChanger}.\n */\nexport interface RealtimeVoiceChangerInterleavedBuffer {\n input: Float32Array;\n output: Float32Array;\n channels: number;\n process: () => void;\n}\n\n/**\n * Zero-copy realtime buffer for {@link RealtimeVoiceChanger} planar stereo\n * processing. Each entry in `channels` is a heap-backed `Float32Array` for one\n * channel (matching AudioWorklet's native layout). Process happens in place:\n * write samples into each channel view, call `process()`, then read back from\n * the same views.\n */\nexport interface RealtimeVoiceChangerPlanarBuffer {\n channels: Float32Array[];\n process: () => void;\n}\n\n// ============================================================================\n// RealtimeVoiceChanger Class\n// ============================================================================\n\nexport class RealtimeVoiceChanger {\n private changer: import('./sonare.js').WasmRealtimeVoiceChanger;\n\n /**\n * Creates a voice changer. Supplying `sampleRate` prepares it immediately,\n * matching the Node and Python constructors; omitting it preserves the\n * explicit {@link prepare} lifecycle for callers that configure later.\n */\n constructor(\n config: RealtimeVoiceChangerConfigInput | RealtimeVoiceChangerPodConfig = 'neutral-monitor',\n sampleRate?: number,\n maxBlockSize = 128,\n channels = 1,\n ) {\n const module = getSonareModule();\n this.changer = module.createRealtimeVoiceChanger(config as Record<string, unknown> | string);\n if (sampleRate !== undefined) {\n this.changer.prepare(sampleRate, maxBlockSize, channels);\n }\n }\n\n prepare(sampleRate: number, maxBlockSize = 128, channels = 1): void {\n this.changer.prepare(sampleRate, maxBlockSize, channels);\n }\n\n reset(): void {\n this.changer.reset();\n }\n\n setConfig(config: RealtimeVoiceChangerConfigInput | RealtimeVoiceChangerPodConfig): void {\n // The shared native parser recognizes the flat POD produced by\n // realtimeVoiceChangerPresetConfig, so bindings never duplicate its 36-field mapping.\n this.changer.setConfig(config as Record<string, unknown> | string);\n }\n\n /**\n * Apply a flat, pre-normalized config without JSON serialization. Intended\n * for AudioWorklet control messages whose sender prepared the POD on the\n * main thread.\n */\n setPodConfig(config: RealtimeVoiceChangerPodConfig): void {\n this.changer.setPodConfig(config);\n }\n\n configJson(): string {\n return this.changer.configJson();\n }\n\n latencySamples(): number {\n return this.changer.latencySamples();\n }\n\n /**\n * Monotonically increases whenever {@link prepare} can replace the native\n * scratch buffers. Cached WASM heap views must be reacquired after it changes.\n */\n bufferGeneration(): number {\n return this.changer.bufferGeneration();\n }\n\n processMono(samples: Float32Array): Float32Array {\n return this.changer.processMono(samples);\n }\n\n processMonoInto(samples: Float32Array, output: Float32Array): void {\n this.changer.processMonoInto(samples, output);\n }\n\n processInterleaved(samples: Float32Array, channels: number): Float32Array {\n return this.changer.processInterleaved(samples, channels);\n }\n\n processInterleavedInto(samples: Float32Array, channels: number, output: Float32Array): void {\n this.changer.processInterleavedInto(samples, channels, output);\n }\n\n /**\n * Acquire a typed-memory view onto the WASM heap for mono input.\n *\n * Write your input samples into the returned `Float32Array` directly (e.g.\n * via `input.set(source)`); no copy crosses the JS↔C++ bridge until\n * {@link processPreparedMono} is called. The view is owned by this\n * RealtimeVoiceChanger and becomes invalid after {@link delete}; it may\n * also be invalidated if you later call this method with a larger\n * `numSamples` value (the underlying buffer may be reallocated).\n */\n getMonoInputBuffer(numSamples: number): Float32Array {\n return this.changer.getMonoInputBuffer(numSamples);\n }\n\n /** Mono output view counterpart to {@link getMonoInputBuffer}. */\n getMonoOutputBuffer(numSamples: number): Float32Array {\n return this.changer.getMonoOutputBuffer(numSamples);\n }\n\n /**\n * Process the previously-acquired mono input buffer in place. The output\n * appears in the buffer returned by {@link getMonoOutputBuffer}. No JS↔C++\n * sample-level crossings happen on this call — it just hands control to\n * the underlying DSP on already-on-heap data.\n */\n processPreparedMono(numSamples: number): void {\n this.changer.processPreparedMono(numSamples);\n }\n\n /** Interleaved input view (layout L0,R0,L1,R1,...). */\n getInterleavedInputBuffer(numFrames: number, numChannels: number): Float32Array {\n return this.changer.getInterleavedInputBuffer(numFrames, numChannels);\n }\n\n /** Interleaved output view counterpart. */\n getInterleavedOutputBuffer(numFrames: number, numChannels: number): Float32Array {\n return this.changer.getInterleavedOutputBuffer(numFrames, numChannels);\n }\n\n /**\n * Process the previously-acquired interleaved buffer in place. Output\n * appears in the buffer returned by {@link getInterleavedOutputBuffer}.\n */\n processPreparedInterleaved(numFrames: number, numChannels: number): void {\n this.changer.processPreparedInterleaved(numFrames, numChannels);\n }\n\n /**\n * Planar-channel input/output view (one Float32Array per channel). Matches\n * AudioWorklet's native layout; processing happens in place.\n */\n getPlanarChannelBuffer(channel: number, numFrames: number): Float32Array {\n return this.changer.getPlanarChannelBuffer(channel, numFrames);\n }\n\n /**\n * Process the previously-acquired planar channel buffers in place. Each\n * channel must have been obtained from {@link getPlanarChannelBuffer}\n * with the same `numFrames`. Output replaces input in the same buffers.\n */\n processPreparedPlanar(numFrames: number): void {\n this.changer.processPreparedPlanar(numFrames);\n }\n\n /**\n * Convenience factory for the mono zero-copy path: returns the input/output\n * heap views plus a `process()` thunk wired to the same `numSamples`. The\n * views are reused across calls and become invalid after {@link delete}.\n */\n createRealtimeMonoBuffer(numSamples: number): RealtimeVoiceChangerMonoBuffer {\n let input = this.getMonoInputBuffer(numSamples);\n let output = this.getMonoOutputBuffer(numSamples);\n let generation = this.bufferGeneration();\n // The cached heap views can detach if WASM linear memory grows (the embind\n // module is built ALLOW_MEMORY_GROWTH). Re-acquire them if detached\n // (byteLength === 0) before use, mirroring the worklet RT path. In the\n // common no-growth case this is a cheap branch with no allocation.\n const reacquireIfDetached = (): void => {\n if (\n generation !== this.bufferGeneration() ||\n input.byteLength === 0 ||\n output.byteLength === 0\n ) {\n input = this.getMonoInputBuffer(numSamples);\n output = this.getMonoOutputBuffer(numSamples);\n generation = this.bufferGeneration();\n }\n };\n return {\n get input(): Float32Array {\n reacquireIfDetached();\n return input;\n },\n get output(): Float32Array {\n reacquireIfDetached();\n return output;\n },\n process: () => {\n reacquireIfDetached();\n this.processPreparedMono(numSamples);\n },\n };\n }\n\n /** Same as {@link createRealtimeMonoBuffer} but for interleaved I/O. */\n createRealtimeInterleavedBuffer(\n numFrames: number,\n numChannels: number,\n ): RealtimeVoiceChangerInterleavedBuffer {\n let input = this.getInterleavedInputBuffer(numFrames, numChannels);\n let output = this.getInterleavedOutputBuffer(numFrames, numChannels);\n let generation = this.bufferGeneration();\n // Re-acquire detached views after WASM memory growth (see\n // createRealtimeMonoBuffer for rationale).\n const reacquireIfDetached = (): void => {\n if (\n generation !== this.bufferGeneration() ||\n input.byteLength === 0 ||\n output.byteLength === 0\n ) {\n input = this.getInterleavedInputBuffer(numFrames, numChannels);\n output = this.getInterleavedOutputBuffer(numFrames, numChannels);\n generation = this.bufferGeneration();\n }\n };\n return {\n get input(): Float32Array {\n reacquireIfDetached();\n return input;\n },\n get output(): Float32Array {\n reacquireIfDetached();\n return output;\n },\n channels: numChannels,\n process: () => {\n reacquireIfDetached();\n this.processPreparedInterleaved(numFrames, numChannels);\n },\n };\n }\n\n /**\n * Convenience factory for the planar zero-copy path. Acquires one\n * heap-backed Float32Array per channel and returns a `process()` thunk\n * wired to the same `numFrames`. Buffers are reused across calls and\n * become invalid after {@link delete}.\n */\n createRealtimePlanarBuffer(\n numFrames: number,\n numChannels: number,\n ): RealtimeVoiceChangerPlanarBuffer {\n let channels: Float32Array[] = [];\n let generation = this.bufferGeneration();\n const acquire = (): void => {\n channels = [];\n for (let ch = 0; ch < numChannels; ch++) {\n channels.push(this.getPlanarChannelBuffer(ch, numFrames));\n }\n generation = this.bufferGeneration();\n };\n acquire();\n // Re-acquire detached views after WASM memory growth (see\n // createRealtimeMonoBuffer for rationale).\n const reacquireIfDetached = (): void => {\n if (generation !== this.bufferGeneration() || (channels[0]?.byteLength ?? 0) === 0) {\n acquire();\n }\n };\n return {\n get channels(): Float32Array[] {\n reacquireIfDetached();\n return channels;\n },\n process: () => {\n reacquireIfDetached();\n this.processPreparedPlanar(numFrames);\n },\n };\n }\n\n delete(): void {\n this.changer.delete();\n }\n}\n\nexport function realtimeVoiceChangerPresetNames(): VoicePresetId[] {\n // Array.from re-roots embind's vector as a plain, structured-cloneable Array.\n return Array.from(getSonareModule().realtimeVoiceChangerPresetNames()) as VoicePresetId[];\n}\n\nexport function realtimeVoiceChangerPresetJson(name: VoicePresetId): string {\n return getSonareModule().realtimeVoiceChangerPresetJson(name);\n}\n\nexport function validateRealtimeVoiceChangerPresetJson(json: string): {\n ok: boolean;\n normalizedJson?: string;\n error?: string;\n} {\n return getSonareModule().validateRealtimeVoiceChangerPresetJson(json);\n}\n","/**\n * sonare - Audio Analysis Library\n *\n * @example\n * ```typescript\n * import { init, detectBpm, detectKey, analyze } from '@libraz/libsonare';\n *\n * await init();\n *\n * // Detect BPM from audio samples\n * const bpm = detectBpm(samples, sampleRate);\n *\n * // Detect musical key\n * const key = detectKey(samples, sampleRate);\n *\n * // Full analysis\n * const result = analyze(samples, sampleRate);\n * ```\n */\n\nimport { setSonareModule } from './module_state';\nimport type {\n CapabilityCatalog,\n RealtimeVoiceChangerPodConfig,\n SonareCapabilities,\n VoicePresetId,\n} from './public_types';\nimport type {\n SonareModule,\n WasmDecomposeResult,\n WasmHpssWithResidualResult,\n WasmMatrix2dResult,\n} from './sonare.js';\n\nexport type { BrowserAudioDecodeOptions } from './audio';\nexport { Audio } from './audio';\nexport type {\n ClipPageStreamerEngine,\n ClipPageStreamerOptions,\n ClipPageStreamerRequest,\n ClipPageStreamSource,\n OpfsClipStream,\n OpfsClipStreamOptions,\n WorkletOpfsClipStreamHost,\n} from './clip_page_streamer';\nexport { attachOpfsClipStream, ClipPageStreamer } from './clip_page_streamer';\nexport type {\n CompressorDetector,\n CompressorOptions,\n DeclickOptions,\n DeclipOptions,\n DecrackleMode,\n DecrackleOptions,\n DehumOptions,\n DenoiseClassicalMode,\n DenoiseClassicalNoiseEstimator,\n DenoiseClassicalOptions,\n DereverbClassicalOptions,\n DynamicsResult,\n GateOptions,\n MasteringChannelPolicy,\n MasteringDynamicsCompressorRequest,\n MasteringDynamicsGateRequest,\n MasteringDynamicsTransientShaperRequest,\n MasteringInsertParamInfo,\n MasteringPairAnalyzeRequest,\n MasteringPairProcessRequest,\n MasteringProcessorCatalogEntry,\n MasteringProcessRequest,\n MasteringProcessStereoRequest,\n MasteringRealtimeCost,\n MasteringRepairDeclickRequest,\n MasteringRepairDeclipRequest,\n MasteringRepairDecrackleRequest,\n MasteringRepairDehumRequest,\n MasteringRepairDenoiseClassicalRequest,\n MasteringRepairDereverbClassicalRequest,\n MasteringRepairTrimSilenceRequest,\n MasteringSamplesParamsRequest,\n MasteringStereoAnalyzeRequest,\n MasteringStereoParamsRequest,\n MasteringStreamingPreviewRequest,\n MasteringStreamingPreviewStereoRequest,\n MixStereoRequest,\n TransientShaperOptions,\n TrimSilenceMode,\n TrimSilenceOptions,\n VoiceChangeOptions,\n VoiceChangeRealtimeOptions,\n VoiceChangeRealtimeRequest,\n VoiceChangeRequest,\n} from './effects_mastering';\nexport {\n harmonic,\n hpss,\n masterAudio,\n masterAudioStereo,\n masterAudioStereoWithProgress,\n masterAudioWithProgress,\n mastering,\n masteringAssistantSuggest,\n masteringAssistantSuggestStereo,\n masteringAudioProfile,\n masteringAudioProfileStereo,\n masteringChain,\n masteringChainStereo,\n masteringChainStereoWithProgress,\n masteringChainWithProgress,\n masteringDynamicsCompressor,\n masteringDynamicsGate,\n masteringDynamicsTransientShaper,\n masteringInsertNames,\n masteringInsertParamInfo,\n masteringInsertParamNames,\n masteringPairAnalysisNames,\n masteringPairAnalyze,\n masteringPairProcess,\n masteringPairProcessorNames,\n masteringPresetNames,\n masteringProcess,\n masteringProcessorCatalog,\n masteringProcessorNames,\n masteringProcessStereo,\n masteringRepairDeclick,\n masteringRepairDeclip,\n masteringRepairDecrackle,\n masteringRepairDehum,\n masteringRepairDenoiseClassical,\n masteringRepairDereverbClassical,\n masteringRepairTrimSilence,\n masteringStereoAnalysisNames,\n masteringStereoAnalyze,\n masteringStreamingPreview,\n masteringStreamingPreviewStereo,\n mixingScenePresetJson,\n mixingScenePresetNames,\n mixStereo,\n normalize,\n noteMove,\n noteStretch,\n percussive,\n pitchCorrectTimevarying,\n pitchCorrectToMidi,\n pitchCorrectToMidiTimevarying,\n pitchShift,\n spectralEdit,\n timeStretch,\n voiceChange,\n voiceChangeRealtime,\n} from './effects_mastering';\nexport type {\n HarmonicRequest,\n HpssRequest,\n NormalizeMode,\n NormalizeRequest,\n NoteMoveRequest,\n NoteStretchRequest,\n PercussiveRequest,\n PitchCorrectTimevaryingRequest,\n PitchCorrectToMidiRequest,\n PitchCorrectToMidiTimevaryingRequest,\n PitchShiftRequest,\n SpectralEditRequest,\n TimeStretchRequest,\n} from './effects_transform';\nexport { ErrorCode, isSonareError, SonareError } from './errors';\nexport type {\n ChirpRequest,\n ClicksRequest,\n CyclicTempogramRequest,\n DbConversionRequest,\n EmphasisRequest,\n FixFramesRequest,\n FixLengthRequest,\n FrameSignalRequest,\n OnsetBacktrackRequest,\n PadCenterRequest,\n PcenRequest,\n PeakPickRequest,\n PlpRequest,\n SilenceRequest,\n TempogramRequest,\n ToneRequest,\n TonnetzRequest,\n VectorNormalizeRequest,\n} from './feature_core';\nexport type {\n AnalyzeMelodyRequest,\n AnalyzeSectionsRequest,\n CqtRequest,\n CqtToAudioRequest,\n FourierTempogramRequest,\n LufsRequest,\n MelodyOptions,\n NnlsChromaRequest,\n OnsetEnvelopeRequest,\n OnsetStrengthMultiRequest,\n TempogramRatioRequest,\n VqtRequest,\n VqtToAudioRequest,\n} from './feature_music';\nexport type {\n NoteSegmentsRequest,\n PiptrackRequest,\n PitchPyinRequest,\n PitchYinRequest,\n} from './feature_pitch';\nexport type { ResampleRequest } from './feature_resample';\nexport type {\n DecomposeRequest,\n DecomposeWithInitRequest,\n Ebur128LoudnessRangeRequest,\n EstimateTuningRequest,\n HpssWithResidualRequest,\n LufsInterleavedRequest,\n NnFilterRequest,\n PhaseVocoderRequest,\n PitchTuningRequest,\n PolyFeaturesRequest,\n RemixRequest,\n SegmentAgglomerativeRequest,\n SegmentCrossSimilarityRequest,\n SegmentLagToRecurrenceRequest,\n SegmentPathEnhanceRequest,\n SegmentRecurrenceMatrixRequest,\n SegmentRecurrenceToLagRequest,\n SegmentSubsegmentRequest,\n SpectralContrastRequest,\n SpectralFrameRequest,\n SpectralRolloffRequest,\n ZeroCrossingRateRequest,\n ZeroCrossingsRequest,\n} from './feature_spectral';\nexport type {\n ChromaSpectrogramRequest,\n GriffinLimRequest,\n MelDeltaRequest,\n MelSpectrogramRequest,\n MelToAudioRequest,\n MelToStftRequest,\n MfccRequest,\n MfccToAudioRequest,\n MfccToMelRequest,\n ReassignedSpectrogramRequest,\n SpectrogramRequest,\n TrimRequest,\n} from './feature_spectrogram';\nexport {\n amplitudeToDb,\n analyzeMelody,\n analyzeSections,\n bassChroma,\n chirp,\n chroma,\n chromaCens,\n chromaCqt,\n clicks,\n cqt,\n cqtToAudio,\n cyclicTempogram,\n dbToAmplitude,\n dbToPower,\n decompose,\n decomposeWithInit,\n deemphasis,\n ebur128LoudnessRange,\n estimateTuning,\n fixFrames,\n fixLength,\n fourierTempogram,\n frameSignal,\n framesToSamples,\n framesToTime,\n griffinLim,\n hpssWithResidual,\n hybridCqt,\n hzToMel,\n hzToMidi,\n hzToNote,\n lufs,\n lufsInterleaved,\n melDelta,\n melSpectrogram,\n melToAudio,\n melToHz,\n melToStft,\n mfcc,\n mfccToAudio,\n mfccToMel,\n midiToHz,\n momentaryLufs,\n nnFilter,\n nnlsChroma,\n noteSegments,\n noteToHz,\n onsetBacktrack,\n onsetEnvelope,\n onsetStrengthMulti,\n padCenter,\n pcen,\n peakPick,\n phaseVocoder,\n piptrack,\n pitchPyin,\n pitchTuning,\n pitchYin,\n plp,\n polyFeatures,\n powerToDb,\n preemphasis,\n pseudoCqt,\n reassignedSpectrogram,\n remix,\n resample,\n rmsEnergy,\n samplesToFrames,\n segmentAgglomerative,\n segmentCrossSimilarity,\n segmentLagToRecurrence,\n segmentPathEnhance,\n segmentRecurrenceMatrix,\n segmentRecurrenceToLag,\n segmentSubsegment,\n shortTermLufs,\n spectralBandwidth,\n spectralCentroid,\n spectralContrast,\n spectralFlatness,\n spectralFlux,\n spectralRolloff,\n splitSilence,\n stft,\n stftDb,\n tempogram,\n tempogramRatio,\n timeToFrames,\n tone,\n tonnetz,\n trim,\n trimSilence,\n vectorNormalize,\n vqt,\n vqtToAudio,\n zeroCrossingRate,\n zeroCrossings,\n} from './features';\nexport type { BindMicrophoneInputOptions, MicrophoneInputBinding } from './live_audio';\nexport { bindMicrophoneInput } from './live_audio';\nexport type {\n MasterAudioRequest,\n MasterAudioStereoRequest,\n MasteringChainRequest,\n MasteringChainStereoRequest,\n} from './mastering_chain';\nexport type { MasteringRequest } from './mastering_core';\nexport type {\n ClippingRegion,\n ClippingReport,\n DynamicRangeReport,\n MeteringDetectClippingOptions,\n MeteringDetectClippingRequest,\n MeteringDynamicRangeOptions,\n MeteringDynamicRangeRequest,\n MeteringSamplesRequest,\n MeteringSilenceRatioRequest,\n MeteringSpectrumFrameRequest,\n MeteringSpectrumRequest,\n MeteringStereoDecimatedRequest,\n MeteringStereoRequest,\n MeteringTruePeakRequest,\n PhaseScopeReport,\n SpectrumOptions,\n SpectrumReport,\n VectorscopeReport,\n WaveformPeakPyramidOptions,\n WaveformPeakPyramidRequest,\n WaveformPeaksOptions,\n WaveformPeaksReport,\n WaveformPeaksRequest,\n} from './metering';\nexport {\n meteringCrestFactorDb,\n meteringCrestFactorDbStereo,\n meteringDcOffset,\n meteringDetectClipping,\n meteringDynamicRange,\n meteringPeakDb,\n meteringPhaseScope,\n meteringPhaseScopeDecimated,\n meteringRmsDb,\n meteringSilenceRatio,\n meteringSpectrum,\n meteringSpectrumFrame,\n meteringStereoCorrelation,\n meteringStereoWidth,\n meteringTruePeakDb,\n meteringVectorscope,\n meteringVectorscopeDecimated,\n waveformPeakPyramid,\n waveformPeaks,\n} from './metering';\nexport type {\n OpfsClipPageProviderBinding,\n OpfsClipPageProviderOptions,\n} from './opfs_clip_pages';\nexport {\n createOpfsClipPageProvider,\n createOpfsClipPageWorker,\n opfsClipPageWorkerSource,\n} from './opfs_clip_pages';\nexport type {\n BuiltinSynthBinding,\n BuiltinSynthConfig,\n BuiltinSynthWaveform,\n ExternalSeparatedStem,\n ExternalSeparatedStemImportRequest,\n ExternalSeparatedStemImportResult,\n MidiCcLearnOptions,\n ProjectAssistSidecar,\n ProjectAssistSidecarInput,\n ProjectAutomationCurve,\n ProjectAutomationLaneDesc,\n ProjectAutomationPoint,\n ProjectAutomationTargetKind,\n ProjectBounceOptions,\n ProjectChordSymbol,\n ProjectClip,\n ProjectClipCompSegment,\n ProjectClipDesc,\n ProjectClipFade,\n ProjectClipTake,\n ProjectCompileResult,\n ProjectFadeCurve,\n ProjectKeySegment,\n ProjectLoopMode,\n ProjectLoopRecordingDesc,\n ProjectLoopRecordingResult,\n ProjectMarker,\n ProjectMidiClipResult,\n ProjectMidiEvent,\n ProjectNotePairValidation,\n ProjectSource,\n ProjectTrack,\n ProjectTrackDesc,\n ProjectTrackKind,\n ProjectWarpAnchor,\n ProjectWarpMapDesc,\n Sf2InstrumentConfig,\n Sf2ProgramStatus,\n SourceBackend,\n SynthBodyType,\n SynthEngineMode,\n SynthEnumTables,\n SynthFilterModel,\n SynthFilterOutput,\n SynthModDestination,\n SynthModRouting,\n SynthModSource,\n SynthOscWaveform,\n SynthPatch,\n} from './project';\nexport {\n AutomationTargetKind,\n BUILTIN_SYNTH_WAVEFORMS,\n EXPECTED_PROJECT_ABI_VERSION,\n MarkerKind,\n PROJECT_AUTOMATION_TARGET_OPAQUE,\n PROJECT_AUTOMATION_TARGET_TRACK_FADER_DB,\n PROJECT_AUTOMATION_TARGET_TRACK_PAN,\n Project,\n projectAbiVersion,\n SYNTH_BODY_TYPES,\n SYNTH_ENGINE_MODES,\n SYNTH_FILTER_MODELS,\n SYNTH_FILTER_OUTPUTS,\n SYNTH_MOD_DESTINATIONS,\n SYNTH_MOD_SOURCES,\n SYNTH_OSC_WAVEFORMS,\n synthEnumTables,\n synthPresetNames,\n synthPresetPatch,\n} from './project';\nexport type {\n AcousticOptions,\n AcousticResult,\n AnalysisResult,\n AnalyzeBpmOptions,\n AnalyzeDynamicsOptions,\n AnalyzeRhythmOptions,\n AnalyzeSectionsOptions,\n AnalyzeTimbreOptions,\n AutomationCurve,\n Beat,\n BpmHypothesis,\n Chord,\n ChordAnalysisResult,\n ChordDetectionOptions,\n ChromaResult,\n CqtResult,\n Dynamics,\n EqBand,\n EqBandPhase,\n EqBandType,\n EqCoeffMode,\n EqMatchOptions,\n EqSpectrumSnapshot,\n EqStereoPlacement,\n GoniometerPoint,\n HpssResult,\n Key,\n KeyCandidate,\n KeyDetectionOptions,\n KeyProfileName,\n LufsResult,\n MasteringChainConfig,\n MasteringChainResult,\n MasteringChainStereoResult,\n MasteringLoudnessSummary,\n MasteringOptions,\n MasteringPreset,\n MasteringProcessorParams,\n MasteringReport,\n MasteringResult,\n MasteringStereoChainResult,\n MasteringStereoResult,\n MelodyPoint,\n MelodyResult,\n MelPowerResult,\n MelSpectrogramResult,\n MeterTap,\n MfccResult,\n MixerProcessResult,\n MixMeterSnapshot,\n MixOptions,\n MixResult,\n NoteSegment,\n NoteStretchOptions,\n PairAnalysis,\n PairProcessor,\n PanLaw,\n PanLawInput,\n PanLawName,\n PanMode,\n PitchCorrectOptions,\n PitchResult,\n RealtimeVoiceChangerConfigInput,\n RealtimeVoiceChangerPodConfig,\n RhythmFeatures,\n RirResult,\n RirSynthOptions,\n RoomEstimateOptions,\n RoomEstimateResult,\n RoomGeometryOptions,\n RoomMorphOptions,\n Section,\n SegmentMatrix,\n SendTiming,\n SoloProcessor,\n SonareCapabilities,\n SpectralEditMode,\n SpectralEditOptions,\n SpectralEditWindow,\n SpectralRegionOp,\n StageGainReduction,\n StereoAnalysis,\n StftPowerResult,\n StftResult,\n StreamingEqualizerConfig,\n StreamingMasteringChainConfig,\n StreamingPlatform,\n StreamingRetuneConfig,\n TempogramMode,\n Timbre,\n TimeSignature,\n VoicedFlags,\n VoicePresetId,\n} from './public_types';\nexport {\n ChordQuality,\n KeyProfile,\n Mode,\n PitchClass,\n SectionType,\n} from './public_types';\nexport type {\n AnalyzeBpmRequest,\n AnalyzeDynamicsRequest,\n AnalyzeImpulseResponseRequest,\n AnalyzeRhythmRequest,\n AnalyzeTimbreRequest,\n AnalyzeWithProgressRequest,\n BpmAnalysisResult,\n BpmCandidate,\n ChordFunctionalAnalysisRequest,\n DetectAcousticRequest,\n DetectChordsRequest,\n DetectKeyRequest,\n DetectOnsetsRequest,\n DynamicsAnalysisResult,\n EstimateRoomRequest,\n MusicAnalyzeRequest,\n RhythmAnalysisResult,\n RoomMorphRequest,\n SamplesRequest,\n TimbreAnalysisResult,\n TimbreFrame,\n} from './quick_analysis';\nexport {\n analyze,\n analyzeBpm,\n analyzeDynamics,\n analyzeImpulseResponse,\n analyzeRhythm,\n analyzeTimbre,\n analyzeWithProgress,\n chordFunctionalAnalysis,\n detectAcoustic,\n detectBeats,\n detectBpm,\n detectChords,\n detectDownbeats,\n detectKey,\n detectKeyCandidates,\n detectOnsets,\n estimateRoom,\n hasFfmpegSupport,\n roomMorph,\n synthesizeRir,\n} from './quick_analysis';\nexport type {\n ClipPageRequest,\n EngineAutomationPoint,\n EngineBounceOptions,\n EngineBounceResult,\n EngineBus,\n EngineCapabilities,\n EngineCaptureSource,\n EngineCaptureStatus,\n EngineClip,\n EngineFreezeOptions,\n EngineFreezeResult,\n EngineGraphSpec,\n EngineMarker,\n EngineMeterTelemetry,\n EngineMeterTelemetryWide,\n EngineMetronomeConfig,\n EngineMidiClipSchedule,\n EngineMidiEvent,\n EngineParameterInfo,\n EngineScopeTelemetry,\n EngineTelemetry,\n EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTrackLane,\n EngineTrackMonitorMode,\n EngineTrackSend,\n EngineTransportState,\n ExternalMidiEvent,\n MidiCcBindOptions,\n TrackMonitorMode,\n} from './realtime_engine';\nexport {\n ClipPageProvider,\n EXPECTED_ENGINE_ABI_VERSION,\n engineCapabilities,\n RealtimeEngine,\n} from './realtime_engine';\nexport { scaleCorrectionSemitones, scalePitchClassEnabled, scaleQuantizeMidi } from './scale';\nexport type { ProgressCallback } from './sonare.js';\nexport { StreamAnalyzer, streamAnalyzerConfigDefaults } from './stream_analyzer';\nexport type {\n AnalyzerStats,\n BarChord,\n ChordChange,\n FrameBuffer,\n PatternScore,\n ProgressiveEstimate,\n StreamConfig,\n StreamConfigDefaults,\n StreamFramesI16,\n StreamFramesU8,\n StreamQuantizeConfig,\n} from './stream_types';\nexport type {\n MixerRealtimeBuffer,\n RealtimeVoiceChangerInterleavedBuffer,\n RealtimeVoiceChangerMonoBuffer,\n RealtimeVoiceChangerPlanarBuffer,\n} from './streaming_mixing';\nexport {\n Mixer,\n RealtimeVoiceChanger,\n realtimeVoiceChangerPresetJson,\n realtimeVoiceChangerPresetNames,\n StreamingEqualizer,\n StreamingMasteringChain,\n StreamingRetune,\n validateRealtimeVoiceChangerPresetJson,\n} from './streaming_mixing';\nexport type { ValidateOptions } from './validation';\nexport type {\n BindWebMidiOptions,\n WebMidiBinding,\n WebMidiCcBinding,\n WebMidiInputInfo,\n} from './web_midi';\nexport { bindWebMidi, isWebMidiAvailable } from './web_midi';\nexport type {\n OfflineWorker,\n OfflineWorkerCallOptions,\n OfflineWorkerClientOptions,\n OfflineWorkerProgress,\n} from './worker_client';\nexport { OfflineWorkerClient, OfflineWorkerTask } from './worker_client';\n\n/** Row-major 2-D matrix as a flat buffer plus its dimensions. */\nexport type Matrix2dResult = WasmMatrix2dResult;\n/** NMF factor matrices { w, h } from {@link decompose}. */\nexport type DecomposeResult = WasmDecomposeResult;\n/** Harmonic / percussive / residual signals from {@link hpssWithResidual}. */\nexport type HpssWithResidualResult = WasmHpssWithResidualResult;\n\n// ============================================================================\n// Module State\n// ============================================================================\n\nlet module: SonareModule | null = null;\nlet initPromise: Promise<void> | null = null;\n\n// ============================================================================\n// Initialization\n// ============================================================================\n\n/**\n * Initialize the WASM module.\n * Must be called before using any analysis functions.\n *\n * @param options - Optional module configuration\n * @returns Promise that resolves when initialization is complete\n */\nexport async function init(options?: {\n locateFile?: (path: string, prefix: string) => string;\n wasmBinary?: ArrayBuffer | Uint8Array;\n moduleFactory?: (options?: {\n locateFile?: (path: string, prefix: string) => string;\n wasmBinary?: ArrayBuffer | Uint8Array;\n }) => Promise<SonareModule>;\n}): Promise<void> {\n if (module) {\n return;\n }\n\n if (initPromise) {\n return initPromise;\n }\n\n initPromise = (async () => {\n try {\n const createModule = options?.moduleFactory ?? (await import('./sonare.js')).default;\n module = await createModule(options);\n setSonareModule(module);\n } catch (error) {\n initPromise = null;\n throw error;\n }\n })();\n\n return initPromise;\n}\n\n/**\n * Check if the module is initialized.\n */\nexport function isInitialized(): boolean {\n return module !== null;\n}\n\n/**\n * Get the library version.\n */\nexport function version(): string {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.version();\n}\n\n/**\n * Return the capabilities of the loaded WASM build.\n *\n * This is synchronous and only describes the already-initialized module.\n */\nexport function capabilities(): SonareCapabilities {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.capabilities();\n}\n\n/** Return the initialized module's processors, parameters, and presets. */\nexport function capabilityCatalog(): CapabilityCatalog {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return JSON.parse(module.capabilityCatalog()) as CapabilityCatalog;\n}\n\n/**\n * Aggregate native ABI version: the per-subsystem ABI macros folded into one\n * 32-bit value. It bumps whenever any flat C POD layout changes, so callers can\n * detect an incompatible prebuilt binary. Matches the Node/Python `abiVersion()`.\n */\nexport function abiVersion(): number {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.abiVersion();\n}\n\nexport function engineAbiVersion(): number {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.engineAbiVersion();\n}\n\nexport function voiceChangerAbiVersion(): number {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.voiceChangerAbiVersion();\n}\n\n// Canonical ordinal order of the built-in voice-character presets, matching the\n// C ABI SonareVoiceCharacterPreset enum and SONARE_REALTIME_VOICE_CHANGER_PRESET_IDS.\nconst VOICE_PRESET_ORDINALS: readonly VoicePresetId[] = [\n 'neutral-monitor',\n 'bright-idol',\n 'soft-whisper',\n 'deep-narrator',\n 'robot-mascot',\n 'dark-villain',\n];\n\nfunction resolveVoicePresetOrdinal(preset: VoicePresetId | number): number {\n if (typeof preset === 'number') {\n if (!Number.isSafeInteger(preset) || preset < 0 || preset >= VOICE_PRESET_ORDINALS.length) {\n throw new RangeError(`Unknown voice-character preset ordinal: ${String(preset)}`);\n }\n return preset;\n }\n const ordinal = VOICE_PRESET_ORDINALS.indexOf(preset);\n if (ordinal < 0) {\n throw new Error(`Unknown voice character preset: ${preset}`);\n }\n return ordinal;\n}\n\n/**\n * Map a voice-character preset ordinal (or canonical id) to its canonical id\n * string (e.g. `'bright-idol'`). Unknown numeric ordinals return `null`;\n * unknown preset ids throw.\n */\nexport function voiceCharacterPresetId(preset: VoicePresetId | number): VoicePresetId | null {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n if (\n typeof preset === 'number' &&\n (!Number.isSafeInteger(preset) || preset < 0 || preset >= VOICE_PRESET_ORDINALS.length)\n ) {\n return null;\n }\n return module.voiceCharacterPresetId(resolveVoicePresetOrdinal(preset)) as VoicePresetId;\n}\n\n/**\n * Return the canonical (normalized) flat POD config for a built-in voice\n * preset, skipping the JSON round-trip. Accepts a canonical preset id or its\n * integer ordinal. Invalid ordinals throw.\n */\nexport function realtimeVoiceChangerPresetConfig(\n preset: VoicePresetId | number,\n): RealtimeVoiceChangerPodConfig {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.realtimeVoiceChangerPresetConfig(resolveVoicePresetOrdinal(preset));\n}\n\n// ============================================================================\n// Re-exports\n// ============================================================================\n\nexport { PitchClass as Pitch } from './public_types';\n","import type {\n EngineParameterInfo,\n EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTrackLane,\n EngineTrackSend,\n} from '../index';\nimport type { SonareEngineSyncTempoMessage } from './messages';\n\n/**\n * Builds the ordered mixer-lane descriptors for a sync message.\n *\n * Each declared track id is paired with its current send list and output bus\n * (both omitted when absent), defensively copying the send entries.\n *\n * @param trackLaneIds Lane order (track ids) declared on the engine.\n * @param trackSends Per-track send lists.\n * @param trackOutputBus Per-track output bus routing.\n * @returns Lane descriptors in lane order.\n */\nexport function buildMixerLanes(\n trackLaneIds: readonly number[],\n trackSends: ReadonlyMap<number, EngineTrackSend[]>,\n trackOutputBus: ReadonlyMap<number, number>,\n): EngineTrackLane[] {\n return trackLaneIds.map((trackId) => {\n const sends = trackSends.get(trackId);\n const outputBusId = trackOutputBus.get(trackId);\n return {\n trackId,\n ...(sends && sends.length > 0 ? { sends: sends.map((send) => ({ ...send })) } : {}),\n ...(outputBusId !== undefined ? { outputBusId } : {}),\n };\n });\n}\n\n/**\n * Builds the out-of-band tempo/time-signature sync message, deep-copying the\n * tempo and time-signature segments so the consumer cannot alias engine state.\n */\nexport function buildTempoSync(\n tempoBpm: number,\n timeSignature: { numerator: number; denominator: number },\n tempoSegments: readonly EngineTempoSegment[],\n timeSignatureSegments: readonly EngineTimeSignatureSegment[],\n): SonareEngineSyncTempoMessage {\n return {\n type: 'syncTempo',\n bpm: tempoBpm,\n timeSignature: { ...timeSignature },\n tempoSegments: tempoSegments.map((segment) => ({ ...segment })),\n timeSignatureSegments: timeSignatureSegments.map((segment) => ({ ...segment })),\n };\n}\n\n/**\n * Resolves a target id from a string or number; non-numeric strings resolve to\n * 0, mirroring the engine's integer-id namespace.\n */\nexport function resolveTargetId(target: string | number): number {\n if (typeof target === 'number') {\n return target;\n }\n const parsed = Number.parseInt(target, 10);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\n/** Resolves a registered parameter name or passes through a numeric id. */\nexport function resolveParamId(\n parameters: readonly EngineParameterInfo[],\n nodeId: string,\n param: string | number,\n): number {\n if (typeof param === 'number') {\n return param;\n }\n const byName = parameters.find((info) => info.name === param);\n if (byName) {\n return byName.id;\n }\n throw new RangeError(`Unknown engine parameter ${JSON.stringify(param)} for node ${nodeId}`);\n}\n\n/** Encodes an automation curve descriptor to the engine's numeric curve code. */\nexport function curveCode(curve: number | 'linear' | 'exponential'): number {\n if (typeof curve === 'number') {\n return curve;\n }\n return curve === 'exponential' ? 1 : 0;\n}\n","import type { EngineAutomationPoint, RealtimeEngine } from '../index';\nimport { curveCode } from './engine-sync';\nimport type { SonareEngineSyncMessage } from './messages';\n\n/**\n * Collaborator surface the automation-lane helpers need from the owning\n * {@link SonareEngine}: the lane store they mutate, the offline engine they\n * mirror into, the sync poster, and the parameter-id resolver.\n */\nexport interface EngineAutomationContext {\n readonly offlineEngine: RealtimeEngine;\n readonly automationLanes: Map<number, EngineAutomationPoint[]>;\n postSync(message: SonareEngineSyncMessage): void;\n resolveParamId(nodeId: string, param: string | number): number;\n}\n\nexport function scheduleParam(\n ctx: EngineAutomationContext,\n nodeId: string,\n param: string | number,\n ppq: number,\n value: number,\n curve: number | 'linear' | 'exponential' = 'linear',\n): void {\n const paramId = ctx.resolveParamId(nodeId, param);\n const lane = ctx.automationLanes.get(paramId) ?? [];\n lane.push({ ppq, value, curveToNext: curveCode(curve) });\n lane.sort((a, b) => a.ppq - b.ppq);\n ctx.automationLanes.set(paramId, lane);\n ctx.offlineEngine.setAutomationLane(paramId, lane);\n // Mirror the lane to the live worklet engine so scheduled automation plays\n // back in real time, not just in renderOffline(). Lanes can exceed the\n // fixed-size SAB command record, so they ride an out-of-band 'syncAutomation'\n // message whose port handler publishes the bounded snapshot consumed by\n // process() (like syncClips/syncMarkers).\n ctx.postSync({ type: 'syncAutomation', paramId, points: lane });\n}\n\nexport function addAutomationPoint(\n ctx: EngineAutomationContext,\n laneId: string | number,\n ppq: number,\n value: number,\n curve: number | 'linear' | 'exponential' = 'linear',\n): void {\n scheduleParam(ctx, '', laneId, ppq, value, curve);\n}\n\n/**\n * Replaces the automation lane for `paramId` with the given breakpoints.\n *\n * Unlike scheduleParam (which appends a single point), this sets the whole\n * lane at once; an empty array clears the lane. The points are defensively\n * copied and sorted by ppq before being mirrored to the offline engine and\n * the live worklet engine.\n *\n * @param paramId Automation target id (registered parameter or a reserved\n * engine mixer target from automationParamId/busAutomationParamId).\n * @param points Lane breakpoints; order does not matter.\n */\nexport function setAutomationLane(\n ctx: EngineAutomationContext,\n paramId: number,\n points: ReadonlyArray<EngineAutomationPoint>,\n): void {\n const sorted = points.map((point) => ({ ...point })).sort((a, b) => a.ppq - b.ppq);\n if (sorted.length === 0) {\n ctx.automationLanes.delete(paramId);\n } else {\n ctx.automationLanes.set(paramId, sorted);\n }\n ctx.offlineEngine.setAutomationLane(paramId, sorted);\n ctx.postSync({ type: 'syncAutomation', paramId, points: sorted });\n}\n","import type { EngineCaptureStatus, EngineMarker, EngineTrackLane, RealtimeEngine } from '../index';\nimport type { SonareEngineSyncCaptureMessage, SonareEngineTransportFacade } from './messages';\n\n/** Capture configuration options accepted by the engine's `configureCapture`. */\nexport interface CaptureOptions {\n bufferFrames: number;\n channels?: number;\n source?: EngineCaptureStatus['source'];\n recordOffsetSamples?: number;\n inputMonitor?: { enabled: boolean; gain?: number };\n}\n\n/**\n * Normalizes capture options into the resolved config carried by the\n * `syncCapture` message, applying integer truncation and defaults.\n *\n * @param options Raw capture options.\n * @param defaultChannels Channel count to use when `options.channels` is unset.\n */\nexport function buildCaptureConfig(\n options: CaptureOptions,\n defaultChannels: number,\n): Omit<SonareEngineSyncCaptureMessage, 'type'> {\n return {\n bufferFrames: Math.trunc(options.bufferFrames),\n channels: Math.trunc(options.channels ?? defaultChannels),\n source: options.source ?? 'output',\n recordOffsetSamples: Math.trunc(options.recordOffsetSamples ?? 0),\n inputMonitor: {\n enabled: Boolean(options.inputMonitor?.enabled),\n gain: options.inputMonitor?.gain ?? 1,\n },\n };\n}\n\n/**\n * Collaborator surface the transport facade needs from the owning engine: the\n * realtime node (sample-accurate command transport), the offline engine it\n * mirrors, and the tempo/loop setters plus playing-state bookkeeping.\n */\nexport interface EngineTransportContext {\n readonly sampleRate: number;\n realtimeNode: {\n play(sampleTime?: number): boolean;\n stop(sampleTime?: number): boolean;\n seekPpq(ppq: number, sampleTime?: number): boolean;\n seekSample(timelineSample: number, sampleTime?: number): boolean;\n };\n offlineEngine: RealtimeEngine;\n flushOfflineMirror(): void;\n setTransportPlaying(playing: boolean): void;\n flushPendingInstrumentSync(): void;\n setTempo(bpm: number): void;\n setTempoSegments(segments: readonly { startPpq: number; bpm: number }[]): void;\n setLoop(startPpq: number, endPpq: number, enabled?: boolean): boolean;\n}\n\n/** Builds the public transport facade that fans control to both engines. */\nexport function buildTransportFacade(ctx: EngineTransportContext): SonareEngineTransportFacade {\n return {\n play: (sampleTime = -1) => {\n const ok = ctx.realtimeNode.play(sampleTime);\n if (ok) {\n ctx.setTransportPlaying(true);\n }\n return ok;\n },\n stop: (sampleTime = -1) => {\n const ok = ctx.realtimeNode.stop(sampleTime);\n if (ok) {\n ctx.setTransportPlaying(false);\n ctx.flushPendingInstrumentSync();\n }\n return ok;\n },\n seekPpq: (ppq, sampleTime = -1) => {\n ctx.offlineEngine.seekPpq(ppq, sampleTime);\n const ok = ctx.realtimeNode.seekPpq(ppq, sampleTime);\n ctx.flushOfflineMirror();\n return ok;\n },\n seekSeconds: (seconds, sampleTime = -1) => {\n const timelineSample = Math.max(0, Math.round(seconds * ctx.sampleRate));\n ctx.offlineEngine.seekSample(timelineSample, sampleTime);\n const ok = ctx.realtimeNode.seekSample(timelineSample, sampleTime);\n ctx.flushOfflineMirror();\n return ok;\n },\n setTempo: (bpm) => ctx.setTempo(bpm),\n setTempoSegments: (segments) => ctx.setTempoSegments(segments),\n setLoop: (startPpq, endPpq, enabled = true) => ctx.setLoop(startPpq, endPpq, enabled),\n };\n}\n\n/**\n * Validates and normalizes an append-only mixer-lane declaration.\n *\n * Lane indices are append-only: the new list must start with the already\n * declared lane ids in their current order and may only append new track ids.\n * Returns the normalized lane entries (numbers coerced to descriptors) and the\n * resulting ordered id list.\n *\n * @throws if any track id is invalid, ids are duplicated, or the existing lane\n * order is not preserved.\n */\nexport function normalizeTrackLanes(\n existing: readonly number[],\n lanes: ReadonlyArray<number | EngineTrackLane>,\n): { entries: EngineTrackLane[]; ids: number[] } {\n const entries = lanes.map((lane) => (typeof lane === 'number' ? { trackId: lane } : lane));\n const ids: number[] = [];\n for (const entry of entries) {\n if (!Number.isInteger(entry.trackId) || entry.trackId <= 0) {\n throw new Error(`Invalid track id for mixer lane: ${String(entry.trackId)}`);\n }\n ids.push(entry.trackId);\n }\n if (new Set(ids).size !== ids.length) {\n throw new Error('Duplicate track id in mixer lane list');\n }\n for (let index = 0; index < existing.length; index++) {\n if (ids[index] !== existing[index]) {\n throw new Error(\n 'Mixer lanes are append-only: keep existing lanes in order and only append new track ids',\n );\n }\n }\n return { entries, ids };\n}\n\n/**\n * Resolves a marker set, assigning fresh ids to entries without one and\n * validating explicit ids (positive, unique).\n *\n * @param markers The marker list to resolve.\n * @param nextMarkerId The id counter to draw fresh ids from.\n * @returns The resolved markers and the advanced id counter.\n * @throws on a non-finite ppq, an invalid id, or a duplicate id.\n */\nexport function resolveMarkerSet(\n markers: ReadonlyArray<{ ppq: number; name?: string; id?: number }>,\n nextMarkerId: number,\n): { resolved: EngineMarker[]; nextMarkerId: number } {\n const resolved: EngineMarker[] = [];\n const seen = new Set<number>();\n let counter = nextMarkerId;\n for (const marker of markers) {\n if (!Number.isFinite(marker.ppq)) {\n throw new Error(`Invalid marker ppq: ${String(marker.ppq)}`);\n }\n if (marker.id !== undefined) {\n if (!Number.isInteger(marker.id) || marker.id <= 0) {\n throw new Error(`Invalid marker id: ${String(marker.id)}`);\n }\n if (seen.has(marker.id)) {\n throw new Error(`Duplicate marker id: ${marker.id}`);\n }\n }\n const id = marker.id ?? counter++;\n seen.add(id);\n if (id >= counter) {\n counter = id + 1;\n }\n resolved.push({ id, ppq: marker.ppq, name: marker.name ?? '' });\n }\n return { resolved, nextMarkerId: counter };\n}\n","import type { EngineMeterTelemetry, EngineTelemetry } from '../index';\n\nconst ENGINE_MIXER_TARGET_BASE = 0x4d580000;\nexport const ENGINE_MIXER_PARAM_FADER_DB = 1;\nexport const ENGINE_MIXER_PARAM_PAN = 2;\n\nexport function engineMixerLaneTarget(laneIndex: number, paramKind: number): number {\n return ENGINE_MIXER_TARGET_BASE | ((laneIndex & 0xff) << 8) | (paramKind & 0xff);\n}\n\nexport function engineMixerBusTarget(busIndex: number, paramKind: number): number {\n return ENGINE_MIXER_TARGET_BASE | (((0xfe - busIndex) & 0xff) << 8) | (paramKind & 0xff);\n}\n\nexport function engineMixerMasterTarget(paramKind: number): number {\n return ENGINE_MIXER_TARGET_BASE | (0xff << 8) | (paramKind & 0xff);\n}\n\nexport interface SonareWorkletMeterSnapshot {\n type: 'meter';\n targetId: number;\n frame: number;\n peakDbL: number;\n peakDbR: number;\n rmsDbL: number;\n rmsDbR: number;\n correlation: number;\n truePeakDbL: number;\n truePeakDbR: number;\n momentaryLufs: number;\n shortTermLufs: number;\n integratedLufs: number;\n gainReductionDb: number;\n}\n\nexport interface SonareWorkletSpectrumSnapshot {\n type: 'spectrum';\n frame: number;\n bands: Float32Array;\n}\n\nexport const SONARE_METER_RING_HEADER_INTS = 4;\n// Record layout: [frameLo, frameHi, targetId, peakDbL, peakDbR, rmsDbL, rmsDbR,\n// correlation, truePeakDbL, truePeakDbR, momentaryLufs, shortTermLufs,\n// integratedLufs, gainReductionDb].\n// The sample-frame index is monotonically increasing and quickly exceeds the\n// 2^24 exact-integer range of a single Float32 slot (~349 s at 48 kHz), so it is\n// stored split across two Float32 lanes (low 24 bits + high bits) for exact\n// reconstruction. See encodeFrameLo/encodeFrameHi/decodeFrame.\nexport const SONARE_METER_RING_RECORD_FLOATS = 14;\nexport const SONARE_SPECTRUM_RING_HEADER_INTS = 5;\n// Scope ring header: [writeIndex, capacity, recordFloats, bands, maxPoints,\n// reserved]. Record layout: [frameLo, frameHi, targetId, bandCount, pointCount,\n// band0..band(bands-1), l0, r0, l1, r1, ... (maxPoints stereo pairs)].\nexport const SONARE_SCOPE_RING_HEADER_INTS = 6;\nexport const SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS = 5;\n\n/** Base for splitting a frame index into two exactly-representable Float32 lanes. */\nconst SONARE_FRAME_LANE_BASE = 0x1000000; // 2^24\n\n/** Low 24 bits of a frame index (exact in Float32). */\nexport function encodeFrameLo(frame: number): number {\n const f = Math.max(0, Math.floor(frame));\n return f % SONARE_FRAME_LANE_BASE;\n}\n\n/** High bits of a frame index above 2^24 (exact in Float32 up to ~2^48). */\nexport function encodeFrameHi(frame: number): number {\n const f = Math.max(0, Math.floor(frame));\n return Math.floor(f / SONARE_FRAME_LANE_BASE);\n}\n\n/** Reconstruct a frame index from its low/high Float32 lanes. */\nexport function decodeFrame(lo: number, hi: number): number {\n return hi * SONARE_FRAME_LANE_BASE + lo;\n}\nexport const SONARE_ENGINE_RING_HEADER_INTS = 5;\nexport const SONARE_ENGINE_COMMAND_RECORD_BYTES = 32;\nexport const SONARE_ENGINE_TELEMETRY_RECORD_BYTES = 48;\n// Clip-page request ring header: [writeIndex, readIndex, capacity,\n// recordUint32s, dropped]. Records are [clipId, pageIndex]. This is an SPSC\n// queue: the AudioWorklet is the sole writer and the main thread is the sole\n// reader. Unlike the telemetry rings, it must not overwrite unread requests:\n// the producer increments `dropped` when the fixed queue is full.\nexport const SONARE_CLIP_PAGE_REQUEST_RING_HEADER_INTS = 5;\nexport const SONARE_CLIP_PAGE_REQUEST_RING_RECORD_UINT32S = 2;\n// External MIDI records: destination ID, render-frame offset, packed MIDI-1\n// bytes (little-endian), and byte count. SPSC worklet -> main-thread ring.\nexport const SONARE_EXTERNAL_MIDI_RING_HEADER_INTS = 5;\nexport const SONARE_EXTERNAL_MIDI_RING_RECORD_UINT32S = 4;\n\nexport enum SonareEngineCommandType {\n SetParam = 0,\n SetParamSmoothed = 1,\n TransportPlay = 2,\n TransportStop = 3,\n TransportSeekSample = 4,\n TransportSeekPpq = 5,\n SetTempoMap = 6,\n SetLoop = 7,\n SwapGraph = 8,\n SwapAutomation = 9,\n SetSoloMute = 10,\n AddClip = 11,\n RemoveClip = 12,\n ArmRecord = 13,\n Punch = 14,\n SetMetronome = 15,\n SetMarker = 16,\n SeekMarker = 17,\n // Queueable lane monitor-mode transition. The worklet command vocabulary\n // deliberately leaves 18..25 unused; this is the stable ABI-v3 ordinal.\n SetTrackMonitorMode = 26,\n}\n\nexport enum SonareEngineTelemetryType {\n ProcessBlock = 0,\n Error = 1,\n}\n\nexport enum SonareEngineTelemetryError {\n None = 0,\n CommandQueueOverflow = 1,\n PendingCommandOverflow = 2,\n BoundaryOverflow = 3,\n TelemetryOverflow = 4,\n CaptureOverflow = 5,\n MaxBlockExceeded = 6,\n UnknownTarget = 7,\n NonRealtimeSafeParameter = 8,\n NotPrepared = 9,\n NonQueueableCommand = 10,\n AutomationBindTargetOverflow = 11,\n StaleAutomationLanes = 12,\n SmoothedParameterCapacity = 13,\n CommandBacklogDeferred = 14,\n ClipPageUnderrun = 15,\n InsertAutomationOverflow = 16,\n MidiClockOverflow = 17,\n MetronomeOverflow = 18,\n InvalidCommand = 19,\n MaxChannelsExceeded = 20,\n}\n\nexport interface SonareMeterRingBuffer {\n sharedBuffer: SharedArrayBuffer;\n header: Int32Array;\n records: Float32Array;\n capacity: number;\n}\n\nexport interface SonareMeterRingReadResult {\n nextReadIndex: number;\n meters: SonareWorkletMeterSnapshot[];\n}\n\nexport interface SonareSpectrumRingBuffer {\n sharedBuffer: SharedArrayBuffer;\n header: Int32Array;\n records: Float32Array;\n capacity: number;\n bands: number;\n}\n\nexport interface SonareSpectrumRingReadResult {\n nextReadIndex: number;\n spectra: SonareWorkletSpectrumSnapshot[];\n}\n\n/**\n * A single target-addressed scope record drained from the realtime engine's\n * scope ring: an FFT magnitude spectrum plus a decimated goniometer/vectorscope\n * point cloud. Unlike {@link SonareWorkletSpectrumSnapshot} (the legacy\n * coarse-DFT meter spectrum), this carries a `targetId` (master/lane/bus) and a\n * stereo point cloud, mirroring the engine's `ScopeTelemetryRecord`.\n */\nexport interface SonareWorkletScopeSnapshot {\n type: 'scope';\n targetId: number;\n frame: number;\n /** Linear-band magnitudes in dB (length = the configured band count). */\n bands: Float32Array;\n /** Interleaved stereo goniometer points: [l0, r0, l1, r1, ...]. */\n points: Float32Array;\n}\n\nexport interface SonareScopeRingBuffer {\n sharedBuffer: SharedArrayBuffer;\n header: Int32Array;\n records: Float32Array;\n capacity: number;\n bands: number;\n maxPoints: number;\n}\n\nexport interface SonareScopeRingReadResult {\n nextReadIndex: number;\n scopes: SonareWorkletScopeSnapshot[];\n}\n\nexport interface SonareExternalMidiRingEvent {\n destinationId: number;\n renderFrame: number;\n byteWord: number;\n byteCount: number;\n}\n\nexport interface SonareExternalMidiRingBuffer {\n sharedBuffer: SharedArrayBuffer;\n header: Int32Array;\n records: Uint32Array;\n capacity: number;\n}\n\nexport interface SharedExternalMidiRingWriter {\n header: Int32Array;\n records: Uint32Array;\n capacity: number;\n}\n\nexport interface SonareExternalMidiRingReadResult {\n events: SonareExternalMidiRingEvent[];\n dropped: number;\n}\n\nexport interface SharedScopeRingWriter {\n header: Int32Array;\n records: Float32Array;\n capacity: number;\n bands: number;\n maxPoints: number;\n recordFloats: number;\n}\n\nexport interface SonareEngineCommandRecord {\n type: SonareEngineCommandType | number;\n targetId?: number;\n sampleTime?: number | bigint;\n argFloat?: number;\n argInt?: number | bigint;\n}\n\nexport interface SonareEngineTelemetryRecord {\n type: SonareEngineTelemetryType | number;\n error: SonareEngineTelemetryError | number;\n renderFrame: number;\n timelineSample: number;\n audibleTimelineSample: number;\n graphLatencySamplesQ8: number;\n value: number;\n}\n\nexport interface SonareEngineCommandRingBuffer {\n sharedBuffer: SharedArrayBuffer;\n header: Int32Array;\n view: DataView;\n capacity: number;\n}\n\nexport interface SonareEngineTelemetryRingBuffer {\n sharedBuffer: SharedArrayBuffer;\n header: Int32Array;\n view: DataView;\n capacity: number;\n}\n\nexport interface SonareEngineTelemetryRingReadResult {\n nextReadIndex: number;\n telemetry: SonareEngineTelemetryRecord[];\n}\n\nexport interface SonareClipPageRequest {\n clipId: number;\n pageIndex: number;\n}\n\nexport interface SonareClipPageRequestRingBuffer {\n sharedBuffer: SharedArrayBuffer;\n header: Int32Array;\n records: Uint32Array;\n capacity: number;\n}\n\nexport interface SharedClipPageRequestRingWriter {\n header: Int32Array;\n records: Uint32Array;\n capacity: number;\n}\n\nexport interface SonareClipPageRequestRingReadResult {\n requests: SonareClipPageRequest[];\n /** Cumulative uint32 drop count for native and SAB-ring overflows. */\n dropped: number;\n}\n\nexport interface SharedMeterRingWriter {\n header: Int32Array;\n records: Float32Array;\n capacity: number;\n}\n\nexport interface SharedSpectrumRingWriter {\n header: Int32Array;\n records: Float32Array;\n capacity: number;\n bands: number;\n recordFloats: number;\n}\n\nexport function toDb(value: number): number {\n return value > 0 ? 20 * Math.log10(value) : Number.NEGATIVE_INFINITY;\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nexport function sonareMeterRingBufferByteLength(capacity: number): number {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n return (\n SONARE_METER_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT +\n clampedCapacity * SONARE_METER_RING_RECORD_FLOATS * Float32Array.BYTES_PER_ELEMENT\n );\n}\n\nexport function createSonareMeterRingBuffer(capacity = 128): SonareMeterRingBuffer {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const sharedBuffer = new SharedArrayBuffer(sonareMeterRingBufferByteLength(clampedCapacity));\n const ring = meterRingFromSharedBuffer(sharedBuffer, clampedCapacity);\n Atomics.store(ring.header, 0, 0);\n Atomics.store(ring.header, 1, clampedCapacity);\n Atomics.store(ring.header, 2, SONARE_METER_RING_RECORD_FLOATS);\n Atomics.store(ring.header, 3, 0);\n return { sharedBuffer, header: ring.header, records: ring.records, capacity: ring.capacity };\n}\n\nexport function readSonareMeterRingBuffer(\n ring: SonareMeterRingBuffer,\n readIndex = 0,\n): SonareMeterRingReadResult {\n const writeIndex = Atomics.load(ring.header, 0);\n const recordFloats = Atomics.load(ring.header, 2) || SONARE_METER_RING_RECORD_FLOATS;\n const nextReadIndex = Math.max(0, Math.min(readIndex, writeIndex));\n const firstReadable = Math.max(nextReadIndex, writeIndex - ring.capacity);\n const meters: SonareWorkletMeterSnapshot[] = [];\n for (let index = firstReadable; index < writeIndex; index++) {\n const offset = (index % ring.capacity) * recordFloats;\n meters.push({\n type: 'meter',\n frame: decodeFrame(ring.records[offset], ring.records[offset + 1]),\n targetId: ring.records[offset + 2],\n peakDbL: ring.records[offset + 3],\n peakDbR: ring.records[offset + 4],\n rmsDbL: ring.records[offset + 5],\n rmsDbR: ring.records[offset + 6],\n correlation: ring.records[offset + 7],\n truePeakDbL: ring.records[offset + 8],\n truePeakDbR: ring.records[offset + 9],\n momentaryLufs: ring.records[offset + 10],\n shortTermLufs: ring.records[offset + 11],\n integratedLufs: ring.records[offset + 12],\n gainReductionDb: ring.records[offset + 13],\n });\n }\n return { nextReadIndex: writeIndex, meters };\n}\n\nexport function sonareSpectrumRingBufferByteLength(capacity: number, bands = 16): number {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const clampedBands = Math.max(1, Math.floor(bands));\n // Record layout: [frameLo, frameHi, bandCount, band0, band1, ...]. frame is\n // split across two Float32 lanes for exact reconstruction beyond 2^24.\n return (\n SONARE_SPECTRUM_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT +\n clampedCapacity * (3 + clampedBands) * Float32Array.BYTES_PER_ELEMENT\n );\n}\n\nexport function createSonareSpectrumRingBuffer(\n capacity = 128,\n bands = 16,\n): SonareSpectrumRingBuffer {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const clampedBands = Math.max(1, Math.floor(bands));\n const sharedBuffer = new SharedArrayBuffer(\n sonareSpectrumRingBufferByteLength(clampedCapacity, clampedBands),\n );\n const ring = spectrumRingFromSharedBuffer(sharedBuffer, clampedCapacity, clampedBands);\n Atomics.store(ring.header, 0, 0);\n Atomics.store(ring.header, 1, clampedCapacity);\n Atomics.store(ring.header, 2, ring.recordFloats);\n Atomics.store(ring.header, 3, clampedBands);\n Atomics.store(ring.header, 4, 0);\n return {\n sharedBuffer,\n header: ring.header,\n records: ring.records,\n capacity: ring.capacity,\n bands: ring.bands,\n };\n}\n\nexport function readSonareSpectrumRingBuffer(\n ring: SonareSpectrumRingBuffer,\n readIndex = 0,\n): SonareSpectrumRingReadResult {\n const writeIndex = Atomics.load(ring.header, 0);\n const recordFloats = Atomics.load(ring.header, 2) || 3 + ring.bands;\n const bands = Atomics.load(ring.header, 3) || ring.bands;\n const nextReadIndex = Math.max(0, Math.min(readIndex, writeIndex));\n const firstReadable = Math.max(nextReadIndex, writeIndex - ring.capacity);\n const spectra: SonareWorkletSpectrumSnapshot[] = [];\n for (let index = firstReadable; index < writeIndex; index++) {\n const offset = (index % ring.capacity) * recordFloats;\n const values = new Float32Array(bands);\n values.set(ring.records.subarray(offset + 3, offset + 3 + bands));\n spectra.push({\n type: 'spectrum',\n frame: decodeFrame(ring.records[offset], ring.records[offset + 1]),\n bands: values,\n });\n }\n return { nextReadIndex: writeIndex, spectra };\n}\n\nexport function sonareScopeRingRecordFloats(bands: number, maxPoints: number): number {\n return SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS + bands + 2 * maxPoints;\n}\n\nexport function sonareScopeRingBufferByteLength(\n capacity: number,\n bands = 48,\n maxPoints = 32,\n): number {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const clampedBands = Math.max(1, Math.floor(bands));\n const clampedPoints = Math.max(0, Math.floor(maxPoints));\n return (\n SONARE_SCOPE_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT +\n clampedCapacity *\n sonareScopeRingRecordFloats(clampedBands, clampedPoints) *\n Float32Array.BYTES_PER_ELEMENT\n );\n}\n\nexport function createSonareScopeRingBuffer(\n capacity = 64,\n bands = 48,\n maxPoints = 32,\n): SonareScopeRingBuffer {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const clampedBands = Math.max(1, Math.floor(bands));\n const clampedPoints = Math.max(0, Math.floor(maxPoints));\n const sharedBuffer = new SharedArrayBuffer(\n sonareScopeRingBufferByteLength(clampedCapacity, clampedBands, clampedPoints),\n );\n const ring = scopeRingFromSharedBuffer(\n sharedBuffer,\n clampedCapacity,\n clampedBands,\n clampedPoints,\n );\n Atomics.store(ring.header, 0, 0);\n Atomics.store(ring.header, 1, clampedCapacity);\n Atomics.store(ring.header, 2, ring.recordFloats);\n Atomics.store(ring.header, 3, clampedBands);\n Atomics.store(ring.header, 4, clampedPoints);\n Atomics.store(ring.header, 5, 0);\n return {\n sharedBuffer,\n header: ring.header,\n records: ring.records,\n capacity: ring.capacity,\n bands: ring.bands,\n maxPoints: ring.maxPoints,\n };\n}\n\nexport function readSonareScopeRingBuffer(\n ring: SonareScopeRingBuffer,\n readIndex = 0,\n): SonareScopeRingReadResult {\n const writeIndex = Atomics.load(ring.header, 0);\n const bands = Atomics.load(ring.header, 3) || ring.bands;\n const maxPoints = Atomics.load(ring.header, 4);\n const recordFloats =\n Atomics.load(ring.header, 2) || sonareScopeRingRecordFloats(bands, maxPoints);\n const nextReadIndex = Math.max(0, Math.min(readIndex, writeIndex));\n const firstReadable = Math.max(nextReadIndex, writeIndex - ring.capacity);\n const scopes: SonareWorkletScopeSnapshot[] = [];\n for (let index = firstReadable; index < writeIndex; index++) {\n const offset = (index % ring.capacity) * recordFloats;\n const bandCount = Math.min(bands, Math.max(0, ring.records[offset + 3]));\n const pointCount = Math.min(maxPoints, Math.max(0, ring.records[offset + 4]));\n const bandsView = new Float32Array(bandCount);\n bandsView.set(\n ring.records.subarray(\n offset + SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS,\n offset + SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS + bandCount,\n ),\n );\n const pointsBase = offset + SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS + bands;\n const pointsView = new Float32Array(pointCount * 2);\n pointsView.set(ring.records.subarray(pointsBase, pointsBase + pointCount * 2));\n scopes.push({\n type: 'scope',\n frame: decodeFrame(ring.records[offset], ring.records[offset + 1]),\n targetId: ring.records[offset + 2],\n bands: bandsView,\n points: pointsView,\n });\n }\n return { nextReadIndex: writeIndex, scopes };\n}\n\nexport function scopeRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n fallbackCapacity?: number,\n fallbackBands?: number,\n fallbackMaxPoints?: number,\n): SharedScopeRingWriter {\n const headerBytes = SONARE_SCOPE_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT;\n const header = new Int32Array(sharedBuffer, 0, SONARE_SCOPE_RING_HEADER_INTS);\n const existingCapacity = Atomics.load(header, 1);\n const existingBands = Atomics.load(header, 3);\n const existingMaxPoints = Atomics.load(header, 4);\n const capacity = Math.max(1, Math.floor(existingCapacity || fallbackCapacity || 1));\n const bands = Math.max(1, Math.floor(existingBands || fallbackBands || 48));\n const maxPoints = Math.max(0, Math.floor(existingMaxPoints || (fallbackMaxPoints ?? 32)));\n const recordFloats = sonareScopeRingRecordFloats(bands, maxPoints);\n const minBytes = sonareScopeRingBufferByteLength(capacity, bands, maxPoints);\n if (sharedBuffer.byteLength < minBytes) {\n throw new Error('scopeSharedBuffer is too small for the requested ring capacity.');\n }\n Atomics.store(header, 1, capacity);\n Atomics.store(header, 2, recordFloats);\n Atomics.store(header, 3, bands);\n Atomics.store(header, 4, maxPoints);\n return {\n header,\n records: new Float32Array(sharedBuffer, headerBytes, capacity * recordFloats),\n capacity,\n bands,\n maxPoints,\n recordFloats,\n };\n}\n\nexport function sonareEngineCommandRingBufferByteLength(capacity: number): number {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n return (\n SONARE_ENGINE_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT +\n clampedCapacity * SONARE_ENGINE_COMMAND_RECORD_BYTES\n );\n}\n\nexport function sonareEngineTelemetryRingBufferByteLength(capacity: number): number {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n return (\n SONARE_ENGINE_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT +\n clampedCapacity * SONARE_ENGINE_TELEMETRY_RECORD_BYTES\n );\n}\n\nexport function sonareClipPageRequestRingBufferByteLength(capacity: number): number {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n return (\n SONARE_CLIP_PAGE_REQUEST_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT +\n clampedCapacity * SONARE_CLIP_PAGE_REQUEST_RING_RECORD_UINT32S * Uint32Array.BYTES_PER_ELEMENT\n );\n}\n\nexport function sonareExternalMidiRingBufferByteLength(capacity: number): number {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n return (\n SONARE_EXTERNAL_MIDI_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT +\n clampedCapacity * SONARE_EXTERNAL_MIDI_RING_RECORD_UINT32S * Uint32Array.BYTES_PER_ELEMENT\n );\n}\n\nexport function externalMidiRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n fallbackCapacity?: number,\n): SharedExternalMidiRingWriter {\n const headerBytes = SONARE_EXTERNAL_MIDI_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT;\n const header = new Int32Array(sharedBuffer, 0, SONARE_EXTERNAL_MIDI_RING_HEADER_INTS);\n const existingCapacity = Atomics.load(header, 2);\n const capacity = Math.max(1, Math.floor(existingCapacity || fallbackCapacity || 1));\n if (sharedBuffer.byteLength < sonareExternalMidiRingBufferByteLength(capacity)) {\n throw new Error('externalMidiSharedBuffer is too small for the requested ring capacity.');\n }\n Atomics.store(header, 2, capacity);\n Atomics.store(header, 3, SONARE_EXTERNAL_MIDI_RING_RECORD_UINT32S);\n return {\n header,\n records: new Uint32Array(\n sharedBuffer,\n headerBytes,\n capacity * SONARE_EXTERNAL_MIDI_RING_RECORD_UINT32S,\n ),\n capacity,\n };\n}\n\nexport function createSonareExternalMidiRingBuffer(capacity = 256): SonareExternalMidiRingBuffer {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const sharedBuffer = new SharedArrayBuffer(\n sonareExternalMidiRingBufferByteLength(clampedCapacity),\n );\n const ring = externalMidiRingFromSharedBuffer(sharedBuffer, clampedCapacity);\n Atomics.store(ring.header, 0, 0);\n Atomics.store(ring.header, 1, 0);\n Atomics.store(ring.header, 4, 0);\n return { sharedBuffer, header: ring.header, records: ring.records, capacity: ring.capacity };\n}\n\n/** Write one lowered MIDI-1 event without allocations from the audio worklet. */\nexport function pushSonareExternalMidiRingBuffer(\n ring: SharedExternalMidiRingWriter,\n destinationId: number,\n renderFrame: number,\n byteWord: number,\n byteCount: number,\n): boolean {\n // Emscripten can expose an int64 render-frame scalar as bigint when the\n // host enables WASM_BIGINT. Normalize at this fixed-record boundary.\n const destination = Number(destinationId);\n const frame = Number(renderFrame);\n const packedBytes = Number(byteWord);\n const count = Number(byteCount);\n if (\n !Number.isSafeInteger(destination) ||\n !Number.isSafeInteger(frame) ||\n frame < 0 ||\n !Number.isSafeInteger(packedBytes) ||\n packedBytes < 0 ||\n packedBytes > 0xff_ffff ||\n !Number.isSafeInteger(count) ||\n count < 1 ||\n count > 3\n ) {\n Atomics.add(ring.header, 4, 1);\n return false;\n }\n const writeIndex = Atomics.load(ring.header, 0);\n const readIndex = Atomics.load(ring.header, 1);\n if (writeIndex - readIndex >= ring.capacity) {\n Atomics.add(ring.header, 4, 1);\n return false;\n }\n const offset = (writeIndex % ring.capacity) * SONARE_EXTERNAL_MIDI_RING_RECORD_UINT32S;\n Atomics.store(ring.records, offset, destination);\n Atomics.store(ring.records, offset + 1, frame);\n Atomics.store(ring.records, offset + 2, packedBytes);\n Atomics.store(ring.records, offset + 3, count);\n Atomics.store(ring.header, 0, writeIndex + 1);\n return true;\n}\n\n/** Main-thread drain. It is intentionally the only place MIDI byte arrays are built. */\nexport function readSonareExternalMidiRingBuffer(\n ring: SonareExternalMidiRingBuffer,\n): SonareExternalMidiRingReadResult {\n const readIndex = Atomics.load(ring.header, 1);\n const writeIndex = Atomics.load(ring.header, 0);\n const events: SonareExternalMidiRingEvent[] = [];\n for (let index = readIndex; index < writeIndex; index++) {\n const offset = (index % ring.capacity) * SONARE_EXTERNAL_MIDI_RING_RECORD_UINT32S;\n events.push({\n destinationId: Atomics.load(ring.records, offset) >>> 0,\n renderFrame: Atomics.load(ring.records, offset + 1) >>> 0,\n byteWord: Atomics.load(ring.records, offset + 2) >>> 0,\n byteCount: Atomics.load(ring.records, offset + 3) >>> 0,\n });\n }\n Atomics.store(ring.header, 1, writeIndex);\n return { events, dropped: Atomics.load(ring.header, 4) >>> 0 };\n}\n\nexport function createSonareClipPageRequestRingBuffer(\n capacity = 128,\n): SonareClipPageRequestRingBuffer {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const sharedBuffer = new SharedArrayBuffer(\n sonareClipPageRequestRingBufferByteLength(clampedCapacity),\n );\n const ring = clipPageRequestRingFromSharedBuffer(sharedBuffer, clampedCapacity);\n Atomics.store(ring.header, 0, 0);\n Atomics.store(ring.header, 1, 0);\n Atomics.store(ring.header, 2, ring.capacity);\n Atomics.store(ring.header, 3, SONARE_CLIP_PAGE_REQUEST_RING_RECORD_UINT32S);\n Atomics.store(ring.header, 4, 0);\n return { sharedBuffer, header: ring.header, records: ring.records, capacity: ring.capacity };\n}\n\n/**\n * Writes one request without allocating. Invalid uint32 coordinates and a full\n * ring are counted as drops so the main thread can surface a bounded-loss\n * diagnostic without receiving a worklet postMessage.\n */\nexport function pushSonareClipPageRequestRingBuffer(\n ring: SharedClipPageRequestRingWriter,\n clipId: number,\n pageIndex: number,\n): boolean {\n if (\n !Number.isSafeInteger(clipId) ||\n clipId < 0 ||\n clipId > 0xffff_ffff ||\n !Number.isSafeInteger(pageIndex) ||\n pageIndex < 0 ||\n pageIndex > 0xffff_ffff\n ) {\n Atomics.add(ring.header, 4, 1);\n return false;\n }\n const writeIndex = Atomics.load(ring.header, 0);\n const readIndex = Atomics.load(ring.header, 1);\n if (writeIndex - readIndex >= ring.capacity) {\n Atomics.add(ring.header, 4, 1);\n return false;\n }\n const offset = (writeIndex % ring.capacity) * SONARE_CLIP_PAGE_REQUEST_RING_RECORD_UINT32S;\n Atomics.store(ring.records, offset, clipId);\n Atomics.store(ring.records, offset + 1, pageIndex);\n // Publish only after both scalar fields have been written.\n Atomics.store(ring.header, 0, writeIndex + 1);\n return true;\n}\n\n/** Drains the SPSC request ring on the main thread. Object creation is here, never in process(). */\nexport function readSonareClipPageRequestRingBuffer(\n ring: SonareClipPageRequestRingBuffer,\n): SonareClipPageRequestRingReadResult {\n const readIndex = Atomics.load(ring.header, 1);\n const writeIndex = Atomics.load(ring.header, 0);\n const requests: SonareClipPageRequest[] = [];\n for (let index = readIndex; index < writeIndex; index++) {\n const offset = (index % ring.capacity) * SONARE_CLIP_PAGE_REQUEST_RING_RECORD_UINT32S;\n requests.push({\n clipId: Atomics.load(ring.records, offset),\n pageIndex: Atomics.load(ring.records, offset + 1),\n });\n }\n Atomics.store(ring.header, 1, writeIndex);\n return { requests, dropped: Atomics.load(ring.header, 4) >>> 0 };\n}\n\nexport function createSonareEngineCommandRingBuffer(capacity = 128): SonareEngineCommandRingBuffer {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const sharedBuffer = new SharedArrayBuffer(\n sonareEngineCommandRingBufferByteLength(clampedCapacity),\n );\n const ring = engineRingFromSharedBuffer(\n sharedBuffer,\n SONARE_ENGINE_COMMAND_RECORD_BYTES,\n clampedCapacity,\n );\n return { sharedBuffer, header: ring.header, view: ring.view, capacity: ring.capacity };\n}\n\nexport function createSonareEngineTelemetryRingBuffer(\n capacity = 128,\n): SonareEngineTelemetryRingBuffer {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const sharedBuffer = new SharedArrayBuffer(\n sonareEngineTelemetryRingBufferByteLength(clampedCapacity),\n );\n const ring = engineRingFromSharedBuffer(\n sharedBuffer,\n SONARE_ENGINE_TELEMETRY_RECORD_BYTES,\n clampedCapacity,\n );\n return { sharedBuffer, header: ring.header, view: ring.view, capacity: ring.capacity };\n}\n\nexport function pushSonareEngineCommandRingBuffer(\n ring: SonareEngineCommandRingBuffer,\n command: SonareEngineCommandRecord,\n): boolean {\n const writeIndex = Atomics.load(ring.header, 0);\n const readIndex = Atomics.load(ring.header, 1);\n if (writeIndex - readIndex >= ring.capacity) {\n Atomics.add(ring.header, 4, 1);\n return false;\n }\n writeEngineCommandRecord(\n ring.view,\n recordOffset(writeIndex, ring.capacity, SONARE_ENGINE_COMMAND_RECORD_BYTES),\n command,\n );\n Atomics.store(ring.header, 0, writeIndex + 1);\n return true;\n}\n\nexport function popSonareEngineCommandRingBuffer(\n ring: SonareEngineCommandRingBuffer,\n): SonareEngineCommandRecord | null {\n const readIndex = Atomics.load(ring.header, 1);\n const writeIndex = Atomics.load(ring.header, 0);\n if (readIndex >= writeIndex) {\n return null;\n }\n const command = readEngineCommandRecord(\n ring.view,\n recordOffset(readIndex, ring.capacity, SONARE_ENGINE_COMMAND_RECORD_BYTES),\n );\n Atomics.store(ring.header, 1, readIndex + 1);\n return command;\n}\n\nexport function writeSonareEngineTelemetryRingBuffer(\n ring: SonareEngineTelemetryRingBuffer,\n telemetry: SonareEngineTelemetryRecord,\n): void {\n const writeIndex = Atomics.load(ring.header, 0);\n writeEngineTelemetryRecord(\n ring.view,\n recordOffset(writeIndex, ring.capacity, SONARE_ENGINE_TELEMETRY_RECORD_BYTES),\n telemetry,\n );\n Atomics.store(ring.header, 0, writeIndex + 1);\n if (writeIndex + 1 > ring.capacity) {\n Atomics.store(ring.header, 4, writeIndex + 1 - ring.capacity);\n }\n}\n\nexport function readSonareEngineTelemetryRingBuffer(\n ring: SonareEngineTelemetryRingBuffer,\n readIndex = 0,\n): SonareEngineTelemetryRingReadResult {\n const writeIndex = Atomics.load(ring.header, 0);\n const nextReadIndex = Math.max(0, Math.min(readIndex, writeIndex));\n const firstReadable = Math.max(nextReadIndex, writeIndex - ring.capacity);\n const telemetry: SonareEngineTelemetryRecord[] = [];\n for (let index = firstReadable; index < writeIndex; index++) {\n telemetry.push(\n readEngineTelemetryRecord(\n ring.view,\n recordOffset(index, ring.capacity, SONARE_ENGINE_TELEMETRY_RECORD_BYTES),\n ),\n );\n }\n return { nextReadIndex: writeIndex, telemetry };\n}\n\nexport function meterRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n fallbackCapacity?: number,\n): SharedMeterRingWriter {\n const headerBytes = SONARE_METER_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT;\n const header = new Int32Array(sharedBuffer, 0, SONARE_METER_RING_HEADER_INTS);\n const existingCapacity = Atomics.load(header, 1);\n const capacity = Math.max(1, Math.floor(existingCapacity || fallbackCapacity || 1));\n const minBytes = sonareMeterRingBufferByteLength(capacity);\n if (sharedBuffer.byteLength < minBytes) {\n throw new Error('meterSharedBuffer is too small for the requested ring capacity.');\n }\n Atomics.store(header, 1, capacity);\n Atomics.store(header, 2, SONARE_METER_RING_RECORD_FLOATS);\n return {\n header,\n records: new Float32Array(\n sharedBuffer,\n headerBytes,\n capacity * SONARE_METER_RING_RECORD_FLOATS,\n ),\n capacity,\n };\n}\n\nexport function spectrumRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n fallbackCapacity?: number,\n fallbackBands?: number,\n): SharedSpectrumRingWriter {\n const headerBytes = SONARE_SPECTRUM_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT;\n const header = new Int32Array(sharedBuffer, 0, SONARE_SPECTRUM_RING_HEADER_INTS);\n const existingCapacity = Atomics.load(header, 1);\n const existingBands = Atomics.load(header, 3);\n const capacity = Math.max(1, Math.floor(existingCapacity || fallbackCapacity || 1));\n const bands = Math.max(1, Math.floor(existingBands || fallbackBands || 16));\n const recordFloats = 3 + bands;\n const minBytes = sonareSpectrumRingBufferByteLength(capacity, bands);\n if (sharedBuffer.byteLength < minBytes) {\n throw new Error('spectrumSharedBuffer is too small for the requested ring capacity.');\n }\n Atomics.store(header, 1, capacity);\n Atomics.store(header, 2, recordFloats);\n Atomics.store(header, 3, bands);\n return {\n header,\n records: new Float32Array(sharedBuffer, headerBytes, capacity * recordFloats),\n capacity,\n bands,\n recordFloats,\n };\n}\n\nexport function engineRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n recordBytes: number,\n fallbackCapacity?: number,\n): { header: Int32Array; view: DataView; capacity: number } {\n const headerBytes = SONARE_ENGINE_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT;\n const header = new Int32Array(sharedBuffer, 0, SONARE_ENGINE_RING_HEADER_INTS);\n const existingCapacity = Atomics.load(header, 2);\n const capacity = Math.max(1, Math.floor(existingCapacity || fallbackCapacity || 1));\n const minBytes = headerBytes + capacity * recordBytes;\n if (sharedBuffer.byteLength < minBytes) {\n throw new Error('engine SharedArrayBuffer is too small for the requested ring capacity.');\n }\n Atomics.store(header, 2, capacity);\n Atomics.store(header, 3, recordBytes);\n return {\n header,\n view: new DataView(sharedBuffer, headerBytes, capacity * recordBytes),\n capacity,\n };\n}\n\nexport function clipPageRequestRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n fallbackCapacity?: number,\n): SharedClipPageRequestRingWriter {\n const headerBytes = SONARE_CLIP_PAGE_REQUEST_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT;\n const header = new Int32Array(sharedBuffer, 0, SONARE_CLIP_PAGE_REQUEST_RING_HEADER_INTS);\n const existingCapacity = Atomics.load(header, 2);\n const capacity = Math.max(1, Math.floor(existingCapacity || fallbackCapacity || 1));\n const minBytes = sonareClipPageRequestRingBufferByteLength(capacity);\n if (sharedBuffer.byteLength < minBytes) {\n throw new Error('clipPageRequestSharedBuffer is too small for the requested ring capacity.');\n }\n Atomics.store(header, 2, capacity);\n Atomics.store(header, 3, SONARE_CLIP_PAGE_REQUEST_RING_RECORD_UINT32S);\n return {\n header,\n records: new Uint32Array(\n sharedBuffer,\n headerBytes,\n capacity * SONARE_CLIP_PAGE_REQUEST_RING_RECORD_UINT32S,\n ),\n capacity,\n };\n}\n\nfunction recordOffset(index: number, capacity: number, recordBytes: number): number {\n return (index % capacity) * recordBytes;\n}\n\nfunction toSafeInteger(value: number | bigint | undefined, fallback: number): number {\n const resolved = typeof value === 'bigint' ? Number(value) : value;\n if (resolved === undefined) {\n return fallback;\n }\n if (!Number.isSafeInteger(resolved)) {\n throw new RangeError('64-bit ring values must be safe integers');\n }\n return resolved;\n}\n\n/** Store a signed 64-bit safe integer as two 32-bit words without BigInt. */\nexport function writeInt64Words(view: DataView, offset: number, value: number): void {\n const integer = toSafeInteger(value, 0);\n view.setUint32(offset, integer >>> 0, true);\n view.setInt32(offset + 4, Math.floor(integer / 0x100000000), true);\n}\n\n/** Reconstruct a signed 64-bit safe integer stored by {@link writeInt64Words}. */\nexport function readInt64Words(view: DataView, offset: number): number {\n return view.getInt32(offset + 4, true) * 0x100000000 + view.getUint32(offset, true);\n}\n\nfunction writeEngineCommandRecord(\n view: DataView,\n offset: number,\n command: SonareEngineCommandRecord,\n): void {\n view.setUint32(offset, command.type, true);\n view.setUint32(offset + 4, command.targetId ?? 0, true);\n writeInt64Words(view, offset + 8, toSafeInteger(command.sampleTime, -1));\n // argFloat occupies a full 8-byte Float64 slot (replacing the old Float32 +\n // 4-byte pad) so PPQ scalars carried here keep full double precision over the\n // SAB transport, matching the engine's double-precision seek/loop contract.\n view.setFloat64(offset + 16, command.argFloat ?? 0, true);\n writeInt64Words(view, offset + 24, toSafeInteger(command.argInt, 0));\n}\n\nfunction readEngineCommandRecord(view: DataView, offset: number): SonareEngineCommandRecord {\n return {\n type: view.getUint32(offset, true),\n targetId: view.getUint32(offset + 4, true),\n sampleTime: readInt64Words(view, offset + 8),\n argFloat: view.getFloat64(offset + 16, true),\n argInt: readInt64Words(view, offset + 24),\n };\n}\n\nfunction writeEngineTelemetryRecord(\n view: DataView,\n offset: number,\n telemetry: SonareEngineTelemetryRecord,\n): void {\n view.setUint32(offset, telemetry.type, true);\n view.setUint32(offset + 4, telemetry.error, true);\n writeInt64Words(view, offset + 8, telemetry.renderFrame);\n writeInt64Words(view, offset + 16, telemetry.timelineSample);\n writeInt64Words(view, offset + 24, telemetry.audibleTimelineSample);\n view.setInt32(offset + 32, telemetry.graphLatencySamplesQ8, true);\n view.setUint32(offset + 36, telemetry.value, true);\n view.setUint32(offset + 40, 0, true);\n view.setUint32(offset + 44, 0, true);\n}\n\nfunction readEngineTelemetryRecord(view: DataView, offset: number): SonareEngineTelemetryRecord {\n return {\n type: view.getUint32(offset, true),\n error: view.getUint32(offset + 4, true),\n renderFrame: readInt64Words(view, offset + 8),\n timelineSample: readInt64Words(view, offset + 16),\n audibleTimelineSample: readInt64Words(view, offset + 24),\n graphLatencySamplesQ8: view.getInt32(offset + 32, true),\n value: view.getUint32(offset + 36, true),\n };\n}\n\nexport function telemetryFromEngine(telemetry: EngineTelemetry): SonareEngineTelemetryRecord {\n return {\n type: telemetry.type,\n error: telemetry.error,\n renderFrame: telemetry.renderFrame,\n timelineSample: telemetry.timelineSample,\n audibleTimelineSample: telemetry.audibleTimelineSample,\n graphLatencySamplesQ8: telemetry.graphLatencySamplesQ8,\n value: telemetry.value,\n };\n}\n\nexport function meterFromEngine(meter: EngineMeterTelemetry): SonareWorkletMeterSnapshot {\n return {\n type: 'meter',\n targetId: meter.targetId,\n frame: meter.renderFrame,\n peakDbL: meter.peakDbL,\n peakDbR: meter.peakDbR,\n rmsDbL: meter.rmsDbL,\n rmsDbR: meter.rmsDbR,\n correlation: meter.correlation,\n truePeakDbL: meter.truePeakDbL,\n truePeakDbR: meter.truePeakDbR,\n momentaryLufs: meter.momentaryLufs,\n shortTermLufs: meter.shortTermLufs,\n integratedLufs: meter.integratedLufs,\n gainReductionDb: meter.gainReductionDb,\n };\n}\n\nexport function magnitudeToDb(value: number): number {\n return value > 1.0e-12 ? 20 * Math.log10(value) : -120;\n}\n","import type { EngineCaptureStatus, RealtimeEngine } from '../index';\nimport type { SonareRealtimeEngineNode } from './engine-node';\nimport { buildCaptureConfig, type CaptureOptions } from './engine-offline';\nimport type { SonareEngineSyncCaptureMessage, SonareEngineSyncMessage } from './messages';\nimport { SonareEngineCommandType } from './protocol';\n\ntype CaptureConfig = Omit<SonareEngineSyncCaptureMessage, 'type'>;\n\n/**\n * Collaborator surface the capture/record/punch setters need from the owning\n * {@link SonareEngine}: the offline engine they mirror into, the realtime node\n * they command and query, the channel count, the out-of-band sync poster, the\n * capture-config accessor, and the target-id resolver.\n */\nexport interface EngineCaptureContext {\n readonly offlineEngine: RealtimeEngine;\n readonly realtimeNode: SonareRealtimeEngineNode;\n sendCommand(command: {\n type: SonareEngineCommandType;\n targetId?: number;\n sampleTime?: number;\n argFloat?: number;\n argInt?: number;\n }): boolean;\n readonly offlineChannelCount: number;\n postSync(message: SonareEngineSyncMessage): void;\n getCaptureConfig(): CaptureConfig | undefined;\n setCaptureConfig(config: CaptureConfig): void;\n}\n\nexport function configureCapture(ctx: EngineCaptureContext, options: CaptureOptions): void {\n const config = buildCaptureConfig(options, ctx.offlineChannelCount);\n ctx.offlineEngine.setCaptureBuffer(config.channels, config.bufferFrames);\n ctx.offlineEngine.setCaptureSource(config.source);\n ctx.offlineEngine.setRecordOffsetSamples(config.recordOffsetSamples);\n ctx.offlineEngine.setInputMonitor(config.inputMonitor.enabled, config.inputMonitor.gain);\n ctx.setCaptureConfig(config);\n ctx.postSync({ type: 'syncCapture', ...config });\n}\n\nexport function armRecord(\n ctx: EngineCaptureContext,\n trackId: string | number,\n enabled: boolean,\n): boolean {\n if (trackId !== 0) {\n throw new RangeError('Capture is global; armRecord only accepts trackId 0');\n }\n if (enabled && !ctx.getCaptureConfig()) {\n throw new Error('Capture buffer is not configured');\n }\n ctx.offlineEngine.armCapture(enabled);\n return ctx.sendCommand({\n type: SonareEngineCommandType.ArmRecord,\n targetId: 0,\n sampleTime: -1,\n argInt: enabled ? 1 : 0,\n });\n}\n\nexport function punch(ctx: EngineCaptureContext, inPpq: number, outPpq: number): boolean {\n const inSample = ctx.offlineEngine.sampleAtPpq(inPpq);\n const outSample = ctx.offlineEngine.sampleAtPpq(outPpq);\n ctx.offlineEngine.setCapturePunch(inSample, outSample, true);\n // Carry BOTH endpoints as already-converted SAMPLES so the realtime engine\n // agrees with the offline engine. The previous code sent the raw PPQ out\n // point and let the consumer multiply by sampleRate (treating PPQ as\n // seconds), which ignored tempo and produced a punch-out ~2x too large at\n // 120 BPM. argInt = in sample, argFloat = out sample (full-precision double).\n return ctx.sendCommand({\n type: SonareEngineCommandType.Punch,\n sampleTime: -1,\n argInt: inSample,\n argFloat: outSample,\n });\n}\n\nexport function captureStatus(ctx: EngineCaptureContext): Promise<EngineCaptureStatus> {\n return ctx.realtimeNode.requestCaptureStatus();\n}\n\nexport function capturedAudio(ctx: EngineCaptureContext): Promise<Float32Array[]> {\n return ctx.realtimeNode.requestCapturedAudio();\n}\n\nexport async function resetCapture(ctx: EngineCaptureContext): Promise<void> {\n ctx.offlineEngine.resetCapture();\n await ctx.realtimeNode.requestCaptureReset();\n}\n","import type { EngineClip, EngineMidiClipSchedule, RealtimeEngine } from '../index';\nimport type { ClipPageProvider } from '../realtime_engine';\nimport type { SonareEngineSyncMessage } from './messages';\n\n/**\n * Collaborator surface the audio/MIDI clip scheduling helpers need from the\n * owning {@link SonareEngine}: the clip stores they mutate, the offline engine\n * they mirror into, the sync poster, and the clip-id allocator / lane resolvers.\n */\nexport interface EngineClipContext {\n readonly offlineEngine: RealtimeEngine;\n readonly clips: Map<number, EngineClip>;\n readonly midiClips: Map<number, EngineMidiClipSchedule>;\n allocateClipId(): number;\n postSync(message: SonareEngineSyncMessage, transfer?: Transferable[]): void;\n resolveTargetId(target: string | number): number;\n ensureTrackLane(target: string | number): number;\n /** Commits a provider already primed through the worklet's OPFS pull bridge. */\n commitWorkletClipPageProvider(clip: EngineClip): boolean;\n}\n\n// Keep control-message work bounded even for long tempo-synced clips. The\n// worklet creates a native page provider, receives these transferable PCM\n// chunks, and only schedules the clip after all pages arrive.\nconst PREBAKED_CLIP_PAGE_THRESHOLD = 16_384;\nconst PREBAKED_CLIP_PAGE_FRAMES = 4_096;\n\nexport function addClip(\n ctx: EngineClipContext,\n trackId: string | number,\n buffer: Float32Array[] | ClipPageProvider,\n startPpq: number,\n opts: Partial<Omit<EngineClip, 'channels' | 'pageProvider' | 'startPpq'>> = {},\n): number {\n const id = opts.id ?? ctx.allocateClipId();\n const clip: EngineClip = {\n ...opts,\n id,\n ...(Array.isArray(buffer) ? { channels: buffer } : { pageProvider: buffer }),\n startPpq,\n trackId: ctx.resolveTargetId(trackId),\n };\n ctx.ensureTrackLane(trackId);\n ctx.clips.set(id, clip);\n syncClipsDelta(ctx, [clip], []);\n return id;\n}\n\nexport function removeClip(ctx: EngineClipContext, clipId: number): void {\n ctx.clips.delete(clipId);\n syncClipsDelta(ctx, [], [clipId]);\n}\n\nexport function setMidiClips(\n ctx: EngineClipContext,\n clips: readonly EngineMidiClipSchedule[],\n): void {\n ctx.midiClips.clear();\n for (const clip of clips) {\n const id = clip.id ?? ctx.allocateClipId();\n ctx.midiClips.set(id, { ...clip, id, events: clip.events.map((event) => ({ ...event })) });\n }\n syncMidiClips(ctx);\n}\n\nfunction syncClipsDelta(ctx: EngineClipContext, upserts: EngineClip[], removeIds: number[]): void {\n const clips = Array.from(ctx.clips.values());\n ctx.offlineEngine.setClips(clips);\n const preparedById = new Map<number, EngineClip>();\n for (const clip of clips) {\n if (clip.id === undefined) {\n continue;\n }\n const bakedChannels = ctx.offlineEngine.prebakedClipChannels(clip.id);\n preparedById.set(\n clip.id,\n bakedChannels === null\n ? clip\n : {\n ...clip,\n channels: bakedChannels,\n clipOffsetSamples: 0,\n lengthSamples: bakedChannels[0]?.length ?? 0,\n loop: false,\n warpMode: 'off',\n warpAnchors: undefined,\n },\n );\n }\n const inlineUpserts: EngineClip[] = [];\n for (const clip of upserts) {\n const prepared = clip.id === undefined ? clip : (preparedById.get(clip.id) ?? clip);\n const channels = prepared.channels;\n if (!channels && prepared.pageProvider !== undefined) {\n if (ctx.commitWorkletClipPageProvider(prepared)) {\n continue;\n }\n throw new Error('A pageProvider on SonareEngine must be created by attachOpfsClipStream().');\n }\n if (\n prepared.id === undefined ||\n prepared.warpMode !== 'off' ||\n !channels ||\n channels.length === 0 ||\n channels[0].length <= PREBAKED_CLIP_PAGE_THRESHOLD\n ) {\n inlineUpserts.push(prepared);\n continue;\n }\n const numSamples = channels[0].length;\n ctx.postSync({\n type: 'syncClipPageProvider',\n clipId: prepared.id,\n clip: { ...prepared, channels: undefined, pageProvider: undefined },\n numChannels: channels.length,\n numSamples,\n pageFrames: PREBAKED_CLIP_PAGE_FRAMES,\n });\n for (\n let start = 0, pageIndex = 0;\n start < numSamples;\n start += PREBAKED_CLIP_PAGE_FRAMES, pageIndex++\n ) {\n const page = channels.map((channel) =>\n channel.slice(start, start + PREBAKED_CLIP_PAGE_FRAMES),\n );\n ctx.postSync(\n { type: 'syncClipPage', clipId: prepared.id, pageIndex, channels: page },\n page.map((channel) => channel.buffer as Transferable),\n );\n }\n ctx.postSync({ type: 'syncClipPageCommit', clipId: prepared.id });\n }\n ctx.postSync({\n type: 'syncClipsDelta',\n upserts: inlineUpserts,\n removeIds,\n });\n}\n\nfunction syncMidiClips(ctx: EngineClipContext): void {\n const clips = Array.from(ctx.midiClips.values());\n ctx.offlineEngine.setMidiClips(clips);\n ctx.postSync({ type: 'syncMidiClips', clips });\n}\n","import type { EngineMarker, RealtimeEngine } from '../index';\nimport { resolveMarkerSet } from './engine-offline';\nimport type { SonareEngineSyncMessage } from './messages';\nimport { type SonareEngineCommandRecord, SonareEngineCommandType } from './protocol';\n\n/**\n * Collaborator surface the marker helpers need from the owning\n * {@link SonareEngine}: the marker store and id counter, the offline engine they\n * mirror into, the sync poster, the realtime command sender, and the loop setter.\n */\nexport interface EngineMarkerContext {\n readonly offlineEngine: RealtimeEngine;\n readonly markers: Map<number, EngineMarker>;\n getNextMarkerId(): number;\n setNextMarkerId(value: number): void;\n postSync(message: SonareEngineSyncMessage): void;\n sendCommand(command: SonareEngineCommandRecord): boolean;\n setLoop(startPpq: number, endPpq: number, enabled: boolean): boolean;\n}\n\nexport function addMarker(ctx: EngineMarkerContext, ppq: number, name = ''): number {\n const id = ctx.getNextMarkerId();\n ctx.setNextMarkerId(id + 1);\n ctx.markers.set(id, { id, ppq, name });\n syncMarkers(ctx);\n return id;\n}\n\n/**\n * Replaces the whole marker set in one call.\n *\n * Entries without an `id` are assigned fresh ids; entries carrying an `id`\n * keep it (ids must be positive and unique within the list). Returns the\n * resolved markers in the order given, so a caller can map its own marker\n * identities to the engine ids used by `seekMarker`/`setLoopFromMarkers`.\n *\n * @param markers The full marker list (an empty list clears all markers).\n * @returns The markers with their resolved engine ids.\n */\nexport function setMarkers(\n ctx: EngineMarkerContext,\n markers: ReadonlyArray<{ ppq: number; name?: string; id?: number }>,\n): EngineMarker[] {\n const { resolved, nextMarkerId } = resolveMarkerSet(markers, ctx.getNextMarkerId());\n ctx.setNextMarkerId(nextMarkerId);\n ctx.markers.clear();\n for (const marker of resolved) {\n ctx.markers.set(marker.id, marker);\n }\n syncMarkers(ctx);\n return resolved.map((marker) => ({ ...marker }));\n}\n\nexport function markerCount(ctx: EngineMarkerContext): number {\n return ctx.offlineEngine.markerCount();\n}\n\nexport function markerByIndex(ctx: EngineMarkerContext, index: number): EngineMarker {\n return ctx.offlineEngine.markerByIndex(index);\n}\n\nexport function marker(ctx: EngineMarkerContext, markerId: number): EngineMarker {\n return ctx.offlineEngine.marker(markerId);\n}\n\nexport function seekMarker(ctx: EngineMarkerContext, markerId: number): boolean {\n ctx.offlineEngine.seekMarker(markerId);\n // Forward to the live worklet engine. Its marker set is kept in sync via the\n // 'syncMarkers' message (see syncMarkers), so a queued kSeekMarker resolves\n // the marker id to its frame on the audio thread.\n return ctx.sendCommand({\n type: SonareEngineCommandType.SeekMarker,\n targetId: markerId,\n sampleTime: -1,\n });\n}\n\nexport function setLoopFromMarkers(\n ctx: EngineMarkerContext,\n startMarkerId: number,\n endMarkerId: number,\n): boolean {\n ctx.offlineEngine.setLoopFromMarkers(startMarkerId, endMarkerId);\n const start = ctx.offlineEngine.marker(startMarkerId);\n const end = ctx.offlineEngine.marker(endMarkerId);\n return ctx.setLoop(start.ppq, end.ppq, true);\n}\n\nfunction syncMarkers(ctx: EngineMarkerContext): void {\n const markers = Array.from(ctx.markers.values()).sort((a, b) => a.ppq - b.ppq);\n ctx.offlineEngine.setMarkers(markers);\n ctx.postSync({ type: 'syncMarkers', markers });\n}\n","import type { EngineBus, EngineTrackLane, EngineTrackSend, RealtimeEngine } from '../index';\nimport { normalizeTrackLanes } from './engine-offline';\nimport { buildMixerLanes } from './engine-sync';\nimport type { SonareEngineSyncMessage } from './messages';\nimport { ENGINE_MIXER_PARAM_FADER_DB, engineMixerBusTarget } from './protocol';\n\n/**\n * Collaborator surface the mixer/routing setters need from the owning\n * {@link SonareEngine}: the offline engine they mirror writes into, the mutable\n * routing stores (held by reference), the out-of-band sync poster, and the\n * lane/bus declaration and mixer-sync helpers.\n */\nexport interface EngineMixerContext {\n readonly offlineEngine: RealtimeEngine;\n readonly trackLaneIds: number[];\n readonly trackSends: Map<number, EngineTrackSend[]>;\n readonly trackOutputBus: Map<number, number>;\n readonly laneSidechains: Map<\n string,\n { trackId: number; insertIndex: number; sourceTrackId: number }\n >;\n readonly buses: EngineBus[];\n readonly trackStripJson: Map<number, string>;\n readonly busStripJson: Map<number, string>;\n postSync(message: SonareEngineSyncMessage): void;\n ensureTrackLane(target: string | number): number;\n ensureBus(busId: number): number;\n mixerLanes(): EngineTrackLane[];\n syncMixer(): void;\n sendSmoothedParam(paramId: number, value: number): boolean;\n getMasterStripJson(): string | undefined;\n}\n\n/** Builds the engine's track-lane descriptors from the current routing stores. */\nexport function mixerLanes(ctx: EngineMixerContext): EngineTrackLane[] {\n return buildMixerLanes(ctx.trackLaneIds, ctx.trackSends, ctx.trackOutputBus);\n}\n\n/**\n * Mirrors the current mixer routing into the offline engine and posts the full\n * mixer-sync message (lanes, buses, strip JSON, sidechains) to the worklet.\n */\nexport function syncMixer(ctx: EngineMixerContext): void {\n const lanes = mixerLanes(ctx);\n const buses = ctx.buses.map((bus) => ({ ...bus }));\n ctx.offlineEngine.setTrackBuses(buses);\n if (lanes.length > 0) {\n ctx.offlineEngine.setTrackLanes(lanes);\n }\n const trackStrips = Array.from(ctx.trackStripJson, ([trackId, sceneJson]) => ({\n trackId,\n sceneJson,\n }));\n const busStrips = Array.from(ctx.busStripJson, ([busId, sceneJson]) => ({\n busId,\n sceneJson,\n }));\n ctx.postSync({\n type: 'syncMixer',\n lanes,\n buses,\n trackStrips,\n laneSidechains: Array.from(ctx.laneSidechains.values()),\n busStrips,\n masterStripJson: ctx.getMasterStripJson(),\n });\n}\n\n/**\n * Declares the mixer track lanes in an explicit order.\n *\n * Lane indices are append-only: once a track id occupies a lane, its index\n * stays fixed for the engine's lifetime. The given list must therefore start\n * with the already-declared lane ids in their current order and may only\n * append new track ids after them. Entries carrying `sends` replace that\n * track's send list; entries without `sends` leave existing sends untouched.\n *\n * @param lanes Track ids or lane descriptors in the desired lane order.\n */\nexport function setTrackLanes(\n ctx: EngineMixerContext,\n lanes: ReadonlyArray<number | EngineTrackLane>,\n): void {\n const { entries, ids } = normalizeTrackLanes(ctx.trackLaneIds, lanes);\n for (const entry of entries) {\n if (entry.sends) {\n ctx.trackSends.set(\n entry.trackId,\n entry.sends.map((send) => ({ ...send })),\n );\n }\n if (entry.outputBusId !== undefined) {\n if (entry.outputBusId === 0) {\n ctx.trackOutputBus.delete(entry.trackId);\n } else {\n ctx.trackOutputBus.set(entry.trackId, entry.outputBusId);\n }\n }\n }\n ctx.trackLaneIds.splice(0, ctx.trackLaneIds.length, ...ids);\n ctx.syncMixer();\n}\n\n/**\n * Routes a track lane's post-fader output into a declared bus instead of\n * the master mix (group/folder routing); busId 0 restores the master mix.\n */\nexport function setTrackOutputBus(\n ctx: EngineMixerContext,\n target: string | number,\n busId: number,\n): void {\n const laneIndex = ctx.ensureTrackLane(target);\n const trackId = ctx.trackLaneIds[laneIndex];\n if (busId === 0) {\n ctx.trackOutputBus.delete(trackId);\n } else {\n ctx.trackOutputBus.set(trackId, busId);\n }\n ctx.syncMixer();\n}\n\n/**\n * Keys one insert of a lane strip from another lane's post-strip pre-fader\n * audio (ducking/sidechainRouter inserts). sourceTarget null removes the\n * binding.\n */\nexport function setLaneSidechain(\n ctx: EngineMixerContext,\n target: string | number,\n insertIndex: number,\n sourceTarget: string | number | null,\n): void {\n const laneIndex = ctx.ensureTrackLane(target);\n const trackId = ctx.trackLaneIds[laneIndex];\n const key = `${trackId}:${insertIndex}`;\n let sourceTrackId = 0;\n if (sourceTarget !== null) {\n const sourceIndex = ctx.ensureTrackLane(sourceTarget);\n sourceTrackId = ctx.trackLaneIds[sourceIndex];\n }\n if (sourceTrackId === 0) {\n ctx.laneSidechains.delete(key);\n } else {\n ctx.laneSidechains.set(key, { trackId, insertIndex, sourceTrackId });\n }\n ctx.offlineEngine.setLaneSidechain(trackId, insertIndex, sourceTrackId);\n ctx.postSync({\n type: 'syncMixer',\n lanes: ctx.mixerLanes(),\n laneSidechains: [{ trackId, insertIndex, sourceTrackId }],\n });\n}\n\nexport function setSends(\n ctx: EngineMixerContext,\n target: string | number,\n sends: EngineTrackSend[],\n): void {\n const laneIndex = ctx.ensureTrackLane(target);\n const trackId = ctx.trackLaneIds[laneIndex];\n ctx.trackSends.set(\n trackId,\n sends.map((send) => ({ ...send })),\n );\n ctx.syncMixer();\n}\n\nexport function setTrackBuses(ctx: EngineMixerContext, buses: EngineBus[]): void {\n ctx.buses.splice(0, ctx.buses.length, ...buses.map((bus) => ({ ...bus })));\n ctx.syncMixer();\n}\n\nexport function setBusGain(ctx: EngineMixerContext, busId: number, db: number): boolean {\n const busIndex = ctx.ensureBus(busId);\n ctx.buses[busIndex] = { ...ctx.buses[busIndex], busId, gainDb: db };\n ctx.offlineEngine.setTrackBuses(ctx.buses);\n return ctx.sendSmoothedParam(engineMixerBusTarget(busIndex, ENGINE_MIXER_PARAM_FADER_DB), db);\n}\n\nexport function setBusStripJson(ctx: EngineMixerContext, busId: number, sceneJson: string): void {\n ctx.ensureBus(busId);\n ctx.offlineEngine.setBusStripJson(busId, sceneJson);\n ctx.busStripJson.set(busId, sceneJson);\n ctx.syncMixer();\n}\n","import type { EngineCaptureStatus } from '../index';\nimport type {\n SonareEngineCaptureRequestMessage,\n SonareEngineCaptureResponseMessageInternal,\n SonareEngineClipPageRequestMessage,\n SonareEngineSyncMessage,\n SonareEngineTransportRequestMessage,\n SonareEngineTransportResponseMessage,\n SonareRealtimeVoiceChangerMessage,\n SonareWorkletExternalMidiMessage,\n SonareWorkletMessage,\n} from './messages';\nimport {\n isRecord,\n type SonareEngineCommandRecord,\n type SonareEngineTelemetryRecord,\n type SonareWorkletMeterSnapshot,\n} from './protocol';\n\nexport function isWorkletMessage(value: unknown): value is SonareWorkletMessage {\n if (!isRecord(value) || typeof value.type !== 'string') {\n return false;\n }\n return (\n value.type === 'scheduleInsertAutomation' ||\n value.type === 'setMeterInterval' ||\n value.type === 'destroy'\n );\n}\n\nexport function isEngineCommandRecord(value: unknown): value is SonareEngineCommandRecord {\n return isRecord(value) && typeof value.type === 'number';\n}\n\nexport function isEngineSyncMessage(value: unknown): value is SonareEngineSyncMessage {\n if (!isRecord(value) || typeof value.type !== 'string') {\n return false;\n }\n return (\n value.type === 'syncClips' ||\n value.type === 'syncClipsDelta' ||\n value.type === 'syncClipPageProvider' ||\n value.type === 'syncClipPage' ||\n value.type === 'syncClipPageClear' ||\n value.type === 'syncClipPageCommit' ||\n value.type === 'syncClipPageDestroy' ||\n value.type === 'syncMidiClips' ||\n value.type === 'syncMarkers' ||\n value.type === 'syncMetronome' ||\n value.type === 'syncAutomation' ||\n value.type === 'syncTempo' ||\n value.type === 'syncMixer' ||\n value.type === 'syncCapture' ||\n value.type === 'syncTrackStripEqBand' ||\n value.type === 'syncMasterStripEqBand' ||\n value.type === 'syncTrackStripInsertBypassed' ||\n value.type === 'syncMasterStripInsertBypassed' ||\n value.type === 'syncTrackStripInsertParamByName' ||\n value.type === 'syncMasterStripInsertParamByName' ||\n value.type === 'syncBusStripInsertParamByName' ||\n value.type === 'syncTrackStripPan' ||\n value.type === 'syncTrackStripPanLaw' ||\n value.type === 'syncTrackStripPanMode' ||\n value.type === 'syncTrackStripDualPan' ||\n value.type === 'syncTrackStripChannelDelaySamples' ||\n value.type === 'syncBuiltinInstrument' ||\n value.type === 'syncSynthInstrument' ||\n value.type === 'syncSf2Instrument' ||\n value.type === 'syncLoadSoundFont' ||\n value.type === 'syncMidiFx' ||\n value.type === 'syncClearMidiFx' ||\n value.type === 'syncMidiNoteOn' ||\n value.type === 'syncMidiNoteOff' ||\n value.type === 'syncMidiCc' ||\n value.type === 'syncMidiUmp' ||\n value.type === 'syncMidiSysex' ||\n value.type === 'syncMidiPanic' ||\n value.type === 'syncMidiDestinationExternal' ||\n value.type === 'syncExternalMidiClock' ||\n value.type === 'destroy'\n );\n}\n\nexport function isEngineCaptureRequestMessage(\n value: unknown,\n): value is SonareEngineCaptureRequestMessage {\n return (\n isRecord(value) &&\n value.type === 'captureRequest' &&\n typeof value.requestId === 'number' &&\n (value.op === 'status' || value.op === 'read' || value.op === 'reset')\n );\n}\n\nfunction isCaptureStatus(value: unknown): value is EngineCaptureStatus {\n return (\n isRecord(value) &&\n typeof value.capturedFrames === 'number' &&\n Number.isSafeInteger(value.capturedFrames) &&\n value.capturedFrames >= 0 &&\n typeof value.overflowCount === 'number' &&\n Number.isSafeInteger(value.overflowCount) &&\n value.overflowCount >= 0 &&\n typeof value.armed === 'boolean' &&\n typeof value.punchEnabled === 'boolean' &&\n (value.source === 'input' || value.source === 'output') &&\n typeof value.recordOffsetSamples === 'number' &&\n Number.isSafeInteger(value.recordOffsetSamples)\n );\n}\n\nfunction isCaptureChannel(value: unknown): value is Float32Array {\n // Capture responses are transferred out of the worklet. A typed view onto\n // the WASM heap or a SharedArrayBuffer must not cross that boundary: the\n // former can be detached by memory growth and the latter cannot be listed\n // in a transfer list. `instanceof` also rejects boxed number arrays.\n return (\n value instanceof Float32Array &&\n typeof ArrayBuffer !== 'undefined' &&\n value.buffer instanceof ArrayBuffer\n );\n}\n\nfunction isCaptureChannels(value: unknown): value is Float32Array[] {\n return Array.isArray(value) && value.every((channel) => isCaptureChannel(channel));\n}\n\nfunction hasOwn(value: Record<string, unknown>, key: string): boolean {\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Object.hasOwn is newer than the ES2020 target.\n return Object.prototype.hasOwnProperty.call(value, key);\n}\n\n/** Return a request ID even when the response payload itself is malformed. */\nexport function engineCaptureResponseRequestId(value: unknown): number | undefined {\n if (\n !isRecord(value) ||\n value.type !== 'captureResponse' ||\n typeof value.requestId !== 'number' ||\n !Number.isSafeInteger(value.requestId)\n ) {\n return undefined;\n }\n return value.requestId;\n}\n\nexport function isEngineCaptureResponseMessage(\n value: unknown,\n): value is SonareEngineCaptureResponseMessageInternal {\n const requestId = engineCaptureResponseRequestId(value);\n if (requestId === undefined || !isRecord(value)) {\n return false;\n }\n if (value.ok === false) {\n return (\n typeof value.error === 'string' && !hasOwn(value, 'status') && !hasOwn(value, 'channels')\n );\n }\n if (value.ok !== true || hasOwn(value, 'error')) {\n return false;\n }\n const hasStatus = hasOwn(value, 'status');\n const hasChannels = hasOwn(value, 'channels');\n if (hasStatus && hasChannels) {\n return false;\n }\n if (hasStatus) {\n return isCaptureStatus(value.status);\n }\n if (hasChannels) {\n return isCaptureChannels(value.channels);\n }\n return true;\n}\n\n/**\n * Check that a strict success response belongs to the requested operation.\n * Failure responses are operation-independent and are therefore valid for\n * every pending request (the node rejects them after this check).\n */\nexport function isEngineCaptureResponseForOperation(\n response: SonareEngineCaptureResponseMessageInternal,\n op: SonareEngineCaptureRequestMessage['op'],\n): boolean {\n if (!response.ok) {\n return true;\n }\n switch (op) {\n case 'status':\n return 'status' in response;\n case 'read':\n return 'channels' in response;\n case 'reset':\n return !('status' in response) && !('channels' in response);\n }\n}\n\nexport function isEngineTransportRequestMessage(\n value: unknown,\n): value is SonareEngineTransportRequestMessage {\n return (\n isRecord(value) &&\n value.type === 'transportRequest' &&\n typeof value.requestId === 'number' &&\n value.op === 'state'\n );\n}\n\nexport function isEngineTransportResponseMessage(\n value: unknown,\n): value is SonareEngineTransportResponseMessage {\n return (\n isRecord(value) &&\n value.type === 'transportResponse' &&\n typeof value.requestId === 'number' &&\n typeof value.ok === 'boolean'\n );\n}\n\nexport function isRealtimeVoiceChangerMessage(\n value: unknown,\n): value is SonareRealtimeVoiceChangerMessage {\n if (!isRecord(value) || typeof value.type !== 'string') {\n return false;\n }\n return value.type === 'setConfig' || value.type === 'reset' || value.type === 'destroy';\n}\n\nexport function isEngineTelemetryRecord(value: unknown): value is SonareEngineTelemetryRecord {\n return (\n isRecord(value) &&\n typeof value.type === 'number' &&\n typeof value.error === 'number' &&\n typeof value.renderFrame === 'number' &&\n typeof value.timelineSample === 'number' &&\n typeof value.audibleTimelineSample === 'number' &&\n typeof value.graphLatencySamplesQ8 === 'number' &&\n typeof value.value === 'number'\n );\n}\n\nexport function isExternalMidiBatchMessage(\n value: unknown,\n): value is SonareWorkletExternalMidiMessage {\n return isRecord(value) && value.type === 'externalMidi' && Array.isArray(value.events);\n}\n\nexport function isClipPageRequestMessage(\n value: unknown,\n): value is SonareEngineClipPageRequestMessage {\n return (\n isRecord(value) &&\n value.type === 'clipPageRequest' &&\n Array.isArray(value.requests) &&\n value.requests.every(\n (request) =>\n isRecord(request) &&\n typeof request.clipId === 'number' &&\n typeof request.pageIndex === 'number',\n )\n );\n}\n\nexport function isMeterSnapshot(value: unknown): value is SonareWorkletMeterSnapshot {\n return (\n isRecord(value) &&\n value.type === 'meter' &&\n typeof value.frame === 'number' &&\n typeof value.peakDbL === 'number' &&\n typeof value.peakDbR === 'number' &&\n typeof value.rmsDbL === 'number' &&\n typeof value.rmsDbR === 'number' &&\n typeof value.correlation === 'number' &&\n (typeof value.targetId === 'number' || value.targetId === undefined)\n );\n}\n","import type { EngineCaptureStatus, EngineTransportState } from '../index';\nimport { engineCapabilities } from '../index';\nimport {\n engineCaptureResponseRequestId,\n isClipPageRequestMessage,\n isEngineCaptureResponseForOperation,\n isEngineCaptureResponseMessage,\n isEngineTelemetryRecord,\n isEngineTransportResponseMessage,\n isExternalMidiBatchMessage,\n isMeterSnapshot,\n} from './guards';\nimport type {\n SonareEngineCaptureRequestMessage,\n SonareEngineCaptureResponseMessageInternal,\n SonareEngineClipPageRequestMessage,\n SonareEngineSyncErrorMessage,\n SonareEngineTransportResponseMessage,\n SonareRealtimeEngineNodeCapabilities,\n SonareRealtimeEngineNodeOptions,\n SonareRealtimeEngineWorkletProcessorOptions,\n SonareWorkletExternalMidiEvent,\n} from './messages';\nimport {\n createSonareClipPageRequestRingBuffer,\n createSonareEngineCommandRingBuffer,\n createSonareEngineTelemetryRingBuffer,\n createSonareExternalMidiRingBuffer,\n createSonareMeterRingBuffer,\n createSonareScopeRingBuffer,\n isRecord,\n pushSonareEngineCommandRingBuffer,\n readSonareClipPageRequestRingBuffer,\n readSonareEngineTelemetryRingBuffer,\n readSonareExternalMidiRingBuffer,\n readSonareMeterRingBuffer,\n readSonareScopeRingBuffer,\n type SonareClipPageRequestRingBuffer,\n type SonareEngineCommandRecord,\n type SonareEngineCommandRingBuffer,\n SonareEngineCommandType,\n type SonareEngineTelemetryRecord,\n type SonareEngineTelemetryRingBuffer,\n type SonareExternalMidiRingBuffer,\n type SonareMeterRingBuffer,\n type SonareScopeRingBuffer,\n type SonareWorkletMeterSnapshot,\n type SonareWorkletScopeSnapshot,\n} from './protocol';\n\nfunction isFiniteInteger(value: number | bigint | undefined): boolean {\n if (value === undefined) {\n return true;\n }\n return typeof value === 'bigint' || (Number.isFinite(value) && Number.isSafeInteger(value));\n}\n\nfunction isTrackMonitorMode(value: number | bigint | undefined): boolean {\n if (value === undefined) {\n return false;\n }\n const mode = typeof value === 'bigint' ? Number(value) : value;\n return typeof mode === 'number' && Number.isSafeInteger(mode) && mode >= 0 && mode <= 2;\n}\n\n/** A track-monitor command cannot infer a lane: its target is a uint32 index. */\nfunction isTrackMonitorLaneIndex(value: number | undefined): boolean {\n return (\n typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 && value <= 0xffff_ffff\n );\n}\n\nfunction isValidCommandRecord(command: SonareEngineCommandRecord): boolean {\n const type = Number(command.type);\n if (\n !Number.isSafeInteger(type) ||\n type < SonareEngineCommandType.SetParam ||\n (type > SonareEngineCommandType.SeekMarker &&\n type !== SonareEngineCommandType.SetTrackMonitorMode)\n ) {\n return false;\n }\n return (\n (command.targetId === undefined || Number.isSafeInteger(command.targetId)) &&\n (command.argFloat === undefined || Number.isFinite(command.argFloat)) &&\n isFiniteInteger(command.argInt) &&\n isFiniteInteger(command.sampleTime) &&\n (type !== SonareEngineCommandType.SetTrackMonitorMode ||\n (isTrackMonitorLaneIndex(command.targetId) && isTrackMonitorMode(command.argInt)))\n );\n}\n\nconst AUDIO_WORKLET_RENDER_QUANTUM = 128;\n\nfunction workletBlockSize(blockSize: number | undefined): number {\n const resolved = blockSize ?? AUDIO_WORKLET_RENDER_QUANTUM;\n if (!Number.isSafeInteger(resolved) || resolved < AUDIO_WORKLET_RENDER_QUANTUM) {\n throw new RangeError(\n `blockSize must be an integer of at least ${AUDIO_WORKLET_RENDER_QUANTUM} frames`,\n );\n }\n return resolved;\n}\n\nexport class SonareRealtimeEngineNode {\n readonly node: AudioWorkletNode;\n readonly capabilities: SonareRealtimeEngineNodeCapabilities;\n readonly commandRing?: SonareEngineCommandRingBuffer;\n readonly telemetryRing?: SonareEngineTelemetryRingBuffer;\n readonly meterRing?: SonareMeterRingBuffer;\n readonly scopeRing?: SonareScopeRingBuffer;\n readonly clipPageRequestRing?: SonareClipPageRequestRingBuffer;\n readonly externalMidiRing?: SonareExternalMidiRingBuffer;\n readonly ready: Promise<void>;\n private telemetryReadIndex = 0;\n private meterReadIndex = 0;\n private scopeReadIndex = 0;\n private clipPageRequestDroppedRead = 0;\n private ringPollTimer: ReturnType<typeof setInterval> | undefined;\n private telemetryListeners = new Set<(telemetry: SonareEngineTelemetryRecord) => void>();\n private meterListeners = new Set<(meter: SonareWorkletMeterSnapshot) => void>();\n private scopeListeners = new Set<(scope: SonareWorkletScopeSnapshot) => void>();\n private midiOutListeners = new Set<(events: SonareWorkletExternalMidiEvent[]) => void>();\n private clipPageRequestListeners = new Set<\n (message: SonareEngineClipPageRequestMessage) => void\n >();\n private syncErrorListeners = new Set<(message: SonareEngineSyncErrorMessage) => void>();\n private captureRequestId = 1;\n private readonly captureRequests = new Map<\n number,\n {\n op: SonareEngineCaptureRequestMessage['op'];\n resolve: (response: SonareEngineCaptureResponseMessageInternal) => void;\n reject: (reason?: unknown) => void;\n }\n >();\n private transportRequestId = 1;\n private readonly transportRequests = new Map<\n number,\n {\n resolve: (response: SonareEngineTransportResponseMessage) => void;\n reject: (reason?: unknown) => void;\n }\n >();\n private resolveReady!: () => void;\n private rejectReady!: (reason?: unknown) => void;\n private destroyed = false;\n\n private constructor(\n node: AudioWorkletNode,\n capabilities: SonareRealtimeEngineNodeCapabilities,\n commandRing?: SonareEngineCommandRingBuffer,\n telemetryRing?: SonareEngineTelemetryRingBuffer,\n meterRing?: SonareMeterRingBuffer,\n scopeRing?: SonareScopeRingBuffer,\n clipPageRequestRing?: SonareClipPageRequestRingBuffer,\n externalMidiRing?: SonareExternalMidiRingBuffer,\n ) {\n this.node = node;\n this.capabilities = capabilities;\n this.commandRing = commandRing;\n this.telemetryRing = telemetryRing;\n this.meterRing = meterRing;\n this.scopeRing = scopeRing;\n this.clipPageRequestRing = clipPageRequestRing;\n this.externalMidiRing = externalMidiRing;\n this.ready = new Promise((resolve, reject) => {\n this.resolveReady = resolve;\n this.rejectReady = reject;\n });\n if (!capabilities.readyMessage) {\n this.resolveReady();\n }\n this.node.port.onmessage = (event: MessageEvent<unknown>) => {\n const captureRequestId = engineCaptureResponseRequestId(event.data);\n if (captureRequestId !== undefined) {\n const pending = this.captureRequests.get(captureRequestId);\n if (pending) {\n this.captureRequests.delete(captureRequestId);\n if (!isEngineCaptureResponseMessage(event.data)) {\n pending.reject(new Error('Malformed capture response.'));\n } else if (!isEngineCaptureResponseForOperation(event.data, pending.op)) {\n pending.reject(new Error('Capture response does not match request operation.'));\n } else if (event.data.ok) {\n pending.resolve(event.data);\n } else {\n pending.reject(new Error(event.data.error));\n }\n }\n } else if (isEngineTransportResponseMessage(event.data)) {\n const pending = this.transportRequests.get(event.data.requestId);\n if (pending) {\n this.transportRequests.delete(event.data.requestId);\n if (event.data.ok) {\n pending.resolve(event.data);\n } else {\n pending.reject(new Error(event.data.error ?? 'Transport request failed'));\n }\n }\n } else if (isEngineTelemetryRecord(event.data)) {\n this.emitTelemetry(event.data);\n } else if (isMeterSnapshot(event.data)) {\n this.emitMeter(event.data);\n } else if (isExternalMidiBatchMessage(event.data)) {\n this.emitMidiOut(event.data.events);\n } else if (isClipPageRequestMessage(event.data)) {\n this.emitClipPageRequests(event.data);\n } else if (isRecord(event.data) && event.data.type === 'syncError') {\n const syncError: SonareEngineSyncErrorMessage = {\n type: 'syncError',\n syncType: String(event.data.syncType) as SonareEngineSyncErrorMessage['syncType'],\n message: String(event.data.message ?? 'AudioWorklet sync failed'),\n };\n for (const listener of this.syncErrorListeners) {\n listener(syncError);\n }\n } else if (isRecord(event.data) && event.data.type === 'ready') {\n this.resolveReady();\n } else if (isRecord(event.data) && event.data.type === 'error') {\n this.rejectReady(new Error(String(event.data.message ?? 'AudioWorklet error')));\n }\n };\n }\n\n /** Subscribes to control-plane sync rejections reported by the worklet. */\n onSyncError(listener: (message: SonareEngineSyncErrorMessage) => void): () => void {\n this.syncErrorListeners.add(listener);\n return () => this.syncErrorListeners.delete(listener);\n }\n\n static async create(\n context: BaseAudioContext,\n options: SonareRealtimeEngineNodeOptions = {},\n ): Promise<SonareRealtimeEngineNode> {\n const blockSize = workletBlockSize(options.blockSize);\n const processorName = options.processorName ?? 'sonare-realtime-engine-processor';\n const moduleUrl = options.moduleUrl;\n if (moduleUrl && context.audioWorklet?.addModule) {\n await context.audioWorklet.addModule(moduleUrl);\n }\n const detectedCapabilities =\n options.engineAbiVersion !== undefined\n ? {\n engineAbiVersion: options.engineAbiVersion,\n expectedEngineAbiVersion: options.expectedEngineAbiVersion ?? options.engineAbiVersion,\n abiCompatible:\n options.engineAbiVersion ===\n (options.expectedEngineAbiVersion ?? options.engineAbiVersion),\n }\n : engineCapabilities();\n if (options.requireAbiCompatible !== false && detectedCapabilities?.abiCompatible === false) {\n throw new Error(\n `Engine ABI mismatch: wasm=${detectedCapabilities.engineAbiVersion}, expected=${detectedCapabilities.expectedEngineAbiVersion}`,\n );\n }\n const sharedArrayBuffer = typeof globalThis.SharedArrayBuffer === 'function';\n const atomics = typeof globalThis.Atomics === 'object';\n const audioWorklet = typeof AudioWorkletNode !== 'undefined' || !!options.nodeFactory;\n const degradedReason =\n options.mode !== 'postMessage' && (!sharedArrayBuffer || !atomics)\n ? 'SharedArrayBuffer or Atomics unavailable; using postMessage transport.'\n : undefined;\n const mode =\n options.mode === 'postMessage' || !sharedArrayBuffer || !atomics ? 'postMessage' : 'sab';\n if (options.mode === 'sab' && mode !== 'sab') {\n throw new Error(\n 'SharedArrayBuffer mode requested but SharedArrayBuffer/Atomics are unavailable.',\n );\n }\n\n const commandRing =\n mode === 'sab'\n ? createSonareEngineCommandRingBuffer(options.commandRingCapacity ?? 128)\n : undefined;\n const telemetryRing =\n mode === 'sab'\n ? createSonareEngineTelemetryRingBuffer(options.telemetryRingCapacity ?? 128)\n : undefined;\n // Meter ring: the engine publishes meters into a SAB ring. Lock-free meter\n // delivery matches the telemetry path and keeps the audio render callback\n // allocation-free in SAB mode.\n const meterRing =\n mode === 'sab' ? createSonareMeterRingBuffer(options.meterRingCapacity ?? 128) : undefined;\n // Scope ring (FFT spectrum + goniometer): opt-in. The per-block FFT is\n // heavier than the meter path, so it is created only when the caller\n // requests scope telemetry via scopeIntervalFrames > 0.\n const scopeIntervalFrames = Math.max(0, Math.floor(options.scopeIntervalFrames ?? 0));\n const scopeRing =\n mode === 'sab' && scopeIntervalFrames > 0\n ? createSonareScopeRingBuffer(options.scopeRingCapacity ?? 64, options.scopeBands ?? 48)\n : undefined;\n // Paged-clip cache misses are a worklet-to-main-thread control signal. A\n // dedicated SPSC SAB ring keeps process() free of both embind request\n // objects and postMessage structured cloning.\n const clipPageRequestRing =\n mode === 'sab'\n ? createSonareClipPageRequestRingBuffer(options.clipPageRequestRingCapacity ?? 128)\n : undefined;\n const externalMidiRing =\n mode === 'sab'\n ? createSonareExternalMidiRingBuffer(options.externalMidiRingCapacity ?? 256)\n : undefined;\n const channelCount = Math.max(1, Math.floor(options.channelCount ?? 2));\n const processorOptions: SonareRealtimeEngineWorkletProcessorOptions = {\n sampleRate: options.sampleRate ?? context.sampleRate,\n blockSize,\n channelCount,\n commandSharedBuffer: commandRing?.sharedBuffer,\n commandRingCapacity: commandRing?.capacity,\n telemetrySharedBuffer: telemetryRing?.sharedBuffer,\n telemetryRingCapacity: telemetryRing?.capacity,\n meterSharedBuffer: meterRing?.sharedBuffer,\n meterRingCapacity: meterRing?.capacity,\n scopeSharedBuffer: scopeRing?.sharedBuffer,\n scopeRingCapacity: scopeRing?.capacity,\n scopeBands: scopeRing?.bands,\n scopeIntervalFrames: scopeRing ? scopeIntervalFrames : undefined,\n clipPageRequestSharedBuffer: clipPageRequestRing?.sharedBuffer,\n clipPageRequestRingCapacity: clipPageRequestRing?.capacity,\n externalMidiSharedBuffer: externalMidiRing?.sharedBuffer,\n externalMidiRingCapacity: externalMidiRing?.capacity,\n wasmBinary: options.wasmBinary,\n initialSyncMessages: options.initialSyncMessages,\n initialCommands: options.initialCommands,\n };\n const factory =\n options.nodeFactory ??\n ((ctx: BaseAudioContext, name: string, nodeOptions: AudioWorkletNodeOptions) =>\n new AudioWorkletNode(ctx, name, nodeOptions));\n const node = factory(context, processorName, {\n numberOfInputs: 1,\n numberOfOutputs: 1,\n outputChannelCount: [channelCount],\n processorOptions,\n });\n return new SonareRealtimeEngineNode(\n node,\n {\n mode,\n runtimeTarget: 'embind',\n sharedArrayBuffer,\n atomics,\n audioWorklet,\n clipPageRequestsRealtimeSafe: mode === 'sab',\n externalMidiRealtimeSafe: mode === 'sab',\n engineAbiVersion: detectedCapabilities?.engineAbiVersion,\n expectedEngineAbiVersion: detectedCapabilities?.expectedEngineAbiVersion,\n abiCompatible: detectedCapabilities?.abiCompatible,\n degradedReason,\n // A processor posts ready/error irrespective of whether its module was\n // loaded here or registered by the host beforehand. Waiting in both\n // cases is the only way to surface a failed worklet-side WASM init.\n readyMessage: true,\n },\n commandRing,\n telemetryRing,\n meterRing,\n scopeRing,\n clipPageRequestRing,\n externalMidiRing,\n );\n }\n\n play(sampleTime = -1): boolean {\n return this.sendCommand({ type: SonareEngineCommandType.TransportPlay, sampleTime });\n }\n\n stop(sampleTime = -1): boolean {\n return this.sendCommand({ type: SonareEngineCommandType.TransportStop, sampleTime });\n }\n\n seekSample(timelineSample: number, sampleTime = -1): boolean {\n return this.sendCommand({\n type: SonareEngineCommandType.TransportSeekSample,\n sampleTime,\n argInt: timelineSample,\n });\n }\n\n seekPpq(ppq: number, sampleTime = -1): boolean {\n if (!Number.isFinite(ppq) || !Number.isSafeInteger(sampleTime)) {\n return false;\n }\n return this.sendCommand({\n type: SonareEngineCommandType.TransportSeekPpq,\n sampleTime,\n argFloat: ppq,\n });\n }\n\n sendCommand(command: SonareEngineCommandRecord): boolean {\n if (this.destroyed || !isValidCommandRecord(command)) {\n return false;\n }\n if (this.commandRing) {\n return pushSonareEngineCommandRingBuffer(this.commandRing, command);\n }\n this.node.port.postMessage(command);\n return true;\n }\n\n requestCaptureStatus(): Promise<EngineCaptureStatus> {\n return this.sendCaptureRequest('status').then((response) => {\n if (!response.ok || !('status' in response)) {\n throw new Error('Capture status response is missing status.');\n }\n return response.status;\n });\n }\n\n requestCapturedAudio(): Promise<Float32Array[]> {\n return this.sendCaptureRequest('read').then((response) => {\n if (!response.ok || !('channels' in response)) {\n throw new Error('Capture read response is missing channels.');\n }\n return response.channels;\n });\n }\n\n requestCaptureReset(): Promise<void> {\n return this.sendCaptureRequest('reset').then(() => undefined);\n }\n\n requestTransportState(): Promise<EngineTransportState> {\n return this.sendTransportRequest().then((response) => {\n if (!response.state) {\n throw new Error('Transport state response is missing state.');\n }\n return response.state;\n });\n }\n\n pollTelemetry(): SonareEngineTelemetryRecord[] {\n if (!this.telemetryRing) {\n return [];\n }\n const read = readSonareEngineTelemetryRingBuffer(this.telemetryRing, this.telemetryReadIndex);\n this.telemetryReadIndex = read.nextReadIndex;\n for (const telemetry of read.telemetry) {\n this.emitTelemetry(telemetry);\n }\n return read.telemetry;\n }\n\n // Drains any meters published into the SAB meter ring (embind SAB mode) and\n // forwards them to onMeter listeners. In postMessage mode meters arrive via\n // node.port.onmessage instead, so this is a no-op then.\n pollMeters(): SonareWorkletMeterSnapshot[] {\n if (!this.meterRing) {\n return [];\n }\n const read = readSonareMeterRingBuffer(this.meterRing, this.meterReadIndex);\n this.meterReadIndex = read.nextReadIndex;\n for (const meter of read.meters) {\n this.emitMeter(meter);\n }\n return read.meters;\n }\n\n // Drains scope telemetry (FFT spectrum + goniometer points) published into the\n // SAB scope ring and forwards each record to onScope listeners. A no-op unless\n // the node was created with scopeIntervalFrames > 0 (embind SAB mode).\n pollScope(): SonareWorkletScopeSnapshot[] {\n if (!this.scopeRing) {\n return [];\n }\n const read = readSonareScopeRingBuffer(this.scopeRing, this.scopeReadIndex);\n this.scopeReadIndex = read.nextReadIndex;\n for (const scope of read.scopes) {\n this.emitScope(scope);\n }\n return read.scopes;\n }\n\n /** Drain lowered MIDI-1 records from the SAB ring on the main thread. */\n pollMidiOut(): SonareWorkletExternalMidiEvent[] {\n if (!this.externalMidiRing) {\n return [];\n }\n const read = readSonareExternalMidiRingBuffer(this.externalMidiRing);\n const events = read.events.map((event) => {\n const bytes: number[] = [];\n for (let index = 0; index < event.byteCount; index++) {\n bytes.push((event.byteWord >>> (8 * index)) & 0xff);\n }\n return {\n destinationId: event.destinationId,\n renderFrame: event.renderFrame,\n bytes,\n };\n });\n if (events.length > 0) {\n this.emitMidiOut(events);\n }\n return events;\n }\n\n /**\n * Drains bounded paged-clip misses from the SAB ring and forwards one batch\n * to subscribers. In postMessage mode the legacy handler remains available,\n * but that degraded path is not realtime-safe for OPFS streaming.\n */\n pollClipPageRequests(): SonareEngineClipPageRequestMessage | undefined {\n if (!this.clipPageRequestRing) {\n return undefined;\n }\n const read = readSonareClipPageRequestRingBuffer(this.clipPageRequestRing);\n const dropped = (read.dropped - this.clipPageRequestDroppedRead) >>> 0;\n this.clipPageRequestDroppedRead = read.dropped;\n if (read.requests.length === 0 && dropped === 0) {\n return undefined;\n }\n const message: SonareEngineClipPageRequestMessage = {\n type: 'clipPageRequest',\n requests: read.requests,\n ...(dropped > 0 ? { dropped } : {}),\n };\n this.emitClipPageRequests(message);\n return message;\n }\n\n onTelemetry(callback: (telemetry: SonareEngineTelemetryRecord) => void): () => void {\n this.telemetryListeners.add(callback);\n this.startRingPolling();\n return () => {\n this.telemetryListeners.delete(callback);\n this.stopRingPollingIfUnused();\n };\n }\n\n onMeter(callback: (meter: SonareWorkletMeterSnapshot) => void): () => void {\n this.meterListeners.add(callback);\n this.startRingPolling();\n return () => {\n this.meterListeners.delete(callback);\n this.stopRingPollingIfUnused();\n };\n }\n\n onScope(callback: (scope: SonareWorkletScopeSnapshot) => void): () => void {\n this.scopeListeners.add(callback);\n this.startRingPolling();\n return () => {\n this.scopeListeners.delete(callback);\n this.stopRingPollingIfUnused();\n };\n }\n\n /**\n * Subscribe to external-MIDI batches drained from the engine (one call per\n * render block that produced events), already lowered to MIDI 1.0 bytes for a\n * Web MIDI output port. Returns an unsubscribe function.\n */\n onMidiOut(callback: (events: SonareWorkletExternalMidiEvent[]) => void): () => void {\n this.midiOutListeners.add(callback);\n this.startRingPolling();\n return () => {\n this.midiOutListeners.delete(callback);\n this.stopRingPollingIfUnused();\n };\n }\n\n /**\n * Subscribe to bounded batches of paged-clip misses from the worklet. The\n * callback runs on the main thread and may initiate asynchronous OPFS I/O.\n */\n onClipPageRequests(callback: (message: SonareEngineClipPageRequestMessage) => void): () => void {\n this.clipPageRequestListeners.add(callback);\n return () => {\n this.clipPageRequestListeners.delete(callback);\n };\n }\n\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n this.destroyed = true;\n if (this.ringPollTimer !== undefined) {\n clearInterval(this.ringPollTimer);\n this.ringPollTimer = undefined;\n }\n this.node.port.postMessage({ type: 'destroy' });\n this.node.disconnect();\n for (const pending of this.captureRequests.values()) {\n pending.reject(new Error('Realtime engine node is destroyed.'));\n }\n this.captureRequests.clear();\n for (const pending of this.transportRequests.values()) {\n pending.reject(new Error('Realtime engine node is destroyed.'));\n }\n this.transportRequests.clear();\n this.telemetryListeners.clear();\n this.meterListeners.clear();\n this.scopeListeners.clear();\n this.midiOutListeners.clear();\n this.clipPageRequestListeners.clear();\n }\n\n private emitTelemetry(telemetry: SonareEngineTelemetryRecord): void {\n for (const listener of this.telemetryListeners) {\n listener(telemetry);\n }\n }\n\n private startRingPolling(): void {\n if (\n this.ringPollTimer !== undefined ||\n (!this.telemetryRing && !this.meterRing && !this.scopeRing && !this.externalMidiRing)\n ) {\n return;\n }\n const poll = () => {\n if (!this.destroyed) {\n this.pollTelemetry();\n this.pollMeters();\n this.pollScope();\n this.pollMidiOut();\n }\n };\n poll();\n this.ringPollTimer = setInterval(poll, 16);\n }\n\n private stopRingPollingIfUnused(): void {\n if (\n this.ringPollTimer !== undefined &&\n this.telemetryListeners.size === 0 &&\n this.meterListeners.size === 0 &&\n this.scopeListeners.size === 0 &&\n this.midiOutListeners.size === 0\n ) {\n clearInterval(this.ringPollTimer);\n this.ringPollTimer = undefined;\n }\n }\n\n private emitMeter(meter: SonareWorkletMeterSnapshot): void {\n for (const listener of this.meterListeners) {\n listener(meter);\n }\n }\n\n private emitMidiOut(events: SonareWorkletExternalMidiEvent[]): void {\n for (const listener of this.midiOutListeners) {\n listener(events);\n }\n }\n\n private emitClipPageRequests(message: SonareEngineClipPageRequestMessage): void {\n for (const listener of this.clipPageRequestListeners) {\n listener(message);\n }\n }\n\n private emitScope(scope: SonareWorkletScopeSnapshot): void {\n for (const listener of this.scopeListeners) {\n listener(scope);\n }\n }\n\n private sendCaptureRequest(\n op: SonareEngineCaptureRequestMessage['op'],\n ): Promise<SonareEngineCaptureResponseMessageInternal> {\n if (this.destroyed) {\n return Promise.reject(new Error('Realtime engine node is destroyed.'));\n }\n const requestId = this.captureRequestId++;\n let rejectRequest!: (reason?: unknown) => void;\n const promise = new Promise<SonareEngineCaptureResponseMessageInternal>((resolve, reject) => {\n rejectRequest = reject;\n this.captureRequests.set(requestId, { op, resolve, reject });\n });\n try {\n this.node.port.postMessage({ type: 'captureRequest', requestId, op });\n } catch (error) {\n this.captureRequests.delete(requestId);\n rejectRequest(error);\n }\n return promise;\n }\n\n private sendTransportRequest(): Promise<SonareEngineTransportResponseMessage> {\n if (this.destroyed) {\n return Promise.reject(new Error('Realtime engine node is destroyed.'));\n }\n const requestId = this.transportRequestId++;\n const promise = new Promise<SonareEngineTransportResponseMessage>((resolve, reject) => {\n this.transportRequests.set(requestId, { resolve, reject });\n });\n this.node.port.postMessage({ type: 'transportRequest', requestId, op: 'state' });\n return promise;\n }\n}\n","import { trackMonitorModeCode } from '../codes';\nimport type {\n EngineAutomationPoint,\n EngineParameterInfo,\n EngineTrackMonitorMode,\n RealtimeEngine,\n} from '../index';\nimport type { SonareEngineSyncMessage } from './messages';\nimport {\n ENGINE_MIXER_PARAM_FADER_DB,\n ENGINE_MIXER_PARAM_PAN,\n engineMixerBusTarget,\n engineMixerLaneTarget,\n engineMixerMasterTarget,\n SonareEngineCommandType,\n} from './protocol';\n\n/**\n * Collaborator surface the parameter / automation-id resolution helpers need\n * from the owning {@link SonareEngine}: the offline engine they mirror into and\n * query, the realtime node they command, the lane/bus declaration helpers, and\n * the declared track-lane id store used to resolve insert-automation ids.\n */\nexport interface EngineParameterContext {\n readonly offlineEngine: RealtimeEngine;\n sendCommand(command: {\n type: SonareEngineCommandType;\n targetId?: number;\n sampleTime?: number;\n argFloat?: number;\n argInt?: number;\n }): boolean;\n postSync(message: SonareEngineSyncMessage): void;\n readonly automationLanes: Map<number, EngineAutomationPoint[]>;\n readonly trackLaneIds: number[];\n resolveParamId(nodeId: string, param: string | number): number;\n ensureTrackLane(target: string | number): number;\n ensureBus(busId: number): number;\n}\n\nexport function setParam(\n ctx: EngineParameterContext,\n nodeId: string,\n param: string | number,\n value: number,\n): boolean {\n const paramId = ctx.resolveParamId(nodeId, param);\n // Mirror the change into the offline engine so a subsequent offline render\n // reflects the live value, then push a sample-accurate command to the\n // realtime runtime (mirrors setTempo/setLoop above).\n ctx.offlineEngine.setParameter(paramId, value);\n return ctx.sendCommand({\n type: SonareEngineCommandType.SetParam,\n targetId: paramId,\n sampleTime: -1,\n argFloat: value,\n });\n}\n\nexport function setSoloMute(\n ctx: EngineParameterContext,\n target: string | number,\n solo: boolean,\n mute: boolean,\n): boolean {\n const laneIndex = ctx.ensureTrackLane(target);\n ctx.offlineEngine.setSoloMute(laneIndex, solo, mute);\n return ctx.sendCommand({\n type: SonareEngineCommandType.SetSoloMute,\n targetId: laneIndex,\n sampleTime: -1,\n argInt: (mute ? 0x1 : 0) | (solo ? 0x2 : 0),\n });\n}\n\nexport function setTrackMonitorMode(\n ctx: EngineParameterContext,\n target: string | number,\n mode: EngineTrackMonitorMode,\n renderFrame = -1,\n): boolean {\n // Resolve the mode before declaring a lane or touching either engine. This\n // keeps booleans, fractions, and unknown spellings from reaching the queue.\n const modeOrdinal = trackMonitorModeCode(mode);\n const laneIndex = ctx.ensureTrackLane(target);\n ctx.offlineEngine.setTrackMonitorMode(\n laneIndex,\n modeOrdinal as EngineTrackMonitorMode,\n renderFrame,\n );\n return ctx.sendCommand({\n type: SonareEngineCommandType.SetTrackMonitorMode,\n targetId: laneIndex,\n sampleTime: renderFrame,\n argInt: modeOrdinal,\n });\n}\n\n/**\n * Returns the automation target id for a mixer strip parameter.\n *\n * The id addresses the engine's reserved mixer namespace, so it can be fed\n * straight to setAutomationLane to automate a fader or pan without\n * registering a parameter.\n *\n * @param target Track id (declares a mixer lane on first use) or 'master'.\n * @param kind Strip parameter to address.\n * @returns Reserved engine parameter id for the strip parameter.\n */\nexport function automationParamId(\n ctx: EngineParameterContext,\n target: string | number,\n kind: 'faderDb' | 'pan',\n): number {\n const paramKind = kind === 'pan' ? ENGINE_MIXER_PARAM_PAN : ENGINE_MIXER_PARAM_FADER_DB;\n if (target === 'master') {\n return engineMixerMasterTarget(paramKind);\n }\n return engineMixerLaneTarget(ctx.ensureTrackLane(target), paramKind);\n}\n\n/**\n * Returns the automation target id for a bus fader.\n *\n * @param busId Bus id (declares the mixer bus on first use).\n * @returns Reserved engine parameter id for the bus fader gain (dB).\n */\nexport function busAutomationParamId(ctx: EngineParameterContext, busId: number): number {\n return engineMixerBusTarget(ctx.ensureBus(busId), ENGINE_MIXER_PARAM_FADER_DB);\n}\n\n/**\n * Resolves a track-lane insert parameter (JSON-key name) to the reserved\n * insert-automation id fed straight to setAutomationLane. Declares the track's\n * mixer lane first (like automationParamId) so the offline engine resolves the\n * same strip selector the realtime engine uses.\n *\n * @param target Track id (declares a mixer lane on first use).\n * @param insertIndex Index into the strip's combined insert sequence.\n * @param paramName Processor JSON-key parameter name.\n * @returns Reserved insert-automation id, or -1 when strip/insert/key unknown.\n */\nexport function resolveTrackInsertAutomationId(\n ctx: EngineParameterContext,\n target: string | number,\n insertIndex: number,\n paramName: string,\n): number {\n const laneIndex = ctx.ensureTrackLane(target);\n return ctx.offlineEngine.resolveTrackInsertAutomationId(\n ctx.trackLaneIds[laneIndex],\n insertIndex,\n paramName,\n );\n}\n\n/**\n * Resolves a master-strip insert parameter to its reserved insert-automation\n * id.\n *\n * @param insertIndex Index into the master strip's insert sequence.\n * @param paramName Processor JSON-key parameter name.\n * @returns Reserved insert-automation id, or -1 when insert/key unknown.\n */\nexport function resolveMasterInsertAutomationId(\n ctx: EngineParameterContext,\n insertIndex: number,\n paramName: string,\n): number {\n return ctx.offlineEngine.resolveMasterInsertAutomationId(insertIndex, paramName);\n}\n\n/**\n * Resolves a bus-strip insert parameter to its reserved insert-automation id.\n * Declares the mixer bus first so the offline engine resolves the same bus\n * selector.\n *\n * @param busId Bus id (declares the mixer bus on first use).\n * @param insertIndex Index into the bus strip's insert sequence.\n * @param paramName Processor JSON-key parameter name.\n * @returns Reserved insert-automation id, or -1 when bus/insert/key unknown.\n */\nexport function resolveBusInsertAutomationId(\n ctx: EngineParameterContext,\n busId: number,\n insertIndex: number,\n paramName: string,\n): number {\n ctx.ensureBus(busId);\n return ctx.offlineEngine.resolveBusInsertAutomationId(busId, insertIndex, paramName);\n}\n\n/**\n * Returns the number of automation lanes installed on the engine, including\n * lanes whose breakpoint list is currently empty.\n *\n * @returns Engine-side automation lane count.\n */\nexport function automationLaneCount(ctx: EngineParameterContext): number {\n return ctx.offlineEngine.automationLaneCount();\n}\n\nexport function listParameters(ctx: EngineParameterContext): EngineParameterInfo[] {\n const parameters: EngineParameterInfo[] = [];\n for (let index = 0; index < ctx.offlineEngine.parameterCount(); index++) {\n parameters.push(ctx.offlineEngine.parameterInfoByIndex(index));\n }\n return parameters;\n}\n\n/** Registers a parameter on both the offline mirror and live worklet engine. */\nexport function addParameter(ctx: EngineParameterContext, info: EngineParameterInfo): void {\n ctx.offlineEngine.addParameter(info);\n ctx.postSync({ type: 'syncParameters', parameters: listParameters(ctx) });\n}\n\n/** Clears registered parameters and their automation lanes on both engines. */\nexport function clearParameters(ctx: EngineParameterContext): void {\n ctx.offlineEngine.clearParameters();\n ctx.automationLanes.clear();\n ctx.postSync({ type: 'syncParameters', parameters: [] });\n}\n","import { panLawCode, panModeCode } from '../codes';\nimport type { EqBand, PanLawInput, PanMode, RealtimeEngine } from '../index';\nimport type { SonareEngineInstrumentSyncMessage, SonareEngineSyncMessage } from './messages';\n\n/**\n * Collaborator surface the strip/pan/EQ/insert/instrument/MIDI setters need from\n * the owning {@link SonareEngine}: the offline engine they mirror writes into,\n * the out-of-band sync posters, and the lane-resolution helpers.\n */\nexport interface EngineStripContext {\n readonly offlineEngine: RealtimeEngine;\n readonly trackLaneIds: number[];\n postSync(message: SonareEngineSyncMessage): void;\n postInstrumentSync(message: SonareEngineInstrumentSyncMessage): void;\n ensureTrackLane(target: string | number): number;\n resolveTargetId(target: string | number): number;\n}\n\nfunction trackIdFor(ctx: EngineStripContext, target: string | number): number {\n return ctx.trackLaneIds[ctx.ensureTrackLane(target)];\n}\n\nexport function setTrackStripJson(\n ctx: EngineStripContext,\n trackId: number,\n sceneJson: string,\n trackStripJson: Map<number, string>,\n): void {\n ctx.offlineEngine.setTrackStripJson(trackId, sceneJson);\n trackStripJson.set(trackId, sceneJson);\n}\n\nexport function setTrackStripEqBand(\n ctx: EngineStripContext,\n target: string | number,\n bandIndex: number,\n band: EqBand | string,\n): void {\n const trackId = trackIdFor(ctx, target);\n const bandJson = typeof band === 'string' ? band : JSON.stringify(band);\n ctx.offlineEngine.setTrackStripEqBandJson(trackId, bandIndex, bandJson);\n ctx.postSync({ type: 'syncTrackStripEqBand', trackId, bandIndex, bandJson });\n}\n\nexport function setTrackStripInsertBypassed(\n ctx: EngineStripContext,\n target: string | number,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass: boolean,\n): void {\n const trackId = trackIdFor(ctx, target);\n ctx.offlineEngine.setTrackStripInsertBypassed(trackId, insertIndex, bypassed, resetOnBypass);\n ctx.postSync({\n type: 'syncTrackStripInsertBypassed',\n trackId,\n insertIndex,\n bypassed,\n resetOnBypass,\n });\n}\n\nexport function setTrackStripInsertParamByName(\n ctx: EngineStripContext,\n target: string | number,\n insertIndex: number,\n paramName: string,\n value: number,\n): void {\n const trackId = trackIdFor(ctx, target);\n ctx.offlineEngine.setTrackStripInsertParamByName(trackId, insertIndex, paramName, value);\n ctx.postSync({ type: 'syncTrackStripInsertParamByName', trackId, insertIndex, paramName, value });\n}\n\nexport function setTrackStripPan(\n ctx: EngineStripContext,\n target: string | number,\n pan: number,\n): void {\n const trackId = trackIdFor(ctx, target);\n ctx.offlineEngine.setTrackStripPan(trackId, pan);\n ctx.postSync({ type: 'syncTrackStripPan', trackId, pan });\n}\n\nexport function setTrackStripPanLaw(\n ctx: EngineStripContext,\n target: string | number,\n panLaw: PanLawInput,\n): void {\n const trackId = trackIdFor(ctx, target);\n const code = panLawCode(panLaw);\n ctx.offlineEngine.setTrackStripPanLaw(trackId, code);\n ctx.postSync({ type: 'syncTrackStripPanLaw', trackId, panLaw: code });\n}\n\nexport function setTrackStripPanMode(\n ctx: EngineStripContext,\n target: string | number,\n panMode: PanMode | number,\n): void {\n const trackId = trackIdFor(ctx, target);\n const code = panModeCode(panMode);\n ctx.offlineEngine.setTrackStripPanMode(trackId, code);\n ctx.postSync({ type: 'syncTrackStripPanMode', trackId, panMode: code });\n}\n\nexport function setTrackStripDualPan(\n ctx: EngineStripContext,\n target: string | number,\n leftPan: number,\n rightPan: number,\n): void {\n const trackId = trackIdFor(ctx, target);\n ctx.offlineEngine.setTrackStripDualPan(trackId, leftPan, rightPan);\n ctx.postSync({ type: 'syncTrackStripDualPan', trackId, leftPan, rightPan });\n}\n\nexport function setTrackStripChannelDelaySamples(\n ctx: EngineStripContext,\n target: string | number,\n delaySamples: number,\n): void {\n const trackId = trackIdFor(ctx, target);\n ctx.offlineEngine.setTrackStripChannelDelaySamples(trackId, delaySamples);\n ctx.postSync({ type: 'syncTrackStripChannelDelaySamples', trackId, delaySamples });\n}\n\nexport function setMasterStripEqBand(\n ctx: EngineStripContext,\n bandIndex: number,\n band: EqBand | string,\n): void {\n const bandJson = typeof band === 'string' ? band : JSON.stringify(band);\n ctx.offlineEngine.setMasterStripEqBandJson(bandIndex, bandJson);\n ctx.postSync({ type: 'syncMasterStripEqBand', bandIndex, bandJson });\n}\n\nexport function setMasterStripInsertBypassed(\n ctx: EngineStripContext,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass: boolean,\n): void {\n ctx.offlineEngine.setMasterStripInsertBypassed(insertIndex, bypassed, resetOnBypass);\n ctx.postSync({ type: 'syncMasterStripInsertBypassed', insertIndex, bypassed, resetOnBypass });\n}\n\nexport function setMasterStripInsertParamByName(\n ctx: EngineStripContext,\n insertIndex: number,\n paramName: string,\n value: number,\n): void {\n ctx.offlineEngine.setMasterStripInsertParamByName(insertIndex, paramName, value);\n ctx.postSync({ type: 'syncMasterStripInsertParamByName', insertIndex, paramName, value });\n}\n\nexport function setBusStripInsertParamByName(\n ctx: EngineStripContext,\n busId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n): void {\n ctx.offlineEngine.setBusStripInsertParamByName(busId, insertIndex, paramName, value);\n ctx.postSync({ type: 'syncBusStripInsertParamByName', busId, insertIndex, paramName, value });\n}\n\nexport function pushMidiNoteOn(\n ctx: EngineStripContext,\n trackId: string | number,\n group: number,\n channel: number,\n note: number,\n velocity: number,\n renderFrame: number,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.pushMidiNoteOn(destinationId, group, channel, note, velocity, renderFrame);\n ctx.postSync({\n type: 'syncMidiNoteOn',\n destinationId,\n group,\n channel,\n note,\n velocity,\n renderFrame,\n });\n}\n\nexport function pushMidiNoteOff(\n ctx: EngineStripContext,\n trackId: string | number,\n group: number,\n channel: number,\n note: number,\n velocity: number,\n renderFrame: number,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.pushMidiNoteOff(destinationId, group, channel, note, velocity, renderFrame);\n ctx.postSync({\n type: 'syncMidiNoteOff',\n destinationId,\n group,\n channel,\n note,\n velocity,\n renderFrame,\n });\n}\n\nexport function pushMidiCc(\n ctx: EngineStripContext,\n trackId: string | number,\n group: number,\n channel: number,\n controller: number,\n value: number,\n renderFrame: number,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.pushMidiCc(destinationId, group, channel, controller, value, renderFrame);\n ctx.postSync({\n type: 'syncMidiCc',\n destinationId,\n group,\n channel,\n controller,\n value,\n renderFrame,\n });\n}\n\nexport function pushMidiUmp(\n ctx: EngineStripContext,\n trackId: string | number,\n word0: number,\n renderFrame: number,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.pushMidiUmp(destinationId, word0, renderFrame);\n ctx.postSync({ type: 'syncMidiUmp', destinationId, word0, renderFrame });\n}\n\nexport function setBuiltinInstrument(\n ctx: EngineStripContext,\n trackId: string | number,\n config: { destinationId?: number } & Record<string, unknown>,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.setBuiltinInstrument(config, destinationId);\n ctx.postInstrumentSync({ type: 'syncBuiltinInstrument', destinationId, config });\n}\n\nexport function setSynthInstrument(\n ctx: EngineStripContext,\n trackId: string | number,\n patch: Record<string, unknown> | string,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.setSynthInstrument(patch, destinationId);\n ctx.postInstrumentSync({ type: 'syncSynthInstrument', destinationId, patch });\n}\n\nexport function loadSoundFont(ctx: EngineStripContext, data: Uint8Array): void {\n ctx.offlineEngine.loadSoundFont(data);\n ctx.postInstrumentSync({ type: 'syncLoadSoundFont', data });\n}\n\nexport function setSf2Instrument(\n ctx: EngineStripContext,\n trackId: string | number,\n config: {\n destinationId?: number;\n gain?: number;\n polyphony?: number;\n preferModelForModeledFamilies?: boolean;\n },\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.setSf2Instrument(config, destinationId);\n ctx.postInstrumentSync({ type: 'syncSf2Instrument', destinationId, config });\n}\n\nexport function setMidiDestinationExternal(\n ctx: EngineStripContext,\n trackId: string | number,\n external: boolean,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.setMidiDestinationExternal(destinationId, external);\n ctx.postSync({ type: 'syncMidiDestinationExternal', destinationId, external });\n}\n\nexport function setExternalMidiClockEnabled(ctx: EngineStripContext, enabled: boolean): void {\n ctx.offlineEngine.setExternalMidiClockEnabled(enabled);\n ctx.postSync({ type: 'syncExternalMidiClock', enabled });\n}\n\nexport function setMidiFx(\n ctx: EngineStripContext,\n trackId: string | number,\n configJson: string,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.setMidiFx(destinationId, configJson);\n ctx.postInstrumentSync({ type: 'syncMidiFx', destinationId, configJson });\n}\n\nexport function clearMidiFx(ctx: EngineStripContext, trackId: string | number): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.clearMidiFx(destinationId);\n ctx.postInstrumentSync({ type: 'syncClearMidiFx', destinationId });\n}\n\nexport function pushMidiSysex(\n ctx: EngineStripContext,\n trackId: string | number,\n data: Uint8Array,\n renderFrame: number,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.pushMidiSysex(destinationId, data, renderFrame);\n ctx.postSync({ type: 'syncMidiSysex', destinationId, data, renderFrame });\n}\n\nexport function pushMidiPanic(ctx: EngineStripContext, renderFrame: number): void {\n ctx.offlineEngine.pushMidiPanic(renderFrame);\n ctx.postSync({ type: 'syncMidiPanic', renderFrame });\n}\n","import type {\n EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTransportState,\n RealtimeEngine,\n} from '../index';\nimport type { SonareRealtimeEngineNode } from './engine-node';\nimport { buildTempoSync } from './engine-sync';\nimport type { SonareEngineSyncMessage } from './messages';\nimport { SonareEngineCommandType } from './protocol';\n\ninterface TimeSignature {\n numerator: number;\n denominator: number;\n}\n\n/**\n * Collaborator surface the tempo / time-signature / loop / transport helpers\n * need from the owning {@link SonareEngine}: the offline engine they mirror\n * into, the realtime node they command and query, the out-of-band sync poster,\n * and getters/setters for the tempo-map and cached-transport state the engine\n * holds (so the helpers mutate it by reference).\n */\nexport interface EngineTempoContext {\n readonly offlineEngine: RealtimeEngine;\n readonly realtimeNode: SonareRealtimeEngineNode;\n sendCommand(command: {\n type: SonareEngineCommandType;\n targetId?: number;\n sampleTime?: number;\n argFloat?: number;\n argInt?: number;\n }): boolean;\n postSync(message: SonareEngineSyncMessage): void;\n getTempoBpm(): number;\n setTempoBpm(bpm: number): void;\n getTimeSignature(): TimeSignature;\n setTimeSignature(signature: TimeSignature): void;\n getTempoSegments(): EngineTempoSegment[];\n setTempoSegments(segments: EngineTempoSegment[]): void;\n getTimeSignatureSegments(): EngineTimeSignatureSegment[];\n setTimeSignatureSegments(segments: EngineTimeSignatureSegment[]): void;\n setLatestTransportState(state: EngineTransportState): void;\n getLatestTransportState(): EngineTransportState | undefined;\n}\n\n// Posts the full tempo/time-signature map to the worklet engine processor.\nexport function postTempoSync(ctx: EngineTempoContext): void {\n ctx.postSync(\n buildTempoSync(\n ctx.getTempoBpm(),\n ctx.getTimeSignature(),\n ctx.getTempoSegments(),\n ctx.getTimeSignatureSegments(),\n ),\n );\n}\n\nexport function setTempo(ctx: EngineTempoContext, bpm: number): void {\n ctx.setTempoBpm(bpm);\n ctx.setTempoSegments([{ startPpq: 0, bpm }]);\n ctx.offlineEngine.setTempo(bpm);\n postTempoSync(ctx);\n}\n\nexport function setTempoSegments(\n ctx: EngineTempoContext,\n segments: readonly EngineTempoSegment[],\n): void {\n const copied = segments.map((segment) => ({ ...segment }));\n ctx.setTempoSegments(copied);\n ctx.setTempoBpm(copied[0]?.bpm ?? ctx.getTempoBpm());\n ctx.offlineEngine.setTempoSegments(copied);\n postTempoSync(ctx);\n}\n\nexport function setTimeSignature(\n ctx: EngineTempoContext,\n numerator: number,\n denominator: number,\n): void {\n ctx.setTimeSignature({ numerator, denominator });\n ctx.setTimeSignatureSegments([{ startPpq: 0, numerator, denominator }]);\n ctx.offlineEngine.setTimeSignature(numerator, denominator);\n postTempoSync(ctx);\n}\n\nexport function setTimeSignatureSegments(\n ctx: EngineTempoContext,\n segments: readonly EngineTimeSignatureSegment[],\n): void {\n const copied = segments.map((segment) => ({ ...segment }));\n ctx.setTimeSignatureSegments(copied);\n const first = copied[0];\n if (first) {\n ctx.setTimeSignature({ numerator: first.numerator, denominator: first.denominator });\n }\n ctx.offlineEngine.setTimeSignatureSegments(copied);\n postTempoSync(ctx);\n}\n\nexport function setLoop(\n ctx: EngineTempoContext,\n startPpq: number,\n endPpq: number,\n enabled = true,\n): boolean {\n ctx.offlineEngine.setLoop(startPpq, endPpq, enabled);\n // Transport precision contract: the SAB command record carries exactly one\n // Float64 lane (argFloat) and one Int64 lane (argInt). startPpq travels in\n // argFloat with full double precision, matching the offline engine; endPpq\n // is carried as micro-PPQ (round(endPpq * 1e6)) in the integer lane and\n // divided back by 1e6 on the consumer. Loop ENDS are therefore snapped to\n // the nearest 1e-6 PPQ over the realtime transport (max 5e-7 PPQ drift),\n // while loop STARTS and the offline path stay exact. This is intentional:\n // the record has no second free Float64 lane, and a micro-PPQ grid on the\n // loop end is well below audible/sample-accurate resolution at any tempo.\n return ctx.sendCommand({\n type: SonareEngineCommandType.SetLoop,\n targetId: enabled ? 1 : 0,\n sampleTime: -1,\n argFloat: startPpq,\n argInt: Math.round(endPpq * 1_000_000),\n });\n}\n\nexport function countInEndSample(\n ctx: EngineTempoContext,\n startSample: number,\n bars: number,\n): number {\n return ctx.offlineEngine.countInEndSample(startSample, bars);\n}\n\nexport async function getTransportState(ctx: EngineTempoContext): Promise<EngineTransportState> {\n const state = await ctx.realtimeNode.requestTransportState();\n ctx.setLatestTransportState(state);\n return state;\n}\n\nexport function cachedTransportState(ctx: EngineTempoContext): EngineTransportState | undefined {\n return ctx.getLatestTransportState();\n}\n","import {\n ClipPageStreamer,\n type ClipPageStreamerRequest,\n type OpfsClipStreamOptions,\n} from '../clip_page_streamer';\nimport type {\n EngineAutomationPoint,\n EngineBus,\n EngineCaptureStatus,\n EngineClip,\n EngineMarker,\n EngineMetronomeConfig,\n EngineMidiClipSchedule,\n EngineParameterInfo,\n EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTrackLane,\n EngineTrackMonitorMode,\n EngineTrackSend,\n EngineTransportState,\n EqBand,\n MidiCcBindOptions,\n PanLaw,\n PanMode,\n} from '../index';\nimport { RealtimeEngine } from '../index';\nimport { createOpfsClipPageProvider, type OpfsClipPageProviderBinding } from '../opfs_clip_pages';\nimport type { ClipPageProvider } from '../realtime_engine';\nimport type { EngineAutomationContext } from './engine-automation';\nimport * as automation from './engine-automation';\nimport type { EngineCaptureContext } from './engine-capture-facade';\nimport * as capture from './engine-capture-facade';\nimport type { EngineClipContext } from './engine-clips';\nimport * as clips from './engine-clips';\nimport type { EngineMarkerContext } from './engine-markers';\nimport * as markers from './engine-markers';\nimport type { EngineMixerContext } from './engine-mixer-facade';\nimport * as mixer from './engine-mixer-facade';\nimport { SonareRealtimeEngineNode } from './engine-node';\nimport { buildTransportFacade, type CaptureOptions } from './engine-offline';\nimport type { SonareEngineOptions, SuspendableAudioContext } from './engine-options';\nimport type { EngineParameterContext } from './engine-parameter-facade';\nimport * as parameter from './engine-parameter-facade';\nimport type { EngineStripContext } from './engine-strips';\nimport * as strips from './engine-strips';\nimport { resolveParamId, resolveTargetId } from './engine-sync';\nimport type { EngineTempoContext } from './engine-tempo-facade';\nimport * as tempo from './engine-tempo-facade';\nimport type {\n SonareEngineInstrumentSyncMessage,\n SonareEngineSyncCaptureMessage,\n SonareEngineSyncMessage,\n SonareEngineTransportFacade,\n SonareRealtimeEngineNodeCapabilities,\n SonareWorkletExternalMidiEvent,\n} from './messages';\nimport {\n ENGINE_MIXER_PARAM_FADER_DB,\n ENGINE_MIXER_PARAM_PAN,\n engineMixerLaneTarget,\n engineMixerMasterTarget,\n SonareEngineCommandType,\n type SonareEngineTelemetryRecord,\n type SonareWorkletMeterSnapshot,\n type SonareWorkletScopeSnapshot,\n} from './protocol';\n\nconst MAX_PENDING_WORKLET_CLIP_PAGE_REQUESTS = 256;\n\nfunction transferableAudioBuffers(channels: readonly Float32Array[]): Transferable[] {\n const transfers: ArrayBuffer[] = [];\n const seen = new Set<ArrayBuffer>();\n for (const channel of channels) {\n const buffer = channel.buffer;\n // SharedArrayBuffer is cloneable but cannot appear in a transfer list. A\n // worker may intentionally return SAB-backed pages, so transfer only plain,\n // distinct ArrayBuffers and let structured clone share SABs by reference.\n if (buffer instanceof ArrayBuffer && !seen.has(buffer)) {\n seen.add(buffer);\n transfers.push(buffer);\n }\n }\n return transfers;\n}\n\nexport class SonareEngine {\n readonly node: AudioWorkletNode;\n readonly capabilities: SonareRealtimeEngineNodeCapabilities;\n readonly transport: SonareEngineTransportFacade;\n private readonly realtimeNode: SonareRealtimeEngineNode;\n private readonly offlineEngine: RealtimeEngine;\n private readonly context: SuspendableAudioContext;\n private readonly sampleRate: number;\n private readonly offlineBlockSize: number;\n private readonly offlineChannelCount: number;\n private readonly automationLanes = new Map<number, EngineAutomationPoint[]>();\n private readonly clips = new Map<number, EngineClip>();\n private readonly midiClips = new Map<number, EngineMidiClipSchedule>();\n private readonly markers = new Map<number, EngineMarker>();\n private readonly trackLaneIds: number[] = [];\n private readonly trackSends = new Map<number, EngineTrackSend[]>();\n private readonly trackOutputBus = new Map<number, number>();\n private readonly laneSidechains = new Map<\n string,\n { trackId: number; insertIndex: number; sourceTrackId: number }\n >();\n private readonly buses: EngineBus[] = [];\n private readonly trackStripJson = new Map<number, string>();\n private readonly busStripJson = new Map<number, string>();\n private masterStripJson: string | undefined;\n private captureConfig: Omit<SonareEngineSyncCaptureMessage, 'type'> | undefined;\n private tempoBpm = 120;\n private timeSignature = { numerator: 4, denominator: 4 };\n private tempoSegments: EngineTempoSegment[] = [{ startPpq: 0, bpm: 120 }];\n private timeSignatureSegments: EngineTimeSignatureSegment[] = [\n { startPpq: 0, numerator: 4, denominator: 4 },\n ];\n private latestTransportState: EngineTransportState | undefined;\n private nextClipId = 1;\n private nextMarkerId = 1;\n private transportPlaying = false;\n private readonly pendingInstrumentSync: SonareEngineInstrumentSyncMessage[] = [];\n // One latest frontier per clip is sufficient: ClipPageStreamer expands it to\n // the bounded read window. A Map both coalesces repeated page misses and\n // places a hard cap on work queued while OPFS I/O is stalled.\n private readonly workletClipPageRequests = new Map<number, ClipPageStreamerRequest>();\n private readonly workletPageProviderClipIds = new Map<number, number>();\n private workletClipStreamer: ClipPageStreamer | undefined;\n private workletClipPump: Promise<void> | undefined;\n private workletClipPagePollTimer: ReturnType<typeof setInterval> | undefined;\n private unsubscribeWorkletClipRequests: (() => void) | undefined;\n private destroyed = false;\n\n private constructor(\n context: BaseAudioContext,\n realtimeNode: SonareRealtimeEngineNode,\n offlineEngine: RealtimeEngine,\n sampleRate: number,\n offlineBlockSize: number,\n offlineChannelCount: number,\n ) {\n this.context = context;\n this.realtimeNode = realtimeNode;\n this.offlineEngine = offlineEngine;\n this.node = realtimeNode.node;\n this.capabilities = realtimeNode.capabilities;\n this.sampleRate = sampleRate;\n this.offlineBlockSize = offlineBlockSize;\n this.offlineChannelCount = offlineChannelCount;\n this.unsubscribeWorkletClipRequests = this.realtimeNode.onClipPageRequests((message) => {\n for (const request of message.requests) {\n this.enqueueWorkletClipPageRequest(request);\n }\n this.pumpWorkletClipPages();\n });\n this.transport = buildTransportFacade({\n sampleRate: this.sampleRate,\n realtimeNode: this.realtimeNode,\n offlineEngine: this.offlineEngine,\n flushOfflineMirror: () => this.flushOfflineMirror(),\n setTransportPlaying: (playing) => {\n this.transportPlaying = playing;\n },\n flushPendingInstrumentSync: () => this.flushPendingInstrumentSync(),\n setTempo: (bpm) => this.setTempo(bpm),\n setTempoSegments: (segments) => this.setTempoSegments(segments),\n setLoop: (startPpq, endPpq, enabled) => this.setLoop(startPpq, endPpq, enabled),\n });\n }\n\n static async create(\n context: BaseAudioContext,\n options: SonareEngineOptions = {},\n ): Promise<SonareEngine> {\n const sampleRate = options.sampleRate ?? context.sampleRate;\n const blockSize = options.offlineBlockSize ?? options.blockSize ?? 128;\n const channelCount = Math.max(\n 1,\n Math.floor(options.offlineChannelCount ?? options.channelCount ?? 2),\n );\n const realtimeNode = await SonareRealtimeEngineNode.create(context, options);\n try {\n // Do not expose the facade while the registered processor is still\n // buffering messages. Long clip sync must either begin after the bridge\n // is ready or fail explicitly; it may never be silently truncated.\n await realtimeNode.ready;\n } catch (error) {\n realtimeNode.destroy();\n throw error;\n }\n const offlineEngine = options.offlineEngine ?? new RealtimeEngine(sampleRate, blockSize);\n const engine = new SonareEngine(\n context,\n realtimeNode,\n offlineEngine,\n sampleRate,\n blockSize,\n channelCount,\n );\n engine.syncParameters();\n return engine;\n }\n\n async suspend(): Promise<void> {\n if (this.destroyed) {\n return;\n }\n await this.context.suspend?.();\n }\n\n async resume(): Promise<void> {\n if (this.destroyed) {\n return;\n }\n await this.context.resume?.();\n }\n\n setTempo(bpm: number): void {\n tempo.setTempo(this.tempoContext, bpm);\n }\n\n setTempoSegments(segments: readonly EngineTempoSegment[]): void {\n tempo.setTempoSegments(this.tempoContext, segments);\n }\n\n setTimeSignature(numerator: number, denominator: number): void {\n tempo.setTimeSignature(this.tempoContext, numerator, denominator);\n }\n\n setTimeSignatureSegments(segments: readonly EngineTimeSignatureSegment[]): void {\n tempo.setTimeSignatureSegments(this.tempoContext, segments);\n }\n\n setLoop(startPpq: number, endPpq: number, enabled = true): boolean {\n return tempo.setLoop(this.tempoContext, startPpq, endPpq, enabled);\n }\n\n countInEndSample(startSample: number, bars: number): number {\n return tempo.countInEndSample(this.tempoContext, startSample, bars);\n }\n\n getTransportState(): Promise<EngineTransportState> {\n return tempo.getTransportState(this.tempoContext);\n }\n\n cachedTransportState(): EngineTransportState | undefined {\n return tempo.cachedTransportState(this.tempoContext);\n }\n\n setParam(nodeId: string, param: string | number, value: number): boolean {\n return parameter.setParam(this.parameterContext, nodeId, param, value);\n }\n\n scheduleParam(\n nodeId: string,\n param: string | number,\n ppq: number,\n value: number,\n curve: number | 'linear' | 'exponential' = 'linear',\n ): void {\n automation.scheduleParam(this.automationContext, nodeId, param, ppq, value, curve);\n }\n\n addAutomationPoint(\n laneId: string | number,\n ppq: number,\n value: number,\n curve: number | 'linear' | 'exponential' = 'linear',\n ): void {\n automation.addAutomationPoint(this.automationContext, laneId, ppq, value, curve);\n }\n\n /**\n * Replaces the automation lane for `paramId` with the given breakpoints. An\n * empty array clears the lane; the points are defensively copied and sorted\n * by ppq before mirroring to the offline and live worklet engines.\n */\n setAutomationLane(paramId: number, points: ReadonlyArray<EngineAutomationPoint>): void {\n automation.setAutomationLane(this.automationContext, paramId, points);\n }\n\n /**\n * Returns the automation target id for a mixer strip parameter.\n *\n * The id addresses the engine's reserved mixer namespace, so it can be fed\n * straight to setAutomationLane to automate a fader or pan without\n * registering a parameter.\n *\n * @param target Track id (declares a mixer lane on first use) or 'master'.\n * @param kind Strip parameter to address.\n * @returns Reserved engine parameter id for the strip parameter.\n */\n automationParamId(target: string | number, kind: 'faderDb' | 'pan'): number {\n return parameter.automationParamId(this.parameterContext, target, kind);\n }\n\n /**\n * Returns the automation target id for a bus fader.\n *\n * @param busId Bus id (declares the mixer bus on first use).\n * @returns Reserved engine parameter id for the bus fader gain (dB).\n */\n busAutomationParamId(busId: number): number {\n return parameter.busAutomationParamId(this.parameterContext, busId);\n }\n\n /**\n * Resolves a track-lane insert parameter (JSON-key name) to the reserved\n * insert-automation id fed straight to setAutomationLane. Declares the track's\n * mixer lane first (like automationParamId) so the offline engine resolves the\n * same strip selector the realtime engine uses.\n *\n * @param target Track id (declares a mixer lane on first use).\n * @param insertIndex Index into the strip's combined insert sequence.\n * @param paramName Processor JSON-key parameter name.\n * @returns Reserved insert-automation id, or -1 when strip/insert/key unknown.\n */\n resolveTrackInsertAutomationId(\n target: string | number,\n insertIndex: number,\n paramName: string,\n ): number {\n return parameter.resolveTrackInsertAutomationId(\n this.parameterContext,\n target,\n insertIndex,\n paramName,\n );\n }\n\n /**\n * Resolves a master-strip insert parameter to its reserved insert-automation\n * id.\n *\n * @param insertIndex Index into the master strip's insert sequence.\n * @param paramName Processor JSON-key parameter name.\n * @returns Reserved insert-automation id, or -1 when insert/key unknown.\n */\n resolveMasterInsertAutomationId(insertIndex: number, paramName: string): number {\n return parameter.resolveMasterInsertAutomationId(this.parameterContext, insertIndex, paramName);\n }\n\n /**\n * Resolves a bus-strip insert parameter to its reserved insert-automation id.\n * Declares the mixer bus first so the offline engine resolves the same bus\n * selector.\n *\n * @param busId Bus id (declares the mixer bus on first use).\n * @param insertIndex Index into the bus strip's insert sequence.\n * @param paramName Processor JSON-key parameter name.\n * @returns Reserved insert-automation id, or -1 when bus/insert/key unknown.\n */\n resolveBusInsertAutomationId(busId: number, insertIndex: number, paramName: string): number {\n return parameter.resolveBusInsertAutomationId(\n this.parameterContext,\n busId,\n insertIndex,\n paramName,\n );\n }\n\n /**\n * Returns the number of automation lanes installed on the engine, including\n * lanes whose breakpoint list is currently empty.\n *\n * @returns Engine-side automation lane count.\n */\n automationLaneCount(): number {\n return parameter.automationLaneCount(this.parameterContext);\n }\n\n listParameters(): EngineParameterInfo[] {\n return parameter.listParameters(this.parameterContext);\n }\n\n /** Registers a custom parameter on the offline mirror and worklet engine. */\n addParameter(info: EngineParameterInfo): void {\n parameter.addParameter(this.parameterContext, info);\n }\n\n /** Clears custom parameters and their automation lanes on both engines. */\n clearParameters(): void {\n parameter.clearParameters(this.parameterContext);\n }\n\n setSoloMute(target: string | number, solo: boolean, mute: boolean): boolean {\n return parameter.setSoloMute(this.parameterContext, target, solo, mute);\n }\n\n /** Queues a per-track PFL/AFL monitor tap mode change. */\n setTrackMonitorMode(\n target: string | number,\n mode: EngineTrackMonitorMode,\n renderFrame = -1,\n ): boolean {\n return parameter.setTrackMonitorMode(this.parameterContext, target, mode, renderFrame);\n }\n\n setStripGain(target: string | number, db: number): boolean {\n return this.sendSmoothedParam(this.stripParamId(target, ENGINE_MIXER_PARAM_FADER_DB), db);\n }\n\n setStripPan(target: string | number, pan: number): boolean {\n return this.sendSmoothedParam(this.stripParamId(target, ENGINE_MIXER_PARAM_PAN), pan);\n }\n\n /**\n * Declares the mixer track lanes in an explicit order.\n *\n * Lane indices are append-only: once a track id occupies a lane, its index\n * stays fixed for the engine's lifetime. The given list must therefore start\n * with the already-declared lane ids in their current order and may only\n * append new track ids after them. Entries carrying `sends` replace that\n * track's send list; entries without `sends` leave existing sends untouched.\n *\n * @param lanes Track ids or lane descriptors in the desired lane order.\n */\n setTrackLanes(lanes: ReadonlyArray<number | EngineTrackLane>): void {\n mixer.setTrackLanes(this.mixerContext, lanes);\n }\n\n /**\n * Routes a track lane's post-fader output into a declared bus instead of\n * the master mix (group/folder routing); busId 0 restores the master mix.\n */\n setTrackOutputBus(target: string | number, busId: number): void {\n mixer.setTrackOutputBus(this.mixerContext, target, busId);\n }\n\n /**\n * Keys one insert of a lane strip from another lane's post-strip pre-fader\n * audio (ducking/sidechainRouter inserts). sourceTarget null removes the\n * binding.\n */\n setLaneSidechain(\n target: string | number,\n insertIndex: number,\n sourceTarget: string | number | null,\n ): void {\n mixer.setLaneSidechain(this.mixerContext, target, insertIndex, sourceTarget);\n }\n\n setSends(target: string | number, sends: EngineTrackSend[]): void {\n mixer.setSends(this.mixerContext, target, sends);\n }\n\n setTrackBuses(buses: EngineBus[]): void {\n mixer.setTrackBuses(this.mixerContext, buses);\n }\n\n setBusGain(busId: number, db: number): boolean {\n return mixer.setBusGain(this.mixerContext, busId, db);\n }\n\n setTrackStripJson(target: string | number, sceneJson: string): void {\n const laneIndex = this.ensureTrackLane(target);\n const trackId = this.trackLaneIds[laneIndex];\n strips.setTrackStripJson(this.stripContext, trackId, sceneJson, this.trackStripJson);\n this.syncMixer();\n }\n\n setTrackStripEqBand(target: string | number, bandIndex: number, band: EqBand | string): void {\n strips.setTrackStripEqBand(this.stripContext, target, bandIndex, band);\n }\n\n setTrackStripInsertBypassed(\n target: string | number,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n strips.setTrackStripInsertBypassed(\n this.stripContext,\n target,\n insertIndex,\n bypassed,\n resetOnBypass,\n );\n }\n\n setTrackStripInsertParamByName(\n target: string | number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n strips.setTrackStripInsertParamByName(this.stripContext, target, insertIndex, paramName, value);\n }\n\n setTrackStripPan(target: string | number, pan: number): void {\n strips.setTrackStripPan(this.stripContext, target, pan);\n }\n\n setTrackStripPanLaw(target: string | number, panLaw: PanLaw | number): void {\n strips.setTrackStripPanLaw(this.stripContext, target, panLaw);\n }\n\n setTrackStripPanMode(target: string | number, panMode: PanMode | number): void {\n strips.setTrackStripPanMode(this.stripContext, target, panMode);\n }\n\n setTrackStripDualPan(target: string | number, leftPan: number, rightPan: number): void {\n strips.setTrackStripDualPan(this.stripContext, target, leftPan, rightPan);\n }\n\n setTrackStripChannelDelaySamples(target: string | number, delaySamples: number): void {\n strips.setTrackStripChannelDelaySamples(this.stripContext, target, delaySamples);\n }\n\n setStripEq(target: string | number, bandIndex: number, band: EqBand | string): void {\n if (target === 'master') {\n this.setMasterStripEqBand(bandIndex, band);\n return;\n }\n this.setTrackStripEqBand(target, bandIndex, band);\n }\n\n setStripInsertBypassed(\n target: string | number,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n if (target === 'master') {\n this.setMasterStripInsertBypassed(insertIndex, bypassed, resetOnBypass);\n return;\n }\n this.setTrackStripInsertBypassed(target, insertIndex, bypassed, resetOnBypass);\n }\n\n setStripInserts(target: string | number, sceneJson: string): void {\n if (target === 'master') {\n this.setMasterStripJson(sceneJson);\n return;\n }\n this.setTrackStripJson(target, sceneJson);\n }\n\n setBusStripJson(busId: number, sceneJson: string): void {\n mixer.setBusStripJson(this.mixerContext, busId, sceneJson);\n }\n\n setMasterStripJson(sceneJson: string): void {\n this.offlineEngine.setMasterStripJson(sceneJson);\n this.masterStripJson = sceneJson;\n this.syncMixer();\n }\n\n setMasterStripEqBand(bandIndex: number, band: EqBand | string): void {\n strips.setMasterStripEqBand(this.stripContext, bandIndex, band);\n }\n\n setMasterStripInsertBypassed(\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n strips.setMasterStripInsertBypassed(this.stripContext, insertIndex, bypassed, resetOnBypass);\n }\n\n setMasterStripInsertParamByName(insertIndex: number, paramName: string, value: number): void {\n strips.setMasterStripInsertParamByName(this.stripContext, insertIndex, paramName, value);\n }\n\n setBusStripInsertParamByName(\n busId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n this.ensureBus(busId);\n strips.setBusStripInsertParamByName(this.stripContext, busId, insertIndex, paramName, value);\n }\n\n setStripInsertParamByName(\n target: string | number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n if (target === 'master') {\n this.setMasterStripInsertParamByName(insertIndex, paramName, value);\n return;\n }\n this.setTrackStripInsertParamByName(target, insertIndex, paramName, value);\n }\n\n setMasterChain(sceneJson: string): void {\n this.setMasterStripJson(sceneJson);\n }\n\n /**\n * Creates and primes an OPFS-backed page provider for this live worklet\n * engine. Pass the returned `provider` to {@link addClip} in place of a\n * `Float32Array[]`; the `clipId` in `options` must equal that clip's explicit\n * `opts.id`. Subsequent cache misses are fetched on the main thread and\n * supplied back to the worklet through its bounded pull protocol.\n */\n async attachOpfsClipStream(\n options: OpfsClipStreamOptions,\n ): Promise<{ binding: OpfsClipPageProviderBinding; provider: ClipPageProvider }> {\n if (this.destroyed) {\n throw new Error('SonareEngine is destroyed.');\n }\n if (!this.capabilities.clipPageRequestsRealtimeSafe) {\n throw new Error(\n 'OPFS clip streaming requires SharedArrayBuffer clip-page requests; the postMessage fallback is not realtime-safe.',\n );\n }\n const { clipId, primePages = 1, ...providerOptions } = options;\n if ([...this.workletPageProviderClipIds.values()].includes(clipId)) {\n throw new Error(`An OPFS stream is already attached for clip ${clipId}.`);\n }\n const streamer = this.ensureWorkletClipStreamer();\n // Allocate the worklet-owned provider before priming: port message order\n // ensures every prime page is adopted before addClip commits its schedule.\n this.postSync({\n type: 'syncClipPageProvider',\n clipId,\n numChannels: providerOptions.numChannels,\n numSamples: providerOptions.numSamples,\n pageFrames: providerOptions.pageFrames,\n });\n let binding: OpfsClipPageProviderBinding;\n binding = createOpfsClipPageProvider(this.offlineEngine, {\n ...providerOptions,\n onPageSupplied: (pageIndex, channels) => {\n this.postSync(\n { type: 'syncClipPage', clipId, pageIndex, channels },\n transferableAudioBuffers(channels),\n );\n },\n onPageCleared: (pageIndex) => {\n this.postSync({ type: 'syncClipPageClear', clipId, pageIndex });\n },\n onClose: () => {\n this.workletPageProviderClipIds.delete(binding.provider.id);\n this.postSync({ type: 'syncClipPageDestroy', clipId });\n },\n });\n this.workletPageProviderClipIds.set(binding.provider.id, clipId);\n const lastPage = Math.ceil(providerOptions.numSamples / providerOptions.pageFrames) - 1;\n const primed: number[] = [];\n try {\n for (let page = 0; page < primePages && page <= lastPage; ++page) {\n if (await binding.supplyPage(page)) {\n primed.push(page);\n }\n }\n streamer.addSource(\n {\n clipId,\n binding,\n pageFrames: providerOptions.pageFrames,\n numSamples: providerOptions.numSamples,\n },\n primed,\n );\n this.startWorkletClipPagePolling();\n } catch (error) {\n binding.close();\n throw error;\n }\n return { binding, provider: binding.provider };\n }\n\n addClip(\n trackId: string | number,\n buffer: Float32Array[] | ClipPageProvider,\n startPpq: number,\n opts: Partial<Omit<EngineClip, 'channels' | 'pageProvider' | 'startPpq'>> = {},\n ): number {\n return clips.addClip(this.clipContext, trackId, buffer, startPpq, opts);\n }\n\n removeClip(clipId: number): void {\n clips.removeClip(this.clipContext, clipId);\n }\n\n setMidiClips(schedules: readonly EngineMidiClipSchedule[]): void {\n clips.setMidiClips(this.clipContext, schedules);\n }\n\n setBuiltinInstrument(\n trackId: string | number,\n config: { destinationId?: number } & Record<string, unknown> = {},\n ): void {\n strips.setBuiltinInstrument(this.stripContext, trackId, config);\n }\n\n setSynthInstrument(trackId: string | number, patch: Record<string, unknown> | string = {}): void {\n strips.setSynthInstrument(this.stripContext, trackId, patch);\n }\n\n loadSoundFont(data: Uint8Array): void {\n strips.loadSoundFont(this.stripContext, data);\n }\n\n setSf2Instrument(\n trackId: string | number,\n config: {\n destinationId?: number;\n gain?: number;\n polyphony?: number;\n preferModelForModeledFamilies?: boolean;\n } = {},\n ): void {\n strips.setSf2Instrument(this.stripContext, trackId, config);\n }\n\n /**\n * Route a track's MIDI to the external output (drained via {@link onMidiOut})\n * instead of an internal instrument, so the track plays an external device.\n * Pass `external=false` to restore internal-synth playback.\n */\n setMidiDestinationExternal(trackId: string | number, external: boolean): void {\n strips.setMidiDestinationExternal(this.stripContext, trackId, external);\n }\n\n /**\n * Enable/disable forwarding MIDI clock + transport (start/continue/stop) to\n * the external output so external gear tracks the transport tempo. The bytes\n * arrive through {@link onMidiOut} tagged with the transport destination.\n */\n setExternalMidiClockEnabled(enabled: boolean): void {\n strips.setExternalMidiClockEnabled(this.stripContext, enabled);\n }\n\n /**\n * Install or replace a live, non-destructive MIDI-FX insert for one\n * destination. The insert transforms the destination's MIDI before\n * synthesis (transpose, quantize, velocity shaping, humanize, harmonize,\n * arpeggiate) without rewriting any stored notes, so it can be bypassed by\n * {@link clearMidiFx}. The config JSON is the flat object the engine's\n * MIDI-FX accepts (the same schema as the offline `Project.bakeMidiFx`).\n */\n setMidiFx(trackId: string | number, configJson: string): void {\n strips.setMidiFx(this.stripContext, trackId, configJson);\n }\n\n /** Remove the live MIDI-FX insert from one destination (a no-op when none). */\n clearMidiFx(trackId: string | number): void {\n strips.clearMidiFx(this.stripContext, trackId);\n }\n\n pushMidiNoteOn(\n trackId: string | number,\n group: number,\n channel: number,\n note: number,\n velocity: number,\n renderFrame = -1,\n ): void {\n strips.pushMidiNoteOn(this.stripContext, trackId, group, channel, note, velocity, renderFrame);\n }\n\n pushMidiNoteOff(\n trackId: string | number,\n group: number,\n channel: number,\n note: number,\n velocity = 0,\n renderFrame = -1,\n ): void {\n strips.pushMidiNoteOff(this.stripContext, trackId, group, channel, note, velocity, renderFrame);\n }\n\n pushMidiCc(\n trackId: string | number,\n group: number,\n channel: number,\n controller: number,\n value: number,\n renderFrame = -1,\n ): void {\n strips.pushMidiCc(this.stripContext, trackId, group, channel, controller, value, renderFrame);\n }\n\n pushMidiUmp(trackId: string | number, word0: number, renderFrame = -1): void {\n strips.pushMidiUmp(this.stripContext, trackId, word0, renderFrame);\n }\n\n pushMidiSysex(trackId: string | number, data: Uint8Array, renderFrame = -1): void {\n strips.pushMidiSysex(this.stripContext, trackId, data, renderFrame);\n }\n\n bindMidiCc(\n channel: number,\n controller: number,\n paramId: number,\n options: MidiCcBindOptions = {},\n ): void {\n const minValue = options.minValue ?? 0;\n const maxValue = options.maxValue ?? 1;\n this.offlineEngine.bindMidiCc(channel, controller, paramId, { minValue, maxValue });\n this.postSync({ type: 'syncMidiCcBinding', channel, controller, paramId, minValue, maxValue });\n }\n\n setMidiInputSource(destinationId = 0): void {\n this.offlineEngine.setMidiInputSource(destinationId);\n this.postSync({ type: 'syncMidiInputSource', destinationId });\n }\n\n clearMidiInputSource(): void {\n this.offlineEngine.clearMidiInputSource();\n this.postSync({ type: 'syncClearMidiInputSource' });\n }\n\n pushMidiInputNoteOn(\n group: number,\n channel: number,\n note: number,\n velocity: number,\n portTimeSamples = 0,\n ): void {\n this.offlineEngine.pushMidiInputNoteOn(group, channel, note, velocity, portTimeSamples);\n this.postSync({\n type: 'syncMidiInputNoteOn',\n group,\n channel,\n data0: note,\n data1: velocity,\n portTimeSamples,\n });\n }\n\n pushMidiInputNoteOff(\n group: number,\n channel: number,\n note: number,\n velocity = 0,\n portTimeSamples = 0,\n ): void {\n this.offlineEngine.pushMidiInputNoteOff(group, channel, note, velocity, portTimeSamples);\n this.postSync({\n type: 'syncMidiInputNoteOff',\n group,\n channel,\n data0: note,\n data1: velocity,\n portTimeSamples,\n });\n }\n\n pushMidiInputCc(\n group: number,\n channel: number,\n controller: number,\n value: number,\n portTimeSamples = 0,\n ): void {\n this.offlineEngine.pushMidiInputCc(group, channel, controller, value, portTimeSamples);\n this.postSync({\n type: 'syncMidiInputCc',\n group,\n channel,\n data0: controller,\n data1: value,\n portTimeSamples,\n });\n }\n\n pushMidiPanic(renderFrame = -1): void {\n this.offlineEngine.pushMidiPanic(renderFrame);\n this.postSync({ type: 'syncMidiPanic', renderFrame });\n }\n\n configureCapture(options: CaptureOptions): void {\n capture.configureCapture(this.captureContext, options);\n }\n\n /**\n * Arms the engine-global capture path. `trackId` is retained for source\n * compatibility and must be `0`; per-track capture is not implemented.\n */\n armRecord(trackId: string | number, enabled: boolean): boolean {\n return capture.armRecord(this.captureContext, trackId, enabled);\n }\n\n punch(inPpq: number, outPpq: number): boolean {\n return capture.punch(this.captureContext, inPpq, outPpq);\n }\n\n captureStatus(): Promise<EngineCaptureStatus> {\n return capture.captureStatus(this.captureContext);\n }\n\n capturedAudio(): Promise<Float32Array[]> {\n return capture.capturedAudio(this.captureContext);\n }\n\n async resetCapture(): Promise<void> {\n return capture.resetCapture(this.captureContext);\n }\n\n setMetronome(opts: EngineMetronomeConfig): void {\n this.offlineEngine.setMetronome(opts);\n // The full config (beatGain/accentGain/clickSamples/clickSeconds) cannot fit\n // the fixed-size SAB command record, so it is delivered out-of-band; the\n // SetMetronome command then toggles enabled state on the audio thread.\n this.postSync({ type: 'syncMetronome', config: opts });\n this.sendMirroredCommand({\n type: SonareEngineCommandType.SetMetronome,\n sampleTime: -1,\n argInt: opts.enabled ? 1 : 0,\n });\n }\n\n addMarker(ppq: number, name = ''): number {\n return markers.addMarker(this.markerContext, ppq, name);\n }\n\n /**\n * Replaces the whole marker set in one call. Entries without an `id` are\n * assigned fresh ids; entries carrying an `id` keep it. Returns the resolved\n * markers in the order given.\n */\n setMarkers(entries: ReadonlyArray<{ ppq: number; name?: string; id?: number }>): EngineMarker[] {\n return markers.setMarkers(this.markerContext, entries);\n }\n\n markerCount(): number {\n return markers.markerCount(this.markerContext);\n }\n\n markerByIndex(index: number): EngineMarker {\n return markers.markerByIndex(this.markerContext, index);\n }\n\n marker(markerId: number): EngineMarker {\n return markers.marker(this.markerContext, markerId);\n }\n\n seekMarker(markerId: number): boolean {\n return markers.seekMarker(this.markerContext, markerId);\n }\n\n setLoopFromMarkers(startMarkerId: number, endMarkerId: number): boolean {\n return markers.setLoopFromMarkers(this.markerContext, startMarkerId, endMarkerId);\n }\n\n async renderOffline(totalFrames: number): Promise<Float32Array[]> {\n const frames = Math.max(0, Math.floor(totalFrames));\n const inputs: Float32Array[] = [];\n for (let ch = 0; ch < this.offlineChannelCount; ch++) {\n inputs.push(new Float32Array(frames));\n }\n return this.offlineEngine.renderOffline(inputs, this.offlineBlockSize);\n }\n\n /**\n * Subscribe to external-MIDI batches (already lowered to MIDI 1.0 bytes) for\n * delivery to Web MIDI output ports. Fires once per render block that\n * produced events. Returns an unsubscribe function.\n */\n onMidiOut(callback: (events: SonareWorkletExternalMidiEvent[]) => void): () => void {\n return this.realtimeNode.onMidiOut(callback);\n }\n\n onMeter(callback: (meter: SonareWorkletMeterSnapshot) => void): () => void {\n return this.realtimeNode.onMeter(callback);\n }\n\n onScope(callback: (scope: SonareWorkletScopeSnapshot) => void): () => void {\n return this.realtimeNode.onScope(callback);\n }\n\n onTelemetry(callback: (telemetry: SonareEngineTelemetryRecord) => void): () => void {\n return this.realtimeNode.onTelemetry(callback);\n }\n\n pollTelemetry(): SonareEngineTelemetryRecord[] {\n return this.realtimeNode.pollTelemetry();\n }\n\n pollMeters(): SonareWorkletMeterSnapshot[] {\n return this.realtimeNode.pollMeters();\n }\n\n pollScope(): SonareWorkletScopeSnapshot[] {\n return this.realtimeNode.pollScope();\n }\n\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n this.unsubscribeWorkletClipRequests?.();\n this.unsubscribeWorkletClipRequests = undefined;\n this.workletClipStreamer?.close();\n this.workletClipStreamer = undefined;\n if (this.workletClipPagePollTimer !== undefined) {\n clearInterval(this.workletClipPagePollTimer);\n this.workletClipPagePollTimer = undefined;\n }\n this.workletClipPageRequests.clear();\n this.destroyed = true;\n this.transport.stop();\n this.realtimeNode.pollTelemetry();\n this.realtimeNode.destroy();\n this.offlineEngine.destroy();\n }\n\n private ensureWorkletClipStreamer(): ClipPageStreamer {\n if (!this.workletClipStreamer) {\n this.workletClipStreamer = new ClipPageStreamer({\n popClipPageRequest: () => this.popWorkletClipPageRequest(),\n });\n }\n return this.workletClipStreamer;\n }\n\n /**\n * SAB requests have no postMessage wake-up by design. Polling on the main\n * thread is therefore intentionally outside the audio callback; 8 ms keeps\n * the bounded OPFS prefetch frontier responsive without adding worklet GC.\n */\n private startWorkletClipPagePolling(): void {\n if (this.workletClipPagePollTimer !== undefined) {\n return;\n }\n const poll = () => {\n if (!this.destroyed) {\n this.realtimeNode.pollClipPageRequests();\n }\n };\n poll();\n this.workletClipPagePollTimer = setInterval(poll, 8);\n }\n\n private pumpWorkletClipPages(): void {\n const streamer = this.workletClipStreamer;\n if (!streamer || this.workletClipPump) {\n return;\n }\n this.workletClipPump = streamer\n .pump()\n .catch((error: unknown) => {\n // The worklet keeps rendering silence for an unavailable page. Surface\n // I/O failures without converting them into an AudioWorklet exception.\n // biome-ignore lint/suspicious/noConsole: asynchronous OPFS diagnostic.\n console.error('Sonare OPFS clip-page supply failed:', error);\n })\n .finally(() => {\n this.workletClipPump = undefined;\n if (this.workletClipPageRequests.size > 0) {\n this.pumpWorkletClipPages();\n }\n });\n }\n\n private enqueueWorkletClipPageRequest(request: ClipPageStreamerRequest): void {\n if (\n !Number.isInteger(request.clipId) ||\n request.clipId < 0 ||\n !Number.isInteger(request.pageIndex) ||\n (request.pageIndex ?? -1) < 0\n ) {\n return;\n }\n // Reinsert an existing id so iteration order represents newest frontiers.\n this.workletClipPageRequests.delete(request.clipId);\n if (this.workletClipPageRequests.size >= MAX_PENDING_WORKLET_CLIP_PAGE_REQUESTS) {\n const oldest = this.workletClipPageRequests.keys().next().value;\n if (oldest !== undefined) {\n this.workletClipPageRequests.delete(oldest);\n }\n }\n this.workletClipPageRequests.set(request.clipId, request);\n }\n\n private popWorkletClipPageRequest(): ClipPageStreamerRequest | null {\n const entry = this.workletClipPageRequests.entries().next().value;\n if (!entry) {\n return null;\n }\n const [clipId, request] = entry;\n this.workletClipPageRequests.delete(clipId);\n return request;\n }\n\n private commitWorkletClipPageProvider(clip: EngineClip): boolean {\n const providerId =\n typeof clip.pageProvider === 'object' && clip.pageProvider !== null\n ? clip.pageProvider.id\n : clip.pageProvider;\n if (providerId === undefined) {\n return false;\n }\n const clipId = this.workletPageProviderClipIds.get(providerId);\n if (clipId === undefined) {\n return false;\n }\n if (clip.id !== clipId) {\n throw new Error(`OPFS stream clipId ${clipId} must match addClip(..., { id: ${clipId} }).`);\n }\n this.postSync({\n type: 'syncClipPageCommit',\n clipId,\n clip: { ...clip, channels: undefined, pageProvider: undefined },\n });\n return true;\n }\n\n private mixerLanes(): EngineTrackLane[] {\n return mixer.mixerLanes(this.mixerContext);\n }\n\n private syncMixer(): void {\n mixer.syncMixer(this.mixerContext);\n }\n\n private postInstrumentSync(message: SonareEngineInstrumentSyncMessage): void {\n if (this.destroyed) {\n return;\n }\n if (this.transportPlaying) {\n this.pendingInstrumentSync.push(message);\n return;\n }\n this.postSync(message);\n }\n\n private flushPendingInstrumentSync(): void {\n if (this.destroyed || this.pendingInstrumentSync.length === 0) {\n return;\n }\n const pending = this.pendingInstrumentSync.splice(0);\n for (const message of pending) {\n this.postSync(message);\n }\n }\n\n // Posts an out-of-band control-sync message to the worklet engine processor.\n // Sync messages use a string `type` so the worklet's message handler routes\n // them to receiveSync() (numeric `type` is reserved for SonareEngineCommandRecord).\n private postSync(message: SonareEngineSyncMessage, transfer?: Transferable[]): void {\n if (this.destroyed) {\n return;\n }\n try {\n if (transfer && transfer.length > 0) {\n this.realtimeNode.node.port.postMessage(message, transfer);\n } else {\n this.realtimeNode.node.port.postMessage(message);\n }\n } finally {\n this.flushOfflineMirror();\n }\n }\n\n // The offline engine is a control-thread mirror. It has no render loop to\n // drain its command ring, so drain it after each control operation. Never\n // call this from the worklet/audio path: it is intentionally control-only.\n private flushOfflineMirror(): void {\n this.offlineEngine.flushControlCommands();\n }\n\n private sendMirroredCommand(\n command: Parameters<SonareRealtimeEngineNode['sendCommand']>[0],\n ): boolean {\n const accepted = this.realtimeNode.sendCommand(command);\n this.flushOfflineMirror();\n return accepted;\n }\n\n // Collaborator surface handed to the mixer/routing free functions so they can\n // mutate the routing stores (held by reference), mirror into the offline\n // engine, post mixer-sync messages, and declare lanes/buses without a\n // back-reference to the whole engine.\n private get mixerContext(): EngineMixerContext {\n return {\n offlineEngine: this.offlineEngine,\n trackLaneIds: this.trackLaneIds,\n trackSends: this.trackSends,\n trackOutputBus: this.trackOutputBus,\n laneSidechains: this.laneSidechains,\n buses: this.buses,\n trackStripJson: this.trackStripJson,\n busStripJson: this.busStripJson,\n postSync: (message) => this.postSync(message),\n ensureTrackLane: (target) => this.ensureTrackLane(target),\n ensureBus: (busId) => this.ensureBus(busId),\n mixerLanes: () => this.mixerLanes(),\n syncMixer: () => this.syncMixer(),\n sendSmoothedParam: (paramId, value) => this.sendSmoothedParam(paramId, value),\n getMasterStripJson: () => this.masterStripJson,\n };\n }\n\n // Collaborator surface handed to the strip/pan/EQ/insert/MIDI free functions\n // so they can mirror into the offline engine, post sync messages, and resolve\n // lanes without each holding a back-reference to the whole engine.\n private get stripContext(): EngineStripContext {\n return {\n offlineEngine: this.offlineEngine,\n trackLaneIds: this.trackLaneIds,\n postSync: (message) => this.postSync(message),\n postInstrumentSync: (message) => this.postInstrumentSync(message),\n ensureTrackLane: (target) => this.ensureTrackLane(target),\n resolveTargetId: (target) => this.resolveTargetId(target),\n };\n }\n\n // Collaborator surface handed to the automation-lane free functions so they\n // can mutate the lane store, mirror into the offline engine, and post\n // automation-sync messages without holding a back-reference.\n private get automationContext(): EngineAutomationContext {\n return {\n offlineEngine: this.offlineEngine,\n automationLanes: this.automationLanes,\n postSync: (message) => this.postSync(message),\n resolveParamId: (nodeId, param) => this.resolveParamId(nodeId, param),\n };\n }\n\n // Collaborator surface handed to the capture/record/punch free functions so\n // they can mirror into and query the offline engine, command the realtime\n // node, and read/write the capture config without a back-reference.\n private get captureContext(): EngineCaptureContext {\n return {\n offlineEngine: this.offlineEngine,\n realtimeNode: this.realtimeNode,\n sendCommand: (command) => this.sendMirroredCommand(command),\n offlineChannelCount: this.offlineChannelCount,\n postSync: (message) => this.postSync(message),\n getCaptureConfig: () => this.captureConfig,\n setCaptureConfig: (config) => {\n this.captureConfig = config;\n },\n };\n }\n\n // Collaborator surface handed to the parameter / automation-id resolution\n // free functions so they can mirror into and query the offline engine,\n // command the realtime node, and declare lanes/buses without holding a\n // back-reference to the whole engine.\n private get parameterContext(): EngineParameterContext {\n return {\n offlineEngine: this.offlineEngine,\n sendCommand: (command) => this.sendMirroredCommand(command),\n postSync: (message) => this.postSync(message),\n automationLanes: this.automationLanes,\n trackLaneIds: this.trackLaneIds,\n resolveParamId: (nodeId, param) => this.resolveParamId(nodeId, param),\n ensureTrackLane: (target) => this.ensureTrackLane(target),\n ensureBus: (busId) => this.ensureBus(busId),\n };\n }\n\n // Collaborator surface handed to the tempo / time-signature free functions so\n // they can mirror into the offline engine, command the realtime node, post\n // tempo-sync messages, and mutate the engine's tempo-map state by reference.\n private get tempoContext(): EngineTempoContext {\n return {\n offlineEngine: this.offlineEngine,\n realtimeNode: this.realtimeNode,\n sendCommand: (command) => this.sendMirroredCommand(command),\n postSync: (message) => this.postSync(message),\n getTempoBpm: () => this.tempoBpm,\n setTempoBpm: (bpm) => {\n this.tempoBpm = bpm;\n },\n getTimeSignature: () => this.timeSignature,\n setTimeSignature: (signature) => {\n this.timeSignature = signature;\n },\n getTempoSegments: () => this.tempoSegments,\n setTempoSegments: (segments) => {\n this.tempoSegments = segments;\n },\n getTimeSignatureSegments: () => this.timeSignatureSegments,\n setTimeSignatureSegments: (segments) => {\n this.timeSignatureSegments = segments;\n },\n setLatestTransportState: (state) => {\n this.latestTransportState = state;\n },\n getLatestTransportState: () => this.latestTransportState,\n };\n }\n\n // Collaborator surface handed to the audio/MIDI clip scheduling free\n // functions so they can mutate the clip stores, mirror into the offline\n // engine, and post clip-sync messages without holding a back-reference.\n private get clipContext(): EngineClipContext {\n return {\n offlineEngine: this.offlineEngine,\n clips: this.clips,\n midiClips: this.midiClips,\n allocateClipId: () => this.nextClipId++,\n postSync: (message, transfer) => this.postSync(message, transfer),\n ensureTrackLane: (target) => this.ensureTrackLane(target),\n resolveTargetId: (target) => this.resolveTargetId(target),\n commitWorkletClipPageProvider: (clip) => this.commitWorkletClipPageProvider(clip),\n };\n }\n\n // Collaborator surface handed to the marker free functions so they can mutate\n // the marker store and id counter, mirror into the offline engine, post\n // marker-sync messages, and drive transport without a back-reference.\n private get markerContext(): EngineMarkerContext {\n return {\n offlineEngine: this.offlineEngine,\n markers: this.markers,\n getNextMarkerId: () => this.nextMarkerId,\n setNextMarkerId: (value) => {\n this.nextMarkerId = value;\n },\n postSync: (message) => this.postSync(message),\n sendCommand: (command) => this.sendMirroredCommand(command),\n setLoop: (startPpq, endPpq, enabled) => this.setLoop(startPpq, endPpq, enabled),\n };\n }\n\n // Resolves the reserved mixer parameter id for a fader/pan target, declaring a\n // track lane on first use; 'master' addresses the master strip namespace.\n private stripParamId(target: string | number, paramKind: number): number {\n if (target === 'master') {\n return engineMixerMasterTarget(paramKind);\n }\n return engineMixerLaneTarget(this.ensureTrackLane(target), paramKind);\n }\n\n // Mirrors a smoothed parameter into the offline engine and pushes a\n // sample-accurate smoothed-param command to the realtime runtime.\n private sendSmoothedParam(paramId: number, value: number): boolean {\n this.offlineEngine.setParameter(paramId, value);\n return this.sendMirroredCommand({\n type: SonareEngineCommandType.SetParamSmoothed,\n targetId: paramId,\n sampleTime: -1,\n argFloat: value,\n });\n }\n\n private resolveParamId(nodeId: string, param: string | number): number {\n return resolveParamId(this.listParameters(), nodeId, param);\n }\n\n private syncParameters(): void {\n const parameters = this.listParameters();\n if (parameters.length > 0) {\n this.postSync({ type: 'syncParameters', parameters });\n }\n }\n\n private resolveTargetId(target: string | number): number {\n return resolveTargetId(target);\n }\n\n private ensureTrackLane(target: string | number): number {\n const trackId = this.resolveTargetId(target);\n if (!Number.isInteger(trackId) || trackId <= 0) {\n throw new Error(`Invalid track id for mixer lane: ${String(target)}`);\n }\n const existing = this.trackLaneIds.indexOf(trackId);\n if (existing >= 0) {\n return existing;\n }\n this.trackLaneIds.push(trackId);\n this.syncMixer();\n return this.trackLaneIds.length - 1;\n }\n\n private ensureBus(busId: number): number {\n const resolved = Math.trunc(busId);\n if (!Number.isInteger(resolved) || resolved <= 0) {\n throw new Error(`Invalid bus id for mixer bus: ${String(busId)}`);\n }\n const existing = this.buses.findIndex((bus) => bus.busId === resolved);\n if (existing >= 0) {\n return existing;\n }\n this.buses.push({ busId: resolved });\n this.syncMixer();\n return this.buses.length - 1;\n }\n}\n","import type {\n EngineAutomationPoint,\n EngineBus,\n EngineCaptureStatus,\n EngineClip,\n EngineMarker,\n EngineMetronomeConfig,\n EngineMidiClipSchedule,\n EngineParameterInfo,\n EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTrackLane,\n EngineTransportState,\n RealtimeVoiceChangerConfigInput,\n RealtimeVoiceChangerPodConfig,\n} from '../index';\nimport type { AutomationCurve } from '../public_types';\nimport type {\n SonareEngineCommandRecord,\n SonareEngineTelemetryRecord,\n SonareWorkletMeterSnapshot,\n SonareWorkletSpectrumSnapshot,\n} from './protocol';\n\nexport interface SonareWorkletProcessorOptions {\n sceneJson: string;\n sampleRate?: number;\n blockSize?: number;\n stripCount?: number;\n meterIntervalFrames?: number;\n meterSharedBuffer?: SharedArrayBuffer;\n meterRingCapacity?: number;\n spectrumIntervalFrames?: number;\n spectrumBands?: number;\n spectrumSharedBuffer?: SharedArrayBuffer;\n spectrumRingCapacity?: number;\n}\n\nexport interface SonareRealtimeEngineWorkletProcessorOptions {\n wasmBinary?: ArrayBuffer | Uint8Array;\n initialSyncMessages?: SonareEngineSyncMessage[];\n initialCommands?: SonareEngineCommandRecord[];\n sampleRate?: number;\n blockSize?: number;\n channelCount?: number;\n meterIntervalFrames?: number;\n commandSharedBuffer?: SharedArrayBuffer;\n commandRingCapacity?: number;\n telemetrySharedBuffer?: SharedArrayBuffer;\n telemetryRingCapacity?: number;\n meterSharedBuffer?: SharedArrayBuffer;\n meterRingCapacity?: number;\n // Scope telemetry (FFT spectrum + goniometer): opt-in. The ring is created\n // only when scopeIntervalFrames > 0, since the per-block FFT is heavier than\n // the meter path. scopeBands selects the linear band resolution.\n scopeIntervalFrames?: number;\n scopeBands?: number;\n scopeSharedBuffer?: SharedArrayBuffer;\n scopeRingCapacity?: number;\n /**\n * Lock-free SPSC queue for clip-page cache misses. Supplying this is required\n * for realtime-safe OPFS streaming: it avoids both embind object creation and\n * postMessage structured cloning from AudioWorklet process().\n */\n clipPageRequestSharedBuffer?: SharedArrayBuffer;\n clipPageRequestRingCapacity?: number;\n /** Lock-free worklet-to-main-thread MIDI-1 output ring. */\n externalMidiSharedBuffer?: SharedArrayBuffer;\n externalMidiRingCapacity?: number;\n}\n\nexport interface SonareRealtimeVoiceChangerWorkletProcessorOptions {\n preset?: RealtimeVoiceChangerConfigInput;\n sampleRate?: number;\n blockSize?: number;\n channelCount?: number;\n}\n\nexport interface SonareRealtimeVoiceChangerSetConfigMessage {\n type: 'setConfig';\n /** Pre-normalized by the main thread; never JSON parsed in the worklet. */\n config: RealtimeVoiceChangerPodConfig;\n}\n\nexport interface SonareRealtimeVoiceChangerResetMessage {\n type: 'reset';\n}\n\nexport interface SonareRealtimeVoiceChangerDestroyMessage {\n type: 'destroy';\n}\n\nexport type SonareRealtimeVoiceChangerMessage =\n | SonareRealtimeVoiceChangerSetConfigMessage\n | SonareRealtimeVoiceChangerResetMessage\n | SonareRealtimeVoiceChangerDestroyMessage;\n\nexport interface SonareRealtimeEngineNodeCapabilities {\n mode: 'sab' | 'postMessage';\n runtimeTarget: 'embind';\n sharedArrayBuffer: boolean;\n atomics: boolean;\n audioWorklet: boolean;\n /** True only when clip-page misses use the bounded SAB ring. */\n clipPageRequestsRealtimeSafe: boolean;\n /** True when external MIDI uses the SAB output ring rather than postMessage. */\n externalMidiRealtimeSafe: boolean;\n engineAbiVersion?: number;\n expectedEngineAbiVersion?: number;\n abiCompatible?: boolean;\n degradedReason?: string;\n readyMessage?: boolean;\n}\n\nexport interface SonareRealtimeEngineNodeOptions\n extends SonareRealtimeEngineWorkletProcessorOptions {\n processorName?: string;\n moduleUrl?: string | URL;\n mode?: 'auto' | 'sab' | 'postMessage';\n engineAbiVersion?: number;\n expectedEngineAbiVersion?: number;\n requireAbiCompatible?: boolean;\n nodeFactory?: (\n context: BaseAudioContext,\n processorName: string,\n options: AudioWorkletNodeOptions,\n ) => AudioWorkletNode;\n}\n\nexport interface SonareEngineTransportFacade {\n play(sampleTime?: number): boolean;\n stop(sampleTime?: number): boolean;\n seekPpq(ppq: number, sampleTime?: number): boolean;\n seekSeconds(seconds: number, sampleTime?: number): boolean;\n setTempo(bpm: number): void;\n setTempoSegments(segments: readonly EngineTempoSegment[]): void;\n setLoop(startPpq: number, endPpq: number, enabled?: boolean): boolean;\n}\n\nexport interface SonareWorkletScheduleInsertAutomationMessage {\n type: 'scheduleInsertAutomation';\n stripIndex: number;\n insertIndex: number;\n paramId: number;\n value: number;\n samplePos?: number;\n curve?: AutomationCurve;\n}\n\nexport interface SonareWorkletSetMeterIntervalMessage {\n type: 'setMeterInterval';\n frames: number;\n}\n\nexport interface SonareWorkletDestroyMessage {\n type: 'destroy';\n}\n\nexport type SonareWorkletMessage =\n | SonareWorkletScheduleInsertAutomationMessage\n | SonareWorkletSetMeterIntervalMessage\n | SonareWorkletDestroyMessage;\n\n/** One external-MIDI event delivered to the main thread, lowered to MIDI 1.0\n * bytes ready for a Web MIDI output port. */\nexport interface SonareWorkletExternalMidiEvent {\n /** Originating track lane, or 0xFFFFFFFF for transport/clock bytes. */\n destinationId: number;\n /** Sample position within the producing block. */\n renderFrame: number;\n /** MIDI 1.0 status + data bytes (1..3 entries). */\n bytes: number[];\n}\n\n/** Batch of external-MIDI events posted from the worklet once per render block. */\nexport interface SonareWorkletExternalMidiMessage {\n type: 'externalMidi';\n events: SonareWorkletExternalMidiEvent[];\n}\n\n/** A control-plane sync message that the worklet rejected without crashing. */\nexport interface SonareEngineSyncErrorMessage {\n type: 'syncError';\n syncType: SonareEngineSyncMessage['type'];\n message: string;\n}\n\nexport type SonareWorkletTransportMessage =\n | SonareWorkletMeterSnapshot\n | SonareWorkletSpectrumSnapshot\n | SonareWorkletExternalMidiMessage\n | SonareEngineClipPageRequestMessage\n | SonareEngineTelemetryRecord;\n\nexport interface WorkletTransport {\n postMessage?: (\n message:\n | SonareWorkletTransportMessage\n | SonareEngineCaptureResponseMessageInternal\n | SonareEngineTransportResponseMessage\n | SonareEngineSyncErrorMessage,\n transfer?: Transferable[],\n ) => void;\n onMeter?: (meter: SonareWorkletMeterSnapshot) => void;\n onSpectrum?: (spectrum: SonareWorkletSpectrumSnapshot) => void;\n}\n\nexport interface ResolvedMetronomeConfig {\n beatGain: number;\n accentGain: number;\n clickSamples: number;\n clickSeconds: number;\n}\n\n// Fallback metronome gains/click length used by the worklet consumer until the\n// host posts a 'syncMetronome' config. Aligned with the embind setMetronome\n// defaults (src/wasm/bindings.cpp) so offline and realtime metronomes match.\nexport const DEFAULT_METRONOME_CONFIG: ResolvedMetronomeConfig = {\n beatGain: 0.35,\n accentGain: 0.7,\n clickSamples: 0,\n clickSeconds: 0,\n};\n\nexport function resolveMetronomeConfig(config: EngineMetronomeConfig): ResolvedMetronomeConfig {\n const resolved = {\n beatGain: config.beatGain ?? DEFAULT_METRONOME_CONFIG.beatGain,\n accentGain: config.accentGain ?? DEFAULT_METRONOME_CONFIG.accentGain,\n clickSamples: config.clickSamples ?? DEFAULT_METRONOME_CONFIG.clickSamples,\n clickSeconds: config.clickSeconds ?? DEFAULT_METRONOME_CONFIG.clickSeconds,\n };\n if (\n !Number.isFinite(resolved.beatGain) ||\n resolved.beatGain < 0 ||\n !Number.isFinite(resolved.accentGain) ||\n resolved.accentGain < 0 ||\n !Number.isInteger(resolved.clickSamples) ||\n resolved.clickSamples < 0 ||\n !Number.isFinite(resolved.clickSeconds) ||\n resolved.clickSeconds < 0 ||\n resolved.clickSamples > 384000 ||\n (config.clickSeconds !== undefined &&\n (!Number.isFinite(config.clickSeconds) || config.clickSeconds < 0 || config.clickSeconds > 1))\n ) {\n throw new RangeError('invalid metronome gains or click length');\n }\n return resolved;\n}\n\n// Out-of-band control messages posted from the main-thread SonareEngine facade\n// to the worklet engine processor over node.port. Unlike SonareEngineCommandRecord\n// (a small POD POSTed/ringed every block) these carry bulk/structured payloads\n// (clip audio buffers, marker lists, metronome config) that cannot fit the\n// fixed-size SAB command record. Their port handlers still execute on the\n// AudioWorklet rendering thread, so consumers must validate them without\n// allocation and publish bounded snapshots for process() to consume.\nexport interface SonareEngineSyncClipsMessage {\n type: 'syncClips';\n clips: EngineClip[];\n}\n\nexport interface SonareEngineSyncClipsDeltaMessage {\n type: 'syncClipsDelta';\n upserts: EngineClip[];\n removeIds: number[];\n}\n\n/** Begins a paged, pre-baked clip transfer. PCM pages follow in FIFO order. */\nexport interface SonareEngineSyncClipPageProviderMessage {\n type: 'syncClipPageProvider';\n clipId: number;\n /** Omitted when an OPFS stream is primed before its clip is scheduled. */\n clip?: EngineClip;\n numChannels: number;\n numSamples: number;\n pageFrames: number;\n}\n\n/** Supplies one bounded PCM page for a pending pre-baked clip transfer. */\nexport interface SonareEngineSyncClipPageMessage {\n type: 'syncClipPage';\n clipId: number;\n pageIndex: number;\n channels: Float32Array[];\n}\n\n/** Evicts one page after the main-thread sliding window advances. */\nexport interface SonareEngineSyncClipPageClearMessage {\n type: 'syncClipPageClear';\n clipId: number;\n pageIndex: number;\n}\n\n/** Releases a provider whose clip was removed or whose stream was closed. */\nexport interface SonareEngineSyncClipPageDestroyMessage {\n type: 'syncClipPageDestroy';\n clipId: number;\n}\n\n/** Makes a fully supplied paged clip visible to the audio engine. */\nexport interface SonareEngineSyncClipPageCommitMessage {\n type: 'syncClipPageCommit';\n clipId: number;\n /**\n * Clip schedule to publish with a provider that was primed before its\n * schedule was known. The original pre-baked push path supplies it on the\n * provider message instead.\n */\n clip?: EngineClip;\n}\n\n/**\n * A bounded batch of page misses emitted by the AudioWorklet. The main thread\n * resolves these from OPFS and responds with `syncClipPage`; a missing page is\n * silent until that response arrives.\n */\nexport interface SonareEngineClipPageRequestMessage {\n type: 'clipPageRequest';\n requests: Array<{ clipId: number; pageIndex: number }>;\n /** Number of misses dropped because a bounded native or SAB request queue was full. */\n dropped?: number;\n}\n\nexport interface SonareEngineSyncMidiClipsMessage {\n type: 'syncMidiClips';\n clips: EngineMidiClipSchedule[];\n}\n\nexport interface SonareEngineSyncMarkersMessage {\n type: 'syncMarkers';\n markers: EngineMarker[];\n}\n\nexport interface SonareEngineSyncMetronomeMessage {\n type: 'syncMetronome';\n config: EngineMetronomeConfig;\n}\n\nexport interface SonareEngineSyncAutomationMessage {\n type: 'syncAutomation';\n paramId: number;\n points: EngineAutomationPoint[];\n}\n\n/** Replaces the live engine's registered custom-parameter set. */\nexport interface SonareEngineSyncParametersMessage {\n type: 'syncParameters';\n parameters: EngineParameterInfo[];\n}\n\nexport interface SonareEngineSyncTempoMessage {\n type: 'syncTempo';\n bpm: number;\n timeSignature: { numerator: number; denominator: number };\n tempoSegments?: EngineTempoSegment[];\n timeSignatureSegments?: EngineTimeSignatureSegment[];\n}\n\nexport interface SonareEngineSyncMixerMessage {\n type: 'syncMixer';\n lanes: EngineTrackLane[];\n buses?: EngineBus[];\n trackStrips?: Array<{ trackId: number; sceneJson: string }>;\n busStrips?: Array<{ busId: number; sceneJson: string }>;\n masterStripJson?: string;\n /** Lane insert sidechain bindings (replayed after lanes/strips). */\n laneSidechains?: Array<{ trackId: number; insertIndex: number; sourceTrackId: number }>;\n}\n\nexport interface SonareEngineSyncCaptureMessage {\n type: 'syncCapture';\n bufferFrames: number;\n channels: number;\n source: EngineCaptureStatus['source'];\n recordOffsetSamples: number;\n inputMonitor: { enabled: boolean; gain: number };\n}\n\nexport interface SonareEngineSyncTrackStripEqBandMessage {\n type: 'syncTrackStripEqBand';\n trackId: number;\n bandIndex: number;\n bandJson: string;\n}\n\nexport interface SonareEngineSyncMasterStripEqBandMessage {\n type: 'syncMasterStripEqBand';\n bandIndex: number;\n bandJson: string;\n}\n\nexport interface SonareEngineSyncTrackStripInsertBypassedMessage {\n type: 'syncTrackStripInsertBypassed';\n trackId: number;\n insertIndex: number;\n bypassed: boolean;\n resetOnBypass: boolean;\n}\n\nexport interface SonareEngineSyncMasterStripInsertBypassedMessage {\n type: 'syncMasterStripInsertBypassed';\n insertIndex: number;\n bypassed: boolean;\n resetOnBypass: boolean;\n}\n\nexport interface SonareEngineSyncTrackStripInsertParamByNameMessage {\n type: 'syncTrackStripInsertParamByName';\n trackId: number;\n insertIndex: number;\n paramName: string;\n value: number;\n}\n\nexport interface SonareEngineSyncMasterStripInsertParamByNameMessage {\n type: 'syncMasterStripInsertParamByName';\n insertIndex: number;\n paramName: string;\n value: number;\n}\n\nexport interface SonareEngineSyncBusStripInsertParamByNameMessage {\n type: 'syncBusStripInsertParamByName';\n busId: number;\n insertIndex: number;\n paramName: string;\n value: number;\n}\n\nexport interface SonareEngineSyncTrackStripPanMessage {\n type: 'syncTrackStripPan';\n trackId: number;\n pan: number;\n}\n\nexport interface SonareEngineSyncTrackStripPanLawMessage {\n type: 'syncTrackStripPanLaw';\n trackId: number;\n panLaw: number;\n}\n\nexport interface SonareEngineSyncTrackStripPanModeMessage {\n type: 'syncTrackStripPanMode';\n trackId: number;\n panMode: number;\n}\n\nexport interface SonareEngineSyncTrackStripDualPanMessage {\n type: 'syncTrackStripDualPan';\n trackId: number;\n leftPan: number;\n rightPan: number;\n}\n\nexport interface SonareEngineSyncTrackStripChannelDelaySamplesMessage {\n type: 'syncTrackStripChannelDelaySamples';\n trackId: number;\n delaySamples: number;\n}\n\nexport interface SonareEngineSyncBuiltinInstrumentMessage {\n type: 'syncBuiltinInstrument';\n destinationId: number;\n config: { destinationId?: number } & Record<string, unknown>;\n}\n\nexport interface SonareEngineSyncSynthInstrumentMessage {\n type: 'syncSynthInstrument';\n destinationId: number;\n patch: Record<string, unknown> | string;\n}\n\nexport interface SonareEngineSyncSf2InstrumentMessage {\n type: 'syncSf2Instrument';\n destinationId: number;\n config: {\n destinationId?: number;\n gain?: number;\n polyphony?: number;\n preferModelForModeledFamilies?: boolean;\n };\n}\n\nexport interface SonareEngineSyncLoadSoundFontMessage {\n type: 'syncLoadSoundFont';\n data: Uint8Array;\n}\n\nexport interface SonareEngineSyncMidiFxMessage {\n type: 'syncMidiFx' | 'syncClearMidiFx';\n destinationId: number;\n /** Engine MIDI-FX config JSON; present for 'syncMidiFx', absent for a clear. */\n configJson?: string;\n}\n\nexport interface SonareEngineSyncMidiNoteMessage {\n type: 'syncMidiNoteOn' | 'syncMidiNoteOff';\n destinationId: number;\n group: number;\n channel: number;\n note: number;\n velocity: number;\n renderFrame: number;\n}\n\nexport interface SonareEngineSyncMidiCcMessage {\n type: 'syncMidiCc';\n destinationId: number;\n group: number;\n channel: number;\n controller: number;\n value: number;\n renderFrame: number;\n}\n\nexport interface SonareEngineSyncMidiUmpMessage {\n type: 'syncMidiUmp';\n destinationId: number;\n word0: number;\n renderFrame: number;\n}\n\nexport interface SonareEngineSyncMidiSysexMessage {\n type: 'syncMidiSysex';\n destinationId: number;\n data: Uint8Array;\n renderFrame: number;\n}\n\nexport interface SonareEngineSyncMidiPanicMessage {\n type: 'syncMidiPanic';\n renderFrame: number;\n}\n\nexport interface SonareEngineSyncMidiDestinationExternalMessage {\n type: 'syncMidiDestinationExternal';\n destinationId: number;\n external: boolean;\n}\n\nexport interface SonareEngineSyncExternalMidiClockMessage {\n type: 'syncExternalMidiClock';\n enabled: boolean;\n}\n\nexport interface SonareEngineSyncMidiInputSourceMessage {\n type: 'syncMidiInputSource' | 'syncClearMidiInputSource';\n destinationId?: number;\n}\n\nexport interface SonareEngineSyncMidiCcBindingMessage {\n type: 'syncMidiCcBinding';\n channel: number;\n controller: number;\n paramId: number;\n minValue: number;\n maxValue: number;\n}\n\nexport interface SonareEngineSyncMidiInputEventMessage {\n type: 'syncMidiInputNoteOn' | 'syncMidiInputNoteOff' | 'syncMidiInputCc';\n group: number;\n channel: number;\n data0: number;\n data1: number;\n portTimeSamples: number;\n}\n\n/** Releases the realtime engine and all worklet-owned clip buffers. */\nexport interface SonareEngineDestroyMessage {\n type: 'destroy';\n}\n\nexport type SonareEngineInstrumentSyncMessage =\n | SonareEngineSyncBuiltinInstrumentMessage\n | SonareEngineSyncSynthInstrumentMessage\n | SonareEngineSyncSf2InstrumentMessage\n | SonareEngineSyncLoadSoundFontMessage\n | SonareEngineSyncMidiFxMessage;\n\nexport type SonareEngineSyncMessage =\n | SonareEngineSyncClipsMessage\n | SonareEngineSyncClipsDeltaMessage\n | SonareEngineSyncClipPageProviderMessage\n | SonareEngineSyncClipPageMessage\n | SonareEngineSyncClipPageClearMessage\n | SonareEngineSyncClipPageCommitMessage\n | SonareEngineSyncClipPageDestroyMessage\n | SonareEngineSyncMidiClipsMessage\n | SonareEngineSyncMarkersMessage\n | SonareEngineSyncMetronomeMessage\n | SonareEngineSyncAutomationMessage\n | SonareEngineSyncParametersMessage\n | SonareEngineSyncTempoMessage\n | SonareEngineSyncMixerMessage\n | SonareEngineSyncCaptureMessage\n | SonareEngineSyncTrackStripEqBandMessage\n | SonareEngineSyncMasterStripEqBandMessage\n | SonareEngineSyncTrackStripInsertBypassedMessage\n | SonareEngineSyncMasterStripInsertBypassedMessage\n | SonareEngineSyncTrackStripInsertParamByNameMessage\n | SonareEngineSyncMasterStripInsertParamByNameMessage\n | SonareEngineSyncBusStripInsertParamByNameMessage\n | SonareEngineSyncTrackStripPanMessage\n | SonareEngineSyncTrackStripPanLawMessage\n | SonareEngineSyncTrackStripPanModeMessage\n | SonareEngineSyncTrackStripDualPanMessage\n | SonareEngineSyncTrackStripChannelDelaySamplesMessage\n | SonareEngineSyncBuiltinInstrumentMessage\n | SonareEngineSyncSynthInstrumentMessage\n | SonareEngineSyncSf2InstrumentMessage\n | SonareEngineSyncLoadSoundFontMessage\n | SonareEngineSyncMidiFxMessage\n | SonareEngineSyncMidiNoteMessage\n | SonareEngineSyncMidiCcMessage\n | SonareEngineSyncMidiUmpMessage\n | SonareEngineSyncMidiSysexMessage\n | SonareEngineSyncMidiPanicMessage\n | SonareEngineSyncMidiDestinationExternalMessage\n | SonareEngineSyncExternalMidiClockMessage\n | SonareEngineSyncMidiInputSourceMessage\n | SonareEngineSyncMidiCcBindingMessage\n | SonareEngineSyncMidiInputEventMessage\n | SonareEngineDestroyMessage;\n\nexport interface WorkletPort {\n postMessage?: (message: unknown, transfer?: Transferable[]) => void;\n onmessage?: (event: { data: unknown }) => void;\n addEventListener?: (type: 'message', listener: (event: { data: unknown }) => void) => void;\n start?: () => void;\n}\n\nexport interface SonareEngineCaptureRequestMessage {\n type: 'captureRequest';\n requestId: number;\n op: 'status' | 'read' | 'reset';\n}\n\n/**\n * Public capture response shape retained for source compatibility.\n *\n * The worklet wire protocol is stricter than this legacy structural type; use\n * `SonareEngineCaptureResponseMessageInternal` inside the implementation.\n */\nexport interface SonareEngineCaptureResponseMessage {\n type: 'captureResponse';\n requestId: number;\n ok: boolean;\n status?: EngineCaptureStatus;\n channels?: Float32Array[] | number[][];\n error?: string;\n}\n\ninterface SonareEngineCaptureStatusResponseMessageInternal {\n type: 'captureResponse';\n requestId: number;\n ok: true;\n status: EngineCaptureStatus;\n}\n\ninterface SonareEngineCaptureReadResponseMessageInternal {\n type: 'captureResponse';\n requestId: number;\n ok: true;\n channels: Float32Array[];\n}\n\ninterface SonareEngineCaptureResetResponseMessageInternal {\n type: 'captureResponse';\n requestId: number;\n ok: true;\n}\n\ninterface SonareEngineCaptureErrorResponseMessageInternal {\n type: 'captureResponse';\n requestId: number;\n ok: false;\n error: string;\n}\n\n/** Strict wire response type used only by the worklet implementation. */\nexport type SonareEngineCaptureResponseMessageInternal =\n | SonareEngineCaptureStatusResponseMessageInternal\n | SonareEngineCaptureReadResponseMessageInternal\n | SonareEngineCaptureResetResponseMessageInternal\n | SonareEngineCaptureErrorResponseMessageInternal;\n\nexport interface SonareEngineTransportRequestMessage {\n type: 'transportRequest';\n requestId: number;\n op: 'state';\n}\n\nexport interface SonareEngineTransportResponseMessage {\n type: 'transportResponse';\n requestId: number;\n ok: boolean;\n state?: EngineTransportState;\n error?: string;\n}\n","import type { EngineClip } from '../index';\nimport { RealtimeEngine } from '../index';\nimport type { WorkletInput, WorkletOutput } from './audio_types';\nimport {\n DEFAULT_METRONOME_CONFIG,\n type ResolvedMetronomeConfig,\n resolveMetronomeConfig,\n type SonareEngineCaptureRequestMessage,\n type SonareEngineCaptureResponseMessageInternal,\n type SonareEngineSyncMessage,\n type SonareEngineTransportRequestMessage,\n type SonareEngineTransportResponseMessage,\n type SonareRealtimeEngineWorkletProcessorOptions,\n type WorkletTransport,\n} from './messages';\nimport {\n clipPageRequestRingFromSharedBuffer,\n encodeFrameHi,\n encodeFrameLo,\n engineRingFromSharedBuffer,\n externalMidiRingFromSharedBuffer,\n meterFromEngine,\n meterRingFromSharedBuffer,\n popSonareEngineCommandRingBuffer,\n pushSonareClipPageRequestRingBuffer,\n pushSonareExternalMidiRingBuffer,\n type SharedClipPageRequestRingWriter,\n type SharedExternalMidiRingWriter,\n type SharedMeterRingWriter,\n type SharedScopeRingWriter,\n SONARE_ENGINE_COMMAND_RECORD_BYTES,\n SONARE_ENGINE_TELEMETRY_RECORD_BYTES,\n SONARE_METER_RING_RECORD_FLOATS,\n SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS,\n type SonareEngineCommandRecord,\n type SonareEngineCommandRingBuffer,\n SonareEngineCommandType,\n SonareEngineTelemetryError,\n type SonareEngineTelemetryRecord,\n type SonareEngineTelemetryRingBuffer,\n SonareEngineTelemetryType,\n type SonareWorkletMeterSnapshot,\n scopeRingFromSharedBuffer,\n telemetryFromEngine,\n writeInt64Words,\n writeSonareEngineTelemetryRingBuffer,\n} from './protocol';\n\nfunction captureTransferList(channels: readonly Float32Array[]): Transferable[] {\n const transfers: ArrayBuffer[] = [];\n const seen = new Set<ArrayBuffer>();\n for (const channel of channels) {\n const buffer = channel.buffer;\n if (!(buffer instanceof ArrayBuffer)) {\n throw new TypeError('capture response channels must use plain ArrayBuffers');\n }\n if (!seen.has(buffer)) {\n seen.add(buffer);\n transfers.push(buffer);\n }\n }\n return transfers;\n}\n\n/**\n * AudioWorklet-style bridge for the DAW realtime engine facade.\n *\n * Backed by the `sonare.wasm` embind facade.\n */\nexport class SonareRealtimeEngineWorkletProcessor {\n private static warnedChannelScratchOverflow = false;\n readonly sampleRate: number;\n readonly blockSize: number;\n readonly channelCount: number;\n private engine: RealtimeEngine;\n private closed = false;\n private commandRing?: SonareEngineCommandRingBuffer;\n private telemetryRing?: SonareEngineTelemetryRingBuffer;\n private meterRing?: SharedMeterRingWriter;\n private scopeRing?: SharedScopeRingWriter;\n private clipPageRequestRing?: SharedClipPageRequestRingWriter;\n private externalMidiRing?: SharedExternalMidiRingWriter;\n private transport?: WorkletTransport;\n private meterIntervalFrames: number;\n private lastMeterFrame = Number.NEGATIVE_INFINITY;\n // Latest metronome gains/click length pushed via 'syncMetronome'. The\n // SetMetronome command only toggles enabled state; the config arrives here.\n private metronomeConfig: ResolvedMetronomeConfig = { ...DEFAULT_METRONOME_CONFIG };\n // Zero-copy prepared realtime path: persistent per-channel views onto the\n // engine's WASM-heap scratch (acquired once on the main thread via\n // getChannelBuffer). process() writes the AudioWorklet input straight into\n // these views, calls engine.processPrepared(frames) which runs the engine IN\n // PLACE, then reads the same views back — no std::vector or JS Float32Array is\n // allocated per render quantum (the old engine.process() round-tripped fresh\n // arrays on both heaps every block, an RT-safety hazard).\n private channelBuffers: Float32Array[];\n private readonly liveClips = new Map<number, EngineClip>();\n private readonly pagedClipProviders = new Map<number, number>();\n private readonly pagedClipPageFrames = new Map<number, number>();\n private readonly pendingPagedClips = new Map<number, EngineClip>();\n // The worklet drains at most this many distinct page misses per render\n // quantum. The fixed scalar buffers avoid retaining an unbounded queue on\n // the audio thread; any remaining native requests stay queued for the next\n // quantum and render silence meanwhile.\n private readonly clipPageRequestClipIds = new Float64Array(64);\n private readonly clipPageRequestPageIndices = new Float64Array(64);\n private clipPageRequestOverflowReported = 0;\n\n constructor(\n options: SonareRealtimeEngineWorkletProcessorOptions = {},\n transport?: WorkletTransport,\n ) {\n this.sampleRate = options.sampleRate ?? 48000;\n this.blockSize = options.blockSize ?? 128;\n this.channelCount = Math.max(1, Math.floor(options.channelCount ?? 2));\n this.transport = transport;\n this.meterIntervalFrames = Math.max(0, Math.floor(options.meterIntervalFrames ?? 2048));\n this.commandRing = options.commandSharedBuffer\n ? this.commandRingFromSharedBuffer(options.commandSharedBuffer, options.commandRingCapacity)\n : undefined;\n this.telemetryRing = options.telemetrySharedBuffer\n ? this.telemetryRingFromSharedBuffer(\n options.telemetrySharedBuffer,\n options.telemetryRingCapacity,\n )\n : undefined;\n this.meterRing = options.meterSharedBuffer\n ? meterRingFromSharedBuffer(options.meterSharedBuffer, options.meterRingCapacity)\n : undefined;\n this.scopeRing = options.scopeSharedBuffer\n ? scopeRingFromSharedBuffer(\n options.scopeSharedBuffer,\n options.scopeRingCapacity,\n options.scopeBands,\n )\n : undefined;\n this.clipPageRequestRing = options.clipPageRequestSharedBuffer\n ? clipPageRequestRingFromSharedBuffer(\n options.clipPageRequestSharedBuffer,\n options.clipPageRequestRingCapacity,\n )\n : undefined;\n this.externalMidiRing = options.externalMidiSharedBuffer\n ? externalMidiRingFromSharedBuffer(\n options.externalMidiSharedBuffer,\n options.externalMidiRingCapacity,\n )\n : undefined;\n this.engine = new RealtimeEngine(\n this.sampleRate,\n this.blockSize,\n 1024,\n 1024,\n this.channelCount,\n );\n // Allocate persistent WASM-heap scratch (worst case: channelCount channels x\n // blockSize frames) and acquire the per-channel heap views once.\n this.engine.prepareChannels(this.channelCount, this.blockSize);\n this.channelBuffers = new Array(this.channelCount);\n for (let ch = 0; ch < this.channelCount; ch++) {\n this.channelBuffers[ch] = this.engine.getChannelBuffer(ch, this.blockSize);\n }\n // Arm the engine's scope producer only when a scope ring was provided. The\n // band count follows the ring's record layout so writeScopeRing never\n // overruns its slot.\n if (this.scopeRing) {\n const interval = Math.max(1, Math.floor(options.scopeIntervalFrames ?? this.blockSize));\n this.engine.configureScopeTelemetry(interval, this.scopeRing.bands);\n }\n }\n\n process(inputs: WorkletInput, outputs: WorkletOutput): boolean {\n if (this.closed) {\n return false;\n }\n const output = outputs[0];\n const firstOutput = output?.[0];\n if (!firstOutput) {\n return true;\n }\n const frames = firstOutput.length;\n if (frames > this.blockSize) {\n for (const channel of output ?? []) {\n channel.fill(0);\n }\n this.publishTelemetry();\n return true;\n }\n\n this.drainCommands();\n\n // Clamp `frames` to the pre-allocated scratch capacity. The earlier\n // `frames > this.blockSize` branch already returns early, so this is\n // defensive — but we warn once if it ever fires so the contract violation\n // is visible.\n let usableFrames = frames;\n if (usableFrames > this.blockSize) {\n if (!SonareRealtimeEngineWorkletProcessor.warnedChannelScratchOverflow) {\n SonareRealtimeEngineWorkletProcessor.warnedChannelScratchOverflow = true;\n // biome-ignore lint/suspicious/noConsole: realtime-safety diagnostic.\n console.warn(\n `SonareRealtimeEngineWorkletProcessor: requested ${usableFrames} frames ` +\n `exceeds pre-allocated capacity ${this.blockSize}; clamping.`,\n );\n }\n usableFrames = this.blockSize;\n }\n\n // Defend against WASM linear-memory growth detaching the cached heap views:\n // if any view's backing ArrayBuffer has been detached (byteLength === 0),\n // re-acquire all of them. This is a control-flow check (no allocation in the\n // common case where memory did not grow).\n if ((this.channelBuffers[0]?.byteLength ?? 0) === 0) {\n this.reacquireChannelBuffers();\n }\n\n const input = inputs[0];\n // Write the AudioWorklet input straight into the engine's WASM-heap views;\n // no per-block heap allocation.\n for (let ch = 0; ch < this.channelCount; ch++) {\n const dst = this.channelBuffers[ch];\n const source = input?.[ch];\n if (source && source.length === usableFrames) {\n dst.set(source.subarray(0, usableFrames));\n } else {\n dst.fill(0, 0, usableFrames);\n }\n }\n\n // Run the engine in place over the prepared scratch (allocation-free).\n this.engine.processPrepared(usableFrames);\n\n for (let ch = 0; ch < output.length; ch++) {\n const target = output[ch];\n const source = this.channelBuffers[ch] ?? this.channelBuffers[0];\n if (source) {\n target.set(source.subarray(0, Math.min(target.length, usableFrames)));\n if (target.length > usableFrames) {\n target.fill(0, usableFrames);\n }\n } else {\n target.fill(0);\n }\n }\n this.publishClipPageRequests();\n this.publishTelemetry();\n this.publishMeters();\n this.publishScope();\n this.publishExternalMidi();\n return true;\n }\n\n private reacquireChannelBuffers(): void {\n for (let ch = 0; ch < this.channelCount; ch++) {\n this.channelBuffers[ch] = this.engine.getChannelBuffer(ch, this.blockSize);\n }\n }\n\n receiveCommand(command: SonareEngineCommandRecord): void {\n if (!this.closed) {\n this.safeApplyCommand(command);\n }\n }\n\n // Applies an out-of-band control-plane sync message on the AudioWorklet\n // thread. These handlers must remain bounded: expensive clip transforms are\n // performed on the main-thread mirror, and long pre-baked PCM arrives in\n // small pages before the final lightweight clip schedule is committed.\n receiveSync(message: SonareEngineSyncMessage): void {\n if (this.closed) {\n return;\n }\n try {\n this.applySync(message);\n } catch (error) {\n this.transport?.postMessage?.({\n type: 'syncError',\n syncType: message.type,\n message: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n private applySync(message: SonareEngineSyncMessage): void {\n switch (message.type) {\n case 'destroy':\n this.destroy();\n return;\n case 'syncClips': {\n // Commit native state before touching the worklet-side mirrors. A\n // rejected embind call must leave a later delta based on the previous\n // clip set, not on a half-applied replacement.\n this.engine.setClips(message.clips);\n this.clearPagedClipProviders();\n this.liveClips.clear();\n for (const clip of message.clips) {\n if (clip.id !== undefined) {\n this.liveClips.set(clip.id, clip);\n }\n }\n break;\n }\n case 'syncClipsDelta': {\n const nextClips = new Map(this.liveClips);\n for (const clipId of message.removeIds) {\n nextClips.delete(clipId);\n }\n for (const clip of message.upserts) {\n if (clip.id !== undefined) {\n nextClips.set(clip.id, clip);\n }\n }\n this.engine.setClips(Array.from(nextClips.values()));\n for (const clipId of message.removeIds) {\n this.removePagedClipProvider(clipId);\n }\n this.liveClips.clear();\n for (const [clipId, clip] of nextClips) {\n this.liveClips.set(clipId, clip);\n }\n break;\n }\n case 'syncClipPageProvider': {\n const provider = this.engine.createClipPageProvider(\n message.numChannels,\n message.numSamples,\n message.pageFrames,\n );\n this.removePagedClipProvider(message.clipId);\n this.pagedClipProviders.set(message.clipId, provider.id);\n this.pagedClipPageFrames.set(message.clipId, message.pageFrames);\n if (message.clip) {\n this.pendingPagedClips.set(message.clipId, message.clip);\n }\n break;\n }\n case 'syncClipPage': {\n const providerId = this.pagedClipProviders.get(message.clipId);\n if (providerId !== undefined) {\n this.engine.supplyClipPage(providerId, message.pageIndex, message.channels);\n }\n break;\n }\n case 'syncClipPageClear': {\n const providerId = this.pagedClipProviders.get(message.clipId);\n if (providerId !== undefined) {\n this.engine.clearClipPage(providerId, message.pageIndex);\n }\n break;\n }\n case 'syncClipPageCommit': {\n const providerId = this.pagedClipProviders.get(message.clipId);\n const clip = message.clip ?? this.pendingPagedClips.get(message.clipId);\n if (providerId !== undefined && clip) {\n const nextClip = { ...clip, pageProvider: providerId };\n const nextClips = new Map(this.liveClips);\n nextClips.set(message.clipId, nextClip);\n this.engine.setClips(Array.from(nextClips.values()));\n this.liveClips.set(message.clipId, nextClip);\n this.pendingPagedClips.delete(message.clipId);\n }\n break;\n }\n case 'syncClipPageDestroy': {\n const nextClips = new Map(this.liveClips);\n nextClips.delete(message.clipId);\n this.engine.setClips(Array.from(nextClips.values()));\n this.liveClips.delete(message.clipId);\n this.removePagedClipProvider(message.clipId);\n break;\n }\n case 'syncMidiClips':\n this.engine.setMidiClips(message.clips);\n break;\n case 'syncMarkers':\n this.engine.setMarkers(message.markers);\n break;\n case 'syncMetronome':\n // Do not publish the cached config until the native engine accepted it.\n // Otherwise a rejected sync would corrupt the command-side fallback.\n {\n const config = resolveMetronomeConfig(message.config);\n this.engine.setMetronome(message.config);\n this.metronomeConfig = config;\n }\n break;\n case 'syncAutomation':\n this.engine.setAutomationLane(message.paramId, message.points);\n break;\n case 'syncParameters':\n this.engine.clearParameters();\n for (const info of message.parameters) {\n this.engine.addParameter(info);\n }\n break;\n case 'syncTempo':\n if (message.tempoSegments) {\n this.engine.setTempoSegments(message.tempoSegments);\n } else {\n this.engine.setTempo(message.bpm);\n }\n if (message.timeSignatureSegments) {\n this.engine.setTimeSignatureSegments(message.timeSignatureSegments);\n } else {\n this.engine.setTimeSignature(\n message.timeSignature.numerator,\n message.timeSignature.denominator,\n );\n }\n break;\n case 'syncMixer':\n if (message.buses) {\n this.engine.setTrackBuses(message.buses);\n }\n this.engine.setTrackLanes(message.lanes);\n for (const strip of message.trackStrips ?? []) {\n this.engine.setTrackStripJson(strip.trackId, strip.sceneJson);\n }\n for (const strip of message.busStrips ?? []) {\n this.engine.setBusStripJson(strip.busId, strip.sceneJson);\n }\n if (message.masterStripJson) {\n this.engine.setMasterStripJson(message.masterStripJson);\n }\n for (const binding of message.laneSidechains ?? []) {\n this.engine.setLaneSidechain(binding.trackId, binding.insertIndex, binding.sourceTrackId);\n }\n break;\n case 'syncCapture':\n this.engine.setCaptureBuffer(message.channels, message.bufferFrames);\n this.engine.setCaptureSource(message.source);\n this.engine.setRecordOffsetSamples(message.recordOffsetSamples);\n this.engine.setInputMonitor(message.inputMonitor.enabled, message.inputMonitor.gain);\n break;\n case 'syncTrackStripEqBand':\n this.engine.setTrackStripEqBandJson(message.trackId, message.bandIndex, message.bandJson);\n break;\n case 'syncMasterStripEqBand':\n this.engine.setMasterStripEqBandJson(message.bandIndex, message.bandJson);\n break;\n case 'syncTrackStripInsertBypassed':\n this.engine.setTrackStripInsertBypassed(\n message.trackId,\n message.insertIndex,\n message.bypassed,\n message.resetOnBypass,\n );\n break;\n case 'syncMasterStripInsertBypassed':\n this.engine.setMasterStripInsertBypassed(\n message.insertIndex,\n message.bypassed,\n message.resetOnBypass,\n );\n break;\n case 'syncTrackStripInsertParamByName':\n this.engine.setTrackStripInsertParamByName(\n message.trackId,\n message.insertIndex,\n message.paramName,\n message.value,\n );\n break;\n case 'syncMasterStripInsertParamByName':\n this.engine.setMasterStripInsertParamByName(\n message.insertIndex,\n message.paramName,\n message.value,\n );\n break;\n case 'syncBusStripInsertParamByName':\n this.engine.setBusStripInsertParamByName(\n message.busId,\n message.insertIndex,\n message.paramName,\n message.value,\n );\n break;\n case 'syncTrackStripPan':\n this.engine.setTrackStripPan(message.trackId, message.pan);\n break;\n case 'syncTrackStripPanLaw':\n this.engine.setTrackStripPanLaw(message.trackId, message.panLaw);\n break;\n case 'syncTrackStripPanMode':\n this.engine.setTrackStripPanMode(message.trackId, message.panMode);\n break;\n case 'syncTrackStripDualPan':\n this.engine.setTrackStripDualPan(message.trackId, message.leftPan, message.rightPan);\n break;\n case 'syncTrackStripChannelDelaySamples':\n this.engine.setTrackStripChannelDelaySamples(message.trackId, message.delaySamples);\n break;\n case 'syncBuiltinInstrument':\n this.engine.setBuiltinInstrument(message.config, message.destinationId);\n break;\n case 'syncSynthInstrument':\n this.engine.setSynthInstrument(message.patch, message.destinationId);\n break;\n case 'syncLoadSoundFont':\n this.engine.loadSoundFont(message.data);\n break;\n case 'syncSf2Instrument':\n this.engine.setSf2Instrument(message.config, message.destinationId);\n break;\n case 'syncMidiFx':\n this.engine.setMidiFx(message.destinationId, message.configJson ?? '');\n break;\n case 'syncClearMidiFx':\n this.engine.clearMidiFx(message.destinationId);\n break;\n case 'syncMidiNoteOn':\n this.engine.pushMidiNoteOn(\n message.destinationId,\n message.group,\n message.channel,\n message.note,\n message.velocity,\n message.renderFrame,\n );\n break;\n case 'syncMidiNoteOff':\n this.engine.pushMidiNoteOff(\n message.destinationId,\n message.group,\n message.channel,\n message.note,\n message.velocity,\n message.renderFrame,\n );\n break;\n case 'syncMidiCc':\n this.engine.pushMidiCc(\n message.destinationId,\n message.group,\n message.channel,\n message.controller,\n message.value,\n message.renderFrame,\n );\n break;\n case 'syncMidiUmp':\n this.engine.pushMidiUmp(message.destinationId, message.word0, message.renderFrame);\n break;\n case 'syncMidiSysex':\n this.engine.pushMidiSysex(message.destinationId, message.data, message.renderFrame);\n break;\n case 'syncMidiPanic':\n this.engine.pushMidiPanic(message.renderFrame);\n break;\n case 'syncMidiDestinationExternal':\n this.engine.setMidiDestinationExternal(message.destinationId, message.external);\n break;\n case 'syncExternalMidiClock':\n this.engine.setExternalMidiClockEnabled(message.enabled);\n break;\n case 'syncMidiInputSource':\n this.engine.setMidiInputSource(message.destinationId ?? 0);\n break;\n case 'syncClearMidiInputSource':\n this.engine.clearMidiInputSource();\n break;\n case 'syncMidiCcBinding':\n this.engine.bindMidiCc(message.channel, message.controller, message.paramId, {\n minValue: message.minValue,\n maxValue: message.maxValue,\n });\n break;\n case 'syncMidiInputNoteOn':\n this.engine.pushMidiInputNoteOn(\n message.group,\n message.channel,\n message.data0,\n message.data1,\n message.portTimeSamples,\n );\n break;\n case 'syncMidiInputNoteOff':\n this.engine.pushMidiInputNoteOff(\n message.group,\n message.channel,\n message.data0,\n message.data1,\n message.portTimeSamples,\n );\n break;\n case 'syncMidiInputCc':\n this.engine.pushMidiInputCc(\n message.group,\n message.channel,\n message.data0,\n message.data1,\n message.portTimeSamples,\n );\n break;\n }\n }\n\n receiveCaptureRequest(message: SonareEngineCaptureRequestMessage): void {\n if (this.closed) {\n return;\n }\n try {\n if (message.op === 'status') {\n const status = this.engine.captureStatus();\n this.transport?.postMessage?.({\n type: 'captureResponse',\n requestId: message.requestId,\n ok: true,\n status: {\n capturedFrames: status.capturedFrames,\n overflowCount: status.overflowCount,\n armed: status.armed,\n punchEnabled: status.punchEnabled,\n source: status.source,\n recordOffsetSamples: status.recordOffsetSamples,\n },\n } satisfies SonareEngineCaptureResponseMessageInternal);\n return;\n }\n if (message.op === 'read') {\n // Embind's outer val::array is array-like but not structured-cloneable\n // in every host. Copy only that tiny container; keep each native\n // Float32Array intact so the channel payload remains transferable.\n const channels = Array.from(this.engine.capturedAudio());\n const transfer = captureTransferList(channels);\n this.transport?.postMessage?.(\n {\n type: 'captureResponse',\n requestId: message.requestId,\n ok: true,\n channels,\n } satisfies SonareEngineCaptureResponseMessageInternal,\n transfer,\n );\n return;\n }\n this.engine.resetCapture();\n this.transport?.postMessage?.({\n type: 'captureResponse',\n requestId: message.requestId,\n ok: true,\n } satisfies SonareEngineCaptureResponseMessageInternal);\n } catch (error) {\n this.transport?.postMessage?.({\n type: 'captureResponse',\n requestId: message.requestId,\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n } satisfies SonareEngineCaptureResponseMessageInternal);\n }\n }\n\n receiveTransportRequest(message: SonareEngineTransportRequestMessage): void {\n if (this.closed) {\n return;\n }\n try {\n this.transport?.postMessage?.({\n type: 'transportResponse',\n requestId: message.requestId,\n ok: true,\n state: this.engine.getTransportState(),\n } satisfies SonareEngineTransportResponseMessage);\n } catch (error) {\n this.transport?.postMessage?.({\n type: 'transportResponse',\n requestId: message.requestId,\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n } satisfies SonareEngineTransportResponseMessage);\n }\n }\n\n destroy(): void {\n if (!this.closed) {\n this.clearPagedClipProviders();\n this.engine.destroy();\n this.closed = true;\n }\n }\n\n private drainCommands(): void {\n if (!this.commandRing) {\n return;\n }\n for (let i = 0; i < 64; i++) {\n const command = popSonareEngineCommandRingBuffer(this.commandRing);\n if (!command) {\n return;\n }\n this.safeApplyCommand(command);\n }\n }\n\n private safeApplyCommand(command: SonareEngineCommandRecord): void {\n try {\n this.applyCommand(command);\n } catch {\n // A malformed control command must never escape AudioWorklet.process():\n // Web Audio permanently stops invoking a processor that throws there.\n this.publishTelemetryRecord({\n type: SonareEngineTelemetryType.Error,\n error: SonareEngineTelemetryError.InvalidCommand,\n renderFrame: 0,\n timelineSample: 0,\n audibleTimelineSample: 0,\n graphLatencySamplesQ8: 0,\n value: Number(command.type),\n });\n }\n }\n\n private applyCommand(command: SonareEngineCommandRecord): void {\n const sampleTime = Number(command.sampleTime ?? -1);\n switch (command.type) {\n case SonareEngineCommandType.SetParam:\n // paramId is carried in targetId, the new value in argFloat (matches the\n // SonareEngine.setParam producer). sampleTime is the render frame.\n this.engine.setParameter(\n Math.trunc(Number(command.targetId ?? 0)),\n Number(command.argFloat ?? 0),\n sampleTime,\n );\n break;\n case SonareEngineCommandType.SetParamSmoothed:\n this.engine.setParameterSmoothed(\n Math.trunc(Number(command.targetId ?? 0)),\n Number(command.argFloat ?? 0),\n sampleTime,\n );\n break;\n case SonareEngineCommandType.TransportPlay:\n this.engine.play(sampleTime);\n break;\n case SonareEngineCommandType.TransportStop:\n this.engine.stop(sampleTime);\n break;\n case SonareEngineCommandType.TransportSeekSample:\n this.engine.seekSample(Number(command.argInt ?? 0), sampleTime);\n break;\n case SonareEngineCommandType.TransportSeekPpq:\n this.engine.seekPpq(Number(command.argFloat ?? 0), sampleTime);\n break;\n case SonareEngineCommandType.SetLoop:\n this.engine.setLoop(\n Number(command.argFloat ?? 0),\n Number(command.argInt ?? 0) / 1_000_000,\n command.targetId !== 0,\n );\n break;\n case SonareEngineCommandType.ArmRecord:\n this.engine.armCapture(Boolean(command.argInt));\n break;\n case SonareEngineCommandType.Punch:\n // Both endpoints already arrive as samples (see SonareEngine.punch);\n // do NOT re-scale by sampleRate.\n this.engine.setCapturePunch(\n Number(command.argInt ?? 0),\n Math.max(0, Math.round(Number(command.argFloat ?? 0))),\n true,\n );\n break;\n case SonareEngineCommandType.SetMetronome:\n // Metronome config (beatGain/accentGain/clickSamples/clickSeconds) is\n // delivered out-of-band via the 'syncMetronome' message so it carries\n // the caller's full config; the command only toggles enabled state as a\n // sample-aligned fallback.\n this.engine.setMetronome({\n enabled: Boolean(command.argInt),\n beatGain: this.metronomeConfig.beatGain,\n accentGain: this.metronomeConfig.accentGain,\n clickSamples: this.metronomeConfig.clickSamples,\n clickSeconds: this.metronomeConfig.clickSeconds,\n });\n break;\n case SonareEngineCommandType.SeekMarker:\n // The realtime engine's markers are kept in sync via 'syncMarkers'\n // (RtPublisher-style swap), so a queued kSeekMarker resolves correctly.\n this.engine.seekMarker(Math.trunc(Number(command.targetId ?? 0)), sampleTime);\n break;\n case SonareEngineCommandType.SetSoloMute:\n this.engine.setSoloMute(\n Math.trunc(Number(command.targetId ?? 0)),\n Boolean((Number(command.argInt ?? 0) & 0x2) !== 0),\n Boolean((Number(command.argInt ?? 0) & 0x1) !== 0),\n sampleTime,\n );\n break;\n case SonareEngineCommandType.SetTrackMonitorMode: {\n const rawMode = command.argInt;\n const mode = typeof rawMode === 'bigint' ? Number(rawMode) : rawMode;\n if (typeof mode !== 'number' || !Number.isSafeInteger(mode) || mode < 0 || mode > 2) {\n throw new RangeError(`Invalid track monitor mode: ${String(rawMode)}`);\n }\n const laneIndex = command.targetId;\n if (\n typeof laneIndex !== 'number' ||\n !Number.isSafeInteger(laneIndex) ||\n laneIndex < 0 ||\n laneIndex > 0xffff_ffff\n ) {\n throw new RangeError(`Invalid track monitor lane index: ${String(laneIndex)}`);\n }\n this.engine.setTrackMonitorMode(laneIndex, mode as 0 | 1 | 2, sampleTime);\n break;\n }\n default:\n this.publishTelemetryRecord({\n type: SonareEngineTelemetryType.Error,\n error: SonareEngineTelemetryError.UnknownTarget,\n renderFrame: 0,\n timelineSample: 0,\n audibleTimelineSample: 0,\n graphLatencySamplesQ8: 0,\n value: Number(command.type),\n });\n break;\n }\n }\n\n private publishTelemetry(): void {\n const ring = this.telemetryRing;\n if (ring) {\n for (let count = 0; count < 64 && this.engine.popTelemetryToScratch(); count++) {\n this.writeTelemetryScratch(ring);\n }\n return;\n }\n for (const item of this.engine.drainTelemetry(64)) {\n this.publishTelemetryRecord(telemetryFromEngine(item));\n }\n }\n\n private writeTelemetryScratch(ring: SonareEngineTelemetryRingBuffer): void {\n const writeIndex = Atomics.load(ring.header, 0);\n const offset = (writeIndex % ring.capacity) * SONARE_ENGINE_TELEMETRY_RECORD_BYTES;\n ring.view.setUint32(offset, this.engine.telemetryScratchType(), true);\n ring.view.setUint32(offset + 4, this.engine.telemetryScratchError(), true);\n writeInt64Words(ring.view, offset + 8, this.engine.telemetryScratchRenderFrame());\n writeInt64Words(ring.view, offset + 16, this.engine.telemetryScratchTimelineSample());\n writeInt64Words(ring.view, offset + 24, this.engine.telemetryScratchAudibleTimelineSample());\n ring.view.setInt32(offset + 32, this.engine.telemetryScratchGraphLatencySamplesQ8(), true);\n ring.view.setUint32(offset + 36, this.engine.telemetryScratchValue(), true);\n ring.view.setUint32(offset + 40, 0, true);\n ring.view.setUint32(offset + 44, 0, true);\n Atomics.store(ring.header, 0, writeIndex + 1);\n if (writeIndex + 1 > ring.capacity) {\n Atomics.store(ring.header, 4, writeIndex + 1 - ring.capacity);\n }\n }\n\n private publishTelemetryRecord(record: SonareEngineTelemetryRecord): void {\n if (this.telemetryRing) {\n writeSonareEngineTelemetryRingBuffer(this.telemetryRing, record);\n return;\n }\n this.transport?.postMessage?.(record);\n }\n\n // Drains the engine meter telemetry queue into the stereo meter ring / transport.\n //\n // Shared-queue contract: `drainMeterTelemetry` and `drainMeterTelemetryWide`\n // pop the SAME single-consumer telemetry queue, so exactly ONE of them may run\n // per engine. The live worklet path owns the queue via the stereo drain below;\n // the worklet meter ring (SONARE_METER_RING_RECORD_FLOATS) is a fixed stereo\n // layout carrying planes 0/1 plus the correlation/LUFS summary. Per-plane\n // surround meters are NOT delivered over the live worklet ring — a host that\n // needs them must use the offline `drainMeterTelemetryWide()` API on a\n // non-worklet engine instance (do not also call it on a worklet-driven engine,\n // or the two drains will starve each other).\n private publishMeters(): void {\n if (this.meterIntervalFrames <= 0 || (!this.transport && !this.meterRing)) {\n return;\n }\n if (this.meterRing) {\n for (let count = 0; count < 64 && this.engine.popMeterTelemetryToScratch(); count++) {\n const frame = this.engine.meterScratchRenderFrame();\n if (\n frame !== this.lastMeterFrame &&\n frame - this.lastMeterFrame < this.meterIntervalFrames\n ) {\n continue;\n }\n if (frame !== this.lastMeterFrame) {\n this.lastMeterFrame = frame;\n }\n this.writeMeterScratch(this.meterRing);\n }\n return;\n }\n for (const item of this.engine.drainMeterTelemetry(64)) {\n const meter = meterFromEngine(item);\n if (\n meter.frame !== this.lastMeterFrame &&\n meter.frame - this.lastMeterFrame < this.meterIntervalFrames\n ) {\n continue;\n }\n if (meter.frame !== this.lastMeterFrame) {\n this.lastMeterFrame = meter.frame;\n }\n // Prefer the lock-free SAB meter ring (matching the telemetry path and\n // SonareWorkletProcessor); only fall back to structured-clone postMessage\n // when no ring was provided, so we do not allocate/post from the audio\n // render callback in SAB mode.\n if (this.meterRing) {\n this.writeMeterRing(meter);\n } else {\n this.transport?.onMeter?.(meter);\n this.transport?.postMessage?.(meter);\n }\n }\n }\n\n private writeMeterScratch(ring: SharedMeterRingWriter): void {\n const writeIndex = Atomics.load(ring.header, 0);\n const offset = (writeIndex % ring.capacity) * SONARE_METER_RING_RECORD_FLOATS;\n const frame = Number(this.engine.meterScratchRenderFrame());\n ring.records[offset] = encodeFrameLo(frame);\n ring.records[offset + 1] = encodeFrameHi(frame);\n ring.records[offset + 2] = this.engine.meterScratchTargetId();\n for (let field = 0; field < 11; field++) {\n ring.records[offset + 3 + field] = this.engine.meterScratchValue(field);\n }\n Atomics.store(ring.header, 0, writeIndex + 1);\n }\n\n private writeMeterRing(meter: SonareWorkletMeterSnapshot): void {\n const ring = this.meterRing;\n if (!ring) {\n return;\n }\n const writeIndex = Atomics.load(ring.header, 0);\n const offset = (writeIndex % ring.capacity) * SONARE_METER_RING_RECORD_FLOATS;\n ring.records[offset] = encodeFrameLo(meter.frame);\n ring.records[offset + 1] = encodeFrameHi(meter.frame);\n ring.records[offset + 2] = meter.targetId;\n ring.records[offset + 3] = meter.peakDbL;\n ring.records[offset + 4] = meter.peakDbR;\n ring.records[offset + 5] = meter.rmsDbL;\n ring.records[offset + 6] = meter.rmsDbR;\n ring.records[offset + 7] = meter.correlation;\n ring.records[offset + 8] = meter.truePeakDbL;\n ring.records[offset + 9] = meter.truePeakDbR;\n ring.records[offset + 10] = meter.momentaryLufs;\n ring.records[offset + 11] = meter.shortTermLufs;\n ring.records[offset + 12] = meter.integratedLufs;\n ring.records[offset + 13] = meter.gainReductionDb;\n Atomics.store(ring.header, 0, writeIndex + 1);\n // writeIndex is a free-running monotonic counter, so an overflow guard here\n // would fire on essentially every write past the first `capacity` records\n // and store an ever-growing value, not a dropped-record count. Readers\n // already detect silent overrun via firstReadable = max(readIndex,\n // writeIndex - capacity), so header slot 3 is left at its initial 0.\n }\n\n // Drains the engine's scope producer (FFT spectrum + goniometer points) into\n // the lock-free SAB scope ring. No allocation on the render path: records are\n // written field-by-field into the ring.\n private publishScope(): void {\n const ring = this.scopeRing;\n if (!ring) {\n return;\n }\n for (let count = 0; count < 64 && this.engine.popScopeTelemetryToScratch(); count++) {\n this.writeScopeScratch(ring);\n }\n }\n\n private writeScopeScratch(ring: SharedScopeRingWriter): void {\n const writeIndex = Atomics.load(ring.header, 0);\n const base = (writeIndex % ring.capacity) * ring.recordFloats;\n const frame = Number(this.engine.scopeScratchRenderFrame());\n ring.records[base] = encodeFrameLo(frame);\n ring.records[base + 1] = encodeFrameHi(frame);\n ring.records[base + 2] = this.engine.scopeScratchTargetId();\n const bandCount = Math.min(ring.bands, this.engine.scopeScratchBandCount());\n ring.records[base + 3] = bandCount;\n const pointCount = Math.min(ring.maxPoints, this.engine.scopeScratchPointCount());\n ring.records[base + 4] = pointCount;\n const bandsBase = base + SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS;\n for (let i = 0; i < bandCount; i++) {\n ring.records[bandsBase + i] = this.engine.scopeScratchBand(i);\n }\n const pointsBase = bandsBase + ring.bands;\n for (let i = 0; i < pointCount; i++) {\n ring.records[pointsBase + 2 * i] = this.engine.scopeScratchPointLeft(i);\n ring.records[pointsBase + 2 * i + 1] = this.engine.scopeScratchPointRight(i);\n }\n Atomics.store(ring.header, 0, writeIndex + 1);\n }\n\n // Drains queued external-MIDI events (already lowered to MIDI 1.0 bytes) and\n // forwards them to the main thread for delivery to Web MIDI output ports.\n // One batch per render block; skipped entirely when nothing is queued, so an\n // all-internal project never allocates or posts here.\n private publishExternalMidi(): void {\n const ring = this.externalMidiRing;\n if (ring) {\n for (let count = 0; count < 256 && this.engine.popExternalMidiToScratch(); count++) {\n pushSonareExternalMidiRingBuffer(\n ring,\n this.engine.externalMidiScratchDestinationId(),\n this.engine.externalMidiScratchRenderFrame(),\n this.engine.externalMidiScratchByteWord(),\n this.engine.externalMidiScratchByteCount(),\n );\n this.engine.consumeExternalMidiScratch();\n }\n return;\n }\n if (!this.transport?.postMessage) {\n return;\n }\n if (this.engine.externalMidiPendingCount() === 0) {\n return;\n }\n const events = this.engine.drainExternalMidi(256);\n if (events.length === 0) {\n return;\n }\n this.transport.postMessage({ type: 'externalMidi', events });\n }\n\n /**\n * Forward a bounded batch of native page misses to the main thread. This\n * deliberately runs after audio rendering: a cache miss is silence for this\n * block, and OPFS I/O must never delay `process()`.\n */\n private publishClipPageRequests(): void {\n const ring = this.clipPageRequestRing;\n const transport = this.transport;\n if (!ring && !transport?.postMessage) {\n return;\n }\n let count = 0;\n let drained = 0;\n while (drained < this.clipPageRequestClipIds.length) {\n drained += 1;\n let clipId: number;\n let sample: number;\n if (ring) {\n // This scalar scratch API is intentionally used only on the SAB path:\n // it avoids embind materialising one JS object for every page miss in\n // AudioWorklet process().\n if (!this.engine.popClipPageRequestToScratch()) {\n break;\n }\n clipId = this.engine.clipPageRequestScratchClipId();\n sample = this.engine.clipPageRequestScratchSample();\n } else {\n // postMessage fallback is explicitly non-RT-safe; retain the public\n // object-returning API only for that degraded control-plane path.\n const request = this.engine.popClipPageRequest();\n if (!request) {\n break;\n }\n clipId = request.clipId;\n sample = request.sample;\n }\n const pageFrames = this.pagedClipPageFrames.get(clipId);\n if (!pageFrames) {\n continue;\n }\n const pageIndex = Math.floor(sample / pageFrames);\n let duplicate = false;\n for (let i = 0; i < count; ++i) {\n if (\n this.clipPageRequestClipIds[i] === clipId &&\n this.clipPageRequestPageIndices[i] === pageIndex\n ) {\n duplicate = true;\n break;\n }\n }\n if (!duplicate) {\n this.clipPageRequestClipIds[count] = clipId;\n this.clipPageRequestPageIndices[count] = pageIndex;\n count += 1;\n }\n }\n const overflowCount = this.engine.clipPageRequestOverflowCount();\n // The native counter is uint32_t; preserve a correct delta across its\n // defined unsigned wraparound instead of emitting a negative count.\n const dropped = (overflowCount - this.clipPageRequestOverflowReported) >>> 0;\n this.clipPageRequestOverflowReported = overflowCount;\n if (ring) {\n // Preserve native-queue loss in the same cumulative counter used for a\n // full SAB request ring. No object, structured clone, or postMessage is\n // created on this path.\n if (dropped > 0) {\n Atomics.add(ring.header, 4, dropped);\n }\n for (let i = 0; i < count; ++i) {\n pushSonareClipPageRequestRingBuffer(\n ring,\n this.clipPageRequestClipIds[i],\n this.clipPageRequestPageIndices[i],\n );\n }\n return;\n }\n if (count === 0 && dropped === 0) {\n return;\n }\n if (!transport?.postMessage) {\n return;\n }\n // A message is necessarily allocated by postMessage; the hot path's\n // resident queue remains fixed-size and no message is built without a miss.\n const requests = new Array<{ clipId: number; pageIndex: number }>(count);\n for (let i = 0; i < count; ++i) {\n requests[i] = {\n clipId: this.clipPageRequestClipIds[i],\n pageIndex: this.clipPageRequestPageIndices[i],\n };\n }\n transport.postMessage({\n type: 'clipPageRequest',\n requests,\n ...(dropped > 0 ? { dropped } : {}),\n });\n }\n\n private removePagedClipProvider(clipId: number): void {\n const providerId = this.pagedClipProviders.get(clipId);\n if (providerId !== undefined) {\n this.engine.destroyClipPageProvider(providerId);\n }\n this.pagedClipProviders.delete(clipId);\n this.pagedClipPageFrames.delete(clipId);\n this.pendingPagedClips.delete(clipId);\n }\n\n private clearPagedClipProviders(): void {\n for (const clipId of this.pagedClipProviders.keys()) {\n this.removePagedClipProvider(clipId);\n }\n }\n\n private commandRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n fallbackCapacity?: number,\n ): SonareEngineCommandRingBuffer {\n const ring = engineRingFromSharedBuffer(\n sharedBuffer,\n SONARE_ENGINE_COMMAND_RECORD_BYTES,\n fallbackCapacity,\n );\n return { sharedBuffer, header: ring.header, view: ring.view, capacity: ring.capacity };\n }\n\n private telemetryRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n fallbackCapacity?: number,\n ): SonareEngineTelemetryRingBuffer {\n const ring = engineRingFromSharedBuffer(\n sharedBuffer,\n SONARE_ENGINE_TELEMETRY_RECORD_BYTES,\n fallbackCapacity,\n );\n return { sharedBuffer, header: ring.header, view: ring.view, capacity: ring.capacity };\n }\n}\n","import { init as initSonareModule, isInitialized } from '../index';\nimport type { SonareModule } from '../sonare.js';\nimport type { WorkletInput, WorkletOutput } from './audio_types';\nimport { SonareRealtimeEngineWorkletProcessor } from './engine-processor';\nimport {\n isEngineCaptureRequestMessage,\n isEngineCommandRecord,\n isEngineSyncMessage,\n isEngineTransportRequestMessage,\n} from './guards';\nimport type { SonareRealtimeEngineWorkletProcessorOptions, WorkletPort } from './messages';\n\nexport function registerSonareRealtimeEngineWorkletProcessor(\n name = 'sonare-realtime-engine-processor',\n): void {\n const scope = globalThis as unknown as {\n AudioWorkletProcessor?: new () => object;\n registerProcessor?: (processorName: string, processorCtor: unknown) => void;\n };\n if (!scope.AudioWorkletProcessor || !scope.registerProcessor) {\n throw new Error('AudioWorkletProcessor is not available in this context.');\n }\n const Base = scope.AudioWorkletProcessor;\n class RegisteredSonareRealtimeEngineWorkletProcessor extends Base {\n private bridge?: SonareRealtimeEngineWorkletProcessor;\n private readonly pendingMessages: unknown[] = [];\n private pendingMessagesOverflowed = false;\n readonly port?: WorkletPort;\n\n constructor(options?: { processorOptions?: SonareRealtimeEngineWorkletProcessorOptions }) {\n super();\n const port = this.port;\n const processorOptions = options?.processorOptions ?? {};\n void this.initializeEmbind(processorOptions, port);\n const onMessage = (event: { data: unknown }) => {\n if (!this.bridge) {\n if (this.pendingMessages.length < 1024) {\n this.pendingMessages.push(event.data);\n } else {\n // A long sync before embind initialization must fail visibly rather\n // than drop a provider/page/commit message and leave silent audio.\n this.pendingMessagesOverflowed = true;\n }\n return;\n }\n if (isEngineCommandRecord(event.data)) {\n this.bridge.receiveCommand(event.data);\n } else if (isEngineSyncMessage(event.data)) {\n this.bridge.receiveSync(event.data);\n } else if (isEngineCaptureRequestMessage(event.data)) {\n this.bridge.receiveCaptureRequest(event.data);\n } else if (isEngineTransportRequestMessage(event.data)) {\n this.bridge.receiveTransportRequest(event.data);\n }\n };\n if (port?.addEventListener) {\n port.addEventListener('message', onMessage);\n port.start?.();\n } else if (port) {\n port.onmessage = onMessage;\n }\n }\n\n process(inputs: WorkletInput, outputs: WorkletOutput): boolean {\n if (this.bridge) {\n return this.bridge.process(inputs, outputs);\n }\n const output = outputs[0];\n for (const channel of output ?? []) {\n channel.fill(0);\n }\n return true;\n }\n\n private replayPendingMessages(): void {\n const messages = this.pendingMessages.splice(0);\n for (const data of messages) {\n if (isEngineCommandRecord(data)) {\n this.bridge?.receiveCommand(data);\n } else if (isEngineSyncMessage(data)) {\n this.bridge?.receiveSync(data);\n } else if (isEngineCaptureRequestMessage(data)) {\n this.bridge?.receiveCaptureRequest(data);\n } else if (isEngineTransportRequestMessage(data)) {\n this.bridge?.receiveTransportRequest(data);\n }\n }\n }\n\n private async initializeEmbind(\n options: SonareRealtimeEngineWorkletProcessorOptions,\n port?: WorkletPort,\n ): Promise<void> {\n try {\n const initPromise = (\n globalThis as typeof globalThis & { SonareEmbindInitPromise?: Promise<void> }\n ).SonareEmbindInitPromise;\n if (initPromise) {\n await initPromise;\n }\n if (!isInitialized()) {\n type EmbindModuleFactory = (options?: {\n locateFile?: (path: string, prefix: string) => string;\n wasmBinary?: ArrayBuffer | Uint8Array;\n }) => Promise<SonareModule>;\n const moduleFactory = (\n globalThis as typeof globalThis & {\n SonareEmbindModuleFactory?: EmbindModuleFactory;\n }\n ).SonareEmbindModuleFactory;\n if (!moduleFactory) {\n throw new Error('embind realtime engine module is not initialized.');\n }\n await initSonareModule({\n locateFile: (path) => path,\n wasmBinary: options.wasmBinary,\n moduleFactory,\n });\n }\n if (this.pendingMessagesOverflowed) {\n throw new Error('AudioWorklet initialization message buffer overflowed.');\n }\n this.bridge = new SonareRealtimeEngineWorkletProcessor(options, {\n postMessage: (message, transfer) => port?.postMessage?.(message, transfer),\n onMeter: (meter) => port?.postMessage?.(meter),\n });\n for (const message of options.initialSyncMessages ?? []) {\n this.bridge.receiveSync(message);\n }\n for (const command of options.initialCommands ?? []) {\n this.bridge.receiveCommand(command);\n }\n this.replayPendingMessages();\n port?.postMessage?.({ type: 'ready', runtimeTarget: 'embind' });\n } catch (error) {\n port?.postMessage?.({\n type: 'error',\n message: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n scope.registerProcessor(name, RegisteredSonareRealtimeEngineWorkletProcessor);\n}\n","import type { MixerRealtimeBuffer } from '../index';\nimport { Mixer } from '../index';\nimport type { WorkletInput, WorkletOutput } from './audio_types';\nimport { isWorkletMessage } from './guards';\nimport type {\n SonareWorkletMessage,\n SonareWorkletProcessorOptions,\n WorkletPort,\n WorkletTransport,\n} from './messages';\nimport {\n encodeFrameHi,\n encodeFrameLo,\n magnitudeToDb,\n meterRingFromSharedBuffer,\n type SharedMeterRingWriter,\n type SharedSpectrumRingWriter,\n SONARE_METER_RING_RECORD_FLOATS,\n type SonareWorkletMeterSnapshot,\n type SonareWorkletSpectrumSnapshot,\n spectrumRingFromSharedBuffer,\n toDb,\n} from './protocol';\n\n/**\n * AudioWorklet-style mixer bridge backed by the package's single `sonare.wasm`.\n *\n * The WASM module must already be initialized via `init()` before constructing\n * this bridge. Each AudioWorklet input is treated as one stereo strip:\n * `inputs[strip][0]` is left and `inputs[strip][1]` is right. Missing channels\n * are replaced with preallocated silence.\n */\nexport class SonareWorkletProcessor {\n readonly sampleRate: number;\n readonly blockSize: number;\n private mixer: Mixer;\n private realtime: MixerRealtimeBuffer;\n private closed = false;\n private processedFrames = 0;\n private lastMeterFrame = 0;\n private meterIntervalFrames: number;\n private spectrumIntervalFrames: number;\n private lastSpectrumFrame = 0;\n private transport?: WorkletTransport;\n private meterRing?: SharedMeterRingWriter;\n private spectrumRing?: SharedSpectrumRingWriter;\n private spectrumBands: Float32Array;\n\n constructor(options: SonareWorkletProcessorOptions, transport?: WorkletTransport) {\n if (!options.sceneJson) {\n throw new Error('sceneJson is required.');\n }\n this.sampleRate = options.sampleRate ?? 48000;\n this.blockSize = options.blockSize ?? 128;\n this.meterIntervalFrames = Math.max(0, Math.floor(options.meterIntervalFrames ?? 2048));\n this.spectrumIntervalFrames = Math.max(0, Math.floor(options.spectrumIntervalFrames ?? 0));\n this.transport = transport;\n this.meterIntervalFrames = Math.max(0, Math.floor(options.meterIntervalFrames ?? 2048));\n this.meterRing = options.meterSharedBuffer\n ? meterRingFromSharedBuffer(options.meterSharedBuffer, options.meterRingCapacity)\n : undefined;\n this.spectrumRing = options.spectrumSharedBuffer\n ? spectrumRingFromSharedBuffer(\n options.spectrumSharedBuffer,\n options.spectrumRingCapacity,\n options.spectrumBands,\n )\n : undefined;\n const spectrumBandCount = this.spectrumRing?.bands ?? Math.max(1, options.spectrumBands ?? 16);\n this.spectrumBands = new Float32Array(spectrumBandCount);\n this.mixer = Mixer.fromSceneJson(options.sceneJson, this.sampleRate, this.blockSize);\n this.mixer.compile();\n const sceneStripCount = this.mixer.stripCount();\n const stripCount = options.stripCount ?? sceneStripCount;\n if (stripCount !== sceneStripCount) {\n throw new Error('stripCount must match the scene strip count.');\n }\n this.realtime = this.mixer.createRealtimeBuffer();\n }\n\n process(inputs: WorkletInput, outputs: WorkletOutput): boolean {\n if (this.closed) {\n return false;\n }\n const output = outputs[0];\n const leftOut = output?.[0];\n const rightOut = output?.[1];\n if (!leftOut) {\n return true;\n }\n const frames = leftOut.length;\n // The mixer's realtime heap buffers are sized to blockSize. A render quantum\n // that differs from blockSize (e.g. a future browser using a quantum other\n // than 128, or a misconfigured blockSize) must NOT return false here:\n // returning false permanently terminates the AudioWorkletProcessor and\n // silently kills the node mid-stream. Instead degrade gracefully by\n // processing min(frames, blockSize) and zero-filling any remainder.\n const usable = Math.min(frames, this.blockSize);\n\n for (let strip = 0; strip < this.realtime.leftInputs.length; strip++) {\n const input = inputs[strip];\n const left = input?.[0];\n const right = input?.[1];\n const leftTarget = this.realtime.leftInputs[strip];\n const rightTarget = this.realtime.rightInputs[strip];\n if (left && left.length >= usable) {\n leftTarget.set(left.subarray(0, usable));\n if (right && right.length >= usable) {\n rightTarget.set(right.subarray(0, usable));\n } else {\n rightTarget.set(left.subarray(0, usable));\n }\n } else {\n leftTarget.fill(0);\n rightTarget.fill(0);\n }\n }\n\n this.realtime.process(usable);\n if (usable === frames) {\n leftOut.set(this.realtime.outLeft.subarray(0, usable));\n if (rightOut) {\n rightOut.set(this.realtime.outRight.subarray(0, usable));\n }\n } else {\n // frames > blockSize: fill the produced part and zero the remaining tail.\n leftOut.fill(0);\n leftOut.set(this.realtime.outLeft.subarray(0, usable));\n if (rightOut) {\n rightOut.fill(0);\n rightOut.set(this.realtime.outRight.subarray(0, usable));\n }\n }\n this.processedFrames += usable;\n this.publishMeter(\n this.realtime.outLeft.subarray(0, usable),\n this.realtime.outRight.subarray(0, usable),\n );\n this.publishSpectrum(\n this.realtime.outLeft.subarray(0, usable),\n this.realtime.outRight.subarray(0, usable),\n );\n return true;\n }\n\n receiveMessage(message: SonareWorkletMessage): void {\n if (this.closed) {\n return;\n }\n if (message.type === 'destroy') {\n this.destroy();\n return;\n }\n if (message.type === 'setMeterInterval') {\n this.meterIntervalFrames = Math.max(0, Math.floor(message.frames));\n return;\n }\n if (message.type === 'scheduleInsertAutomation') {\n this.mixer.scheduleInsertAutomation(\n message.stripIndex,\n message.insertIndex,\n message.paramId,\n message.samplePos ?? this.processedFrames,\n message.value,\n message.curve ?? 'linear',\n );\n }\n }\n\n destroy(): void {\n if (!this.closed) {\n this.mixer.delete();\n this.closed = true;\n }\n }\n\n private publishMeter(left: Float32Array, right: Float32Array): void {\n if (!this.transport || this.meterIntervalFrames <= 0) {\n return;\n }\n if (this.processedFrames - this.lastMeterFrame < this.meterIntervalFrames) {\n return;\n }\n this.lastMeterFrame = this.processedFrames;\n\n let peakL = 0;\n let peakR = 0;\n let sumL = 0;\n let sumR = 0;\n let sumLR = 0;\n for (let i = 0; i < left.length; i++) {\n const l = left[i] ?? 0;\n const r = right[i] ?? 0;\n const absL = Math.abs(l);\n const absR = Math.abs(r);\n if (absL > peakL) {\n peakL = absL;\n }\n if (absR > peakR) {\n peakR = absR;\n }\n sumL += l * l;\n sumR += r * r;\n sumLR += l * r;\n }\n const rmsL = Math.sqrt(sumL / Math.max(1, left.length));\n const rmsR = Math.sqrt(sumR / Math.max(1, right.length));\n const denominator = Math.sqrt(sumL * sumR);\n const meter: SonareWorkletMeterSnapshot = {\n type: 'meter',\n targetId: 0,\n frame: this.processedFrames,\n peakDbL: toDb(peakL),\n peakDbR: toDb(peakR),\n rmsDbL: toDb(rmsL),\n rmsDbR: toDb(rmsR),\n correlation: denominator > 0 ? sumLR / denominator : 0,\n truePeakDbL: toDb(peakL),\n truePeakDbR: toDb(peakR),\n momentaryLufs: Number.NaN,\n shortTermLufs: Number.NaN,\n integratedLufs: Number.NaN,\n gainReductionDb: Number.NaN,\n };\n this.transport.onMeter?.(meter);\n if (this.meterRing) {\n this.writeMeterRing(meter);\n } else {\n this.transport.postMessage?.(meter);\n }\n }\n\n private writeMeterRing(meter: SonareWorkletMeterSnapshot): void {\n const ring = this.meterRing;\n if (!ring) {\n return;\n }\n const writeIndex = Atomics.load(ring.header, 0);\n const offset = (writeIndex % ring.capacity) * SONARE_METER_RING_RECORD_FLOATS;\n ring.records[offset] = encodeFrameLo(meter.frame);\n ring.records[offset + 1] = encodeFrameHi(meter.frame);\n ring.records[offset + 2] = meter.targetId;\n ring.records[offset + 3] = meter.peakDbL;\n ring.records[offset + 4] = meter.peakDbR;\n ring.records[offset + 5] = meter.rmsDbL;\n ring.records[offset + 6] = meter.rmsDbR;\n ring.records[offset + 7] = meter.correlation;\n ring.records[offset + 8] = meter.truePeakDbL;\n ring.records[offset + 9] = meter.truePeakDbR;\n ring.records[offset + 10] = meter.momentaryLufs;\n ring.records[offset + 11] = meter.shortTermLufs;\n ring.records[offset + 12] = meter.integratedLufs;\n ring.records[offset + 13] = meter.gainReductionDb;\n Atomics.store(ring.header, 0, writeIndex + 1);\n // writeIndex is a free-running monotonic counter, so an overflow guard here\n // would fire on essentially every write past the first `capacity` records\n // and store an ever-growing value, not a dropped-record count. Readers\n // already detect silent overrun via firstReadable = max(readIndex,\n // writeIndex - capacity), so header slot 3 is left at its initial 0.\n }\n\n private publishSpectrum(left: Float32Array, right: Float32Array): void {\n if (this.spectrumIntervalFrames <= 0) {\n return;\n }\n if (this.processedFrames - this.lastSpectrumFrame < this.spectrumIntervalFrames) {\n return;\n }\n this.lastSpectrumFrame = this.processedFrames;\n this.computeSpectrum(left, right);\n if (this.spectrumRing) {\n this.writeSpectrumRing(this.processedFrames, this.spectrumBands);\n return;\n }\n const spectrum: SonareWorkletSpectrumSnapshot = {\n type: 'spectrum',\n frame: this.processedFrames,\n bands: new Float32Array(this.spectrumBands),\n };\n this.transport?.onSpectrum?.(spectrum);\n this.transport?.postMessage?.(spectrum);\n }\n\n private computeSpectrum(left: Float32Array, right: Float32Array): void {\n // Coarse per-render-quantum band energy, NOT a full FFT analyzer: each band\n // is a single-bin DFT (bin = band + 1) evaluated over the current block of n\n // samples. Bins at or above the block Nyquist (band + 1 > floor(n / 2))\n // alias, so the evaluated band count is clamped to floor(n / 2) and any\n // higher bands are pinned to the silence floor. Bin resolution is therefore\n // tied to the render quantum (typically 128 samples); treat the output as a\n // rough spectral tilt, not a precise spectrum.\n const n = Math.max(1, Math.min(left.length, right.length));\n const maxBand = Math.floor(n / 2);\n for (let band = 0; band < this.spectrumBands.length; band++) {\n if (band >= maxBand) {\n this.spectrumBands[band] = magnitudeToDb(0);\n continue;\n }\n const bin = band + 1;\n let real = 0;\n let imag = 0;\n for (let i = 0; i < n; i++) {\n const sample = 0.5 * ((left[i] ?? 0) + (right[i] ?? 0));\n const phase = (-2 * Math.PI * bin * i) / n;\n real += sample * Math.cos(phase);\n imag += sample * Math.sin(phase);\n }\n this.spectrumBands[band] = magnitudeToDb((2 * Math.hypot(real, imag)) / n);\n }\n }\n\n private writeSpectrumRing(frame: number, bands: Float32Array): void {\n const ring = this.spectrumRing;\n if (!ring) {\n return;\n }\n const writeIndex = Atomics.load(ring.header, 0);\n const offset = (writeIndex % ring.capacity) * ring.recordFloats;\n ring.records[offset] = encodeFrameLo(frame);\n ring.records[offset + 1] = encodeFrameHi(frame);\n ring.records[offset + 2] = bands.length;\n ring.records.set(bands.subarray(0, ring.bands), offset + 3);\n Atomics.store(ring.header, 0, writeIndex + 1);\n // See writeMeterRing: header slot 4 (the spectrum-ring overflow slot) is\n // left at its initial 0; readers detect silent overrun via the\n // firstReadable = max(readIndex, writeIndex - capacity) clamp. (Slot 3 here\n // holds the band count and is still written at ring creation.)\n }\n}\n\nexport function registerSonareWorkletProcessor(name = 'sonare-worklet-processor'): void {\n const scope = globalThis as unknown as {\n AudioWorkletProcessor?: new () => object;\n registerProcessor?: (processorName: string, processorCtor: unknown) => void;\n };\n if (!scope.AudioWorkletProcessor || !scope.registerProcessor) {\n throw new Error('AudioWorkletProcessor is not available in this context.');\n }\n const Base = scope.AudioWorkletProcessor;\n class RegisteredSonareWorkletProcessor extends Base {\n private bridge: SonareWorkletProcessor;\n readonly port?: WorkletPort;\n\n constructor(options?: { processorOptions?: SonareWorkletProcessorOptions }) {\n super();\n const port = this.port;\n this.bridge = new SonareWorkletProcessor(options?.processorOptions ?? { sceneJson: '' }, {\n postMessage: (message) => port?.postMessage?.(message),\n });\n const onMessage = (event: { data: unknown }) => {\n if (isWorkletMessage(event.data)) {\n this.bridge.receiveMessage(event.data);\n }\n };\n if (port?.addEventListener) {\n port.addEventListener('message', onMessage);\n port.start?.();\n } else if (port) {\n port.onmessage = onMessage;\n }\n }\n\n process(inputs: WorkletInput, outputs: WorkletOutput): boolean {\n return this.bridge.process(inputs, outputs);\n }\n }\n scope.registerProcessor(name, RegisteredSonareWorkletProcessor);\n}\n","import { RealtimeVoiceChanger } from '../index';\nimport type { WorkletInput, WorkletOutput } from './audio_types';\nimport { isRealtimeVoiceChangerMessage } from './guards';\nimport type {\n SonareRealtimeVoiceChangerMessage,\n SonareRealtimeVoiceChangerWorkletProcessorOptions,\n WorkletPort,\n} from './messages';\n\nexport class SonareRealtimeVoiceChangerWorkletProcessor {\n private static warnedMonoOverflow = false;\n private static warnedInterleavedOverflow = false;\n private changer: RealtimeVoiceChanger;\n private readonly sampleRate: number;\n private readonly blockSize: number;\n private readonly channelCount: number;\n // WASM-heap typed-memory views, sized to the worst case (blockSize *\n // channelCount). Acquired on the main thread (constructor) so the\n // audio-thread process() never crosses an allocation boundary.\n private monoInput: Float32Array;\n private monoOutput: Float32Array;\n private bufferGeneration: number;\n // Planar heap-backed views (one Float32Array per channel) used by the\n // multi-channel path. AudioWorklet inputs/outputs are already planar\n // Float32Arrays, so this avoids the per-sample interleave/deinterleave\n // passes that the older interleaved path needed.\n private planarChannels: Float32Array[];\n private destroyed = false;\n\n constructor(options: SonareRealtimeVoiceChangerWorkletProcessorOptions = {}) {\n this.sampleRate = options.sampleRate ?? 48000;\n this.blockSize = options.blockSize ?? 128;\n this.channelCount = Math.max(1, Math.floor(options.channelCount ?? 1));\n this.changer = new RealtimeVoiceChanger(options.preset ?? 'neutral-monitor');\n this.changer.prepare(this.sampleRate, this.blockSize, this.channelCount);\n // Acquire WASM-heap views once, sized to the worst case. These are alive\n // for the lifetime of the changer; if the host requests more frames per\n // process() than blockSize, we clamp (see ensure*Capacity).\n this.monoInput = this.changer.getMonoInputBuffer(this.blockSize);\n this.monoOutput = this.changer.getMonoOutputBuffer(this.blockSize);\n this.bufferGeneration = this.changer.bufferGeneration();\n this.planarChannels = [];\n if (this.channelCount > 1) {\n for (let ch = 0; ch < this.channelCount; ch++) {\n this.planarChannels.push(this.changer.getPlanarChannelBuffer(ch, this.blockSize));\n }\n }\n }\n\n /**\n * Handles a control-plane message from the main thread. AudioWorklet port\n * handlers run on the same audio rendering thread as `process()`: this path\n * therefore accepts only a pre-normalized POD and never parses JSON.\n */\n receiveMessage(message: SonareRealtimeVoiceChangerMessage): void {\n if (this.destroyed) {\n return;\n }\n if (message.type === 'setConfig') {\n this.changer.setPodConfig(message.config);\n } else if (message.type === 'reset') {\n this.changer.reset();\n } else if (message.type === 'destroy') {\n this.destroy();\n }\n }\n\n process(inputs: WorkletInput, outputs: WorkletOutput): boolean {\n const output = outputs[0];\n if (this.destroyed || !output || output.length === 0) {\n return !this.destroyed;\n }\n\n // The cached heap views can detach if WASM linear memory grows (the embind\n // module is built ALLOW_MEMORY_GROWTH). Re-acquire them if detached\n // (byteLength === 0) before touching them; in the common no-growth case this\n // is a cheap branch with no allocation.\n if (\n this.bufferGeneration !== this.changer.bufferGeneration() ||\n this.monoInput.byteLength === 0\n ) {\n this.reacquireBuffers();\n }\n\n const input = inputs[0];\n const requestedFrames = output[0]?.length ?? 0;\n const requestedChannels = Math.min(this.channelCount, output.length);\n if (requestedFrames === 0 || requestedChannels === 0) {\n return true;\n }\n\n if (requestedChannels === 1) {\n // Clamp to the pre-allocated capacity; warn (once) if the host violated\n // the contract. We never reallocate on the audio thread.\n const frames = this.ensureMonoCapacity(requestedFrames);\n const source = input?.[0];\n if (source) {\n this.monoInput.set(source.subarray(0, frames));\n } else {\n this.monoInput.fill(0, 0, frames);\n }\n this.changer.processPreparedMono(frames);\n output[0].set(this.monoOutput.subarray(0, frames));\n return true;\n }\n\n const frames = this.ensureInterleavedCapacity(requestedFrames, requestedChannels);\n const channels = requestedChannels;\n // Planar zero-copy path: AudioWorklet's input[ch] is already a\n // Float32Array per channel, so we set() straight into the heap-backed\n // planar view and processPreparedPlanar runs in place.\n for (let ch = 0; ch < channels; ch++) {\n const src = input?.[ch];\n const dst = this.planarChannels[ch];\n if (!dst) {\n continue;\n }\n if (src) {\n dst.set(src.subarray(0, frames));\n } else {\n dst.fill(0, 0, frames);\n }\n }\n this.changer.processPreparedPlanar(frames);\n for (let ch = 0; ch < channels; ch++) {\n const src = this.planarChannels[ch];\n if (src) {\n output[ch].set(src.subarray(0, frames));\n }\n // No `for frame` inner loop needed; output[ch] is a Float32Array.\n }\n return true;\n }\n\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n this.destroyed = true;\n this.changer.delete();\n }\n\n // Re-acquires the cached WASM-heap views after a memory-growth detachment.\n // The underlying C++ vectors are pre-warmed (ensure_*_capacity ran at prepare\n // time), so getMono*/getPlanar* return fresh views onto the SAME storage\n // without reallocating it.\n private reacquireBuffers(): void {\n this.monoInput = this.changer.getMonoInputBuffer(this.blockSize);\n this.monoOutput = this.changer.getMonoOutputBuffer(this.blockSize);\n if (this.channelCount > 1) {\n for (let ch = 0; ch < this.channelCount; ch++) {\n this.planarChannels[ch] = this.changer.getPlanarChannelBuffer(ch, this.blockSize);\n }\n }\n this.bufferGeneration = this.changer.bufferGeneration();\n }\n\n /**\n * Returns the number of frames we can actually process given the\n * pre-allocated capacity. If the host requests more frames than the\n * worst-case block size declared at construction time, we clamp to the\n * available capacity and warn once — we MUST NOT reallocate on the\n * realtime audio thread.\n */\n private ensureMonoCapacity(frames: number): number {\n const capacity = this.monoInput.length;\n if (frames <= capacity) {\n return frames;\n }\n if (!SonareRealtimeVoiceChangerWorkletProcessor.warnedMonoOverflow) {\n SonareRealtimeVoiceChangerWorkletProcessor.warnedMonoOverflow = true;\n // biome-ignore lint/suspicious/noConsole: realtime-safety diagnostic.\n console.warn(\n `SonareRealtimeVoiceChangerWorkletProcessor: requested ${frames} mono frames ` +\n `exceeds pre-allocated capacity ${capacity}; clamping. ` +\n 'Increase blockSize at construction time to avoid this.',\n );\n }\n return capacity;\n }\n\n /**\n * Same contract as ensureMonoCapacity but for the planar per-channel\n * scratch. Returns the number of frames that fit in the available capacity.\n */\n private ensureInterleavedCapacity(frames: number, channels: number): number {\n const capacity = this.planarChannels[0]?.length ?? 0;\n if (frames <= capacity) {\n return frames;\n }\n if (!SonareRealtimeVoiceChangerWorkletProcessor.warnedInterleavedOverflow) {\n SonareRealtimeVoiceChangerWorkletProcessor.warnedInterleavedOverflow = true;\n // biome-ignore lint/suspicious/noConsole: realtime-safety diagnostic.\n console.warn(\n `SonareRealtimeVoiceChangerWorkletProcessor: requested ${frames}x${channels} ` +\n `planar frames exceeds pre-allocated capacity ${capacity}; clamping. ` +\n 'Increase blockSize or channelCount at construction time to avoid this.',\n );\n }\n return capacity;\n }\n}\n\nexport function registerSonareRealtimeVoiceChangerWorkletProcessor(\n name = 'sonare-realtime-voice-changer-processor',\n): void {\n const scope = globalThis as unknown as {\n AudioWorkletProcessor?: new () => object;\n registerProcessor?: (processorName: string, processorCtor: unknown) => void;\n };\n if (!scope.AudioWorkletProcessor || !scope.registerProcessor) {\n throw new Error('AudioWorkletProcessor is not available in this context.');\n }\n const Base = scope.AudioWorkletProcessor;\n class RegisteredSonareRealtimeVoiceChangerWorkletProcessor extends Base {\n private bridge: SonareRealtimeVoiceChangerWorkletProcessor;\n readonly port?: WorkletPort;\n\n constructor(options?: {\n processorOptions?: SonareRealtimeVoiceChangerWorkletProcessorOptions;\n }) {\n super();\n const port = this.port;\n this.bridge = new SonareRealtimeVoiceChangerWorkletProcessor(options?.processorOptions ?? {});\n const onMessage = (event: { data: unknown }) => {\n if (isRealtimeVoiceChangerMessage(event.data)) {\n this.bridge.receiveMessage(event.data);\n }\n };\n if (port?.addEventListener) {\n port.addEventListener('message', onMessage);\n port.start?.();\n } else if (port) {\n port.onmessage = onMessage;\n }\n }\n\n process(inputs: WorkletInput, outputs: WorkletOutput): boolean {\n return this.bridge.process(inputs, outputs);\n }\n }\n scope.registerProcessor(name, RegisteredSonareRealtimeVoiceChangerWorkletProcessor);\n}\n"],"mappings":"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","names":["module","module","module","module","marker","SonareEngineCommandType","SonareEngineTelemetryType","SonareEngineTelemetryError","marker","initPromise","frames"]}
1
+ {"version":3,"sources":["../src/opfs_clip_pages.ts","../src/clip_page_streamer.ts","../src/errors.ts","../src/module_state.ts","../src/_chain_config.ts","../src/codes.ts","../src/realtime_engine.ts","../src/mixer.ts","../src/realtime_voice_changer.ts","../src/streaming_processors.ts","../src/index.ts","../src/worklet/engine-sync.ts","../src/worklet/engine-automation.ts","../src/worklet/engine-offline.ts","../src/worklet/protocol.ts","../src/worklet/engine-capture-facade.ts","../src/worklet/engine-clips.ts","../src/worklet/engine-markers.ts","../src/worklet/engine-mixer-facade.ts","../src/worklet/guards.ts","../src/worklet/engine-node.ts","../src/worklet/engine-parameter-facade.ts","../src/worklet/engine-strips.ts","../src/worklet/engine-tempo-facade.ts","../src/worklet/engine.ts","../src/worklet/messages.ts","../src/worklet/engine-processor.ts","../src/worklet/engine-register.ts","../src/worklet/mixer-processor.ts","../src/worklet/voice-changer-processor.ts"],"sourcesContent":["import type { ClipPageProvider, ClipPageRequest, RealtimeEngine } from './realtime_engine';\n\nexport interface OpfsClipPageProviderOptions {\n path: string;\n numChannels: number;\n numSamples: number;\n pageFrames: number;\n dataOffsetBytes?: number;\n worker?: Worker;\n terminateWorkerOnClose?: boolean;\n /** Internal bridge hook used to mirror a supplied page into an AudioWorklet. */\n onPageSupplied?: (pageIndex: number, channels: Float32Array[]) => void;\n /** Internal bridge hook used to mirror an eviction into an AudioWorklet. */\n onPageCleared?: (pageIndex: number) => void;\n /** Internal bridge hook called after the local provider is destroyed. */\n onClose?: () => void;\n}\n\nexport interface OpfsClipPageProviderBinding {\n provider: ClipPageProvider;\n supplyPage(pageIndex: number): Promise<boolean>;\n supplyRequest(request: ClipPageRequest): Promise<boolean>;\n /** Evict one resident page from every configured consumer. */\n clearPage?(pageIndex: number): void;\n close(): void;\n}\n\ninterface PageResponse {\n type: 'sonare:clip-page';\n requestId: number;\n pageIndex: number;\n ok: boolean;\n frames?: number;\n channels?: Float32Array[];\n channelBuffers?: ArrayBufferLike[];\n error?: string;\n}\n\nexport const opfsClipPageWorkerSource = `\nconst sonareClipPageReadQueues = new Map();\n\nfunction sonareEnqueueClipPageRead(key, task) {\n const previous = sonareClipPageReadQueues.get(key) || Promise.resolve();\n const next = previous.catch(() => undefined).then(task);\n const queued = next.finally(() => {\n if (sonareClipPageReadQueues.get(key) === queued) {\n sonareClipPageReadQueues.delete(key);\n }\n });\n sonareClipPageReadQueues.set(key, queued);\n return next;\n}\n\nself.onmessage = async (event) => {\n const message = event.data;\n if (!message || message.type !== 'sonare:read-clip-page') return;\n const { requestId, path, pageIndex, numChannels, numSamples, pageFrames, dataOffsetBytes = 0 } = message;\n await sonareEnqueueClipPageRead(String(path), async () => {\n try {\n if (pageIndex < 0) {\n self.postMessage({ type: 'sonare:clip-page', requestId, pageIndex, ok: false });\n return;\n }\n const startFrame = pageIndex * pageFrames;\n if (startFrame >= numSamples) {\n self.postMessage({ type: 'sonare:clip-page', requestId, pageIndex, ok: false });\n return;\n }\n const root = await self.navigator.storage.getDirectory();\n let dir = root;\n const parts = String(path).split('/').filter(Boolean);\n for (let i = 0; i < parts.length - 1; ++i) {\n dir = await dir.getDirectoryHandle(parts[i]);\n }\n const fileHandle = await dir.getFileHandle(parts[parts.length - 1]);\n const access = await fileHandle.createSyncAccessHandle();\n try {\n const frames = Math.min(pageFrames, numSamples - startFrame);\n const frameBytes = numChannels * 4;\n const bytes = new Uint8Array(frames * frameBytes);\n let bytesReadTotal = 0;\n const readOffset = dataOffsetBytes + startFrame * frameBytes;\n while (bytesReadTotal < bytes.byteLength) {\n const bytesRead = access.read(bytes.subarray(bytesReadTotal), {\n at: readOffset + bytesReadTotal,\n });\n if (bytesRead <= 0) {\n break;\n }\n bytesReadTotal += bytesRead;\n }\n if (bytesReadTotal !== bytes.byteLength || bytesReadTotal % frameBytes !== 0) {\n self.postMessage({ type: 'sonare:clip-page', requestId, pageIndex, ok: false });\n return;\n }\n const framesRead = bytesReadTotal / frameBytes;\n const view = new DataView(bytes.buffer, 0, framesRead * frameBytes);\n const channelBuffers = Array.from({ length: numChannels }, () => new ArrayBuffer(framesRead * 4));\n for (let ch = 0; ch < numChannels; ++ch) {\n const channel = new Float32Array(channelBuffers[ch]);\n for (let frame = 0; frame < framesRead; ++frame) {\n channel[frame] = view.getFloat32((frame * numChannels + ch) * 4, true);\n }\n }\n self.postMessage(\n { type: 'sonare:clip-page', requestId, pageIndex, ok: true, frames: framesRead, channelBuffers },\n channelBuffers,\n );\n } finally {\n access.close();\n }\n } catch (error) {\n self.postMessage({\n type: 'sonare:clip-page',\n requestId,\n pageIndex,\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n });\n};\n`;\n\nexport function createOpfsClipPageWorker(): Worker {\n const blob = new Blob([opfsClipPageWorkerSource], { type: 'text/javascript' });\n const url = URL.createObjectURL(blob);\n try {\n return new Worker(url);\n } finally {\n // Worker construction retains the script URL internally; keeping this\n // object URL alive after construction leaks one browser registration per\n // attach/close cycle.\n URL.revokeObjectURL(url);\n }\n}\n\nexport function createOpfsClipPageProvider(\n engine: RealtimeEngine,\n options: OpfsClipPageProviderOptions,\n): OpfsClipPageProviderBinding {\n if (options.numChannels <= 0 || options.numSamples <= 0 || options.pageFrames <= 0) {\n throw new Error('numChannels, numSamples, and pageFrames must be positive');\n }\n const provider = engine.createClipPageProvider(\n options.numChannels,\n options.numSamples,\n options.pageFrames,\n );\n const worker = options.worker ?? createOpfsClipPageWorker();\n const ownsWorker = options.worker === undefined || options.terminateWorkerOnClose === true;\n let nextRequestId = 1;\n let closed = false;\n let readQueue: Promise<void> = Promise.resolve();\n const pending = new Map<\n number,\n { resolve: (value: boolean) => void; reject: (reason: unknown) => void }\n >();\n\n const onMessage = (event: MessageEvent<PageResponse>) => {\n const response = event.data;\n if (response?.type !== 'sonare:clip-page') {\n return;\n }\n const entry = pending.get(response.requestId);\n if (!entry) {\n return;\n }\n pending.delete(response.requestId);\n if (!response.ok) {\n entry.resolve(false);\n return;\n }\n const channels =\n response.channels ??\n response.channelBuffers?.map(\n (buffer) => new Float32Array(buffer, 0, response.frames ?? buffer.byteLength / 4),\n );\n if (!channels || channels.length === 0) {\n entry.resolve(false);\n return;\n }\n try {\n provider.supply(response.pageIndex, channels);\n options.onPageSupplied?.(response.pageIndex, channels);\n } catch {\n entry.resolve(false);\n return;\n }\n entry.resolve(true);\n };\n worker.addEventListener('message', onMessage as EventListener);\n\n const supplyPage = (pageIndex: number): Promise<boolean> => {\n if (closed) {\n return Promise.reject(new Error('OpfsClipPageProvider is closed'));\n }\n const requestId = nextRequestId++;\n const promise = new Promise<boolean>((resolve, reject) => {\n pending.set(requestId, { resolve, reject });\n });\n readQueue = readQueue\n .catch(() => undefined)\n .then(() => {\n if (closed) {\n const entry = pending.get(requestId);\n pending.delete(requestId);\n entry?.reject(new Error('OpfsClipPageProvider is closed'));\n return;\n }\n worker.postMessage({\n type: 'sonare:read-clip-page',\n requestId,\n path: options.path,\n pageIndex,\n numChannels: options.numChannels,\n numSamples: options.numSamples,\n pageFrames: options.pageFrames,\n dataOffsetBytes: options.dataOffsetBytes ?? 0,\n });\n return promise.then(\n () => undefined,\n () => undefined,\n );\n });\n readQueue.catch(() => {\n // The per-request promise carries the user-visible failure.\n });\n return promise;\n };\n\n return {\n provider,\n supplyPage,\n supplyRequest(request: ClipPageRequest) {\n return supplyPage(Math.floor(request.sample / options.pageFrames));\n },\n clearPage(pageIndex: number) {\n if (closed) {\n return;\n }\n provider.clear(pageIndex);\n options.onPageCleared?.(pageIndex);\n },\n close() {\n if (closed) {\n return;\n }\n closed = true;\n worker.removeEventListener('message', onMessage as EventListener);\n for (const entry of pending.values()) {\n entry.reject(new Error('OpfsClipPageProvider is closed'));\n }\n pending.clear();\n provider.destroy();\n options.onClose?.();\n if (ownsWorker) {\n worker.terminate();\n }\n },\n };\n}\n","import {\n createOpfsClipPageProvider,\n type OpfsClipPageProviderBinding,\n type OpfsClipPageProviderOptions,\n} from './opfs_clip_pages';\nimport type { ClipPageProvider, ClipPageRequest, RealtimeEngine } from './realtime_engine';\n\n/**\n * Minimal engine surface the streamer drives. {@link RealtimeEngine} satisfies\n * this structurally; tests can supply a lightweight stand-in.\n */\nexport interface ClipPageStreamerEngine {\n /** Drain one pending audio-thread page-miss request, or `null` when empty. */\n popClipPageRequest(): ClipPageStreamerRequest | null;\n}\n\n/**\n * A page miss reported by either a direct engine (`sample`) or the worklet\n * bridge (`pageIndex`). Exactly one position form is required.\n */\nexport interface ClipPageStreamerRequest {\n clipId: number;\n sample?: number;\n pageIndex?: number;\n}\n\n/** A paged clip the streamer keeps fed from its backing store. */\nexport interface ClipPageStreamSource {\n /** Clip schedule id passed to `setClips` (matches {@link ClipPageRequest.clipId}). */\n clipId: number;\n /** OPFS-backed page provider binding for this clip. */\n binding: OpfsClipPageProviderBinding;\n /** Page size in frames (must equal the provider's `pageFrames`). */\n pageFrames: number;\n /** Total sample count of the clip source. */\n numSamples: number;\n}\n\nexport interface ClipPageStreamerOptions {\n /**\n * Pages to prefetch ahead of the page a miss was reported for. Larger values\n * hide fetch latency at the cost of more resident memory. Default 2.\n */\n readAheadPages?: number;\n /**\n * Pages to retain behind the playback frontier before eviction, so a small\n * backward seek does not immediately miss. Default 1.\n */\n retainBehindPages?: number;\n /**\n * Upper bound on requests drained per {@link ClipPageStreamer.pump} call, so a\n * burst of misses cannot spin unbounded. Default 256.\n */\n maxRequestsPerPump?: number;\n}\n\ninterface SourceState {\n source: ClipPageStreamSource;\n lastPage: number;\n /** Playback-window generation; advanced on reset or backward discontinuity. */\n generation: number;\n /** Most recently serviced playback frontier, or null before the first miss. */\n lastFrontier: number | null;\n /** Resident page -> generation, so in-flight stale fetches cannot alias. */\n resident: Map<number, number>;\n}\n\n/**\n * Keeps OPFS-paged clips fed within a bounded sliding window around the live\n * playback position, so a multitrack arrangement never holds its full PCM in\n * WASM memory.\n *\n * The audio thread reports a page miss whenever the {@link ClipPlayer} reads a\n * sample whose page is not resident. {@link pump} drains those requests, fetches\n * the missing page plus a read-ahead window from each clip's backing store, and\n * evicts pages that fall outside the window via the provider's `clear`. The\n * resident set per clip is therefore bounded to\n * `retainBehindPages + readAheadPages + 1` pages regardless of clip length.\n *\n * Call {@link pump} on a cadence that keeps up with playback — typically once\n * per animation frame or per worklet control tick on the main/control thread\n * (never the audio thread; fetches are asynchronous).\n */\nexport class ClipPageStreamer {\n private readonly engine: ClipPageStreamerEngine;\n private readonly readAheadPages: number;\n private readonly retainBehindPages: number;\n private readonly maxRequestsPerPump: number;\n private readonly sources = new Map<number, SourceState>();\n private closed = false;\n\n constructor(engine: ClipPageStreamerEngine, options: ClipPageStreamerOptions = {}) {\n this.engine = engine;\n this.readAheadPages = Math.max(0, Math.floor(options.readAheadPages ?? 2));\n this.retainBehindPages = Math.max(0, Math.floor(options.retainBehindPages ?? 1));\n this.maxRequestsPerPump = Math.max(1, Math.floor(options.maxRequestsPerPump ?? 256));\n }\n\n /**\n * Register a paged clip. Pages already supplied to the provider before\n * registration (for example a primed first page) should be passed in\n * `initialResidentPages` so they participate in eviction.\n */\n addSource(source: ClipPageStreamSource, initialResidentPages: Iterable<number> = []): void {\n if (source.pageFrames <= 0 || source.numSamples <= 0) {\n throw new Error('pageFrames and numSamples must be positive');\n }\n const lastPage = Math.ceil(source.numSamples / source.pageFrames) - 1;\n const previous = this.sources.get(source.clipId);\n if (previous) {\n this.resetState(previous);\n }\n this.sources.set(source.clipId, {\n source,\n lastPage,\n generation: 0,\n lastFrontier: null,\n resident: new Map(Array.from(initialResidentPages, (page) => [page, 0])),\n });\n }\n\n /** Stop tracking a clip. Does not close its binding (the caller owns that). */\n removeSource(clipId: number): void {\n const state = this.sources.get(clipId);\n if (state) {\n this.resetState(state);\n }\n this.sources.delete(clipId);\n }\n\n /**\n * Explicitly start a new playback generation after a host seek/loop. Resident\n * pages are evicted and any older in-flight fetch is cleared when it settles.\n * The next miss establishes the new bounded window.\n */\n resetSource(clipId: number): void {\n const state = this.sources.get(clipId);\n if (state) {\n this.resetState(state);\n }\n }\n\n /**\n * Drain pending page-miss requests, fetch the missing pages plus their\n * read-ahead window, and evict out-of-window pages. Resolves once this round's\n * fetches settle. Concurrent fetches are serialized inside each binding.\n */\n async pump(): Promise<void> {\n if (this.closed) {\n return;\n }\n // Collapse this round's misses to the latest observed frontier per clip.\n // Queue order reflects playback order, so a backward seek/loop request that\n // follows a stale high-page miss must win even though its page index is\n // smaller. Multiple channel misses still collapse to one service window.\n const frontiers = new Map<number, number>();\n for (let drained = 0; drained < this.maxRequestsPerPump; ++drained) {\n const request = this.engine.popClipPageRequest();\n if (!request) {\n break;\n }\n const state = this.sources.get(request.clipId);\n if (!state) {\n continue;\n }\n const page =\n request.pageIndex !== undefined\n ? request.pageIndex\n : Math.floor((request.sample ?? Number.NaN) / state.source.pageFrames);\n if (!Number.isInteger(page) || page < 0 || page > state.lastPage) {\n continue;\n }\n frontiers.set(request.clipId, page);\n }\n\n const fetches: Promise<unknown>[] = [];\n for (const [clipId, frontier] of frontiers) {\n const state = this.sources.get(clipId);\n if (!state) {\n continue;\n }\n fetches.push(...this.serviceFrontier(state, frontier));\n }\n await Promise.all(fetches);\n }\n\n /** Close every registered clip's binding and stop tracking. */\n close(): void {\n if (this.closed) {\n return;\n }\n this.closed = true;\n for (const state of this.sources.values()) {\n this.resetState(state);\n state.source.binding.close();\n }\n this.sources.clear();\n }\n\n private serviceFrontier(state: SourceState, frontier: number): Promise<unknown>[] {\n // A lower frontier after a previously serviced high page is a seek/loop\n // discontinuity. Advance generation before scheduling its new window so an\n // older asynchronous fetch can never become resident in the new window.\n if (state.lastFrontier !== null && frontier < state.lastFrontier) {\n this.resetState(state);\n }\n state.lastFrontier = frontier;\n const generation = state.generation;\n const low = Math.max(0, frontier - this.retainBehindPages);\n const high = Math.min(state.lastPage, frontier + this.readAheadPages);\n\n // Evict pages outside the window first so a burst of fetches never exceeds\n // the bound by transiently holding old pages alongside new ones.\n for (const page of state.resident.keys()) {\n if (page < low || page > high) {\n this.clearPage(state, page);\n state.resident.delete(page);\n }\n }\n\n const fetches: Promise<unknown>[] = [];\n for (let page = low; page <= high; ++page) {\n if (state.resident.get(page) === generation) {\n continue;\n }\n // Mark resident eagerly so the same page is not fetched twice across\n // overlapping windows; drop it again if the fetch reports a miss.\n state.resident.set(page, generation);\n const pageIndex = page;\n fetches.push(\n state.source.binding.supplyPage(pageIndex).then(\n (ok) => {\n if (state.generation !== generation) {\n // The fetch crossed a seek/reset boundary. supplyPage may have\n // installed it after resetState's clear pass, so clear it again.\n this.clearPage(state, pageIndex);\n } else if (!ok && state.resident.get(pageIndex) === generation) {\n state.resident.delete(pageIndex);\n }\n return ok;\n },\n (error) => {\n if (state.resident.get(pageIndex) === generation) {\n state.resident.delete(pageIndex);\n }\n throw error;\n },\n ),\n );\n }\n return fetches;\n }\n\n private resetState(state: SourceState): void {\n state.generation += 1;\n state.lastFrontier = null;\n for (const page of state.resident.keys()) {\n this.clearPage(state, page);\n }\n state.resident.clear();\n }\n\n private clearPage(state: SourceState, pageIndex: number): void {\n // `clearPage` mirrors eviction into the AudioWorklet. Keep the older\n // provider-only form working for direct-engine callers and test doubles.\n if (state.source.binding.clearPage) {\n state.source.binding.clearPage(pageIndex);\n } else {\n state.source.binding.provider.clear(pageIndex);\n }\n }\n}\n\nexport interface OpfsClipStreamOptions extends OpfsClipPageProviderOptions {\n /** Clip schedule id used in `setClips` (matches the page-miss request clipId). */\n clipId: number;\n /**\n * Leading pages fetched synchronously before returning, so playback can start\n * without an immediate miss. Default 1.\n */\n primePages?: number;\n}\n\nexport interface OpfsClipStream {\n binding: OpfsClipPageProviderBinding;\n /** Pass as `addClip`'s buffer argument to schedule the streaming clip. */\n provider: ClipPageProvider;\n}\n\n/** Structural seam implemented by the AudioWorklet-backed `SonareEngine`. */\nexport interface WorkletOpfsClipStreamHost {\n attachOpfsClipStream(options: OpfsClipStreamOptions): Promise<OpfsClipStream>;\n}\n\n/**\n * One-call wiring of an OPFS-backed streaming clip: creates the page provider,\n * primes the leading pages, and registers it with `streamer` so later misses are\n * serviced within the bounded window. Returns the binding (for `close`) and the\n * provider to schedule via `addClip(trackId, provider, startPpq, { id: clipId })`.\n *\n * @param streamer Shared streamer pumped on the control thread.\n * @param engine Engine the provider is created on (the same one `streamer` drives).\n * @param options Provider options plus `clipId` and optional `primePages`.\n */\nexport function attachOpfsClipStream(\n streamer: ClipPageStreamer,\n engine: RealtimeEngine,\n options: OpfsClipStreamOptions,\n): Promise<OpfsClipStream>;\n/**\n * Worklet overload: delegates to `SonareEngine.attachOpfsClipStream`, which\n * creates the remote provider and drives this same sliding-window policy from\n * worklet page-miss messages.\n */\nexport function attachOpfsClipStream(\n engine: WorkletOpfsClipStreamHost,\n options: OpfsClipStreamOptions,\n): Promise<OpfsClipStream>;\nexport async function attachOpfsClipStream(\n streamerOrEngine: ClipPageStreamer | WorkletOpfsClipStreamHost,\n engineOrOptions: RealtimeEngine | OpfsClipStreamOptions,\n maybeOptions?: OpfsClipStreamOptions,\n): Promise<OpfsClipStream> {\n if (!(streamerOrEngine instanceof ClipPageStreamer)) {\n return streamerOrEngine.attachOpfsClipStream(engineOrOptions as OpfsClipStreamOptions);\n }\n const streamer = streamerOrEngine;\n const engine = engineOrOptions as RealtimeEngine;\n const options = maybeOptions;\n if (!options) {\n throw new Error('attachOpfsClipStream requires options.');\n }\n const { clipId, primePages = 1, ...providerOptions } = options;\n const binding = createOpfsClipPageProvider(engine, providerOptions);\n const lastPage = Math.ceil(providerOptions.numSamples / providerOptions.pageFrames) - 1;\n const primed: number[] = [];\n for (let page = 0; page < primePages && page <= lastPage; ++page) {\n if (await binding.supplyPage(page)) {\n primed.push(page);\n }\n }\n streamer.addSource(\n {\n clipId,\n binding,\n pageFrames: providerOptions.pageFrames,\n numSamples: providerOptions.numSamples,\n },\n primed,\n );\n return { binding, provider: binding.provider };\n}\n","/**\n * Numeric error codes carried by a {@link SonareError}. Mirrors the C ABI\n * `SonareError` enum (and the Node / Python surfaces), so the same failure\n * reports the same numeric code on every binding.\n */\nexport enum ErrorCode {\n Ok = 0,\n FileNotFound = 1,\n InvalidFormat = 2,\n DecodeFailed = 3,\n InvalidParameter = 4,\n OutOfMemory = 5,\n NotSupported = 6,\n InvalidState = 7,\n Cancelled = 8,\n Unknown = 99,\n}\n\n/**\n * Error thrown by libsonare on a native (C++) failure. Carries a numeric\n * {@link ErrorCode} `code` plus its canonical `codeName`, so callers can branch\n * on the cause instead of matching message text.\n */\nexport class SonareError extends Error {\n /** Numeric error code, equal to an {@link ErrorCode} value. */\n readonly code: number;\n /** Canonical name of `code`, e.g. `'InvalidParameter'`. */\n readonly codeName: string;\n\n constructor(code: number, codeName: string, message: string) {\n super(message);\n this.name = 'SonareError';\n this.code = code;\n this.codeName = codeName;\n }\n}\n\n/** Type guard: whether a caught value is a libsonare {@link SonareError}. */\nexport function isSonareError(value: unknown): value is SonareError {\n return (\n value instanceof Error &&\n (value as { name?: unknown }).name === 'SonareError' &&\n typeof (value as { code?: unknown }).code === 'number'\n );\n}\n","import { ErrorCode, SonareError } from './errors';\nimport type { SonareModule } from './sonare.js';\n\nlet wrappedModule: SonareModule | null = null;\n\n/**\n * Shape of the structured info the native `sonareExceptionInfo(ptr)` returns.\n */\ninterface NativeExceptionInfo {\n code: number;\n codeName: string;\n message: string;\n}\n\n/**\n * Recover the native exception-object pointer from a value thrown across the\n * WASM boundary. emscripten surfaces a C++ throw in two shapes depending on the\n * toolchain/exception mode:\n * - a raw pointer number (older / classic surfacing), or\n * - a `CppException` object exposing the pointer as `excPtr` (emscripten with\n * `-fexceptions`).\n * Returns null when the thrown value is neither (a genuine JS error), so the\n * caller rethrows it unchanged.\n */\nfunction nativeExceptionPtr(error: unknown): number | null {\n if (typeof error === 'number') {\n return error;\n }\n if (error !== null && typeof error === 'object') {\n const ptr = (error as { excPtr?: unknown }).excPtr;\n if (typeof ptr === 'number') {\n return ptr;\n }\n }\n return null;\n}\n\n/**\n * Turn a thrown native exception pointer into a {@link SonareError}. The bound\n * `sonareExceptionInfo` decodes the pointer back into { code, codeName,\n * message }.\n */\nfunction makeSonareError(raw: SonareModule, thrown: number): SonareError {\n let code: number = ErrorCode.Unknown;\n let codeName = 'Unknown';\n let message = `libsonare native exception (${thrown})`;\n try {\n const info = (\n raw as unknown as { sonareExceptionInfo?: (ptr: number) => NativeExceptionInfo }\n ).sonareExceptionInfo?.(thrown);\n if (info) {\n code = info.code ?? code;\n codeName = info.codeName ?? codeName;\n message = info.message || message;\n }\n } catch {\n // Fall back to the generic message if decoding fails.\n }\n return new SonareError(code, codeName, message);\n}\n\n/**\n * Wrap the embind module so a native C++ exception (which surfaces as a raw\n * pointer number or a `CppException` carrying one) is rethrown as a\n * {@link SonareError}. Only function-valued\n * members are wrapped, and the wrapper is cached per member so repeated access\n * stays cheap; non-function members (typed-array heap views, etc.) pass through\n * unchanged.\n */\nfunction wrapModuleErrors(raw: SonareModule): SonareModule {\n const cache = new Map<PropertyKey, unknown>();\n const objectCache = new WeakMap<object, unknown>();\n const convert = (error: unknown): never => {\n const ptr = nativeExceptionPtr(error);\n if (ptr !== null) {\n throw makeSonareError(raw, ptr);\n }\n throw error;\n };\n\n const wrapNativeObject = (value: unknown): unknown => {\n if (value === null || typeof value !== 'object') {\n return value;\n }\n if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer || value instanceof Promise) {\n return value;\n }\n const objectValue = value as object;\n const cached = objectCache.get(objectValue);\n if (cached) {\n return cached;\n }\n const methodCache = new Map<PropertyKey, unknown>();\n const wrapped = new Proxy(objectValue, {\n get(target, prop, receiver) {\n const member = Reflect.get(target, prop, receiver);\n if (typeof member !== 'function') {\n return member;\n }\n const cachedMethod = methodCache.get(prop);\n if (cachedMethod) {\n return cachedMethod;\n }\n const method = member as (...a: unknown[]) => unknown;\n const wrappedMethod = (...args: unknown[]) => {\n try {\n return wrapNativeObject(Reflect.apply(method, target, args));\n } catch (error) {\n return convert(error);\n }\n };\n methodCache.set(prop, wrappedMethod);\n return wrappedMethod;\n },\n });\n objectCache.set(objectValue, wrapped);\n return wrapped;\n };\n\n const wrapFunction = (value: (...a: unknown[]) => unknown): unknown => {\n const fnCache = new Map<PropertyKey, unknown>();\n return new Proxy(value, {\n get(target, prop, receiver) {\n const member = Reflect.get(target, prop, receiver);\n if (typeof member !== 'function') {\n return member;\n }\n const cachedMember = fnCache.get(prop);\n if (cachedMember) {\n return cachedMember;\n }\n const fn = member as (...a: unknown[]) => unknown;\n const wrappedMember = (...args: unknown[]) => {\n try {\n return wrapNativeObject(Reflect.apply(fn, target, args));\n } catch (error) {\n return convert(error);\n }\n };\n fnCache.set(prop, wrappedMember);\n return wrappedMember;\n },\n apply(t, thisArg, args) {\n try {\n return wrapNativeObject(Reflect.apply(t, thisArg, args as unknown[]));\n } catch (error) {\n return convert(error);\n }\n },\n construct(t, args, newTarget) {\n try {\n return wrapNativeObject(Reflect.construct(t, args as unknown[], newTarget)) as object;\n } catch (error) {\n return convert(error) as object;\n }\n },\n });\n };\n\n return new Proxy(raw, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (typeof value !== 'function') {\n return value;\n }\n const cached = cache.get(prop);\n if (cached) {\n return cached;\n }\n // Wrap as a Proxy (not a plain function) so embind class constructors\n // invoked via `new module.Foo(...)` keep their `[[Construct]]` behaviour\n // and prototype while still converting thrown native pointers.\n const wrapped = wrapFunction(value as (...a: unknown[]) => unknown);\n cache.set(prop, wrapped);\n return wrapped;\n },\n }) as SonareModule;\n}\n\nexport function setSonareModule(module: SonareModule): void {\n wrappedModule = wrapModuleErrors(module);\n}\n\nexport function getSonareModule(): SonareModule {\n if (!wrappedModule) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return wrappedModule;\n}\n","import type { MasteringChainConfig } from './public_types';\n\ntype ChainSection = { [key: string]: number | boolean | ChainSection | undefined };\n\n/**\n * Flattens a nested {@link MasteringChainConfig} into the dot-notation\n * `{ \"module.processor.param\": value }` map the core consumes. Internal helper\n * shared by the mastering-chain / master-audio entry points. The core owns\n * legacy leaf-name aliases, so this remains a structural flattening step.\n *\n * A key the caller already wrote in dot notation carries through untouched, so\n * both spellings a {@link MasteringChainConfig} accepts reach the core as the\n * same parameter — matching what the Python binding documents. An unknown key\n * in either spelling is rejected by the core, not here.\n */\nexport function flattenChainConfig(config: MasteringChainConfig): Record<string, number | boolean> {\n const out: Record<string, number | boolean> = {};\n const walk = (node: ChainSection, prefix: string): void => {\n for (const [key, value] of Object.entries(node)) {\n const path = prefix ? `${prefix}.${key}` : key;\n if (typeof value === 'number' || typeof value === 'boolean') {\n out[path] = value;\n } else if (value !== null && typeof value === 'object') {\n walk(value, path);\n } else if (value !== undefined) {\n throw new TypeError(`Mastering override '${path}' must be a number or boolean.`);\n }\n }\n };\n walk(config as ChainSection, '');\n\n return out;\n}\n","import type { AutomationCurve, MeterTap, PanLawInput, PanMode, SendTiming } from './public_types';\n\n/** Resolve a numeric ordinal in an inclusive range without coercion. */\nexport function resolveOrdinalInRange(\n value: unknown,\n min: number,\n max: number,\n enumName: string,\n): number {\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < min || value > max) {\n throw new RangeError(`Invalid ${enumName}: ${String(value)}`);\n }\n return value;\n}\n\n/** Resolve a public enum spelling or ordinal without permitting unknown values. */\nexport function resolveEnumOrdinal(\n value: unknown,\n values: Readonly<Record<string, number>>,\n enumName: string,\n): number {\n if (typeof value === 'number') {\n const ordinals = Object.values(values);\n const ordinal = resolveOrdinalInRange(\n value,\n Math.min(...ordinals),\n Math.max(...ordinals),\n enumName,\n );\n if (!ordinals.includes(ordinal)) {\n throw new RangeError(`Invalid ${enumName}: ${String(value)}`);\n }\n return ordinal;\n }\n if (typeof value === 'string') {\n const ordinal = values[value];\n if (ordinal !== undefined) {\n return ordinal;\n }\n }\n throw new RangeError(`Invalid ${enumName}: ${String(value)}`);\n}\n\nconst AUTOMATION_CURVE_VALUES = {\n linear: 0,\n exponential: 1,\n hold: 2,\n 's-curve': 3,\n} as const;\nconst PAN_LAW_VALUES: Readonly<Record<string, number>> = {\n const3db: 0,\n 'const-3db': 0,\n '-3db': 0,\n 'const4.5db': 1,\n 'const-4.5db': 1,\n '-4.5db': 1,\n const6db: 2,\n 'const-6db': 2,\n '-6db': 2,\n linear0db: 3,\n 'linear-0db': 3,\n linear: 3,\n '0db': 3,\n} as const;\nconst PAN_MODE_VALUES = {\n balance: 0,\n pan: 1,\n stereopan: 1,\n 'stereo-pan': 1,\n dualpan: 2,\n 'dual-pan': 2,\n} as const;\nconst METER_TAP_VALUES = { preFader: 0, postFader: 1 } as const;\nconst SEND_TIMING_VALUES = { postFader: 0, preFader: 1 } as const;\nconst TRACK_MONITOR_MODE_VALUES = { off: 0, pfl: 1, afl: 2 } as const;\n\nexport function automationCurveCode(curve: AutomationCurve): number {\n return resolveEnumOrdinal(curve, AUTOMATION_CURVE_VALUES, 'automation curve');\n}\n\nexport function panLawCode(panLaw: PanLawInput): number {\n const normalized = typeof panLaw === 'string' ? panLaw.toLowerCase().replace(/_/g, '-') : panLaw;\n return resolveEnumOrdinal(normalized, PAN_LAW_VALUES, 'pan law');\n}\n\nexport function panModeCode(panMode: PanMode | number): number {\n const normalized =\n typeof panMode === 'string' ? panMode.replace(/_/g, '-').toLowerCase() : panMode;\n return resolveEnumOrdinal(normalized, PAN_MODE_VALUES, 'pan mode');\n}\n\nexport function meterTapCode(tap: MeterTap | number): number {\n return resolveEnumOrdinal(tap, METER_TAP_VALUES, 'meter tap');\n}\n\nexport function sendTimingCode(timing: SendTiming | number): number {\n // Mirrors SonareSendTiming: post-fader is 0 (so an omitted/zeroed value is\n // post-fader), pre-fader is 1. A raw number is passed through as the C ABI int.\n // An unknown string is rejected rather than silently routed to post-fader,\n // matching the sibling enum-code helpers and Node's sendTimingValue.\n return resolveEnumOrdinal(timing, SEND_TIMING_VALUES, 'send timing');\n}\n\n/** Resolve a per-track PFL/AFL monitor mode to its C-ABI ordinal. */\nexport function trackMonitorModeCode(mode: unknown): number {\n return resolveEnumOrdinal(mode, TRACK_MONITOR_MODE_VALUES, 'track monitor mode');\n}\n","import { panLawCode, panModeCode, sendTimingCode, trackMonitorModeCode } from './codes';\nimport { ErrorCode, SonareError } from './errors';\nimport { getSonareModule } from './module_state';\nimport type { ProjectMidiCcBinding, SynthPatch } from './project';\nimport type { EqBand, PanLawInput, PanMode, SendTiming } from './public_types';\nimport type {\n WasmClipPageRequest,\n WasmEngineAutomationPoint,\n WasmEngineBounceOptions,\n WasmEngineBounceResult,\n WasmEngineCaptureStatus,\n WasmEngineClip,\n WasmEngineFreezeOptions,\n WasmEngineFreezeResult,\n WasmEngineGraphSpec,\n WasmEngineMarker,\n WasmEngineMeterTelemetry,\n WasmEngineMeterTelemetryWide,\n WasmEngineMetronomeConfig,\n WasmEngineParameterInfo,\n WasmEngineProcessWithMonitorResult,\n WasmEngineScopeTelemetry,\n WasmEngineTelemetry,\n WasmEngineTempoSegment,\n WasmEngineTimeSignatureSegment,\n WasmEngineTransportState,\n WasmExternalMidiEvent,\n WasmRealtimeEngine,\n} from './sonare.js';\n\nexport type ExternalMidiEvent = WasmExternalMidiEvent;\n\nexport type EngineClip = WasmEngineClip;\nexport type ClipPageRequest = WasmClipPageRequest;\nexport type EngineParameterInfo = WasmEngineParameterInfo;\nexport type EngineAutomationPoint = WasmEngineAutomationPoint;\nexport type EngineMarker = WasmEngineMarker;\nexport type EngineMetronomeConfig = WasmEngineMetronomeConfig;\nexport type EngineGraphSpec = WasmEngineGraphSpec;\nexport type EngineCaptureStatus = WasmEngineCaptureStatus;\nexport type EngineCaptureSource = EngineCaptureStatus['source'] | number;\nexport type EngineBounceOptions = WasmEngineBounceOptions;\nexport type EngineBounceResult = WasmEngineBounceResult;\nexport type EngineFreezeOptions = WasmEngineFreezeOptions;\nexport type EngineFreezeResult = WasmEngineFreezeResult;\nexport type EngineTelemetry = WasmEngineTelemetry;\nexport type EngineMeterTelemetry = WasmEngineMeterTelemetry;\nexport type EngineMeterTelemetryWide = WasmEngineMeterTelemetryWide;\nexport type EngineScopeTelemetry = WasmEngineScopeTelemetry;\nexport type EngineTransportState = WasmEngineTransportState;\nexport type EngineTempoSegment = WasmEngineTempoSegment;\nexport type EngineTimeSignatureSegment = WasmEngineTimeSignatureSegment;\n\nexport interface EngineTrackSend {\n busId: number;\n levelDb?: number;\n enabled?: boolean;\n /**\n * Pre/post-fader tap point. Defaults to post-fader when omitted, matching the\n * historical lane-send behavior and the scene-JSON default.\n */\n sendTiming?: SendTiming | number;\n}\n\nexport interface EngineTrackLane {\n trackId: number;\n sends?: EngineTrackSend[];\n /**\n * Bus the lane's post-fader output sums into instead of the master mix\n * (group/folder routing); 0 or absent keeps the lane on the master mix.\n */\n outputBusId?: number;\n /**\n * Input channel layout of the source feeding this lane (`SonareChannelLayout`:\n * 0 mono, 1 stereo, 2 5.1, 3 7.1). Absent defaults to stereo. Stored but inert\n * until the surround DSP path lands.\n */\n sourceChannelLayout?: number;\n}\n\n/** Per-track cue/monitor tap mode: off, pre-fader listen, or after-fader listen. */\nexport type EngineTrackMonitorMode = 'off' | 'pfl' | 'afl' | 0 | 1 | 2;\n\n/** Short alias for {@link EngineTrackMonitorMode}. */\nexport type TrackMonitorMode = EngineTrackMonitorMode;\n\nexport interface EngineBus {\n busId: number;\n gainDb?: number;\n /**\n * Channel layout of the bus (`SonareChannelLayout`: 0 mono, 1 stereo, 2 5.1,\n * 3 7.1). A surround layout makes this a surround group bus: lanes routed to\n * it are surround-panned and it sums into the master plane-by-plane. Defaults\n * to stereo.\n */\n channelLayout?: number;\n}\n\nexport interface EngineMidiEvent {\n renderFrame: number;\n word0?: number;\n word1?: number;\n word2?: number;\n word3?: number;\n wordCount?: number;\n group?: number;\n sysexHandle?: number;\n data0?: number;\n data1?: number;\n}\n\nexport interface EngineMidiClipSchedule {\n id?: number;\n trackId?: number;\n destinationId?: number;\n startSample?: number;\n startPpq?: number;\n lengthSamples?: number;\n loop?: boolean;\n loopLengthSamples?: number;\n events: EngineMidiEvent[];\n}\n\nexport const EXPECTED_ENGINE_ABI_VERSION = 3;\n\n/** Options for {@link RealtimeEngine.bindMidiCc}. All fields are optional. */\nexport interface MidiCcBindOptions {\n /** Lower end of the mapped parameter range. Default `0`. */\n minValue?: number;\n /** Upper end of the mapped parameter range. Default `1`. */\n maxValue?: number;\n}\n\nexport interface EngineCapabilities {\n engineAbiVersion: number;\n expectedEngineAbiVersion: number;\n abiCompatible: boolean;\n sharedArrayBuffer: boolean;\n atomics: boolean;\n audioWorklet: boolean;\n mode: 'sab' | 'postMessage';\n}\n\nexport function engineCapabilities(): EngineCapabilities {\n const abiVersion = getSonareModule().engineAbiVersion();\n const sharedArrayBuffer = typeof globalThis.SharedArrayBuffer === 'function';\n const atomics = typeof globalThis.Atomics === 'object';\n const audioWorklet =\n typeof AudioWorkletNode !== 'undefined' ||\n typeof (globalThis as typeof globalThis & { AudioWorkletProcessor?: unknown })\n .AudioWorkletProcessor !== 'undefined';\n return {\n engineAbiVersion: abiVersion,\n expectedEngineAbiVersion: EXPECTED_ENGINE_ABI_VERSION,\n abiCompatible: abiVersion === EXPECTED_ENGINE_ABI_VERSION,\n sharedArrayBuffer,\n atomics,\n audioWorklet,\n mode: sharedArrayBuffer && atomics ? 'sab' : 'postMessage',\n };\n}\n\nexport class RealtimeEngine {\n private native: WasmRealtimeEngine;\n\n constructor(\n sampleRate = 48000,\n maxBlockSize = 128,\n commandCapacity = 1024,\n telemetryCapacity = 1024,\n maxChannels = 64,\n ) {\n const module = getSonareModule();\n const capabilities = engineCapabilities();\n if (!capabilities.abiCompatible) {\n throw new Error(\n `Engine ABI mismatch: wasm=${capabilities.engineAbiVersion}, expected=${capabilities.expectedEngineAbiVersion}`,\n );\n }\n this.native = new module.RealtimeEngine(\n sampleRate,\n maxBlockSize,\n commandCapacity,\n telemetryCapacity,\n maxChannels,\n );\n }\n\n prepare(\n sampleRate: number,\n maxBlockSize: number,\n commandCapacity = 1024,\n telemetryCapacity = 1024,\n maxChannels = 64,\n ): void {\n this.native.prepareWithChannels(\n sampleRate,\n maxBlockSize,\n commandCapacity,\n telemetryCapacity,\n maxChannels,\n );\n }\n\n /** Queue a sample-accurate parameter change (engine kSetParam). */\n setParameter(paramId: number, value: number, renderFrame = -1): void {\n this.native.setParameter(paramId, value, renderFrame);\n }\n\n /** Queue a smoothed parameter change (engine kSetParamSmoothed). */\n setParameterSmoothed(paramId: number, value: number, renderFrame = -1): void {\n this.native.setParameterSmoothed(paramId, value, renderFrame);\n }\n\n /**\n * Set the default ramp time (ms) for engine-level smoothed parameters —\n * fader/pan glides, insert-parameter automation, and MIDI-CC mappings. The\n * default is 20 ms; pass `0` for instant (un-ramped) changes.\n */\n setParamSmoothingMs(smoothingMs: number): void {\n this.native.setParamSmoothingMs(smoothingMs);\n }\n\n setSoloMute(laneIndex: number, solo: boolean, mute: boolean, renderFrame = -1): void {\n this.native.setSoloMute(laneIndex, solo, mute, renderFrame);\n }\n\n /** Queue a per-track PFL/AFL monitor tap mode change. */\n setTrackMonitorMode(laneIndex: number, mode: EngineTrackMonitorMode, renderFrame = -1): void {\n this.native.setTrackMonitorMode(laneIndex, trackMonitorModeCode(mode), renderFrame);\n }\n\n setMidiClips(clips: readonly EngineMidiClipSchedule[]): void {\n this.native.setMidiClips(clips);\n }\n\n setBuiltinInstrument(\n config: { destinationId?: number } & Record<string, unknown> = {},\n destinationId = config.destinationId ?? 0,\n ): void {\n this.native.setBuiltinInstrument(destinationId, config);\n }\n\n /**\n * Bind the patch-driven NativeSynth to a realtime MIDI destination. `patch`\n * is a {@link SynthPatch} or a preset-name string (`'saw-lead'` /\n * `'va:saw-lead'`; see {@link synthPresetNames}), resolving exactly like\n * {@link Project.bounceWithSynthInstrument}. Live note/CC commands and\n * scheduled MIDI clips routed to that destination render through the synth.\n * Unknown preset names throw. An object patch's `destinationId` is a JS\n * binding convenience, not part of the NativeSynth patch itself.\n */\n setSynthInstrument(\n patch: SynthPatch | string = {},\n destinationId = (typeof patch === 'object' ? patch.destinationId : undefined) ?? 0,\n ): void {\n this.native.setSynthInstrument(destinationId, patch);\n }\n\n /**\n * Load (parse) SoundFont 2 bytes into the engine so SF2 instruments can be\n * bound with {@link setSf2Instrument}. The host fetches the `.sf2` and\n * passes the raw bytes; they are copied into linear memory for the call and\n * not referenced afterwards. Replaces any previously loaded SoundFont.\n */\n loadSoundFont(data: Uint8Array): void {\n this.native.loadSoundFont(data);\n }\n\n /**\n * Bind a GS-compatible SoundFont player to a realtime MIDI destination, fed\n * by the engine's loaded SoundFont ({@link loadSoundFont}). Live note/CC\n * commands and scheduled MIDI clips routed to that destination render\n * through the player (16 MIDI channels, channel 10 drums, GS NRPN part\n * edits, GS/GM SysEx resets). Without a loaded SoundFont — or for programs\n * the SoundFont does not cover — notes play through the built-in\n * synthesizer GM fallback bank (the data-free floor).\n */\n setSf2Instrument(\n config: {\n destinationId?: number;\n gain?: number;\n polyphony?: number;\n preferModelForModeledFamilies?: boolean;\n } = {},\n destinationId = config.destinationId ?? 0,\n ): void {\n this.native.setSf2Instrument(destinationId, config);\n }\n\n clearMidiInstrument(destinationId = 0): void {\n this.native.clearMidiInstrument(destinationId);\n }\n\n midiInstrumentCount(): number {\n return this.native.midiInstrumentCount();\n }\n\n /**\n * Bind a live MIDI CC to an engine automation parameter. The MIDI event still\n * reaches the destination instrument; when bound, its 7-bit value is also\n * mapped into [minValue, maxValue] for `paramId`.\n */\n bindMidiCc(\n channel: number,\n controller: number,\n paramId: number,\n options: MidiCcBindOptions = {},\n ): void {\n this.native.bindMidiCc(\n channel,\n controller,\n paramId,\n options.minValue ?? 0,\n options.maxValue ?? 1,\n );\n }\n\n /** Bind a 7/14-bit CC, RPN, or NRPN descriptor to a live parameter. */\n bindMidiCcBinding(binding: ProjectMidiCcBinding): void {\n this.native.bindMidiCcBinding(binding);\n }\n\n clearMidiCcBindings(): void {\n this.native.clearMidiCcBindings();\n }\n\n midiCcBindingCount(): number {\n return this.native.midiCcBindingCount();\n }\n\n /** Install/replace a live non-destructive MIDI-FX insert for one destination. */\n setMidiFx(destinationId: number, configJson: string): void {\n this.native.setMidiFx(destinationId, configJson);\n }\n\n clearMidiFx(destinationId = 0): void {\n this.native.clearMidiFx(destinationId);\n }\n\n /** Enable the engine-owned live MIDI input source for a destination. */\n setMidiInputSource(destinationId = 0): void {\n this.native.setMidiInputSource(destinationId);\n }\n\n clearMidiInputSource(): void {\n this.native.clearMidiInputSource();\n }\n\n midiInputPendingCount(): number {\n return this.native.midiInputPendingCount();\n }\n\n /**\n * Route a destination's (track lane's) MIDI to the external output queue\n * instead of the internal instrument rack, so the track plays an external\n * device. Clearing it restores internal-synth playback.\n */\n setMidiDestinationExternal(destinationId: number, external: boolean): void {\n this.native.setMidiDestinationExternal(destinationId, external);\n }\n\n /**\n * Enable/disable forwarding MIDI clock + transport (start/continue/stop) to\n * the external output queue so external gear tracks the transport tempo.\n */\n setExternalMidiClockEnabled(enabled: boolean): void {\n this.native.setExternalMidiClockEnabled(enabled);\n }\n\n /** Count of external-MIDI events dropped because the output queue was full. */\n externalMidiDroppedCount(): number {\n return this.native.externalMidiDroppedCount();\n }\n\n externalMidiPendingCount(): number {\n return this.native.externalMidiPendingCount();\n }\n\n /**\n * Drain queued external-MIDI events, already lowered to MIDI 1.0 byte\n * messages ready to write to a Web MIDI output port. Call once per audio\n * block / animation frame. `maxRecords` caps the number of output events\n * returned — the shared unit across every surface. Events past the cap stay\n * queued for the next call (lossless); call again to drain the rest.\n */\n drainExternalMidi(maxRecords = 1024): WasmExternalMidiEvent[] {\n return this.native.drainExternalMidi(maxRecords);\n }\n\n /** Scalar, allocation-free external-MIDI drain for AudioWorklet SAB output. */\n popExternalMidiToScratch(): boolean {\n return this.native.popExternalMidiToScratch();\n }\n\n externalMidiScratchDestinationId(): number {\n return this.native.externalMidiScratchDestinationId();\n }\n\n externalMidiScratchRenderFrame(): number {\n return this.native.externalMidiScratchRenderFrame();\n }\n\n externalMidiScratchByteWord(): number {\n return this.native.externalMidiScratchByteWord();\n }\n\n externalMidiScratchByteCount(): number {\n return this.native.externalMidiScratchByteCount();\n }\n\n consumeExternalMidiScratch(): void {\n this.native.consumeExternalMidiScratch();\n }\n\n pushMidiInputNoteOn(\n group: number,\n channel: number,\n note: number,\n velocity: number,\n portTimeSamples = 0,\n ): void {\n this.native.pushMidiInputNoteOn(group, channel, note, velocity, portTimeSamples);\n }\n\n pushMidiInputNoteOff(\n group: number,\n channel: number,\n note: number,\n velocity = 0,\n portTimeSamples = 0,\n ): void {\n this.native.pushMidiInputNoteOff(group, channel, note, velocity, portTimeSamples);\n }\n\n pushMidiInputCc(\n group: number,\n channel: number,\n controller: number,\n value: number,\n portTimeSamples = 0,\n ): void {\n this.native.pushMidiInputCc(group, channel, controller, value, portTimeSamples);\n }\n\n pushMidiNoteOn(\n destinationId: number,\n group: number,\n channel: number,\n note: number,\n velocity: number,\n renderFrame = -1,\n ): void {\n this.native.pushMidiNoteOn(destinationId, group, channel, note, velocity, renderFrame);\n }\n\n pushMidiNoteOff(\n destinationId: number,\n group: number,\n channel: number,\n note: number,\n velocity = 0,\n renderFrame = -1,\n ): void {\n this.native.pushMidiNoteOff(destinationId, group, channel, note, velocity, renderFrame);\n }\n\n /**\n * Queue an immediate (live) MIDI control change to a MIDI destination\n * (engine kMidiCcImmediate). `group`/`channel` are 0..15; `controller`/`value`\n * are 7-bit (0..127). `renderFrame` is the frame to fire at, or -1 for\n * immediate. Mirrors the Node/Python/C-ABI `pushMidiCc`.\n */\n pushMidiCc(\n destinationId: number,\n group: number,\n channel: number,\n controller: number,\n value: number,\n renderFrame = -1,\n ): void {\n this.native.pushMidiCc(destinationId, group, channel, controller, value, renderFrame);\n }\n\n /** Queue one immediate MIDI 1.0 channel-voice UMP word for a destination. */\n pushMidiUmp(destinationId: number, word0: number, renderFrame = -1): void {\n this.native.pushMidiUmp(destinationId, word0, renderFrame);\n }\n\n /**\n * Queue an immediate (live) MIDI SysEx frame to a MIDI destination. `data` is\n * the full message including the leading 0xF0 and trailing 0xF7 (1..512\n * bytes). `renderFrame` is the frame to fire at, or -1 for immediate. Mirrors\n * the Node/Python/C-ABI `pushMidiSysex`.\n */\n pushMidiSysex(destinationId: number, data: Uint8Array, renderFrame = -1): void {\n this.native.pushMidiSysex(destinationId, data, renderFrame);\n }\n\n /**\n * Queue a MIDI panic (all-notes-off) releasing every sounding note at\n * `renderFrame` (-1 = immediate). Mirrors the C-ABI `pushMidiPanic`.\n */\n pushMidiPanic(renderFrame = -1): void {\n this.native.pushMidiPanic(renderFrame);\n }\n\n /**\n * Remove all registered parameters (and their automation lanes). Control-thread\n * only; not realtime-safe. Mirrors the C-ABI `clearParameters`.\n */\n clearParameters(): void {\n this.native.clearParameters();\n }\n\n /** Read back the current transport state snapshot. */\n getTransportState(): EngineTransportState {\n return this.native.getTransportState();\n }\n\n play(renderFrame = -1): void {\n this.native.play(renderFrame);\n }\n\n stop(renderFrame = -1): void {\n this.native.stop(renderFrame);\n }\n\n seekSample(timelineSample: number, renderFrame = -1): void {\n this.native.seekSample(timelineSample, renderFrame);\n }\n\n /**\n * Snaps every in-flight parameter ramp (engine-level smoothed params, mixer\n * lane fader/pan/gate, bus gains) to its target value. Offline renders call\n * this after a priming process() block so the first audible block renders at\n * settled values instead of ramping in from defaults.\n */\n settleParameters(): void {\n this.native.settleParameters();\n }\n\n /** Drains queued commands on an offline/control-only engine immediately. */\n flushControlCommands(): void {\n this.native.flushControlCommands();\n }\n\n seekPpq(ppq: number, renderFrame = -1): void {\n this.native.seekPpq(ppq, renderFrame);\n }\n\n /** Set a finite tempo in the range (0, 100000] BPM. */\n setTempo(bpm: number): void {\n this.native.setTempo(bpm);\n }\n\n setTempoSegments(segments: readonly EngineTempoSegment[]): void {\n this.native.setTempoSegments([...segments]);\n }\n\n setTimeSignature(numerator: number, denominator: number): void {\n this.native.setTimeSignature(numerator, denominator);\n }\n\n setTimeSignatureSegments(segments: readonly EngineTimeSignatureSegment[]): void {\n this.native.setTimeSignatureSegments([...segments]);\n }\n\n sampleAtPpq(ppq: number): number {\n return Number(this.native.sampleAtPpq(ppq));\n }\n\n setLoop(startPpq: number, endPpq: number, enabled = true): void {\n this.native.setLoop(startPpq, endPpq, enabled);\n }\n\n addParameter(info: EngineParameterInfo): void {\n this.native.addParameter(info);\n }\n\n parameterCount(): number {\n return this.native.parameterCount();\n }\n\n parameterInfoByIndex(index: number): EngineParameterInfo {\n return this.native.parameterInfoByIndex(index);\n }\n\n parameterInfo(id: number): EngineParameterInfo {\n return this.native.parameterInfo(id);\n }\n\n setAutomationLane(paramId: number, points: EngineAutomationPoint[]): void {\n this.native.setAutomationLane(paramId, points);\n }\n\n automationLaneCount(): number {\n return this.native.automationLaneCount();\n }\n\n setMarkers(markers: EngineMarker[]): void {\n this.native.setMarkers(markers);\n }\n\n markerCount(): number {\n return this.native.markerCount();\n }\n\n markerByIndex(index: number): EngineMarker {\n return this.native.markerByIndex(index);\n }\n\n marker(id: number): EngineMarker {\n return this.native.marker(id);\n }\n\n seekMarker(markerId: number, renderFrame = -1): void {\n this.native.seekMarker(markerId, renderFrame);\n }\n\n setLoopFromMarkers(startMarkerId: number, endMarkerId: number): void {\n this.native.setLoopFromMarkers(startMarkerId, endMarkerId);\n }\n\n /** Set a metronome config; click lengths are limited to one second. */\n setMetronome(config: EngineMetronomeConfig): void {\n this.native.setMetronome(config);\n }\n\n metronome(): Required<EngineMetronomeConfig> {\n return this.native.metronome();\n }\n\n countInEndSample(startSample: number, bars: number): number {\n return Number(this.native.countInEndSample(startSample, bars));\n }\n\n setGraph(spec: EngineGraphSpec): void {\n this.native.setGraph(spec);\n }\n\n graphNodeCount(): number {\n return this.native.graphNodeCount();\n }\n\n graphConnectionCount(): number {\n return this.native.graphConnectionCount();\n }\n\n setClips(clips: EngineClip[]): void {\n this.native.setClips(\n clips.map((clip) => ({\n ...clip,\n pageProvider:\n typeof clip.pageProvider === 'object' && clip.pageProvider !== null\n ? clip.pageProvider.id\n : clip.pageProvider,\n })),\n );\n }\n\n /**\n * Returns the PCM generated for a tempo-sync clip by the control-thread\n * setter, or `null` when the clip did not require a tempo-sync bake.\n */\n prebakedClipChannels(clipId: number): Float32Array[] | null {\n return this.native.prebakedClipChannels(clipId);\n }\n\n clipCount(): number {\n return this.native.clipCount();\n }\n\n setTrackLanes(lanes: Array<number | EngineTrackLane>): void {\n this.native.setTrackLanes(\n lanes.map((lane) => {\n if (typeof lane === 'number') {\n return { trackId: lane };\n }\n if (!lane.sends) {\n return lane;\n }\n // Normalize each send's pre/post tap point to the integer the native\n // layer reads (defaults to post-fader when omitted).\n return {\n ...lane,\n sends: lane.sends.map((send) => ({\n ...send,\n // Post-fader (0) is the default for an omitted sendTiming.\n sendTiming: send.sendTiming === undefined ? 0 : sendTimingCode(send.sendTiming),\n })),\n };\n }),\n );\n }\n\n /**\n * Keys one insert of a lane strip from another lane's post-strip audio\n * (ducking/sidechainRouter inserts). sourceTrackId 0 removes the binding.\n */\n setLaneSidechain(trackId: number, insertIndex: number, sourceTrackId: number): void {\n this.native.setLaneSidechain(trackId, insertIndex, sourceTrackId);\n }\n\n setTrackBuses(buses: EngineBus[]): void {\n this.native.setTrackBuses(buses);\n }\n\n setBusStripJson(busId: number, sceneJson: string): void {\n try {\n JSON.parse(sceneJson);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'invalid bus strip JSON';\n throw new SonareError(ErrorCode.InvalidFormat, 'InvalidFormat', message);\n }\n this.native.setBusStripJson(busId, sceneJson);\n }\n\n setTrackStripJson(trackId: number, sceneJson: string): void {\n try {\n JSON.parse(sceneJson);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'invalid track strip JSON';\n throw new SonareError(ErrorCode.InvalidFormat, 'InvalidFormat', message);\n }\n this.native.setTrackStripJson(trackId, sceneJson);\n }\n\n setTrackStripEqBand(trackId: number, bandIndex: number, band: EqBand | string): void {\n this.native.setTrackStripEqBandJson(\n trackId,\n bandIndex,\n typeof band === 'string' ? band : JSON.stringify(band),\n );\n }\n\n setTrackStripEqBandJson(trackId: number, bandIndex: number, bandJson: string): void {\n this.native.setTrackStripEqBandJson(trackId, bandIndex, bandJson);\n }\n\n setTrackStripInsertBypassed(\n trackId: number,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n this.native.setTrackStripInsertBypassed(trackId, insertIndex, bypassed, resetOnBypass);\n }\n\n setMasterStripJson(sceneJson: string): void {\n try {\n JSON.parse(sceneJson);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'invalid master strip JSON';\n throw new SonareError(ErrorCode.InvalidFormat, 'InvalidFormat', message);\n }\n this.native.setMasterStripJson(sceneJson);\n }\n\n setMasterStripEqBand(bandIndex: number, band: EqBand | string): void {\n this.native.setMasterStripEqBandJson(\n bandIndex,\n typeof band === 'string' ? band : JSON.stringify(band),\n );\n }\n\n setMasterStripEqBandJson(bandIndex: number, bandJson: string): void {\n this.native.setMasterStripEqBandJson(bandIndex, bandJson);\n }\n\n setMasterStripInsertBypassed(\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n this.native.setMasterStripInsertBypassed(insertIndex, bypassed, resetOnBypass);\n }\n\n /**\n * Changes one track-strip insert parameter in realtime, addressed by the\n * processor's JSON-key parameter name (see {@link masteringInsertParamInfo}).\n * Applied at the next block head via the engine command queue; safe during\n * playback. Throws if the track, insert, or name is unknown, the param is not\n * realtime-safe, or the command queue is full.\n */\n setTrackStripInsertParamByName(\n trackId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n this.native.setTrackStripInsertParamByName(trackId, insertIndex, paramName, value);\n }\n\n /** Master-strip counterpart of {@link setTrackStripInsertParamByName}. */\n setMasterStripInsertParamByName(insertIndex: number, paramName: string, value: number): void {\n this.native.setMasterStripInsertParamByName(insertIndex, paramName, value);\n }\n\n /** Bus-strip counterpart of {@link setTrackStripInsertParamByName}. */\n setBusStripInsertParamByName(\n busId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n this.native.setBusStripInsertParamByName(busId, insertIndex, paramName, value);\n }\n\n /** Bus-strip counterpart of {@link setTrackStripInsertBypassed}. */\n setBusStripInsertBypassed(\n busId: number,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n this.native.setBusStripInsertBypassed(busId, insertIndex, bypassed, resetOnBypass);\n }\n\n /**\n * Resolves a track-lane insert parameter (by its JSON-key name) to the\n * reserved automation id usable with `setAutomationLane` / `setParameter`.\n * Returns `-1` when the track, insert, or name is unknown. (The Python binding\n * raises a `SonareError` for an unknown id where Node/WASM return the `-1`\n * sentinel.)\n *\n * This trio is how a mastering processor gets time-varying automation: the\n * `eq.*`, `dynamics.*`, `saturation.*`, `spectral.*`, `stereo.*`,\n * `maximizer.*` and `multiband.*` processors are all available as strip\n * inserts, so placing one on a strip and resolving its parameter here drives\n * it at audio-block precision, live and offline alike. The whole-signal\n * stages of the offline mastering chain (`repair.*`, `loudness`, and the\n * match stages) have no insert form and no automation id: they buffer the\n * entire signal by construction and do not run on the realtime path.\n */\n resolveTrackInsertAutomationId(trackId: number, insertIndex: number, paramName: string): number {\n return this.native.resolveTrackInsertAutomationId(trackId, insertIndex, paramName);\n }\n\n resolveMasterInsertAutomationId(insertIndex: number, paramName: string): number {\n return this.native.resolveMasterInsertAutomationId(insertIndex, paramName);\n }\n\n resolveBusInsertAutomationId(busId: number, insertIndex: number, paramName: string): number {\n return this.native.resolveBusInsertAutomationId(busId, insertIndex, paramName);\n }\n\n /** Sets a track lane strip's pan position in realtime (glitch-free). */\n setTrackStripPan(trackId: number, pan: number): void {\n this.native.setTrackStripPan(trackId, pan);\n }\n\n /** Sets a track lane strip's pan law in realtime. */\n setTrackStripPanLaw(trackId: number, panLaw: PanLawInput): void {\n this.native.setTrackStripPanLaw(trackId, panLawCode(panLaw));\n }\n\n /** Sets a track lane strip's pan mode in realtime. */\n setTrackStripPanMode(trackId: number, panMode: PanMode | number): void {\n this.native.setTrackStripPanMode(trackId, panModeCode(panMode));\n }\n\n /** Sets a track lane strip's dual-pan left/right positions in realtime. */\n setTrackStripDualPan(trackId: number, leftPan: number, rightPan: number): void {\n this.native.setTrackStripDualPan(trackId, leftPan, rightPan);\n }\n\n /**\n * Sets a track lane strip's inter-channel alignment delay (whole samples).\n * Adjusts strip latency, so PDC and reported graph latency are refreshed.\n */\n setTrackStripChannelDelaySamples(trackId: number, delaySamples: number): void {\n this.native.setTrackStripChannelDelaySamples(trackId, delaySamples);\n }\n\n createClipPageProvider(\n numChannels: number,\n numSamples: number,\n pageFrames: number,\n ): ClipPageProvider {\n const id = this.native.createClipPageProvider(numChannels, numSamples, pageFrames);\n return new ClipPageProvider(this, id);\n }\n\n supplyClipPage(providerId: number, pageIndex: number, channels: Float32Array[]): void {\n this.native.supplyClipPage(providerId, pageIndex, channels);\n }\n\n clearClipPage(providerId: number, pageIndex: number): void {\n this.native.clearClipPage(providerId, pageIndex);\n }\n\n destroyClipPageProvider(providerId: number): void {\n this.native.destroyClipPageProvider(providerId);\n }\n\n popClipPageRequest(): ClipPageRequest | null {\n return this.native.popClipPageRequest();\n }\n\n /**\n * Moves one native request into the binding's persistent scalar scratch.\n * This avoids creating an embind JS object in AudioWorklet process().\n */\n popClipPageRequestToScratch(): boolean {\n return this.native.popClipPageRequestToScratch();\n }\n\n clipPageRequestScratchClipId(): number {\n return this.native.clipPageRequestScratchClipId();\n }\n\n clipPageRequestScratchSample(): number {\n return this.native.clipPageRequestScratchSample();\n }\n\n /** Cumulative page misses dropped because the native bounded request queue was full. */\n clipPageRequestOverflowCount(): number {\n return this.native.clipPageRequestOverflowCount();\n }\n\n setCaptureBuffer(numChannels: number, capacityFrames: number): void {\n this.native.setCaptureBuffer(numChannels, capacityFrames);\n }\n\n armCapture(armed = true): void {\n this.native.armCapture(armed);\n }\n\n setCapturePunch(startSample: number, endSample: number, enabled = true): void {\n this.native.setCapturePunch(startSample, endSample, enabled);\n }\n\n setCaptureSource(source: EngineCaptureSource): void {\n this.native.setCaptureSource(source);\n }\n\n /** Positive values delay capture relative to the punch window. */\n setRecordOffsetSamples(offsetSamples: number): void {\n this.native.setRecordOffsetSamples(offsetSamples);\n }\n\n setInputMonitor(enabled: boolean, gain = 1): void {\n this.native.setInputMonitor(enabled, gain);\n }\n\n resetCapture(): void {\n this.native.resetCapture();\n }\n\n captureStatus(): EngineCaptureStatus {\n return this.native.captureStatus();\n }\n\n capturedAudio(): Float32Array[] {\n return this.native.capturedAudio();\n }\n\n /**\n * Renders in place, adding engine output to `channels`. Zero each plane first\n * when it contains no upstream input.\n */\n process(channels: Float32Array[]): Float32Array[] {\n return this.native.process(channels);\n }\n\n /**\n * Allocates persistent per-channel WASM-heap scratch for the zero-copy\n * `getChannelBuffer` / `processPrepared` realtime path. Call once (off the\n * audio thread) before driving `processPrepared` from an AudioWorklet so the\n * render callback never allocates on the C++/JS heap.\n */\n prepareChannels(numChannels: number, maxFrames: number): void {\n this.native.prepareChannels(numChannels, maxFrames);\n }\n\n /**\n * Returns a Float32Array view onto the persistent WASM-heap scratch for one\n * channel (valid for up to `numFrames`). Fill it, call `processPrepared`, then\n * read the same view back. Re-acquire after WASM memory growth.\n */\n getChannelBuffer(channel: number, numFrames: number): Float32Array {\n return this.native.getChannelBuffer(channel, numFrames);\n }\n\n /**\n * Runs the engine in place over the prepared per-channel scratch buffers.\n * Zero each active span first when it contains no upstream input.\n * Allocation-free: safe to call on the AudioWorklet render thread after\n * `prepareChannels`.\n */\n processPrepared(numFrames: number): void {\n this.native.processPrepared(numFrames);\n }\n\n /**\n * Allocates the cue-bus counterpart of {@link prepareChannels}. Needed only\n * when PFL/AFL monitoring must reach a separate output: `processPrepared`\n * folds the cue bus into the program output, while\n * {@link processPreparedWithMonitor} keeps the two apart. Call once, off the\n * audio thread, with at least as many channels as `prepareChannels` got.\n */\n prepareMonitorChannels(numChannels: number, maxFrames: number): void {\n this.native.prepareMonitorChannels(numChannels, maxFrames);\n }\n\n /**\n * Returns a Float32Array view onto the persistent cue-bus scratch for one\n * channel (valid for up to `numFrames`). Read it after\n * {@link processPreparedWithMonitor}. Re-acquire after WASM memory growth.\n */\n getMonitorChannelBuffer(channel: number, numFrames: number): Float32Array {\n return this.native.getMonitorChannelBuffer(channel, numFrames);\n }\n\n /**\n * Runs the engine in place over the prepared scratch, writing the cue bus to\n * the monitor scratch instead of folding it into the program output.\n * Allocation-free: safe on the AudioWorklet render thread after\n * `prepareChannels` and `prepareMonitorChannels`.\n */\n processPreparedWithMonitor(numFrames: number): void {\n this.native.processPreparedWithMonitor(numFrames);\n }\n\n processWithMonitor(channels: Float32Array[]): WasmEngineProcessWithMonitorResult {\n return this.native.processWithMonitor(channels);\n }\n\n renderOffline(channels: Float32Array[], blockSize = 128): Float32Array[] {\n return this.native.renderOffline(channels, blockSize);\n }\n\n bounceOffline(options: EngineBounceOptions): EngineBounceResult {\n return this.native.bounceOffline(options);\n }\n\n freezeOffline(options: EngineFreezeOptions): EngineFreezeResult {\n return this.native.freezeOffline(options);\n }\n\n drainTelemetry(maxRecords = 1024): EngineTelemetry[] {\n return this.native.drainTelemetry(maxRecords);\n }\n\n popTelemetryToScratch(): boolean {\n return this.native.popTelemetryToScratch();\n }\n\n telemetryScratchType(): number {\n return this.native.telemetryScratchType();\n }\n\n telemetryScratchError(): number {\n return this.native.telemetryScratchError();\n }\n\n telemetryScratchRenderFrame(): number {\n return Number(this.native.telemetryScratchRenderFrame());\n }\n\n telemetryScratchTimelineSample(): number {\n return Number(this.native.telemetryScratchTimelineSample());\n }\n\n telemetryScratchAudibleTimelineSample(): number {\n return Number(this.native.telemetryScratchAudibleTimelineSample());\n }\n\n telemetryScratchGraphLatencySamplesQ8(): number {\n return this.native.telemetryScratchGraphLatencySamplesQ8();\n }\n\n telemetryScratchValue(): number {\n return this.native.telemetryScratchValue();\n }\n\n popMeterTelemetryToScratch(): boolean {\n return this.native.popMeterTelemetryToScratch();\n }\n meterScratchTargetId(): number {\n return this.native.meterScratchTargetId();\n }\n meterScratchRenderFrame(): number {\n return Number(this.native.meterScratchRenderFrame());\n }\n meterScratchValue(field: number): number {\n return this.native.meterScratchValue(field);\n }\n\n drainMeterTelemetry(maxRecords = 1024): EngineMeterTelemetry[] {\n return this.native.drainMeterTelemetry(maxRecords);\n }\n\n /**\n * Drains pending meter telemetry as per-plane (wide) records for a surround\n * target. Use this for a surround mix target; {@link drainMeterTelemetry}\n * stays the stereo fast path. The two share one queue — call only one per\n * target. The live AudioWorklet path owns the queue via the stereo drain, so\n * this wide drain is for an offline (non-worklet) engine instance; per-plane\n * surround meters are not delivered over the live worklet meter ring.\n */\n drainMeterTelemetryWide(maxRecords = 1024): EngineMeterTelemetryWide[] {\n return this.native.drainMeterTelemetryWide(maxRecords);\n }\n\n /**\n * Enables per-target spectrum + vectorscope capture. @param intervalFrames is\n * the minimum render-frame gap between snapshots (0 disables). @param bandCount\n * is the FFT band resolution (1..64); changing it re-prepares the tap. Returns\n * the band count actually applied.\n */\n configureScopeTelemetry(intervalFrames: number, bandCount: number): number {\n return this.native.configureScopeTelemetry(intervalFrames, bandCount);\n }\n\n /** Drains pending spectrum + vectorscope snapshots (per mix target). */\n drainScopeTelemetry(maxRecords = 1024): EngineScopeTelemetry[] {\n return this.native.drainScopeTelemetry(maxRecords);\n }\n\n popScopeTelemetryToScratch(): boolean {\n return this.native.popScopeTelemetryToScratch();\n }\n scopeScratchTargetId(): number {\n return this.native.scopeScratchTargetId();\n }\n scopeScratchRenderFrame(): number {\n return Number(this.native.scopeScratchRenderFrame());\n }\n scopeScratchBandCount(): number {\n return this.native.scopeScratchBandCount();\n }\n scopeScratchBand(index: number): number {\n return this.native.scopeScratchBand(index);\n }\n scopeScratchPointCount(): number {\n return this.native.scopeScratchPointCount();\n }\n scopeScratchPointLeft(index: number): number {\n return this.native.scopeScratchPointLeft(index);\n }\n scopeScratchPointRight(index: number): number {\n return this.native.scopeScratchPointRight(index);\n }\n\n destroy(): void {\n this.native.delete();\n }\n}\n\nexport class ClipPageProvider {\n private disposed = false;\n\n constructor(\n private readonly engine: RealtimeEngine,\n readonly id: number,\n ) {}\n\n supply(pageIndex: number, channels: Float32Array[]): void {\n if (this.disposed) {\n throw new Error('ClipPageProvider is destroyed');\n }\n this.engine.supplyClipPage(this.id, pageIndex, channels);\n }\n\n clear(pageIndex: number): void {\n if (this.disposed) {\n return;\n }\n this.engine.clearClipPage(this.id, pageIndex);\n }\n\n destroy(): void {\n if (this.disposed) {\n return;\n }\n this.disposed = true;\n this.engine.destroyClipPageProvider(this.id);\n }\n}\n","import {\n automationCurveCode,\n meterTapCode,\n panLawCode,\n panModeCode,\n sendTimingCode,\n} from './codes';\nimport { getSonareModule } from './module_state';\nimport type {\n AutomationCurve,\n GoniometerPoint,\n MeterTap,\n MixerProcessResult,\n MixMeterSnapshot,\n PanLawInput,\n PanMode,\n SendTiming,\n SurroundPan,\n} from './public_types';\n\nexport interface MixerRealtimeBuffer {\n leftInputs: Float32Array[];\n rightInputs: Float32Array[];\n outLeft: Float32Array;\n outRight: Float32Array;\n process: (numSamples?: number) => void;\n}\n\n// ============================================================================\n// Mixer Class (scene-based persistent mixer)\n// ============================================================================\n\n/**\n * Persistent, scene-based stereo mixer.\n *\n * Build one from a scene JSON string (e.g. {@link mixingScenePresetJson} or a\n * hand-authored scene), then feed per-strip stereo blocks through\n * {@link processStereo} to get the routed stereo master. Strips, sends, buses,\n * and inserts are described entirely by the scene; the routing graph is\n * compiled lazily on the first {@link processStereo} call (or eagerly via\n * {@link compile}).\n *\n * Call {@link delete} (or use a `try/finally`) to release the underlying WASM\n * object — the embind handle is not garbage-collected automatically.\n *\n * @example\n * ```typescript\n * const mixer = Mixer.fromSceneJson(mixingScenePresetJson('basicStereo'), 48000, 512);\n * try {\n * const out = mixer.processStereo([stripL], [stripR]);\n * } finally {\n * mixer.delete();\n * }\n * ```\n */\nexport class Mixer {\n private mixer: import('./sonare.js').WasmMixer;\n private readonly blockSize: number;\n\n private constructor(mixer: import('./sonare.js').WasmMixer, blockSize: number) {\n this.mixer = mixer;\n this.blockSize = blockSize;\n }\n\n /**\n * Build a mixer from a scene JSON string.\n *\n * @param json - Scene JSON (strips, buses, sends, connections, inserts)\n * @param sampleRate - Sample rate in Hz (default: 48000)\n * @param blockSize - Maximum block size per {@link processStereo} call (default: 512)\n */\n static fromSceneJson(json: string, sampleRate = 48000, blockSize = 512): Mixer {\n const module = getSonareModule();\n return new Mixer(module.createMixerFromSceneJson(json, sampleRate, blockSize), blockSize);\n }\n\n /**\n * Rebuild and compile the routing graph without resetting its absolute\n * automation sample position or queued strip automation.\n */\n compile(): void {\n this.mixer.compile();\n }\n\n /**\n * Non-fatal warnings captured when this mixer was built from scene JSON: one\n * entry per channel-strip insert that was handed param keys it does not read\n * (a likely typo, or a key meant for a different processor). The scene still\n * loaded; these keys simply took no effect. Empty when every key was consumed.\n * Use {@link masteringInsertParamNames} to discover the keys an insert accepts.\n */\n sceneWarnings(): string[] {\n return this.mixer.sceneWarnings();\n }\n\n /**\n * Mix one block of per-strip stereo audio into the stereo master.\n *\n * @param leftChannels - `leftChannels[i]` is the left channel of strip `i`\n * @param rightChannels - `rightChannels[i]` is the right channel of strip `i`\n * @returns Mixed stereo master (`left`, `right`, `sampleRate`)\n */\n processStereo(leftChannels: Float32Array[], rightChannels: Float32Array[]): MixerProcessResult {\n if (leftChannels.length !== rightChannels.length) {\n throw new Error('leftChannels and rightChannels must have the same length.');\n }\n return this.mixer.processStereo(leftChannels, rightChannels);\n }\n\n /**\n * Mix one block into caller-owned output arrays.\n *\n * This avoids allocating the result object and result `Float32Array`s. It is\n * intended for realtime bridges such as AudioWorklet; the input channel count\n * must match the scene strip count and all arrays must have the same length.\n */\n processStereoInto(\n leftChannels: Float32Array[],\n rightChannels: Float32Array[],\n outLeft: Float32Array,\n outRight: Float32Array,\n ): void {\n if (leftChannels.length !== rightChannels.length) {\n throw new Error('leftChannels and rightChannels must have the same length.');\n }\n if (outLeft.length !== outRight.length) {\n throw new Error('outLeft and outRight must have the same length.');\n }\n this.mixer.processStereoInto(leftChannels, rightChannels, outLeft, outRight);\n }\n\n /**\n * Create reusable WASM-heap input/output views for realtime-style processing.\n *\n * Fill `leftInputs[i]` / `rightInputs[i]`, call `process()`, then read\n * `outLeft` / `outRight`. The views are owned by this mixer and become invalid\n * after {@link delete}.\n */\n createRealtimeBuffer(): MixerRealtimeBuffer {\n const stripCount = this.stripCount();\n let leftInputs: Float32Array[] = [];\n let rightInputs: Float32Array[] = [];\n let outLeft = this.mixer.outputLeftView();\n let outRight = this.mixer.outputRightView();\n const acquire = (): void => {\n leftInputs = [];\n rightInputs = [];\n for (let index = 0; index < stripCount; index++) {\n leftInputs.push(this.mixer.inputLeftView(index));\n rightInputs.push(this.mixer.inputRightView(index));\n }\n outLeft = this.mixer.outputLeftView();\n outRight = this.mixer.outputRightView();\n };\n acquire();\n // The cached heap views can detach if WASM linear memory grows (the embind\n // module is built ALLOW_MEMORY_GROWTH). Re-acquire them if detached\n // (byteLength === 0) before use, mirroring the worklet RT path.\n const reacquireIfDetached = (): void => {\n if (outLeft.byteLength === 0 || (leftInputs[0]?.byteLength ?? 1) === 0) {\n acquire();\n }\n };\n return {\n get leftInputs(): Float32Array[] {\n reacquireIfDetached();\n return leftInputs;\n },\n get rightInputs(): Float32Array[] {\n reacquireIfDetached();\n return rightInputs;\n },\n get outLeft(): Float32Array {\n reacquireIfDetached();\n return outLeft;\n },\n get outRight(): Float32Array {\n reacquireIfDetached();\n return outRight;\n },\n process: (numSamples = outLeft.length) => {\n reacquireIfDetached();\n this.mixer.processPreparedStereo(numSamples);\n },\n };\n }\n\n /** Number of strips in the mixer (e.g. strips loaded from the scene). */\n stripCount(): number {\n return this.mixer.stripCount();\n }\n\n /**\n * Schedule sample-accurate insert-parameter automation on a strip's insert.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param insertIndex - Index into the strip's combined insert sequence\n * (`[pre-inserts... post-inserts...]`)\n * @param paramId - Processor-specific parameter id\n * @param samplePos - Absolute samples from the start of processing (the mixer\n * advances an internal position from 0 on the first {@link processStereo}\n * call; recompiling resets it to 0)\n * @param value - Target parameter value\n * @param curve - Interpolation curve (default: `'linear'`)\n * @throws If the strip index is out of range or the schedule call fails\n * (unknown curve, out-of-range insert index, or full event lane)\n */\n scheduleInsertAutomation(\n stripIndex: number,\n insertIndex: number,\n paramId: number,\n samplePos: number,\n value: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleInsertAutomation(\n stripIndex,\n insertIndex,\n paramId,\n samplePos,\n value,\n automationCurveCode(curve),\n );\n }\n\n /**\n * Resolve a strip's index in `[0, stripCount())` from its scene id, or `null`\n * when no strip with that id exists (matches the Node binding's `number | null`).\n */\n stripById(id: string): number | null {\n const index = this.mixer.stripById(id);\n return index < 0 ? null : index;\n }\n\n /**\n * Add a bus to the mixer topology. `role` is one of `'master'`, `'aux'`, or\n * `'submix'` (defaults to `'aux'`). Marks the routing graph dirty; call\n * {@link compile} (or {@link processStereo}) to rebuild.\n */\n addBus(id: string, role = 'aux'): void {\n this.mixer.addBus(id, role);\n }\n\n /** Remove a bus by id. Marks the routing graph dirty. */\n removeBus(id: string): void {\n this.mixer.removeBus(id);\n }\n\n /** Number of buses in the mixer topology. */\n busCount(): number {\n return this.mixer.busCount();\n }\n\n /**\n * Add a VCA group with the given gain offset (dB). `members` is a list of\n * strip ids governed by the group (may be empty).\n */\n addVcaGroup(id: string, gainDb = 0.0, members: string[] = []): void {\n this.mixer.addVcaGroup(id, gainDb, members);\n }\n\n /** Set an existing VCA group's gain in dB. */\n setVcaGroupGainDb(id: string, gainDb: number): void {\n this.mixer.setVcaGroupGainDb(id, gainDb);\n }\n\n /** Replace an existing VCA group's strip membership. */\n setVcaGroupMembers(id: string, members: string[]): void {\n this.mixer.setVcaGroupMembers(id, members);\n }\n\n /** Remove a VCA group by id. */\n removeVcaGroup(id: string): void {\n this.mixer.removeVcaGroup(id);\n }\n\n /** Number of VCA groups in the mixer topology. */\n vcaGroupCount(): number {\n return this.mixer.vcaGroupCount();\n }\n\n /** Set the strip's input trim in dB. */\n setInputTrimDb(stripIndex: number, db: number): void {\n this.mixer.setInputTrimDb(stripIndex, db);\n }\n\n /** Set the strip's fader level in dB. */\n setFaderDb(stripIndex: number, db: number): void {\n this.mixer.setFaderDb(stripIndex, db);\n }\n\n /**\n * Set the strip's pan position.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param pan - Pan position in `[-1, 1]`\n * @param panMode - Optional pan mode. When omitted the strip's current pan\n * mode is kept (passes `SONARE_PAN_MODE_KEEP`), so a plain pan nudge does\n * not reset a scene-defined `'stereoPan'` / `'dualPan'` mode back to\n * balance. Pass `'balance'` (or `0`) explicitly to force balance mode.\n */\n setPan(stripIndex: number, pan: number, panMode?: PanMode | number): void {\n // SONARE_PAN_MODE_KEEP (-1) = keep the strip's current pan mode.\n const mode = panMode === undefined ? -1 : panModeCode(panMode);\n this.mixer.setPan(stripIndex, pan, mode);\n }\n\n /** Set the strip's stereo width. */\n setWidth(stripIndex: number, width: number): void {\n this.mixer.setWidth(stripIndex, width);\n }\n\n /** Set the strip's mute state. */\n setMuted(stripIndex: number, muted: boolean): void {\n this.mixer.setMuted(stripIndex, muted);\n }\n\n /**\n * Set a strip's solo state. Takes effect on the next process without a\n * graph recompile.\n */\n setSoloed(stripIndex: number, soloed: boolean): void {\n this.mixer.setSoloed(stripIndex, soloed);\n }\n\n /**\n * Mark a strip solo-safe so it is never implied-muted by another strip's\n * solo. Takes effect on the next process without a graph recompile.\n */\n setSoloSafe(stripIndex: number, soloSafe: boolean): void {\n this.mixer.setSoloSafe(stripIndex, soloSafe);\n }\n\n /** Invert the polarity of the left and/or right channel of a strip. */\n setPolarityInvert(stripIndex: number, invertLeft: boolean, invertRight: boolean): void {\n this.mixer.setPolarityInvert(stripIndex, invertLeft, invertRight);\n }\n\n /** Set the strip's pan law (a {@link PanLawName} alias or raw C ABI ordinal). */\n setPanLaw(stripIndex: number, panLaw: PanLawInput): void {\n this.mixer.setPanLaw(stripIndex, panLawCode(panLaw));\n }\n\n /**\n * Set a per-strip channel delay in samples. This changes the strip's reported\n * latency; recompile to re-run latency compensation.\n */\n setChannelDelaySamples(stripIndex: number, delaySamples: number): void {\n this.mixer.setChannelDelaySamples(stripIndex, delaySamples);\n }\n\n /** Set the strip's live VCA gain offset in dB (not persisted to the scene). */\n setVcaOffsetDb(stripIndex: number, offsetDb: number): void {\n this.mixer.setVcaOffsetDb(stripIndex, offsetDb);\n }\n\n /** Set independent left/right pan positions (dual-pan mode). */\n setDualPan(stripIndex: number, leftPan: number, rightPan: number): void {\n this.mixer.setDualPan(stripIndex, leftPan, rightPan);\n }\n\n /**\n * Set the strip's surround pan position, used when it feeds a >2-channel bus.\n * Stored on the scene; inert until the surround DSP path applies it.\n */\n setSurroundPan(stripIndex: number, pan: SurroundPan): void {\n this.mixer.setSurroundPan(stripIndex, pan);\n }\n\n /**\n * Add a send to a strip after construction.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param id - Send id\n * @param destinationBusId - Destination bus id\n * @param sendDb - Initial send level in dB\n * @param timing - `'preFader'` or `'postFader'` (default: `'postFader'`)\n * @returns The new send's index\n */\n addSend(\n stripIndex: number,\n id: string,\n destinationBusId: string,\n sendDb = 0.0,\n timing: SendTiming | number = 'postFader',\n ): number {\n return this.mixer.addSend(stripIndex, id, destinationBusId, sendDb, sendTimingCode(timing));\n }\n\n /** Set the send level (in dB) for an existing send by index. */\n setSendDb(stripIndex: number, sendIndex: number, sendDb: number): void {\n this.mixer.setSendDb(stripIndex, sendIndex, sendDb);\n }\n\n /**\n * Remove an existing send from a strip by index.\n *\n * Sends are addressed in add order. After removal, sends with a higher index\n * than `sendIndex` shift down by one. Recompile (or process) before reading\n * results so the routing graph rebuilds.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param sendIndex - Send index in add order\n */\n removeSend(stripIndex: number, sendIndex: number): void {\n this.mixer.removeSend(stripIndex, sendIndex);\n }\n\n /**\n * Read a strip's meter snapshot at the given tap point.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param tap - `'preFader'` or `'postFader'` (default: `'postFader'`)\n */\n meterTap(stripIndex: number, tap: MeterTap = 'postFader'): MixMeterSnapshot {\n return this.mixer.meterTap(stripIndex, meterTapCode(tap));\n }\n\n /**\n * Read a strip's meter snapshot.\n *\n * With no `tap` argument this reads the strip's own (post-fader) meter,\n * matching the Node/Python tap-less `stripMeter` contract. Pass an optional\n * `tap` (`'preFader'` / `'postFader'`) to read the tap-selectable snapshot\n * instead — the same backing call as {@link meterTap}.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param tap - Optional tap point (`'preFader'` / `'postFader'`); when omitted\n * the tap-less post-fader strip meter is read.\n */\n stripMeter(stripIndex: number, tap?: MeterTap | number): MixMeterSnapshot {\n if (tap === undefined) {\n return this.mixer.stripMeter(stripIndex);\n }\n return this.mixer.meterTap(stripIndex, meterTapCode(tap));\n }\n\n /** Read the post-insert meter for a compiled bus, including master. */\n busMeter(busId: string): MixMeterSnapshot {\n return this.mixer.busMeter(busId);\n }\n\n /**\n * Schedule sample-accurate fader automation on a strip.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param samplePos - Absolute samples from the start of processing\n * @param faderDb - Target fader level in dB\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n scheduleFaderAutomation(\n stripIndex: number,\n samplePos: number,\n faderDb: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleFaderAutomation(stripIndex, samplePos, faderDb, automationCurveCode(curve));\n }\n\n /**\n * Schedule sample-accurate pan automation on a strip.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param samplePos - Absolute samples from the start of processing\n * @param pan - Target pan position\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n schedulePanAutomation(\n stripIndex: number,\n samplePos: number,\n pan: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.schedulePanAutomation(stripIndex, samplePos, pan, automationCurveCode(curve));\n }\n\n /**\n * Schedule sample-accurate width automation on a strip.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param samplePos - Absolute samples from the start of processing\n * @param width - Target stereo width\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n scheduleWidthAutomation(\n stripIndex: number,\n samplePos: number,\n width: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleWidthAutomation(stripIndex, samplePos, width, automationCurveCode(curve));\n }\n\n /**\n * Schedule sample-accurate send-level automation on a strip's send.\n *\n * @param stripIndex - Strip index in `[0, stripCount())`\n * @param sendIndex - Send index in the strip's add order\n * @param samplePos - Absolute samples from the start of processing\n * @param db - Target send level in dB\n * @param curve - Interpolation curve (default: `'linear'`)\n */\n scheduleSendAutomation(\n stripIndex: number,\n sendIndex: number,\n samplePos: number,\n db: number,\n curve: AutomationCurve = 'linear',\n ): void {\n this.mixer.scheduleSendAutomation(\n stripIndex,\n sendIndex,\n samplePos,\n db,\n automationCurveCode(curve),\n );\n }\n\n /**\n * Read up to `maxPoints` of a strip's most recent goniometer samples\n * (oldest to newest).\n */\n readGoniometerLatest(stripIndex: number, maxPoints: number): GoniometerPoint[] {\n return this.mixer.readGoniometerLatest(stripIndex, maxPoints);\n }\n\n /** Serialize the current scene (strips, buses, sends, connections) to JSON. */\n toSceneJson(): string {\n return this.mixer.toSceneJson();\n }\n\n /**\n * Longest audible serial processor-tail path to the master, in samples. Lazily\n * compiles the routing graph if the topology is dirty.\n */\n tailSamples(): number {\n return this.mixer.tailSamples();\n }\n\n /**\n * Reported latency (samples) of the compiled mixer graph, for aligning\n * dry/wet material. Lazily compiles the routing graph if the topology is dirty.\n */\n latencySamples(): number {\n return this.mixer.latencySamples();\n }\n\n /**\n * Drain delayed / tail audio by processing a zero-input block of `numSamples`\n * frames after the host stops feeding strip inputs. Returns the mixed stereo\n * master (`left`, `right`, `sampleRate`).\n */\n drainTailStereo(numSamples: number): MixerProcessResult {\n if (!Number.isSafeInteger(numSamples) || numSamples <= 0 || numSamples > this.blockSize) {\n throw new RangeError(\n `Mixer.drainTailStereo: numSamples must be an integer in [1, ${this.blockSize}]`,\n );\n }\n return this.mixer.drainTailStereo(numSamples);\n }\n\n /** Release the underlying WASM object. Safe to call only once. */\n delete(): void {\n this.mixer.delete();\n }\n\n /** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */\n destroy(): void {\n this.delete();\n }\n}\n","import { getSonareModule } from './module_state';\nimport type {\n RealtimeVoiceChangerConfigInput,\n RealtimeVoiceChangerPodConfig,\n VoicePresetId,\n} from './public_types';\n\n/**\n * Zero-copy realtime buffer pair for {@link RealtimeVoiceChanger} mono\n * processing. The `input` / `output` `Float32Array`s are typed-memory views\n * onto the WASM heap — write samples into `input`, call `process()`, then\n * read from `output`. The views are owned by the {@link RealtimeVoiceChanger}\n * and remain valid until `delete()` is called on it.\n */\nexport interface RealtimeVoiceChangerMonoBuffer {\n input: Float32Array;\n output: Float32Array;\n process: () => void;\n}\n\n/**\n * Zero-copy realtime buffer pair for {@link RealtimeVoiceChanger} interleaved\n * multi-channel processing. Layout is L0,R0,L1,R1,... for stereo. The views\n * are owned by the {@link RealtimeVoiceChanger}.\n */\nexport interface RealtimeVoiceChangerInterleavedBuffer {\n input: Float32Array;\n output: Float32Array;\n channels: number;\n process: () => void;\n}\n\n/**\n * Zero-copy realtime buffer for {@link RealtimeVoiceChanger} planar stereo\n * processing. Each entry in `channels` is a heap-backed `Float32Array` for one\n * channel (matching AudioWorklet's native layout). Process happens in place:\n * write samples into each channel view, call `process()`, then read back from\n * the same views.\n */\nexport interface RealtimeVoiceChangerPlanarBuffer {\n channels: Float32Array[];\n process: () => void;\n}\n\n// ============================================================================\n// RealtimeVoiceChanger Class\n// ============================================================================\n\nexport class RealtimeVoiceChanger {\n private changer: import('./sonare.js').WasmRealtimeVoiceChanger;\n\n /**\n * Creates a voice changer. Supplying `sampleRate` prepares it immediately,\n * matching the Node and Python constructors; omitting it preserves the\n * explicit {@link prepare} lifecycle for callers that configure later.\n */\n constructor(\n config: RealtimeVoiceChangerConfigInput | RealtimeVoiceChangerPodConfig = 'neutral-monitor',\n sampleRate?: number,\n maxBlockSize = 128,\n channels = 1,\n ) {\n const module = getSonareModule();\n this.changer = module.createRealtimeVoiceChanger(config as Record<string, unknown> | string);\n if (sampleRate !== undefined) {\n this.changer.prepare(sampleRate, maxBlockSize, channels);\n }\n }\n\n prepare(sampleRate: number, maxBlockSize = 128, channels = 1): void {\n this.changer.prepare(sampleRate, maxBlockSize, channels);\n }\n\n reset(): void {\n this.changer.reset();\n }\n\n setConfig(config: RealtimeVoiceChangerConfigInput | RealtimeVoiceChangerPodConfig): void {\n // The shared native parser recognizes the flat POD produced by\n // realtimeVoiceChangerPresetConfig, so bindings never duplicate its 36-field mapping.\n this.changer.setConfig(config as Record<string, unknown> | string);\n }\n\n /**\n * Apply a flat, pre-normalized config without JSON serialization. Intended\n * for AudioWorklet control messages whose sender prepared the POD on the\n * main thread.\n */\n setPodConfig(config: RealtimeVoiceChangerPodConfig): void {\n this.changer.setPodConfig(config);\n }\n\n configJson(): string {\n return this.changer.configJson();\n }\n\n latencySamples(): number {\n return this.changer.latencySamples();\n }\n\n /**\n * Monotonically increases whenever {@link prepare} can replace the native\n * scratch buffers. Cached WASM heap views must be reacquired after it changes.\n */\n bufferGeneration(): number {\n return this.changer.bufferGeneration();\n }\n\n processMono(samples: Float32Array): Float32Array {\n return this.changer.processMono(samples);\n }\n\n processMonoInto(samples: Float32Array, output: Float32Array): void {\n this.changer.processMonoInto(samples, output);\n }\n\n processInterleaved(samples: Float32Array, channels: number): Float32Array {\n return this.changer.processInterleaved(samples, channels);\n }\n\n processInterleavedInto(samples: Float32Array, channels: number, output: Float32Array): void {\n this.changer.processInterleavedInto(samples, channels, output);\n }\n\n /**\n * Acquire a typed-memory view onto the WASM heap for mono input.\n *\n * Write your input samples into the returned `Float32Array` directly (e.g.\n * via `input.set(source)`); no copy crosses the JS↔C++ bridge until\n * {@link processPreparedMono} is called. The view is owned by this\n * RealtimeVoiceChanger and becomes invalid after {@link delete}; it may\n * also be invalidated if you later call this method with a larger\n * `numSamples` value (the underlying buffer may be reallocated).\n */\n getMonoInputBuffer(numSamples: number): Float32Array {\n return this.changer.getMonoInputBuffer(numSamples);\n }\n\n /** Mono output view counterpart to {@link getMonoInputBuffer}. */\n getMonoOutputBuffer(numSamples: number): Float32Array {\n return this.changer.getMonoOutputBuffer(numSamples);\n }\n\n /**\n * Process the previously-acquired mono input buffer in place. The output\n * appears in the buffer returned by {@link getMonoOutputBuffer}. No JS↔C++\n * sample-level crossings happen on this call — it just hands control to\n * the underlying DSP on already-on-heap data.\n */\n processPreparedMono(numSamples: number): void {\n this.changer.processPreparedMono(numSamples);\n }\n\n /** Interleaved input view (layout L0,R0,L1,R1,...). */\n getInterleavedInputBuffer(numFrames: number, numChannels: number): Float32Array {\n return this.changer.getInterleavedInputBuffer(numFrames, numChannels);\n }\n\n /** Interleaved output view counterpart. */\n getInterleavedOutputBuffer(numFrames: number, numChannels: number): Float32Array {\n return this.changer.getInterleavedOutputBuffer(numFrames, numChannels);\n }\n\n /**\n * Process the previously-acquired interleaved buffer in place. Output\n * appears in the buffer returned by {@link getInterleavedOutputBuffer}.\n */\n processPreparedInterleaved(numFrames: number, numChannels: number): void {\n this.changer.processPreparedInterleaved(numFrames, numChannels);\n }\n\n /**\n * Planar-channel input/output view (one Float32Array per channel). Matches\n * AudioWorklet's native layout; processing happens in place.\n */\n getPlanarChannelBuffer(channel: number, numFrames: number): Float32Array {\n return this.changer.getPlanarChannelBuffer(channel, numFrames);\n }\n\n /**\n * Process the previously-acquired planar channel buffers in place. Each\n * channel must have been obtained from {@link getPlanarChannelBuffer}\n * with the same `numFrames`. Output replaces input in the same buffers.\n */\n processPreparedPlanar(numFrames: number): void {\n this.changer.processPreparedPlanar(numFrames);\n }\n\n /**\n * Convenience factory for the mono zero-copy path: returns the input/output\n * heap views plus a `process()` thunk wired to the same `numSamples`. The\n * views are reused across calls and become invalid after {@link delete}.\n */\n createRealtimeMonoBuffer(numSamples: number): RealtimeVoiceChangerMonoBuffer {\n let input = this.getMonoInputBuffer(numSamples);\n let output = this.getMonoOutputBuffer(numSamples);\n let generation = this.bufferGeneration();\n // The cached heap views can detach if WASM linear memory grows (the embind\n // module is built ALLOW_MEMORY_GROWTH). Re-acquire them if detached\n // (byteLength === 0) before use, mirroring the worklet RT path. In the\n // common no-growth case this is a cheap branch with no allocation.\n const reacquireIfDetached = (): void => {\n if (\n generation !== this.bufferGeneration() ||\n input.byteLength === 0 ||\n output.byteLength === 0\n ) {\n input = this.getMonoInputBuffer(numSamples);\n output = this.getMonoOutputBuffer(numSamples);\n generation = this.bufferGeneration();\n }\n };\n return {\n get input(): Float32Array {\n reacquireIfDetached();\n return input;\n },\n get output(): Float32Array {\n reacquireIfDetached();\n return output;\n },\n process: () => {\n reacquireIfDetached();\n this.processPreparedMono(numSamples);\n },\n };\n }\n\n /** Same as {@link createRealtimeMonoBuffer} but for interleaved I/O. */\n createRealtimeInterleavedBuffer(\n numFrames: number,\n numChannels: number,\n ): RealtimeVoiceChangerInterleavedBuffer {\n let input = this.getInterleavedInputBuffer(numFrames, numChannels);\n let output = this.getInterleavedOutputBuffer(numFrames, numChannels);\n let generation = this.bufferGeneration();\n // Re-acquire detached views after WASM memory growth (see\n // createRealtimeMonoBuffer for rationale).\n const reacquireIfDetached = (): void => {\n if (\n generation !== this.bufferGeneration() ||\n input.byteLength === 0 ||\n output.byteLength === 0\n ) {\n input = this.getInterleavedInputBuffer(numFrames, numChannels);\n output = this.getInterleavedOutputBuffer(numFrames, numChannels);\n generation = this.bufferGeneration();\n }\n };\n return {\n get input(): Float32Array {\n reacquireIfDetached();\n return input;\n },\n get output(): Float32Array {\n reacquireIfDetached();\n return output;\n },\n channels: numChannels,\n process: () => {\n reacquireIfDetached();\n this.processPreparedInterleaved(numFrames, numChannels);\n },\n };\n }\n\n /**\n * Convenience factory for the planar zero-copy path. Acquires one\n * heap-backed Float32Array per channel and returns a `process()` thunk\n * wired to the same `numFrames`. Buffers are reused across calls and\n * become invalid after {@link delete}.\n */\n createRealtimePlanarBuffer(\n numFrames: number,\n numChannels: number,\n ): RealtimeVoiceChangerPlanarBuffer {\n let channels: Float32Array[] = [];\n let generation = this.bufferGeneration();\n const acquire = (): void => {\n channels = [];\n for (let ch = 0; ch < numChannels; ch++) {\n channels.push(this.getPlanarChannelBuffer(ch, numFrames));\n }\n generation = this.bufferGeneration();\n };\n acquire();\n // Re-acquire detached views after WASM memory growth (see\n // createRealtimeMonoBuffer for rationale).\n const reacquireIfDetached = (): void => {\n if (generation !== this.bufferGeneration() || (channels[0]?.byteLength ?? 0) === 0) {\n acquire();\n }\n };\n return {\n get channels(): Float32Array[] {\n reacquireIfDetached();\n return channels;\n },\n process: () => {\n reacquireIfDetached();\n this.processPreparedPlanar(numFrames);\n },\n };\n }\n\n delete(): void {\n this.changer.delete();\n }\n}\n\nexport function realtimeVoiceChangerPresetNames(): VoicePresetId[] {\n // Array.from re-roots embind's vector as a plain, structured-cloneable Array.\n return Array.from(getSonareModule().realtimeVoiceChangerPresetNames()) as VoicePresetId[];\n}\n\nexport function realtimeVoiceChangerPresetJson(name: VoicePresetId): string {\n return getSonareModule().realtimeVoiceChangerPresetJson(name);\n}\n\nexport function validateRealtimeVoiceChangerPresetJson(json: string): {\n ok: boolean;\n normalizedJson?: string;\n error?: string;\n} {\n return getSonareModule().validateRealtimeVoiceChangerPresetJson(json);\n}\n","import { flattenChainConfig } from './_chain_config';\nimport { getSonareModule } from './module_state';\nimport type {\n EqBand,\n EqMatchOptions,\n EqSpectrumSnapshot,\n StreamingEqualizerConfig,\n StreamingMasteringChainConfig,\n StreamingRetuneConfig,\n} from './public_types';\n\ntype EqPhaseMode =\n | 'zero'\n | 'zero-latency'\n | 'zero_latency'\n | 'natural'\n | 'natural-phase'\n | 'natural_phase'\n | 'linear'\n | 'linear-phase'\n | 'linear_phase'\n | number;\n\nconst EQ_PHASE_MODES: Record<string, number> = {\n zero: 1,\n 'zero-latency': 1,\n zero_latency: 1,\n natural: 2,\n 'natural-phase': 2,\n natural_phase: 2,\n linear: 3,\n 'linear-phase': 3,\n linear_phase: 3,\n};\n\n// ============================================================================\n// StreamingMasteringChain Class\n// ============================================================================\n\n/**\n * Block-by-block streaming variant of {@link masteringChain}.\n *\n * Maintains processor state across {@link processMono}/{@link processStereo}\n * calls. Only ProcessorBase-backed stages are supported. Configurations that\n * enable `repair.denoise` throw at construction. An enabled `loudness` stage\n * also throws unless {@link StreamingMasteringChainConfig.loudnessStaticGainDb}\n * supplies a precomputed normalization gain.\n *\n * Call {@link delete} (or use a `try/finally`) to release the underlying WASM\n * object — the embind handle is not garbage-collected automatically.\n *\n * Reachable from the AudioWorklet realm through the `sonare/worklet` entry, but\n * the realtime contract is the caller's to keep:\n *\n * - {@link prepare} builds the processors and allocates. Call it once from a\n * message handler, never from `AudioWorkletProcessor.process()`.\n * - {@link processMono}/{@link processStereo} return fresh arrays. On the render\n * thread, reuse the returned reference for the block rather than retaining it.\n * - An enabled `loudness` stage needs `loudnessStaticGainDb` measured offline,\n * because whole-signal integrated LUFS cannot be measured block by block. Pass\n * `loudnessStaticGainPeakDb` too and the static gain is clamped exactly as the\n * offline chain clamps it, so the live preview matches the render.\n * - {@link flush} output starts {@link latencySamples} samples early; discard\n * that many leading samples when time alignment matters.\n *\n * The chain is a host-side stage, not an engine insert: it does not participate\n * in the engine's PDC or bypass, so latency compensation against other engine\n * outputs is also the caller's.\n *\n * @example\n * ```typescript\n * const chain = new StreamingMasteringChain({ eq: { tiltDb: 1.0 } });\n * try {\n * chain.prepare(44100, 512, 1);\n * const out = chain.processMono(blockSamples);\n * } finally {\n * chain.delete();\n * }\n * ```\n */\nexport class StreamingMasteringChain {\n private chain: import('./sonare.js').WasmStreamingMasteringChain;\n\n constructor(config: StreamingMasteringChainConfig) {\n const module = getSonareModule();\n const { loudnessStaticGainDb, loudnessStaticGainPeakDb, ...chainConfig } = config;\n this.chain = module.createStreamingMasteringChain({\n __flatParams: flattenChainConfig(chainConfig),\n loudnessStaticGainDb,\n loudnessStaticGainPeakDb,\n });\n }\n\n /**\n * Initialize processors for the given sample rate and block layout.\n *\n * @param sampleRate - Sample rate in Hz\n * @param maxBlockSize - Maximum block size per process call\n * @param numChannels - 1 (mono) or 2 (stereo)\n */\n prepare(sampleRate: number, maxBlockSize: number, numChannels: number): void {\n this.chain.prepare(sampleRate, maxBlockSize, numChannels);\n }\n\n /**\n * Process one mono block, returning the processed samples (same length).\n */\n processMono(samples: Float32Array): Float32Array {\n return this.chain.processMono(samples);\n }\n\n /**\n * Process one stereo block, returning the processed channels.\n */\n processStereo(\n left: Float32Array,\n right: Float32Array,\n ): { left: Float32Array; right: Float32Array } {\n if (left.length !== right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n return this.chain.processStereo(left, right);\n }\n\n /**\n * Emit delayed audio and finite processor tails after the final mono block.\n * Call until this returns an empty array. The initial `latencySamples()`\n * samples of the concatenated stream are delayed and should be discarded for\n * time-aligned output.\n */\n flushMono(): Float32Array {\n return this.chain.flushMono();\n }\n\n /** Stereo counterpart of {@link flushMono}. */\n flushStereo(): { left: Float32Array; right: Float32Array } {\n return this.chain.flushStereo();\n }\n\n /** Reset all processor state without rebuilding. */\n reset(): void {\n this.chain.reset();\n }\n\n /** Total reported latency in samples across all active processors. */\n latencySamples(): number {\n return this.chain.latencySamples();\n }\n\n /** Ordered stage names that will run (e.g. `\"eq.tilt\"`). */\n stageNames(): string[] {\n return this.chain.stageNames();\n }\n\n /** Release the underlying WASM object. Safe to call only once. */\n delete(): void {\n this.chain.delete();\n }\n}\n\n// ============================================================================\n// StreamingEqualizer Class\n// ============================================================================\n\n/**\n * Block-by-block streaming equalizer wrapping the unified C++\n * `EqualizerProcessor` (up to 24 bands, RBJ/Vicanek biquads, dynamic EQ,\n * linear-phase FIR, mid/side processing, and auto-gain).\n *\n * State is maintained across {@link processMono}/{@link processStereo} calls.\n * Call {@link delete} (or use `try/finally`) to release the underlying WASM\n * object — the embind handle is not garbage-collected automatically.\n *\n * @example\n * ```typescript\n * const eq = new StreamingEqualizer({ sampleRate: 48000, maxBlockSize: 512 });\n * try {\n * eq.setBand(0, { type: 'HighShelf', frequencyHz: 8000, gainDb: 6, enabled: true });\n * const out = eq.processStereo(left, right);\n * const snapshot = eq.spectrum();\n * } finally {\n * eq.delete();\n * }\n * ```\n */\nexport class StreamingEqualizer {\n private eq: import('./sonare.js').WasmStreamingEqualizer;\n\n constructor(config: StreamingEqualizerConfig = {}) {\n const module = getSonareModule();\n this.eq = module.createEqualizer(config as Record<string, unknown>);\n }\n\n /**\n * Configure the band at `index` (0..23). Omitted fields use C++ defaults.\n */\n setBand(index: number, band: EqBand): void {\n this.eq.setBand(index, band as Record<string, unknown>);\n }\n\n /** Disable and reset every band. */\n clear(): void {\n this.eq.clear();\n }\n\n /**\n * Set the global phase mode: `'zero'` | `'natural'` | `'linear'` or 1/2/3.\n */\n setPhaseMode(mode: EqPhaseMode): void {\n const value = typeof mode === 'number' ? mode : EQ_PHASE_MODES[mode.toLowerCase()];\n if (value === undefined) {\n throw new Error(`unknown EQ phase mode: ${mode}`);\n }\n this.eq.setPhaseMode(value);\n }\n\n /** Enable or disable output auto-gain compensation. */\n setAutoGain(enabled: boolean): void {\n this.eq.setAutoGain(enabled);\n }\n\n /** Set all-band EQ gain scale as a 0.0..2.0 multiplier. */\n setGainScale(scale: number): void {\n this.eq.setGainScale(scale);\n }\n\n /** Set post-EQ output gain in dB. */\n setOutputGainDb(gainDb: number): void {\n this.eq.setOutputGainDb(gainDb);\n }\n\n /** Set post-EQ stereo balance in -1.0..1.0; mono input ignores pan. */\n setOutputPan(pan: number): void {\n this.eq.setOutputPan(pan);\n }\n\n /**\n * Provide a mono external sidechain key for dynamic bands that opt into\n * `external_sidechain`. The samples are copied into an owned buffer.\n */\n setSidechainMono(samples: Float32Array): void {\n this.eq.setSidechainMono(samples);\n }\n\n /**\n * Provide a stereo external sidechain key. Both channels must match length.\n */\n setSidechainStereo(left: Float32Array, right: Float32Array): void {\n if (left.length !== right.length) {\n throw new Error('Sidechain channel lengths must match.');\n }\n this.eq.setSidechainStereo(left, right);\n }\n\n /** Release any borrowed external sidechain buffers. */\n clearSidechain(): void {\n this.eq.clearSidechain();\n }\n\n /** Auto-gain applied on the most recent block, in dB. */\n lastAutoGainDb(): number {\n return this.eq.lastAutoGainDb();\n }\n\n /** Reported processing latency in samples (non-zero for linear-phase bands). */\n latencySamples(): number {\n return this.eq.latencySamples();\n }\n\n /**\n * Process one mono block, returning the equalized samples (same length).\n */\n processMono(samples: Float32Array): Float32Array {\n return this.eq.processMono(samples);\n }\n\n /**\n * Process one stereo block, returning the equalized channels.\n */\n processStereo(\n left: Float32Array,\n right: Float32Array,\n ): { left: Float32Array; right: Float32Array } {\n if (left.length !== right.length) {\n throw new Error('Stereo channel lengths must match.');\n }\n return this.eq.processStereo(left, right);\n }\n\n /**\n * Read the latest pre/post spectrum snapshot for metering. `seq` increments\n * each time a new snapshot is published.\n */\n spectrum(): EqSpectrumSnapshot {\n return this.eq.spectrum();\n }\n\n /**\n * Configure bands so the source spectrum matches the reference spectrum.\n *\n * @param source - Source audio (mono samples)\n * @param reference - Reference audio (mono samples)\n * @param options - `sampleRate` (default 48000) and `maxBands` (default 8)\n */\n match(source: Float32Array, reference: Float32Array, options: EqMatchOptions = {}): void {\n this.eq.match(source, reference, options as Record<string, unknown>);\n }\n\n /** Release the underlying WASM object. Safe to call only once. */\n delete(): void {\n this.eq.delete();\n }\n}\n\n// ============================================================================\n// StreamingRetune Class\n// ============================================================================\n\n/**\n * Block-by-block mono voice retune / pitch shifter.\n *\n * State is maintained across {@link processMono} calls. Call {@link prepare}\n * before processing, and call {@link delete} (or use `try/finally`) to release\n * the underlying WASM object.\n */\nexport class StreamingRetune {\n private retune: import('./sonare.js').WasmStreamingRetune;\n\n constructor(config: StreamingRetuneConfig = {}) {\n const module = getSonareModule();\n this.retune = module.createStreamingRetune(config as Record<string, unknown>);\n }\n\n /**\n * Allocate and initialize native state for the given sample rate and maximum\n * process block size.\n */\n prepare(sampleRate: number, maxBlockSize: number): void {\n this.retune.prepare(sampleRate, maxBlockSize);\n }\n\n /** Reset delay, grain, and overlap-add state without changing config. */\n reset(): void {\n this.retune.reset();\n }\n\n /**\n * Update retune settings. Changing `grainSize` takes effect after the next\n * {@link prepare} call.\n */\n setConfig(config: StreamingRetuneConfig): void {\n this.retune.setConfig(config as Record<string, unknown>);\n }\n\n /** Current native config. */\n config(): Required<StreamingRetuneConfig> {\n return this.retune.config();\n }\n\n /** Resolved grain size in samples after {@link prepare}. */\n grainSize(): number {\n return this.retune.grainSize();\n }\n\n /** Process one mono block, returning the shifted samples (same length). */\n processMono(samples: Float32Array): Float32Array {\n return this.retune.processMono(samples);\n }\n\n /** Release the underlying WASM object. Safe to call only once. */\n delete(): void {\n this.retune.delete();\n }\n}\n","/**\n * sonare - Audio Analysis Library\n *\n * @example\n * ```typescript\n * import { init, detectBpm, detectKey, analyze } from '@libraz/libsonare';\n *\n * await init();\n *\n * // Detect BPM from audio samples\n * const bpm = detectBpm(samples, sampleRate);\n *\n * // Detect musical key\n * const key = detectKey(samples, sampleRate);\n *\n * // Full analysis\n * const result = analyze(samples, sampleRate);\n * ```\n */\n\nimport { setSonareModule } from './module_state';\nimport type {\n CapabilityCatalog,\n RealtimeVoiceChangerPodConfig,\n SonareCapabilities,\n VoicePresetId,\n} from './public_types';\nimport type {\n SonareModule,\n WasmDecomposeResult,\n WasmHpssWithResidualResult,\n WasmMatrix2dResult,\n} from './sonare.js';\n\nexport type { BrowserAudioDecodeOptions } from './audio';\nexport { Audio } from './audio';\nexport type {\n ClipPageStreamerEngine,\n ClipPageStreamerOptions,\n ClipPageStreamerRequest,\n ClipPageStreamSource,\n OpfsClipStream,\n OpfsClipStreamOptions,\n WorkletOpfsClipStreamHost,\n} from './clip_page_streamer';\nexport { attachOpfsClipStream, ClipPageStreamer } from './clip_page_streamer';\nexport type {\n CompressorDetector,\n CompressorOptions,\n DeclickOptions,\n DeclipOptions,\n DecrackleMode,\n DecrackleOptions,\n DehumOptions,\n DenoiseClassicalMode,\n DenoiseClassicalNoiseEstimator,\n DenoiseClassicalOptions,\n DereverbClassicalOptions,\n DynamicsResult,\n GateOptions,\n MasteringChannelPolicy,\n MasteringDynamicsCompressorRequest,\n MasteringDynamicsGateRequest,\n MasteringDynamicsTransientShaperRequest,\n MasteringInsertParamInfo,\n MasteringPairAnalyzeRequest,\n MasteringPairProcessRequest,\n MasteringProcessorCatalogEntry,\n MasteringProcessRequest,\n MasteringProcessStereoRequest,\n MasteringRealtimeCost,\n MasteringRepairDeclickRequest,\n MasteringRepairDeclipRequest,\n MasteringRepairDecrackleRequest,\n MasteringRepairDehumRequest,\n MasteringRepairDenoiseClassicalRequest,\n MasteringRepairDereverbClassicalRequest,\n MasteringRepairTrimSilenceRequest,\n MasteringSamplesParamsRequest,\n MasteringStereoAnalyzeRequest,\n MasteringStereoParamsRequest,\n MasteringStreamingPreviewRequest,\n MasteringStreamingPreviewStereoRequest,\n MixStereoRequest,\n TransientShaperOptions,\n TrimSilenceMode,\n TrimSilenceOptions,\n VoiceChangeOptions,\n VoiceChangeRealtimeOptions,\n VoiceChangeRealtimeRequest,\n VoiceChangeRequest,\n} from './effects_mastering';\nexport {\n harmonic,\n hpss,\n masterAudio,\n masterAudioStereo,\n masterAudioStereoWithProgress,\n masterAudioWithProgress,\n mastering,\n masteringAssistantSuggest,\n masteringAssistantSuggestStereo,\n masteringAudioProfile,\n masteringAudioProfileStereo,\n masteringChain,\n masteringChainStereo,\n masteringChainStereoWithProgress,\n masteringChainWithProgress,\n masteringDynamicsCompressor,\n masteringDynamicsGate,\n masteringDynamicsTransientShaper,\n masteringInsertNames,\n masteringInsertParamInfo,\n masteringInsertParamNames,\n masteringPairAnalysisNames,\n masteringPairAnalyze,\n masteringPairProcess,\n masteringPairProcessorNames,\n masteringPresetNames,\n masteringProcess,\n masteringProcessorCatalog,\n masteringProcessorNames,\n masteringProcessStereo,\n masteringRepairDeclick,\n masteringRepairDeclip,\n masteringRepairDecrackle,\n masteringRepairDehum,\n masteringRepairDenoiseClassical,\n masteringRepairDereverbClassical,\n masteringRepairTrimSilence,\n masteringStereoAnalysisNames,\n masteringStereoAnalyze,\n masteringStreamingPreview,\n masteringStreamingPreviewStereo,\n mixingScenePresetJson,\n mixingScenePresetNames,\n mixStereo,\n normalize,\n noteMove,\n noteStretch,\n percussive,\n pitchCorrectTimevarying,\n pitchCorrectToMidi,\n pitchCorrectToMidiTimevarying,\n pitchShift,\n spectralEdit,\n timeStretch,\n voiceChange,\n voiceChangeRealtime,\n} from './effects_mastering';\nexport type {\n HarmonicRequest,\n HpssRequest,\n NormalizeMode,\n NormalizeRequest,\n NoteMoveRequest,\n NoteStretchRequest,\n PercussiveRequest,\n PitchCorrectTimevaryingRequest,\n PitchCorrectToMidiRequest,\n PitchCorrectToMidiTimevaryingRequest,\n PitchShiftRequest,\n SpectralEditRequest,\n TimeStretchRequest,\n} from './effects_transform';\nexport { ErrorCode, isSonareError, SonareError } from './errors';\nexport type {\n ChirpRequest,\n ClicksRequest,\n CyclicTempogramRequest,\n DbConversionRequest,\n EmphasisRequest,\n FixFramesRequest,\n FixLengthRequest,\n FrameSignalRequest,\n OnsetBacktrackRequest,\n PadCenterRequest,\n PcenRequest,\n PeakPickRequest,\n PlpRequest,\n SilenceRequest,\n TempogramRequest,\n ToneRequest,\n TonnetzRequest,\n VectorNormalizeRequest,\n} from './feature_core';\nexport type {\n AnalyzeMelodyRequest,\n AnalyzeSectionsRequest,\n CqtRequest,\n CqtToAudioRequest,\n FourierTempogramRequest,\n LufsRequest,\n MelodyOptions,\n NnlsChromaRequest,\n OnsetEnvelopeRequest,\n OnsetStrengthMultiRequest,\n TempogramRatioRequest,\n VqtRequest,\n VqtToAudioRequest,\n} from './feature_music';\nexport type {\n NoteSegmentsRequest,\n PiptrackRequest,\n PitchPyinRequest,\n PitchYinRequest,\n} from './feature_pitch';\nexport type { ResampleRequest } from './feature_resample';\nexport type {\n DecomposeRequest,\n DecomposeWithInitRequest,\n Ebur128LoudnessRangeRequest,\n EstimateTuningRequest,\n HpssWithResidualRequest,\n LufsInterleavedRequest,\n NnFilterRequest,\n PhaseVocoderRequest,\n PitchTuningRequest,\n PolyFeaturesRequest,\n RemixRequest,\n SegmentAgglomerativeRequest,\n SegmentCrossSimilarityRequest,\n SegmentLagToRecurrenceRequest,\n SegmentPathEnhanceRequest,\n SegmentRecurrenceMatrixRequest,\n SegmentRecurrenceToLagRequest,\n SegmentSubsegmentRequest,\n SpectralContrastRequest,\n SpectralFrameRequest,\n SpectralRolloffRequest,\n ZeroCrossingRateRequest,\n ZeroCrossingsRequest,\n} from './feature_spectral';\nexport type {\n ChromaSpectrogramRequest,\n GriffinLimRequest,\n MelDeltaRequest,\n MelSpectrogramRequest,\n MelToAudioRequest,\n MelToStftRequest,\n MfccRequest,\n MfccToAudioRequest,\n MfccToMelRequest,\n ReassignedSpectrogramRequest,\n SpectrogramRequest,\n TrimRequest,\n} from './feature_spectrogram';\nexport {\n amplitudeToDb,\n analyzeMelody,\n analyzeSections,\n bassChroma,\n chirp,\n chroma,\n chromaCens,\n chromaCqt,\n clicks,\n cqt,\n cqtToAudio,\n cyclicTempogram,\n dbToAmplitude,\n dbToPower,\n decompose,\n decomposeWithInit,\n deemphasis,\n ebur128LoudnessRange,\n estimateTuning,\n fixFrames,\n fixLength,\n fourierTempogram,\n frameSignal,\n framesToSamples,\n framesToTime,\n griffinLim,\n hpssWithResidual,\n hybridCqt,\n hzToMel,\n hzToMidi,\n hzToNote,\n lufs,\n lufsInterleaved,\n melDelta,\n melSpectrogram,\n melToAudio,\n melToHz,\n melToStft,\n mfcc,\n mfccToAudio,\n mfccToMel,\n midiToHz,\n momentaryLufs,\n nnFilter,\n nnlsChroma,\n noteSegments,\n noteToHz,\n onsetBacktrack,\n onsetEnvelope,\n onsetStrengthMulti,\n padCenter,\n pcen,\n peakPick,\n phaseVocoder,\n piptrack,\n pitchPyin,\n pitchTuning,\n pitchYin,\n plp,\n polyFeatures,\n powerToDb,\n preemphasis,\n pseudoCqt,\n reassignedSpectrogram,\n remix,\n resample,\n rmsEnergy,\n samplesToFrames,\n segmentAgglomerative,\n segmentCrossSimilarity,\n segmentLagToRecurrence,\n segmentPathEnhance,\n segmentRecurrenceMatrix,\n segmentRecurrenceToLag,\n segmentSubsegment,\n shortTermLufs,\n spectralBandwidth,\n spectralCentroid,\n spectralContrast,\n spectralFlatness,\n spectralFlux,\n spectralRolloff,\n splitSilence,\n stft,\n stftDb,\n tempogram,\n tempogramRatio,\n timeToFrames,\n tone,\n tonnetz,\n trim,\n trimSilence,\n vectorNormalize,\n vqt,\n vqtToAudio,\n zeroCrossingRate,\n zeroCrossings,\n} from './features';\nexport type { BindMicrophoneInputOptions, MicrophoneInputBinding } from './live_audio';\nexport { bindMicrophoneInput } from './live_audio';\nexport type {\n MasterAudioRequest,\n MasterAudioStereoRequest,\n MasteringChainRequest,\n MasteringChainStereoRequest,\n} from './mastering_chain';\nexport type { MasteringRequest } from './mastering_core';\nexport type {\n ClippingRegion,\n ClippingReport,\n DynamicRangeReport,\n MeteringDetectClippingOptions,\n MeteringDetectClippingRequest,\n MeteringDynamicRangeOptions,\n MeteringDynamicRangeRequest,\n MeteringSamplesRequest,\n MeteringSilenceRatioRequest,\n MeteringSpectrumFrameRequest,\n MeteringSpectrumRequest,\n MeteringStereoDecimatedRequest,\n MeteringStereoRequest,\n MeteringTruePeakRequest,\n PhaseScopeReport,\n SpectrumOptions,\n SpectrumReport,\n VectorscopeReport,\n WaveformPeakPyramidOptions,\n WaveformPeakPyramidRequest,\n WaveformPeaksOptions,\n WaveformPeaksReport,\n WaveformPeaksRequest,\n} from './metering';\nexport {\n meteringCrestFactorDb,\n meteringCrestFactorDbStereo,\n meteringDcOffset,\n meteringDetectClipping,\n meteringDynamicRange,\n meteringPeakDb,\n meteringPhaseScope,\n meteringPhaseScopeDecimated,\n meteringRmsDb,\n meteringSilenceRatio,\n meteringSpectrum,\n meteringSpectrumFrame,\n meteringStereoCorrelation,\n meteringStereoWidth,\n meteringTruePeakDb,\n meteringVectorscope,\n meteringVectorscopeDecimated,\n waveformPeakPyramid,\n waveformPeaks,\n} from './metering';\nexport type {\n OpfsClipPageProviderBinding,\n OpfsClipPageProviderOptions,\n} from './opfs_clip_pages';\nexport {\n createOpfsClipPageProvider,\n createOpfsClipPageWorker,\n opfsClipPageWorkerSource,\n} from './opfs_clip_pages';\nexport type {\n BuiltinSynthBinding,\n BuiltinSynthConfig,\n BuiltinSynthWaveform,\n ExternalSeparatedStem,\n ExternalSeparatedStemImportRequest,\n ExternalSeparatedStemImportResult,\n MidiCcLearnOptions,\n ProjectAssistSidecar,\n ProjectAssistSidecarInput,\n ProjectAutomationCurve,\n ProjectAutomationLaneDesc,\n ProjectAutomationPoint,\n ProjectAutomationTargetKind,\n ProjectBounceOptions,\n ProjectChordSymbol,\n ProjectClip,\n ProjectClipCompSegment,\n ProjectClipDesc,\n ProjectClipFade,\n ProjectClipTake,\n ProjectCompileResult,\n ProjectFadeCurve,\n ProjectKeySegment,\n ProjectLoopMode,\n ProjectLoopRecordingDesc,\n ProjectLoopRecordingResult,\n ProjectMarker,\n ProjectMidiClipResult,\n ProjectMidiEvent,\n ProjectMidiFxBakeRequest,\n ProjectMidiFxBakeResult,\n ProjectMidiFxPreviewRequest,\n ProjectNotePairValidation,\n ProjectSource,\n ProjectTrack,\n ProjectTrackDesc,\n ProjectTrackKind,\n ProjectWarpAnchor,\n ProjectWarpMapDesc,\n Sf2InstrumentConfig,\n Sf2ProgramStatus,\n SourceBackend,\n SynthBodyType,\n SynthEngineMode,\n SynthEnumTables,\n SynthFilterModel,\n SynthFilterOutput,\n SynthModDestination,\n SynthModRouting,\n SynthModSource,\n SynthOscWaveform,\n SynthPatch,\n} from './project';\nexport {\n AutomationTargetKind,\n BUILTIN_SYNTH_WAVEFORMS,\n EXPECTED_PROJECT_ABI_VERSION,\n MarkerKind,\n PROJECT_AUTOMATION_TARGET_OPAQUE,\n PROJECT_AUTOMATION_TARGET_TRACK_FADER_DB,\n PROJECT_AUTOMATION_TARGET_TRACK_PAN,\n Project,\n projectAbiVersion,\n SYNTH_BODY_TYPES,\n SYNTH_ENGINE_MODES,\n SYNTH_FILTER_MODELS,\n SYNTH_FILTER_OUTPUTS,\n SYNTH_MOD_DESTINATIONS,\n SYNTH_MOD_SOURCES,\n SYNTH_OSC_WAVEFORMS,\n synthEnumTables,\n synthPresetNames,\n synthPresetPatch,\n} from './project';\nexport type {\n AcousticOptions,\n AcousticResult,\n AnalysisResult,\n AnalyzeBpmOptions,\n AnalyzeDynamicsOptions,\n AnalyzeRhythmOptions,\n AnalyzeSectionsOptions,\n AnalyzeTimbreOptions,\n AutomationCurve,\n Beat,\n BpmHypothesis,\n Chord,\n ChordAnalysisResult,\n ChordDetectionOptions,\n ChromaResult,\n CqtResult,\n Dynamics,\n EqBand,\n EqBandPhase,\n EqBandType,\n EqCoeffMode,\n EqMatchOptions,\n EqSpectrumSnapshot,\n EqStereoPlacement,\n GoniometerPoint,\n HpssResult,\n Key,\n KeyCandidate,\n KeyDetectionOptions,\n KeyProfileName,\n LufsResult,\n MasteringChainConfig,\n MasteringChainResult,\n MasteringChainStereoResult,\n MasteringLoudnessSummary,\n MasteringOptions,\n MasteringPreset,\n MasteringProcessorParams,\n MasteringReport,\n MasteringResult,\n MasteringStereoChainResult,\n MasteringStereoResult,\n MelodyPoint,\n MelodyResult,\n MelPowerResult,\n MelSpectrogramResult,\n MeterTap,\n MfccResult,\n MixerProcessResult,\n MixMeterSnapshot,\n MixOptions,\n MixResult,\n NoteSegment,\n NoteStretchOptions,\n PairAnalysis,\n PairProcessor,\n PanLaw,\n PanLawInput,\n PanLawName,\n PanMode,\n PitchCorrectOptions,\n PitchResult,\n RealtimeVoiceChangerConfigInput,\n RealtimeVoiceChangerPodConfig,\n RhythmFeatures,\n RirResult,\n RirSynthOptions,\n RoomEstimateOptions,\n RoomEstimateResult,\n RoomGeometryOptions,\n RoomMorphOptions,\n Section,\n SegmentMatrix,\n SendTiming,\n SoloProcessor,\n SonareCapabilities,\n SpectralEditMode,\n SpectralEditOptions,\n SpectralEditWindow,\n SpectralRegionOp,\n StageGainReduction,\n StereoAnalysis,\n StftPowerResult,\n StftResult,\n StreamingEqualizerConfig,\n StreamingMasteringChainConfig,\n StreamingPlatform,\n StreamingRetuneConfig,\n TempogramMode,\n Timbre,\n TimeSignature,\n VoicedFlags,\n VoicePresetId,\n} from './public_types';\nexport {\n ChordQuality,\n KeyProfile,\n Mode,\n PitchClass,\n SectionType,\n} from './public_types';\nexport type {\n AnalyzeBpmRequest,\n AnalyzeDynamicsRequest,\n AnalyzeImpulseResponseRequest,\n AnalyzeRhythmRequest,\n AnalyzeTimbreRequest,\n AnalyzeWithProgressRequest,\n BpmAnalysisResult,\n BpmCandidate,\n ChordFunctionalAnalysisRequest,\n DetectAcousticRequest,\n DetectChordsRequest,\n DetectKeyRequest,\n DetectOnsetsRequest,\n DynamicsAnalysisResult,\n EstimateRoomRequest,\n MusicAnalyzeRequest,\n RhythmAnalysisResult,\n RoomMorphRequest,\n SamplesRequest,\n TimbreAnalysisResult,\n TimbreFrame,\n} from './quick_analysis';\nexport {\n analyze,\n analyzeBpm,\n analyzeDynamics,\n analyzeImpulseResponse,\n analyzeRhythm,\n analyzeTimbre,\n analyzeWithProgress,\n chordFunctionalAnalysis,\n detectAcoustic,\n detectBeats,\n detectBpm,\n detectChords,\n detectDownbeats,\n detectKey,\n detectKeyCandidates,\n detectOnsets,\n estimateRoom,\n hasFfmpegSupport,\n roomMorph,\n synthesizeRir,\n} from './quick_analysis';\nexport type {\n ClipPageRequest,\n EngineAutomationPoint,\n EngineBounceOptions,\n EngineBounceResult,\n EngineBus,\n EngineCapabilities,\n EngineCaptureSource,\n EngineCaptureStatus,\n EngineClip,\n EngineFreezeOptions,\n EngineFreezeResult,\n EngineGraphSpec,\n EngineMarker,\n EngineMeterTelemetry,\n EngineMeterTelemetryWide,\n EngineMetronomeConfig,\n EngineMidiClipSchedule,\n EngineMidiEvent,\n EngineParameterInfo,\n EngineScopeTelemetry,\n EngineTelemetry,\n EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTrackLane,\n EngineTrackMonitorMode,\n EngineTrackSend,\n EngineTransportState,\n ExternalMidiEvent,\n MidiCcBindOptions,\n TrackMonitorMode,\n} from './realtime_engine';\nexport {\n ClipPageProvider,\n EXPECTED_ENGINE_ABI_VERSION,\n engineCapabilities,\n RealtimeEngine,\n} from './realtime_engine';\nexport { scaleCorrectionSemitones, scalePitchClassEnabled, scaleQuantizeMidi } from './scale';\nexport type { ProgressCallback } from './sonare.js';\nexport { StreamAnalyzer, streamAnalyzerConfigDefaults } from './stream_analyzer';\nexport type {\n AnalyzerStats,\n BarChord,\n ChordChange,\n FrameBuffer,\n PatternScore,\n ProgressiveEstimate,\n StreamConfig,\n StreamConfigDefaults,\n StreamFramesI16,\n StreamFramesU8,\n StreamQuantizeConfig,\n} from './stream_types';\nexport type {\n MixerRealtimeBuffer,\n RealtimeVoiceChangerInterleavedBuffer,\n RealtimeVoiceChangerMonoBuffer,\n RealtimeVoiceChangerPlanarBuffer,\n} from './streaming_mixing';\nexport {\n Mixer,\n RealtimeVoiceChanger,\n realtimeVoiceChangerPresetJson,\n realtimeVoiceChangerPresetNames,\n StreamingEqualizer,\n StreamingMasteringChain,\n StreamingRetune,\n validateRealtimeVoiceChangerPresetJson,\n} from './streaming_mixing';\nexport type { ValidateOptions } from './validation';\nexport type {\n BindWebMidiOptions,\n WebMidiBinding,\n WebMidiCcBinding,\n WebMidiInputInfo,\n} from './web_midi';\nexport { bindWebMidi, isWebMidiAvailable } from './web_midi';\nexport type {\n OfflineWorker,\n OfflineWorkerCallOptions,\n OfflineWorkerClientOptions,\n OfflineWorkerProgress,\n} from './worker_client';\nexport { OfflineWorkerClient, OfflineWorkerTask } from './worker_client';\n\n/** Row-major 2-D matrix as a flat buffer plus its dimensions. */\nexport type Matrix2dResult = WasmMatrix2dResult;\n/** NMF factor matrices { w, h } from {@link decompose}. */\nexport type DecomposeResult = WasmDecomposeResult;\n/** Harmonic / percussive / residual signals from {@link hpssWithResidual}. */\nexport type HpssWithResidualResult = WasmHpssWithResidualResult;\n\n// ============================================================================\n// Module State\n// ============================================================================\n\nlet module: SonareModule | null = null;\nlet initPromise: Promise<void> | null = null;\n\n// ============================================================================\n// Initialization\n// ============================================================================\n\n/**\n * Initialize the WASM module.\n * Must be called before using any analysis functions.\n *\n * @param options - Optional module configuration\n * @returns Promise that resolves when initialization is complete\n */\nexport async function init(options?: {\n locateFile?: (path: string, prefix: string) => string;\n wasmBinary?: ArrayBuffer | Uint8Array;\n moduleFactory?: (options?: {\n locateFile?: (path: string, prefix: string) => string;\n wasmBinary?: ArrayBuffer | Uint8Array;\n }) => Promise<SonareModule>;\n}): Promise<void> {\n if (module) {\n return;\n }\n\n if (initPromise) {\n return initPromise;\n }\n\n initPromise = (async () => {\n try {\n const createModule = options?.moduleFactory ?? (await import('./sonare.js')).default;\n module = await createModule(options);\n setSonareModule(module);\n } catch (error) {\n initPromise = null;\n throw error;\n }\n })();\n\n return initPromise;\n}\n\n/**\n * Check if the module is initialized.\n */\nexport function isInitialized(): boolean {\n return module !== null;\n}\n\n/**\n * Get the library version.\n */\nexport function version(): string {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.version();\n}\n\n/**\n * Return the capabilities of the loaded WASM build.\n *\n * This is synchronous and only describes the already-initialized module.\n */\nexport function capabilities(): SonareCapabilities {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.capabilities();\n}\n\n/** Return the initialized module's processors, parameters, and presets. */\nexport function capabilityCatalog(): CapabilityCatalog {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return JSON.parse(module.capabilityCatalog()) as CapabilityCatalog;\n}\n\n/**\n * Aggregate native ABI version: the per-subsystem ABI macros folded into one\n * 32-bit value. It bumps whenever any flat C POD layout changes, so callers can\n * detect an incompatible prebuilt binary. Matches the Node/Python `abiVersion()`.\n */\nexport function abiVersion(): number {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.abiVersion();\n}\n\nexport function engineAbiVersion(): number {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.engineAbiVersion();\n}\n\nexport function voiceChangerAbiVersion(): number {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.voiceChangerAbiVersion();\n}\n\n// Canonical ordinal order of the built-in voice-character presets, matching the\n// C ABI SonareVoiceCharacterPreset enum and SONARE_REALTIME_VOICE_CHANGER_PRESET_IDS.\nconst VOICE_PRESET_ORDINALS: readonly VoicePresetId[] = [\n 'neutral-monitor',\n 'bright-idol',\n 'soft-whisper',\n 'deep-narrator',\n 'robot-mascot',\n 'dark-villain',\n];\n\nfunction resolveVoicePresetOrdinal(preset: VoicePresetId | number): number {\n if (typeof preset === 'number') {\n if (!Number.isSafeInteger(preset) || preset < 0 || preset >= VOICE_PRESET_ORDINALS.length) {\n throw new RangeError(`Unknown voice-character preset ordinal: ${String(preset)}`);\n }\n return preset;\n }\n const ordinal = VOICE_PRESET_ORDINALS.indexOf(preset);\n if (ordinal < 0) {\n throw new Error(`Unknown voice character preset: ${preset}`);\n }\n return ordinal;\n}\n\n/**\n * Map a voice-character preset ordinal (or canonical id) to its canonical id\n * string (e.g. `'bright-idol'`). Unknown numeric ordinals return `null`;\n * unknown preset ids throw.\n */\nexport function voiceCharacterPresetId(preset: VoicePresetId | number): VoicePresetId | null {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n if (\n typeof preset === 'number' &&\n (!Number.isSafeInteger(preset) || preset < 0 || preset >= VOICE_PRESET_ORDINALS.length)\n ) {\n return null;\n }\n return module.voiceCharacterPresetId(resolveVoicePresetOrdinal(preset)) as VoicePresetId;\n}\n\n/**\n * Return the canonical (normalized) flat POD config for a built-in voice\n * preset, skipping the JSON round-trip. Accepts a canonical preset id or its\n * integer ordinal. Invalid ordinals throw.\n */\nexport function realtimeVoiceChangerPresetConfig(\n preset: VoicePresetId | number,\n): RealtimeVoiceChangerPodConfig {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.realtimeVoiceChangerPresetConfig(resolveVoicePresetOrdinal(preset));\n}\n\n// ============================================================================\n// Re-exports\n// ============================================================================\n\nexport { PitchClass as Pitch } from './public_types';\n","import type {\n EngineParameterInfo,\n EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTrackLane,\n EngineTrackSend,\n} from '../index';\nimport type { SonareEngineSyncTempoMessage } from './messages';\n\n/**\n * Builds the ordered mixer-lane descriptors for a sync message.\n *\n * Each declared track id is paired with its current send list and output bus\n * (both omitted when absent), defensively copying the send entries.\n *\n * @param trackLaneIds Lane order (track ids) declared on the engine.\n * @param trackSends Per-track send lists.\n * @param trackOutputBus Per-track output bus routing.\n * @returns Lane descriptors in lane order.\n */\nexport function buildMixerLanes(\n trackLaneIds: readonly number[],\n trackSends: ReadonlyMap<number, EngineTrackSend[]>,\n trackOutputBus: ReadonlyMap<number, number>,\n): EngineTrackLane[] {\n return trackLaneIds.map((trackId) => {\n const sends = trackSends.get(trackId);\n const outputBusId = trackOutputBus.get(trackId);\n return {\n trackId,\n ...(sends && sends.length > 0 ? { sends: sends.map((send) => ({ ...send })) } : {}),\n ...(outputBusId !== undefined ? { outputBusId } : {}),\n };\n });\n}\n\n/**\n * Builds the out-of-band tempo/time-signature sync message, deep-copying the\n * tempo and time-signature segments so the consumer cannot alias engine state.\n */\nexport function buildTempoSync(\n tempoBpm: number,\n timeSignature: { numerator: number; denominator: number },\n tempoSegments: readonly EngineTempoSegment[],\n timeSignatureSegments: readonly EngineTimeSignatureSegment[],\n): SonareEngineSyncTempoMessage {\n return {\n type: 'syncTempo',\n bpm: tempoBpm,\n timeSignature: { ...timeSignature },\n tempoSegments: tempoSegments.map((segment) => ({ ...segment })),\n timeSignatureSegments: timeSignatureSegments.map((segment) => ({ ...segment })),\n };\n}\n\n/**\n * Resolves a target id from a string or number; non-numeric strings resolve to\n * 0, mirroring the engine's integer-id namespace.\n */\nexport function resolveTargetId(target: string | number): number {\n if (typeof target === 'number') {\n return target;\n }\n const parsed = Number.parseInt(target, 10);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\n/** Resolves a registered parameter name or passes through a numeric id. */\nexport function resolveParamId(\n parameters: readonly EngineParameterInfo[],\n nodeId: string,\n param: string | number,\n): number {\n if (typeof param === 'number') {\n return param;\n }\n const byName = parameters.find((info) => info.name === param);\n if (byName) {\n return byName.id;\n }\n throw new RangeError(`Unknown engine parameter ${JSON.stringify(param)} for node ${nodeId}`);\n}\n\n/** Encodes an automation curve descriptor to the engine's numeric curve code. */\nexport function curveCode(curve: number | 'linear' | 'exponential'): number {\n if (typeof curve === 'number') {\n return curve;\n }\n return curve === 'exponential' ? 1 : 0;\n}\n","import type { EngineAutomationPoint, RealtimeEngine } from '../index';\nimport { curveCode } from './engine-sync';\nimport type { SonareEngineSyncMessage } from './messages';\n\n/**\n * Collaborator surface the automation-lane helpers need from the owning\n * {@link SonareEngine}: the lane store they mutate, the offline engine they\n * mirror into, the sync poster, and the parameter-id resolver.\n */\nexport interface EngineAutomationContext {\n readonly offlineEngine: RealtimeEngine;\n readonly automationLanes: Map<number, EngineAutomationPoint[]>;\n postSync(message: SonareEngineSyncMessage): void;\n resolveParamId(nodeId: string, param: string | number): number;\n}\n\nexport function scheduleParam(\n ctx: EngineAutomationContext,\n nodeId: string,\n param: string | number,\n ppq: number,\n value: number,\n curve: number | 'linear' | 'exponential' = 'linear',\n): void {\n const paramId = ctx.resolveParamId(nodeId, param);\n const lane = ctx.automationLanes.get(paramId) ?? [];\n lane.push({ ppq, value, curveToNext: curveCode(curve) });\n lane.sort((a, b) => a.ppq - b.ppq);\n ctx.automationLanes.set(paramId, lane);\n ctx.offlineEngine.setAutomationLane(paramId, lane);\n // Mirror the lane to the live worklet engine so scheduled automation plays\n // back in real time, not just in renderOffline(). Lanes can exceed the\n // fixed-size SAB command record, so they ride an out-of-band 'syncAutomation'\n // message whose port handler publishes the bounded snapshot consumed by\n // process() (like syncClips/syncMarkers).\n ctx.postSync({ type: 'syncAutomation', paramId, points: lane });\n}\n\nexport function addAutomationPoint(\n ctx: EngineAutomationContext,\n laneId: string | number,\n ppq: number,\n value: number,\n curve: number | 'linear' | 'exponential' = 'linear',\n): void {\n scheduleParam(ctx, '', laneId, ppq, value, curve);\n}\n\n/**\n * Replaces the automation lane for `paramId` with the given breakpoints.\n *\n * Unlike scheduleParam (which appends a single point), this sets the whole\n * lane at once; an empty array clears the lane. The points are defensively\n * copied and sorted by ppq before being mirrored to the offline engine and\n * the live worklet engine.\n *\n * @param paramId Automation target id (registered parameter or a reserved\n * engine mixer target from automationParamId/busAutomationParamId).\n * @param points Lane breakpoints; order does not matter.\n */\nexport function setAutomationLane(\n ctx: EngineAutomationContext,\n paramId: number,\n points: ReadonlyArray<EngineAutomationPoint>,\n): void {\n const sorted = points.map((point) => ({ ...point })).sort((a, b) => a.ppq - b.ppq);\n if (sorted.length === 0) {\n ctx.automationLanes.delete(paramId);\n } else {\n ctx.automationLanes.set(paramId, sorted);\n }\n ctx.offlineEngine.setAutomationLane(paramId, sorted);\n ctx.postSync({ type: 'syncAutomation', paramId, points: sorted });\n}\n","import type { EngineCaptureStatus, EngineMarker, EngineTrackLane, RealtimeEngine } from '../index';\nimport type { SonareEngineSyncCaptureMessage, SonareEngineTransportFacade } from './messages';\n\n/** Capture configuration options accepted by the engine's `configureCapture`. */\nexport interface CaptureOptions {\n bufferFrames: number;\n channels?: number;\n source?: EngineCaptureStatus['source'];\n recordOffsetSamples?: number;\n inputMonitor?: { enabled: boolean; gain?: number };\n}\n\n/**\n * Normalizes capture options into the resolved config carried by the\n * `syncCapture` message, applying integer truncation and defaults.\n *\n * @param options Raw capture options.\n * @param defaultChannels Channel count to use when `options.channels` is unset.\n */\nexport function buildCaptureConfig(\n options: CaptureOptions,\n defaultChannels: number,\n): Omit<SonareEngineSyncCaptureMessage, 'type'> {\n return {\n bufferFrames: Math.trunc(options.bufferFrames),\n channels: Math.trunc(options.channels ?? defaultChannels),\n source: options.source ?? 'output',\n recordOffsetSamples: Math.trunc(options.recordOffsetSamples ?? 0),\n inputMonitor: {\n enabled: Boolean(options.inputMonitor?.enabled),\n gain: options.inputMonitor?.gain ?? 1,\n },\n };\n}\n\n/**\n * Collaborator surface the transport facade needs from the owning engine: the\n * realtime node (sample-accurate command transport), the offline engine it\n * mirrors, and the tempo/loop setters plus playing-state bookkeeping.\n */\nexport interface EngineTransportContext {\n readonly sampleRate: number;\n realtimeNode: {\n play(sampleTime?: number): boolean;\n stop(sampleTime?: number): boolean;\n seekPpq(ppq: number, sampleTime?: number): boolean;\n seekSample(timelineSample: number, sampleTime?: number): boolean;\n };\n offlineEngine: RealtimeEngine;\n flushOfflineMirror(): void;\n setTransportPlaying(playing: boolean): void;\n flushPendingInstrumentSync(): void;\n setTempo(bpm: number): void;\n setTempoSegments(segments: readonly { startPpq: number; bpm: number }[]): void;\n setLoop(startPpq: number, endPpq: number, enabled?: boolean): boolean;\n}\n\n/** Builds the public transport facade that fans control to both engines. */\nexport function buildTransportFacade(ctx: EngineTransportContext): SonareEngineTransportFacade {\n return {\n play: (sampleTime = -1) => {\n const ok = ctx.realtimeNode.play(sampleTime);\n if (ok) {\n ctx.setTransportPlaying(true);\n }\n return ok;\n },\n stop: (sampleTime = -1) => {\n const ok = ctx.realtimeNode.stop(sampleTime);\n if (ok) {\n ctx.setTransportPlaying(false);\n ctx.flushPendingInstrumentSync();\n }\n return ok;\n },\n seekPpq: (ppq, sampleTime = -1) => {\n ctx.offlineEngine.seekPpq(ppq, sampleTime);\n const ok = ctx.realtimeNode.seekPpq(ppq, sampleTime);\n ctx.flushOfflineMirror();\n return ok;\n },\n seekSeconds: (seconds, sampleTime = -1) => {\n const timelineSample = Math.max(0, Math.round(seconds * ctx.sampleRate));\n ctx.offlineEngine.seekSample(timelineSample, sampleTime);\n const ok = ctx.realtimeNode.seekSample(timelineSample, sampleTime);\n ctx.flushOfflineMirror();\n return ok;\n },\n setTempo: (bpm) => ctx.setTempo(bpm),\n setTempoSegments: (segments) => ctx.setTempoSegments(segments),\n setLoop: (startPpq, endPpq, enabled = true) => ctx.setLoop(startPpq, endPpq, enabled),\n };\n}\n\n/**\n * Validates and normalizes an append-only mixer-lane declaration.\n *\n * Lane indices are append-only: the new list must start with the already\n * declared lane ids in their current order and may only append new track ids.\n * Returns the normalized lane entries (numbers coerced to descriptors) and the\n * resulting ordered id list.\n *\n * @throws if any track id is invalid, ids are duplicated, or the existing lane\n * order is not preserved.\n */\nexport function normalizeTrackLanes(\n existing: readonly number[],\n lanes: ReadonlyArray<number | EngineTrackLane>,\n): { entries: EngineTrackLane[]; ids: number[] } {\n const entries = lanes.map((lane) => (typeof lane === 'number' ? { trackId: lane } : lane));\n const ids: number[] = [];\n for (const entry of entries) {\n if (!Number.isInteger(entry.trackId) || entry.trackId <= 0) {\n throw new Error(`Invalid track id for mixer lane: ${String(entry.trackId)}`);\n }\n ids.push(entry.trackId);\n }\n if (new Set(ids).size !== ids.length) {\n throw new Error('Duplicate track id in mixer lane list');\n }\n for (let index = 0; index < existing.length; index++) {\n if (ids[index] !== existing[index]) {\n throw new Error(\n 'Mixer lanes are append-only: keep existing lanes in order and only append new track ids',\n );\n }\n }\n return { entries, ids };\n}\n\n/**\n * Resolves a marker set, assigning fresh ids to entries without one and\n * validating explicit ids (positive, unique).\n *\n * @param markers The marker list to resolve.\n * @param nextMarkerId The id counter to draw fresh ids from.\n * @returns The resolved markers and the advanced id counter.\n * @throws on a non-finite ppq, an invalid id, or a duplicate id.\n */\nexport function resolveMarkerSet(\n markers: ReadonlyArray<{ ppq: number; name?: string; id?: number }>,\n nextMarkerId: number,\n): { resolved: EngineMarker[]; nextMarkerId: number } {\n const resolved: EngineMarker[] = [];\n const seen = new Set<number>();\n let counter = nextMarkerId;\n for (const marker of markers) {\n if (!Number.isFinite(marker.ppq)) {\n throw new Error(`Invalid marker ppq: ${String(marker.ppq)}`);\n }\n if (marker.id !== undefined) {\n if (!Number.isInteger(marker.id) || marker.id <= 0) {\n throw new Error(`Invalid marker id: ${String(marker.id)}`);\n }\n if (seen.has(marker.id)) {\n throw new Error(`Duplicate marker id: ${marker.id}`);\n }\n }\n const id = marker.id ?? counter++;\n seen.add(id);\n if (id >= counter) {\n counter = id + 1;\n }\n resolved.push({ id, ppq: marker.ppq, name: marker.name ?? '' });\n }\n return { resolved, nextMarkerId: counter };\n}\n","import type { EngineMeterTelemetry, EngineTelemetry } from '../index';\n\nconst ENGINE_MIXER_TARGET_BASE = 0x4d580000;\nexport const ENGINE_MIXER_PARAM_FADER_DB = 1;\nexport const ENGINE_MIXER_PARAM_PAN = 2;\n\nexport function engineMixerLaneTarget(laneIndex: number, paramKind: number): number {\n return ENGINE_MIXER_TARGET_BASE | ((laneIndex & 0xff) << 8) | (paramKind & 0xff);\n}\n\nexport function engineMixerBusTarget(busIndex: number, paramKind: number): number {\n return ENGINE_MIXER_TARGET_BASE | (((0xfe - busIndex) & 0xff) << 8) | (paramKind & 0xff);\n}\n\nexport function engineMixerMasterTarget(paramKind: number): number {\n return ENGINE_MIXER_TARGET_BASE | (0xff << 8) | (paramKind & 0xff);\n}\n\nexport interface SonareWorkletMeterSnapshot {\n type: 'meter';\n targetId: number;\n frame: number;\n peakDbL: number;\n peakDbR: number;\n rmsDbL: number;\n rmsDbR: number;\n correlation: number;\n truePeakDbL: number;\n truePeakDbR: number;\n momentaryLufs: number;\n shortTermLufs: number;\n integratedLufs: number;\n gainReductionDb: number;\n}\n\nexport interface SonareWorkletSpectrumSnapshot {\n type: 'spectrum';\n frame: number;\n bands: Float32Array;\n}\n\nexport const SONARE_METER_RING_HEADER_INTS = 4;\n// Record layout: [frameLo, frameHi, targetId, peakDbL, peakDbR, rmsDbL, rmsDbR,\n// correlation, truePeakDbL, truePeakDbR, momentaryLufs, shortTermLufs,\n// integratedLufs, gainReductionDb].\n// The sample-frame index is monotonically increasing and quickly exceeds the\n// 2^24 exact-integer range of a single Float32 slot (~349 s at 48 kHz), so it is\n// stored split across two Float32 lanes (low 24 bits + high bits) for exact\n// reconstruction. See encodeFrameLo/encodeFrameHi/decodeFrame.\nexport const SONARE_METER_RING_RECORD_FLOATS = 14;\nexport const SONARE_SPECTRUM_RING_HEADER_INTS = 5;\n// Scope ring header: [writeIndex, capacity, recordFloats, bands, maxPoints,\n// reserved]. Record layout: [frameLo, frameHi, targetId, bandCount, pointCount,\n// band0..band(bands-1), l0, r0, l1, r1, ... (maxPoints stereo pairs)].\nexport const SONARE_SCOPE_RING_HEADER_INTS = 6;\nexport const SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS = 5;\n\n/** Base for splitting a frame index into two exactly-representable Float32 lanes. */\nconst SONARE_FRAME_LANE_BASE = 0x1000000; // 2^24\n\n/** Low 24 bits of a frame index (exact in Float32). */\nexport function encodeFrameLo(frame: number): number {\n const f = Math.max(0, Math.floor(frame));\n return f % SONARE_FRAME_LANE_BASE;\n}\n\n/** High bits of a frame index above 2^24 (exact in Float32 up to ~2^48). */\nexport function encodeFrameHi(frame: number): number {\n const f = Math.max(0, Math.floor(frame));\n return Math.floor(f / SONARE_FRAME_LANE_BASE);\n}\n\n/** Reconstruct a frame index from its low/high Float32 lanes. */\nexport function decodeFrame(lo: number, hi: number): number {\n return hi * SONARE_FRAME_LANE_BASE + lo;\n}\nexport const SONARE_ENGINE_RING_HEADER_INTS = 5;\nexport const SONARE_ENGINE_COMMAND_RECORD_BYTES = 32;\nexport const SONARE_ENGINE_TELEMETRY_RECORD_BYTES = 48;\n// Clip-page request ring header: [writeIndex, readIndex, capacity,\n// recordUint32s, dropped]. Records are [clipId, pageIndex]. This is an SPSC\n// queue: the AudioWorklet is the sole writer and the main thread is the sole\n// reader. Unlike the telemetry rings, it must not overwrite unread requests:\n// the producer increments `dropped` when the fixed queue is full.\nexport const SONARE_CLIP_PAGE_REQUEST_RING_HEADER_INTS = 5;\nexport const SONARE_CLIP_PAGE_REQUEST_RING_RECORD_UINT32S = 2;\n// External MIDI records: destination ID, render-frame offset, packed MIDI-1\n// bytes (little-endian), and byte count. SPSC worklet -> main-thread ring.\nexport const SONARE_EXTERNAL_MIDI_RING_HEADER_INTS = 5;\nexport const SONARE_EXTERNAL_MIDI_RING_RECORD_UINT32S = 4;\n\nexport enum SonareEngineCommandType {\n SetParam = 0,\n SetParamSmoothed = 1,\n TransportPlay = 2,\n TransportStop = 3,\n TransportSeekSample = 4,\n TransportSeekPpq = 5,\n SetTempoMap = 6,\n SetLoop = 7,\n SwapGraph = 8,\n SwapAutomation = 9,\n SetSoloMute = 10,\n AddClip = 11,\n RemoveClip = 12,\n ArmRecord = 13,\n Punch = 14,\n SetMetronome = 15,\n SetMarker = 16,\n SeekMarker = 17,\n // Queueable lane monitor-mode transition. The worklet command vocabulary\n // deliberately leaves 18..25 unused; this is the stable ABI-v3 ordinal.\n SetTrackMonitorMode = 26,\n}\n\nexport enum SonareEngineTelemetryType {\n ProcessBlock = 0,\n Error = 1,\n}\n\nexport enum SonareEngineTelemetryError {\n None = 0,\n CommandQueueOverflow = 1,\n PendingCommandOverflow = 2,\n BoundaryOverflow = 3,\n TelemetryOverflow = 4,\n CaptureOverflow = 5,\n MaxBlockExceeded = 6,\n UnknownTarget = 7,\n NonRealtimeSafeParameter = 8,\n NotPrepared = 9,\n NonQueueableCommand = 10,\n AutomationBindTargetOverflow = 11,\n StaleAutomationLanes = 12,\n SmoothedParameterCapacity = 13,\n CommandBacklogDeferred = 14,\n ClipPageUnderrun = 15,\n InsertAutomationOverflow = 16,\n MidiClockOverflow = 17,\n MetronomeOverflow = 18,\n InvalidCommand = 19,\n MaxChannelsExceeded = 20,\n}\n\nexport interface SonareMeterRingBuffer {\n sharedBuffer: SharedArrayBuffer;\n header: Int32Array;\n records: Float32Array;\n capacity: number;\n}\n\nexport interface SonareMeterRingReadResult {\n nextReadIndex: number;\n meters: SonareWorkletMeterSnapshot[];\n}\n\nexport interface SonareSpectrumRingBuffer {\n sharedBuffer: SharedArrayBuffer;\n header: Int32Array;\n records: Float32Array;\n capacity: number;\n bands: number;\n}\n\nexport interface SonareSpectrumRingReadResult {\n nextReadIndex: number;\n spectra: SonareWorkletSpectrumSnapshot[];\n}\n\n/**\n * A single target-addressed scope record drained from the realtime engine's\n * scope ring: an FFT magnitude spectrum plus a decimated goniometer/vectorscope\n * point cloud. Unlike {@link SonareWorkletSpectrumSnapshot} (the legacy\n * coarse-DFT meter spectrum), this carries a `targetId` (master/lane/bus) and a\n * stereo point cloud, mirroring the engine's `ScopeTelemetryRecord`.\n */\nexport interface SonareWorkletScopeSnapshot {\n type: 'scope';\n targetId: number;\n frame: number;\n /** Linear-band magnitudes in dB (length = the configured band count). */\n bands: Float32Array;\n /** Interleaved stereo goniometer points: [l0, r0, l1, r1, ...]. */\n points: Float32Array;\n}\n\nexport interface SonareScopeRingBuffer {\n sharedBuffer: SharedArrayBuffer;\n header: Int32Array;\n records: Float32Array;\n capacity: number;\n bands: number;\n maxPoints: number;\n}\n\nexport interface SonareScopeRingReadResult {\n nextReadIndex: number;\n scopes: SonareWorkletScopeSnapshot[];\n}\n\nexport interface SonareExternalMidiRingEvent {\n destinationId: number;\n renderFrame: number;\n byteWord: number;\n byteCount: number;\n}\n\nexport interface SonareExternalMidiRingBuffer {\n sharedBuffer: SharedArrayBuffer;\n header: Int32Array;\n records: Uint32Array;\n capacity: number;\n}\n\nexport interface SharedExternalMidiRingWriter {\n header: Int32Array;\n records: Uint32Array;\n capacity: number;\n}\n\nexport interface SonareExternalMidiRingReadResult {\n events: SonareExternalMidiRingEvent[];\n dropped: number;\n}\n\nexport interface SharedScopeRingWriter {\n header: Int32Array;\n records: Float32Array;\n capacity: number;\n bands: number;\n maxPoints: number;\n recordFloats: number;\n}\n\nexport interface SonareEngineCommandRecord {\n type: SonareEngineCommandType | number;\n targetId?: number;\n sampleTime?: number | bigint;\n argFloat?: number;\n argInt?: number | bigint;\n}\n\nexport interface SonareEngineTelemetryRecord {\n type: SonareEngineTelemetryType | number;\n error: SonareEngineTelemetryError | number;\n renderFrame: number;\n timelineSample: number;\n audibleTimelineSample: number;\n graphLatencySamplesQ8: number;\n value: number;\n}\n\nexport interface SonareEngineCommandRingBuffer {\n sharedBuffer: SharedArrayBuffer;\n header: Int32Array;\n view: DataView;\n capacity: number;\n}\n\nexport interface SonareEngineTelemetryRingBuffer {\n sharedBuffer: SharedArrayBuffer;\n header: Int32Array;\n view: DataView;\n capacity: number;\n}\n\nexport interface SonareEngineTelemetryRingReadResult {\n nextReadIndex: number;\n telemetry: SonareEngineTelemetryRecord[];\n}\n\nexport interface SonareClipPageRequest {\n clipId: number;\n pageIndex: number;\n}\n\nexport interface SonareClipPageRequestRingBuffer {\n sharedBuffer: SharedArrayBuffer;\n header: Int32Array;\n records: Uint32Array;\n capacity: number;\n}\n\nexport interface SharedClipPageRequestRingWriter {\n header: Int32Array;\n records: Uint32Array;\n capacity: number;\n}\n\nexport interface SonareClipPageRequestRingReadResult {\n requests: SonareClipPageRequest[];\n /** Cumulative uint32 drop count for native and SAB-ring overflows. */\n dropped: number;\n}\n\nexport interface SharedMeterRingWriter {\n header: Int32Array;\n records: Float32Array;\n capacity: number;\n}\n\nexport interface SharedSpectrumRingWriter {\n header: Int32Array;\n records: Float32Array;\n capacity: number;\n bands: number;\n recordFloats: number;\n}\n\nexport function toDb(value: number): number {\n return value > 0 ? 20 * Math.log10(value) : Number.NEGATIVE_INFINITY;\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nexport function sonareMeterRingBufferByteLength(capacity: number): number {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n return (\n SONARE_METER_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT +\n clampedCapacity * SONARE_METER_RING_RECORD_FLOATS * Float32Array.BYTES_PER_ELEMENT\n );\n}\n\nexport function createSonareMeterRingBuffer(capacity = 128): SonareMeterRingBuffer {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const sharedBuffer = new SharedArrayBuffer(sonareMeterRingBufferByteLength(clampedCapacity));\n const ring = meterRingFromSharedBuffer(sharedBuffer, clampedCapacity);\n Atomics.store(ring.header, 0, 0);\n Atomics.store(ring.header, 1, clampedCapacity);\n Atomics.store(ring.header, 2, SONARE_METER_RING_RECORD_FLOATS);\n Atomics.store(ring.header, 3, 0);\n return { sharedBuffer, header: ring.header, records: ring.records, capacity: ring.capacity };\n}\n\nexport function readSonareMeterRingBuffer(\n ring: SonareMeterRingBuffer,\n readIndex = 0,\n): SonareMeterRingReadResult {\n const writeIndex = Atomics.load(ring.header, 0);\n const recordFloats = Atomics.load(ring.header, 2) || SONARE_METER_RING_RECORD_FLOATS;\n const nextReadIndex = Math.max(0, Math.min(readIndex, writeIndex));\n const firstReadable = Math.max(nextReadIndex, writeIndex - ring.capacity);\n const meters: SonareWorkletMeterSnapshot[] = [];\n for (let index = firstReadable; index < writeIndex; index++) {\n const offset = (index % ring.capacity) * recordFloats;\n meters.push({\n type: 'meter',\n frame: decodeFrame(ring.records[offset], ring.records[offset + 1]),\n targetId: ring.records[offset + 2],\n peakDbL: ring.records[offset + 3],\n peakDbR: ring.records[offset + 4],\n rmsDbL: ring.records[offset + 5],\n rmsDbR: ring.records[offset + 6],\n correlation: ring.records[offset + 7],\n truePeakDbL: ring.records[offset + 8],\n truePeakDbR: ring.records[offset + 9],\n momentaryLufs: ring.records[offset + 10],\n shortTermLufs: ring.records[offset + 11],\n integratedLufs: ring.records[offset + 12],\n gainReductionDb: ring.records[offset + 13],\n });\n }\n return { nextReadIndex: writeIndex, meters };\n}\n\nexport function sonareSpectrumRingBufferByteLength(capacity: number, bands = 16): number {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const clampedBands = Math.max(1, Math.floor(bands));\n // Record layout: [frameLo, frameHi, bandCount, band0, band1, ...]. frame is\n // split across two Float32 lanes for exact reconstruction beyond 2^24.\n return (\n SONARE_SPECTRUM_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT +\n clampedCapacity * (3 + clampedBands) * Float32Array.BYTES_PER_ELEMENT\n );\n}\n\nexport function createSonareSpectrumRingBuffer(\n capacity = 128,\n bands = 16,\n): SonareSpectrumRingBuffer {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const clampedBands = Math.max(1, Math.floor(bands));\n const sharedBuffer = new SharedArrayBuffer(\n sonareSpectrumRingBufferByteLength(clampedCapacity, clampedBands),\n );\n const ring = spectrumRingFromSharedBuffer(sharedBuffer, clampedCapacity, clampedBands);\n Atomics.store(ring.header, 0, 0);\n Atomics.store(ring.header, 1, clampedCapacity);\n Atomics.store(ring.header, 2, ring.recordFloats);\n Atomics.store(ring.header, 3, clampedBands);\n Atomics.store(ring.header, 4, 0);\n return {\n sharedBuffer,\n header: ring.header,\n records: ring.records,\n capacity: ring.capacity,\n bands: ring.bands,\n };\n}\n\nexport function readSonareSpectrumRingBuffer(\n ring: SonareSpectrumRingBuffer,\n readIndex = 0,\n): SonareSpectrumRingReadResult {\n const writeIndex = Atomics.load(ring.header, 0);\n const recordFloats = Atomics.load(ring.header, 2) || 3 + ring.bands;\n const bands = Atomics.load(ring.header, 3) || ring.bands;\n const nextReadIndex = Math.max(0, Math.min(readIndex, writeIndex));\n const firstReadable = Math.max(nextReadIndex, writeIndex - ring.capacity);\n const spectra: SonareWorkletSpectrumSnapshot[] = [];\n for (let index = firstReadable; index < writeIndex; index++) {\n const offset = (index % ring.capacity) * recordFloats;\n const values = new Float32Array(bands);\n values.set(ring.records.subarray(offset + 3, offset + 3 + bands));\n spectra.push({\n type: 'spectrum',\n frame: decodeFrame(ring.records[offset], ring.records[offset + 1]),\n bands: values,\n });\n }\n return { nextReadIndex: writeIndex, spectra };\n}\n\nexport function sonareScopeRingRecordFloats(bands: number, maxPoints: number): number {\n return SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS + bands + 2 * maxPoints;\n}\n\nexport function sonareScopeRingBufferByteLength(\n capacity: number,\n bands = 48,\n maxPoints = 32,\n): number {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const clampedBands = Math.max(1, Math.floor(bands));\n const clampedPoints = Math.max(0, Math.floor(maxPoints));\n return (\n SONARE_SCOPE_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT +\n clampedCapacity *\n sonareScopeRingRecordFloats(clampedBands, clampedPoints) *\n Float32Array.BYTES_PER_ELEMENT\n );\n}\n\nexport function createSonareScopeRingBuffer(\n capacity = 64,\n bands = 48,\n maxPoints = 32,\n): SonareScopeRingBuffer {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const clampedBands = Math.max(1, Math.floor(bands));\n const clampedPoints = Math.max(0, Math.floor(maxPoints));\n const sharedBuffer = new SharedArrayBuffer(\n sonareScopeRingBufferByteLength(clampedCapacity, clampedBands, clampedPoints),\n );\n const ring = scopeRingFromSharedBuffer(\n sharedBuffer,\n clampedCapacity,\n clampedBands,\n clampedPoints,\n );\n Atomics.store(ring.header, 0, 0);\n Atomics.store(ring.header, 1, clampedCapacity);\n Atomics.store(ring.header, 2, ring.recordFloats);\n Atomics.store(ring.header, 3, clampedBands);\n Atomics.store(ring.header, 4, clampedPoints);\n Atomics.store(ring.header, 5, 0);\n return {\n sharedBuffer,\n header: ring.header,\n records: ring.records,\n capacity: ring.capacity,\n bands: ring.bands,\n maxPoints: ring.maxPoints,\n };\n}\n\nexport function readSonareScopeRingBuffer(\n ring: SonareScopeRingBuffer,\n readIndex = 0,\n): SonareScopeRingReadResult {\n const writeIndex = Atomics.load(ring.header, 0);\n const bands = Atomics.load(ring.header, 3) || ring.bands;\n const maxPoints = Atomics.load(ring.header, 4);\n const recordFloats =\n Atomics.load(ring.header, 2) || sonareScopeRingRecordFloats(bands, maxPoints);\n const nextReadIndex = Math.max(0, Math.min(readIndex, writeIndex));\n const firstReadable = Math.max(nextReadIndex, writeIndex - ring.capacity);\n const scopes: SonareWorkletScopeSnapshot[] = [];\n for (let index = firstReadable; index < writeIndex; index++) {\n const offset = (index % ring.capacity) * recordFloats;\n const bandCount = Math.min(bands, Math.max(0, ring.records[offset + 3]));\n const pointCount = Math.min(maxPoints, Math.max(0, ring.records[offset + 4]));\n const bandsView = new Float32Array(bandCount);\n bandsView.set(\n ring.records.subarray(\n offset + SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS,\n offset + SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS + bandCount,\n ),\n );\n const pointsBase = offset + SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS + bands;\n const pointsView = new Float32Array(pointCount * 2);\n pointsView.set(ring.records.subarray(pointsBase, pointsBase + pointCount * 2));\n scopes.push({\n type: 'scope',\n frame: decodeFrame(ring.records[offset], ring.records[offset + 1]),\n targetId: ring.records[offset + 2],\n bands: bandsView,\n points: pointsView,\n });\n }\n return { nextReadIndex: writeIndex, scopes };\n}\n\nexport function scopeRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n fallbackCapacity?: number,\n fallbackBands?: number,\n fallbackMaxPoints?: number,\n): SharedScopeRingWriter {\n const headerBytes = SONARE_SCOPE_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT;\n const header = new Int32Array(sharedBuffer, 0, SONARE_SCOPE_RING_HEADER_INTS);\n const existingCapacity = Atomics.load(header, 1);\n const existingBands = Atomics.load(header, 3);\n const existingMaxPoints = Atomics.load(header, 4);\n const capacity = Math.max(1, Math.floor(existingCapacity || fallbackCapacity || 1));\n const bands = Math.max(1, Math.floor(existingBands || fallbackBands || 48));\n const maxPoints = Math.max(0, Math.floor(existingMaxPoints || (fallbackMaxPoints ?? 32)));\n const recordFloats = sonareScopeRingRecordFloats(bands, maxPoints);\n const minBytes = sonareScopeRingBufferByteLength(capacity, bands, maxPoints);\n if (sharedBuffer.byteLength < minBytes) {\n throw new Error('scopeSharedBuffer is too small for the requested ring capacity.');\n }\n Atomics.store(header, 1, capacity);\n Atomics.store(header, 2, recordFloats);\n Atomics.store(header, 3, bands);\n Atomics.store(header, 4, maxPoints);\n return {\n header,\n records: new Float32Array(sharedBuffer, headerBytes, capacity * recordFloats),\n capacity,\n bands,\n maxPoints,\n recordFloats,\n };\n}\n\nexport function sonareEngineCommandRingBufferByteLength(capacity: number): number {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n return (\n SONARE_ENGINE_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT +\n clampedCapacity * SONARE_ENGINE_COMMAND_RECORD_BYTES\n );\n}\n\nexport function sonareEngineTelemetryRingBufferByteLength(capacity: number): number {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n return (\n SONARE_ENGINE_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT +\n clampedCapacity * SONARE_ENGINE_TELEMETRY_RECORD_BYTES\n );\n}\n\nexport function sonareClipPageRequestRingBufferByteLength(capacity: number): number {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n return (\n SONARE_CLIP_PAGE_REQUEST_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT +\n clampedCapacity * SONARE_CLIP_PAGE_REQUEST_RING_RECORD_UINT32S * Uint32Array.BYTES_PER_ELEMENT\n );\n}\n\nexport function sonareExternalMidiRingBufferByteLength(capacity: number): number {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n return (\n SONARE_EXTERNAL_MIDI_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT +\n clampedCapacity * SONARE_EXTERNAL_MIDI_RING_RECORD_UINT32S * Uint32Array.BYTES_PER_ELEMENT\n );\n}\n\nexport function externalMidiRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n fallbackCapacity?: number,\n): SharedExternalMidiRingWriter {\n const headerBytes = SONARE_EXTERNAL_MIDI_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT;\n const header = new Int32Array(sharedBuffer, 0, SONARE_EXTERNAL_MIDI_RING_HEADER_INTS);\n const existingCapacity = Atomics.load(header, 2);\n const capacity = Math.max(1, Math.floor(existingCapacity || fallbackCapacity || 1));\n if (sharedBuffer.byteLength < sonareExternalMidiRingBufferByteLength(capacity)) {\n throw new Error('externalMidiSharedBuffer is too small for the requested ring capacity.');\n }\n Atomics.store(header, 2, capacity);\n Atomics.store(header, 3, SONARE_EXTERNAL_MIDI_RING_RECORD_UINT32S);\n return {\n header,\n records: new Uint32Array(\n sharedBuffer,\n headerBytes,\n capacity * SONARE_EXTERNAL_MIDI_RING_RECORD_UINT32S,\n ),\n capacity,\n };\n}\n\nexport function createSonareExternalMidiRingBuffer(capacity = 256): SonareExternalMidiRingBuffer {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const sharedBuffer = new SharedArrayBuffer(\n sonareExternalMidiRingBufferByteLength(clampedCapacity),\n );\n const ring = externalMidiRingFromSharedBuffer(sharedBuffer, clampedCapacity);\n Atomics.store(ring.header, 0, 0);\n Atomics.store(ring.header, 1, 0);\n Atomics.store(ring.header, 4, 0);\n return { sharedBuffer, header: ring.header, records: ring.records, capacity: ring.capacity };\n}\n\n/** Write one lowered MIDI-1 event without allocations from the audio worklet. */\nexport function pushSonareExternalMidiRingBuffer(\n ring: SharedExternalMidiRingWriter,\n destinationId: number,\n renderFrame: number,\n byteWord: number,\n byteCount: number,\n): boolean {\n // Emscripten can expose an int64 render-frame scalar as bigint when the\n // host enables WASM_BIGINT. Normalize at this fixed-record boundary.\n const destination = Number(destinationId);\n const frame = Number(renderFrame);\n const packedBytes = Number(byteWord);\n const count = Number(byteCount);\n if (\n !Number.isSafeInteger(destination) ||\n !Number.isSafeInteger(frame) ||\n frame < 0 ||\n !Number.isSafeInteger(packedBytes) ||\n packedBytes < 0 ||\n packedBytes > 0xff_ffff ||\n !Number.isSafeInteger(count) ||\n count < 1 ||\n count > 3\n ) {\n Atomics.add(ring.header, 4, 1);\n return false;\n }\n const writeIndex = Atomics.load(ring.header, 0);\n const readIndex = Atomics.load(ring.header, 1);\n if (writeIndex - readIndex >= ring.capacity) {\n Atomics.add(ring.header, 4, 1);\n return false;\n }\n const offset = (writeIndex % ring.capacity) * SONARE_EXTERNAL_MIDI_RING_RECORD_UINT32S;\n Atomics.store(ring.records, offset, destination);\n Atomics.store(ring.records, offset + 1, frame);\n Atomics.store(ring.records, offset + 2, packedBytes);\n Atomics.store(ring.records, offset + 3, count);\n Atomics.store(ring.header, 0, writeIndex + 1);\n return true;\n}\n\n/** Main-thread drain. It is intentionally the only place MIDI byte arrays are built. */\nexport function readSonareExternalMidiRingBuffer(\n ring: SonareExternalMidiRingBuffer,\n): SonareExternalMidiRingReadResult {\n const readIndex = Atomics.load(ring.header, 1);\n const writeIndex = Atomics.load(ring.header, 0);\n const events: SonareExternalMidiRingEvent[] = [];\n for (let index = readIndex; index < writeIndex; index++) {\n const offset = (index % ring.capacity) * SONARE_EXTERNAL_MIDI_RING_RECORD_UINT32S;\n events.push({\n destinationId: Atomics.load(ring.records, offset) >>> 0,\n renderFrame: Atomics.load(ring.records, offset + 1) >>> 0,\n byteWord: Atomics.load(ring.records, offset + 2) >>> 0,\n byteCount: Atomics.load(ring.records, offset + 3) >>> 0,\n });\n }\n Atomics.store(ring.header, 1, writeIndex);\n return { events, dropped: Atomics.load(ring.header, 4) >>> 0 };\n}\n\nexport function createSonareClipPageRequestRingBuffer(\n capacity = 128,\n): SonareClipPageRequestRingBuffer {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const sharedBuffer = new SharedArrayBuffer(\n sonareClipPageRequestRingBufferByteLength(clampedCapacity),\n );\n const ring = clipPageRequestRingFromSharedBuffer(sharedBuffer, clampedCapacity);\n Atomics.store(ring.header, 0, 0);\n Atomics.store(ring.header, 1, 0);\n Atomics.store(ring.header, 2, ring.capacity);\n Atomics.store(ring.header, 3, SONARE_CLIP_PAGE_REQUEST_RING_RECORD_UINT32S);\n Atomics.store(ring.header, 4, 0);\n return { sharedBuffer, header: ring.header, records: ring.records, capacity: ring.capacity };\n}\n\n/**\n * Writes one request without allocating. Invalid uint32 coordinates and a full\n * ring are counted as drops so the main thread can surface a bounded-loss\n * diagnostic without receiving a worklet postMessage.\n */\nexport function pushSonareClipPageRequestRingBuffer(\n ring: SharedClipPageRequestRingWriter,\n clipId: number,\n pageIndex: number,\n): boolean {\n if (\n !Number.isSafeInteger(clipId) ||\n clipId < 0 ||\n clipId > 0xffff_ffff ||\n !Number.isSafeInteger(pageIndex) ||\n pageIndex < 0 ||\n pageIndex > 0xffff_ffff\n ) {\n Atomics.add(ring.header, 4, 1);\n return false;\n }\n const writeIndex = Atomics.load(ring.header, 0);\n const readIndex = Atomics.load(ring.header, 1);\n if (writeIndex - readIndex >= ring.capacity) {\n Atomics.add(ring.header, 4, 1);\n return false;\n }\n const offset = (writeIndex % ring.capacity) * SONARE_CLIP_PAGE_REQUEST_RING_RECORD_UINT32S;\n Atomics.store(ring.records, offset, clipId);\n Atomics.store(ring.records, offset + 1, pageIndex);\n // Publish only after both scalar fields have been written.\n Atomics.store(ring.header, 0, writeIndex + 1);\n return true;\n}\n\n/** Drains the SPSC request ring on the main thread. Object creation is here, never in process(). */\nexport function readSonareClipPageRequestRingBuffer(\n ring: SonareClipPageRequestRingBuffer,\n): SonareClipPageRequestRingReadResult {\n const readIndex = Atomics.load(ring.header, 1);\n const writeIndex = Atomics.load(ring.header, 0);\n const requests: SonareClipPageRequest[] = [];\n for (let index = readIndex; index < writeIndex; index++) {\n const offset = (index % ring.capacity) * SONARE_CLIP_PAGE_REQUEST_RING_RECORD_UINT32S;\n requests.push({\n clipId: Atomics.load(ring.records, offset),\n pageIndex: Atomics.load(ring.records, offset + 1),\n });\n }\n Atomics.store(ring.header, 1, writeIndex);\n return { requests, dropped: Atomics.load(ring.header, 4) >>> 0 };\n}\n\nexport function createSonareEngineCommandRingBuffer(capacity = 128): SonareEngineCommandRingBuffer {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const sharedBuffer = new SharedArrayBuffer(\n sonareEngineCommandRingBufferByteLength(clampedCapacity),\n );\n const ring = engineRingFromSharedBuffer(\n sharedBuffer,\n SONARE_ENGINE_COMMAND_RECORD_BYTES,\n clampedCapacity,\n );\n return { sharedBuffer, header: ring.header, view: ring.view, capacity: ring.capacity };\n}\n\nexport function createSonareEngineTelemetryRingBuffer(\n capacity = 128,\n): SonareEngineTelemetryRingBuffer {\n const clampedCapacity = Math.max(1, Math.floor(capacity));\n const sharedBuffer = new SharedArrayBuffer(\n sonareEngineTelemetryRingBufferByteLength(clampedCapacity),\n );\n const ring = engineRingFromSharedBuffer(\n sharedBuffer,\n SONARE_ENGINE_TELEMETRY_RECORD_BYTES,\n clampedCapacity,\n );\n return { sharedBuffer, header: ring.header, view: ring.view, capacity: ring.capacity };\n}\n\nexport function pushSonareEngineCommandRingBuffer(\n ring: SonareEngineCommandRingBuffer,\n command: SonareEngineCommandRecord,\n): boolean {\n const writeIndex = Atomics.load(ring.header, 0);\n const readIndex = Atomics.load(ring.header, 1);\n if (writeIndex - readIndex >= ring.capacity) {\n Atomics.add(ring.header, 4, 1);\n return false;\n }\n writeEngineCommandRecord(\n ring.view,\n recordOffset(writeIndex, ring.capacity, SONARE_ENGINE_COMMAND_RECORD_BYTES),\n command,\n );\n Atomics.store(ring.header, 0, writeIndex + 1);\n return true;\n}\n\nexport function popSonareEngineCommandRingBuffer(\n ring: SonareEngineCommandRingBuffer,\n): SonareEngineCommandRecord | null {\n const readIndex = Atomics.load(ring.header, 1);\n const writeIndex = Atomics.load(ring.header, 0);\n if (readIndex >= writeIndex) {\n return null;\n }\n const command = readEngineCommandRecord(\n ring.view,\n recordOffset(readIndex, ring.capacity, SONARE_ENGINE_COMMAND_RECORD_BYTES),\n );\n Atomics.store(ring.header, 1, readIndex + 1);\n return command;\n}\n\nexport function writeSonareEngineTelemetryRingBuffer(\n ring: SonareEngineTelemetryRingBuffer,\n telemetry: SonareEngineTelemetryRecord,\n): void {\n const writeIndex = Atomics.load(ring.header, 0);\n writeEngineTelemetryRecord(\n ring.view,\n recordOffset(writeIndex, ring.capacity, SONARE_ENGINE_TELEMETRY_RECORD_BYTES),\n telemetry,\n );\n Atomics.store(ring.header, 0, writeIndex + 1);\n if (writeIndex + 1 > ring.capacity) {\n Atomics.store(ring.header, 4, writeIndex + 1 - ring.capacity);\n }\n}\n\nexport function readSonareEngineTelemetryRingBuffer(\n ring: SonareEngineTelemetryRingBuffer,\n readIndex = 0,\n): SonareEngineTelemetryRingReadResult {\n const writeIndex = Atomics.load(ring.header, 0);\n const nextReadIndex = Math.max(0, Math.min(readIndex, writeIndex));\n const firstReadable = Math.max(nextReadIndex, writeIndex - ring.capacity);\n const telemetry: SonareEngineTelemetryRecord[] = [];\n for (let index = firstReadable; index < writeIndex; index++) {\n telemetry.push(\n readEngineTelemetryRecord(\n ring.view,\n recordOffset(index, ring.capacity, SONARE_ENGINE_TELEMETRY_RECORD_BYTES),\n ),\n );\n }\n return { nextReadIndex: writeIndex, telemetry };\n}\n\nexport function meterRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n fallbackCapacity?: number,\n): SharedMeterRingWriter {\n const headerBytes = SONARE_METER_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT;\n const header = new Int32Array(sharedBuffer, 0, SONARE_METER_RING_HEADER_INTS);\n const existingCapacity = Atomics.load(header, 1);\n const capacity = Math.max(1, Math.floor(existingCapacity || fallbackCapacity || 1));\n const minBytes = sonareMeterRingBufferByteLength(capacity);\n if (sharedBuffer.byteLength < minBytes) {\n throw new Error('meterSharedBuffer is too small for the requested ring capacity.');\n }\n Atomics.store(header, 1, capacity);\n Atomics.store(header, 2, SONARE_METER_RING_RECORD_FLOATS);\n return {\n header,\n records: new Float32Array(\n sharedBuffer,\n headerBytes,\n capacity * SONARE_METER_RING_RECORD_FLOATS,\n ),\n capacity,\n };\n}\n\nexport function spectrumRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n fallbackCapacity?: number,\n fallbackBands?: number,\n): SharedSpectrumRingWriter {\n const headerBytes = SONARE_SPECTRUM_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT;\n const header = new Int32Array(sharedBuffer, 0, SONARE_SPECTRUM_RING_HEADER_INTS);\n const existingCapacity = Atomics.load(header, 1);\n const existingBands = Atomics.load(header, 3);\n const capacity = Math.max(1, Math.floor(existingCapacity || fallbackCapacity || 1));\n const bands = Math.max(1, Math.floor(existingBands || fallbackBands || 16));\n const recordFloats = 3 + bands;\n const minBytes = sonareSpectrumRingBufferByteLength(capacity, bands);\n if (sharedBuffer.byteLength < minBytes) {\n throw new Error('spectrumSharedBuffer is too small for the requested ring capacity.');\n }\n Atomics.store(header, 1, capacity);\n Atomics.store(header, 2, recordFloats);\n Atomics.store(header, 3, bands);\n return {\n header,\n records: new Float32Array(sharedBuffer, headerBytes, capacity * recordFloats),\n capacity,\n bands,\n recordFloats,\n };\n}\n\nexport function engineRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n recordBytes: number,\n fallbackCapacity?: number,\n): { header: Int32Array; view: DataView; capacity: number } {\n const headerBytes = SONARE_ENGINE_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT;\n const header = new Int32Array(sharedBuffer, 0, SONARE_ENGINE_RING_HEADER_INTS);\n const existingCapacity = Atomics.load(header, 2);\n const capacity = Math.max(1, Math.floor(existingCapacity || fallbackCapacity || 1));\n const minBytes = headerBytes + capacity * recordBytes;\n if (sharedBuffer.byteLength < minBytes) {\n throw new Error('engine SharedArrayBuffer is too small for the requested ring capacity.');\n }\n Atomics.store(header, 2, capacity);\n Atomics.store(header, 3, recordBytes);\n return {\n header,\n view: new DataView(sharedBuffer, headerBytes, capacity * recordBytes),\n capacity,\n };\n}\n\nexport function clipPageRequestRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n fallbackCapacity?: number,\n): SharedClipPageRequestRingWriter {\n const headerBytes = SONARE_CLIP_PAGE_REQUEST_RING_HEADER_INTS * Int32Array.BYTES_PER_ELEMENT;\n const header = new Int32Array(sharedBuffer, 0, SONARE_CLIP_PAGE_REQUEST_RING_HEADER_INTS);\n const existingCapacity = Atomics.load(header, 2);\n const capacity = Math.max(1, Math.floor(existingCapacity || fallbackCapacity || 1));\n const minBytes = sonareClipPageRequestRingBufferByteLength(capacity);\n if (sharedBuffer.byteLength < minBytes) {\n throw new Error('clipPageRequestSharedBuffer is too small for the requested ring capacity.');\n }\n Atomics.store(header, 2, capacity);\n Atomics.store(header, 3, SONARE_CLIP_PAGE_REQUEST_RING_RECORD_UINT32S);\n return {\n header,\n records: new Uint32Array(\n sharedBuffer,\n headerBytes,\n capacity * SONARE_CLIP_PAGE_REQUEST_RING_RECORD_UINT32S,\n ),\n capacity,\n };\n}\n\nfunction recordOffset(index: number, capacity: number, recordBytes: number): number {\n return (index % capacity) * recordBytes;\n}\n\nfunction toSafeInteger(value: number | bigint | undefined, fallback: number): number {\n const resolved = typeof value === 'bigint' ? Number(value) : value;\n if (resolved === undefined) {\n return fallback;\n }\n if (!Number.isSafeInteger(resolved)) {\n throw new RangeError('64-bit ring values must be safe integers');\n }\n return resolved;\n}\n\n/** Store a signed 64-bit safe integer as two 32-bit words without BigInt. */\nexport function writeInt64Words(view: DataView, offset: number, value: number): void {\n const integer = toSafeInteger(value, 0);\n view.setUint32(offset, integer >>> 0, true);\n view.setInt32(offset + 4, Math.floor(integer / 0x100000000), true);\n}\n\n/** Reconstruct a signed 64-bit safe integer stored by {@link writeInt64Words}. */\nexport function readInt64Words(view: DataView, offset: number): number {\n return view.getInt32(offset + 4, true) * 0x100000000 + view.getUint32(offset, true);\n}\n\nfunction writeEngineCommandRecord(\n view: DataView,\n offset: number,\n command: SonareEngineCommandRecord,\n): void {\n view.setUint32(offset, command.type, true);\n view.setUint32(offset + 4, command.targetId ?? 0, true);\n writeInt64Words(view, offset + 8, toSafeInteger(command.sampleTime, -1));\n // argFloat occupies a full 8-byte Float64 slot (replacing the old Float32 +\n // 4-byte pad) so PPQ scalars carried here keep full double precision over the\n // SAB transport, matching the engine's double-precision seek/loop contract.\n view.setFloat64(offset + 16, command.argFloat ?? 0, true);\n writeInt64Words(view, offset + 24, toSafeInteger(command.argInt, 0));\n}\n\nfunction readEngineCommandRecord(view: DataView, offset: number): SonareEngineCommandRecord {\n return {\n type: view.getUint32(offset, true),\n targetId: view.getUint32(offset + 4, true),\n sampleTime: readInt64Words(view, offset + 8),\n argFloat: view.getFloat64(offset + 16, true),\n argInt: readInt64Words(view, offset + 24),\n };\n}\n\nfunction writeEngineTelemetryRecord(\n view: DataView,\n offset: number,\n telemetry: SonareEngineTelemetryRecord,\n): void {\n view.setUint32(offset, telemetry.type, true);\n view.setUint32(offset + 4, telemetry.error, true);\n writeInt64Words(view, offset + 8, telemetry.renderFrame);\n writeInt64Words(view, offset + 16, telemetry.timelineSample);\n writeInt64Words(view, offset + 24, telemetry.audibleTimelineSample);\n view.setInt32(offset + 32, telemetry.graphLatencySamplesQ8, true);\n view.setUint32(offset + 36, telemetry.value, true);\n view.setUint32(offset + 40, 0, true);\n view.setUint32(offset + 44, 0, true);\n}\n\nfunction readEngineTelemetryRecord(view: DataView, offset: number): SonareEngineTelemetryRecord {\n return {\n type: view.getUint32(offset, true),\n error: view.getUint32(offset + 4, true),\n renderFrame: readInt64Words(view, offset + 8),\n timelineSample: readInt64Words(view, offset + 16),\n audibleTimelineSample: readInt64Words(view, offset + 24),\n graphLatencySamplesQ8: view.getInt32(offset + 32, true),\n value: view.getUint32(offset + 36, true),\n };\n}\n\nexport function telemetryFromEngine(telemetry: EngineTelemetry): SonareEngineTelemetryRecord {\n return {\n type: telemetry.type,\n error: telemetry.error,\n renderFrame: telemetry.renderFrame,\n timelineSample: telemetry.timelineSample,\n audibleTimelineSample: telemetry.audibleTimelineSample,\n graphLatencySamplesQ8: telemetry.graphLatencySamplesQ8,\n value: telemetry.value,\n };\n}\n\nexport function meterFromEngine(meter: EngineMeterTelemetry): SonareWorkletMeterSnapshot {\n return {\n type: 'meter',\n targetId: meter.targetId,\n frame: meter.renderFrame,\n peakDbL: meter.peakDbL,\n peakDbR: meter.peakDbR,\n rmsDbL: meter.rmsDbL,\n rmsDbR: meter.rmsDbR,\n correlation: meter.correlation,\n truePeakDbL: meter.truePeakDbL,\n truePeakDbR: meter.truePeakDbR,\n momentaryLufs: meter.momentaryLufs,\n shortTermLufs: meter.shortTermLufs,\n integratedLufs: meter.integratedLufs,\n gainReductionDb: meter.gainReductionDb,\n };\n}\n\nexport function magnitudeToDb(value: number): number {\n return value > 1.0e-12 ? 20 * Math.log10(value) : -120;\n}\n","import type { EngineCaptureStatus, RealtimeEngine } from '../index';\nimport type { SonareRealtimeEngineNode } from './engine-node';\nimport { buildCaptureConfig, type CaptureOptions } from './engine-offline';\nimport type { SonareEngineSyncCaptureMessage, SonareEngineSyncMessage } from './messages';\nimport { SonareEngineCommandType } from './protocol';\n\ntype CaptureConfig = Omit<SonareEngineSyncCaptureMessage, 'type'>;\n\n/**\n * Collaborator surface the capture/record/punch setters need from the owning\n * {@link SonareEngine}: the offline engine they mirror into, the realtime node\n * they command and query, the channel count, the out-of-band sync poster, the\n * capture-config accessor, and the target-id resolver.\n */\nexport interface EngineCaptureContext {\n readonly offlineEngine: RealtimeEngine;\n readonly realtimeNode: SonareRealtimeEngineNode;\n sendCommand(command: {\n type: SonareEngineCommandType;\n targetId?: number;\n sampleTime?: number;\n argFloat?: number;\n argInt?: number;\n }): boolean;\n readonly offlineChannelCount: number;\n postSync(message: SonareEngineSyncMessage): void;\n getCaptureConfig(): CaptureConfig | undefined;\n setCaptureConfig(config: CaptureConfig): void;\n}\n\nexport function configureCapture(ctx: EngineCaptureContext, options: CaptureOptions): void {\n const config = buildCaptureConfig(options, ctx.offlineChannelCount);\n ctx.offlineEngine.setCaptureBuffer(config.channels, config.bufferFrames);\n ctx.offlineEngine.setCaptureSource(config.source);\n ctx.offlineEngine.setRecordOffsetSamples(config.recordOffsetSamples);\n ctx.offlineEngine.setInputMonitor(config.inputMonitor.enabled, config.inputMonitor.gain);\n ctx.setCaptureConfig(config);\n ctx.postSync({ type: 'syncCapture', ...config });\n}\n\nexport function armRecord(\n ctx: EngineCaptureContext,\n trackId: string | number,\n enabled: boolean,\n): boolean {\n if (trackId !== 0) {\n throw new RangeError('Capture is global; armRecord only accepts trackId 0');\n }\n if (enabled && !ctx.getCaptureConfig()) {\n throw new Error('Capture buffer is not configured');\n }\n ctx.offlineEngine.armCapture(enabled);\n return ctx.sendCommand({\n type: SonareEngineCommandType.ArmRecord,\n targetId: 0,\n sampleTime: -1,\n argInt: enabled ? 1 : 0,\n });\n}\n\nexport function punch(ctx: EngineCaptureContext, inPpq: number, outPpq: number): boolean {\n const inSample = ctx.offlineEngine.sampleAtPpq(inPpq);\n const outSample = ctx.offlineEngine.sampleAtPpq(outPpq);\n ctx.offlineEngine.setCapturePunch(inSample, outSample, true);\n // Carry BOTH endpoints as already-converted SAMPLES so the realtime engine\n // agrees with the offline engine. The previous code sent the raw PPQ out\n // point and let the consumer multiply by sampleRate (treating PPQ as\n // seconds), which ignored tempo and produced a punch-out ~2x too large at\n // 120 BPM. argInt = in sample, argFloat = out sample (full-precision double).\n return ctx.sendCommand({\n type: SonareEngineCommandType.Punch,\n sampleTime: -1,\n argInt: inSample,\n argFloat: outSample,\n });\n}\n\nexport function captureStatus(ctx: EngineCaptureContext): Promise<EngineCaptureStatus> {\n return ctx.realtimeNode.requestCaptureStatus();\n}\n\nexport function capturedAudio(ctx: EngineCaptureContext): Promise<Float32Array[]> {\n return ctx.realtimeNode.requestCapturedAudio();\n}\n\nexport async function resetCapture(ctx: EngineCaptureContext): Promise<void> {\n ctx.offlineEngine.resetCapture();\n await ctx.realtimeNode.requestCaptureReset();\n}\n","import type { EngineClip, EngineMidiClipSchedule, RealtimeEngine } from '../index';\nimport type { ClipPageProvider } from '../realtime_engine';\nimport type { SonareEngineSyncMessage } from './messages';\n\n/**\n * Collaborator surface the audio/MIDI clip scheduling helpers need from the\n * owning {@link SonareEngine}: the clip stores they mutate, the offline engine\n * they mirror into, the sync poster, and the clip-id allocator / lane resolvers.\n */\nexport interface EngineClipContext {\n readonly offlineEngine: RealtimeEngine;\n readonly clips: Map<number, EngineClip>;\n readonly midiClips: Map<number, EngineMidiClipSchedule>;\n allocateClipId(): number;\n postSync(message: SonareEngineSyncMessage, transfer?: Transferable[]): void;\n resolveTargetId(target: string | number): number;\n ensureTrackLane(target: string | number): number;\n /** Commits a provider already primed through the worklet's OPFS pull bridge. */\n commitWorkletClipPageProvider(clip: EngineClip): boolean;\n}\n\n// Keep control-message work bounded even for long tempo-synced clips. The\n// worklet creates a native page provider, receives these transferable PCM\n// chunks, and only schedules the clip after all pages arrive.\nconst PREBAKED_CLIP_PAGE_THRESHOLD = 16_384;\nconst PREBAKED_CLIP_PAGE_FRAMES = 4_096;\n\nexport function addClip(\n ctx: EngineClipContext,\n trackId: string | number,\n buffer: Float32Array[] | ClipPageProvider,\n startPpq: number,\n opts: Partial<Omit<EngineClip, 'channels' | 'pageProvider' | 'startPpq'>> = {},\n): number {\n const id = opts.id ?? ctx.allocateClipId();\n const clip: EngineClip = {\n ...opts,\n id,\n ...(Array.isArray(buffer) ? { channels: buffer } : { pageProvider: buffer }),\n startPpq,\n trackId: ctx.resolveTargetId(trackId),\n };\n ctx.ensureTrackLane(trackId);\n ctx.clips.set(id, clip);\n syncClipsDelta(ctx, [clip], []);\n return id;\n}\n\nexport function removeClip(ctx: EngineClipContext, clipId: number): void {\n ctx.clips.delete(clipId);\n syncClipsDelta(ctx, [], [clipId]);\n}\n\nexport function setMidiClips(\n ctx: EngineClipContext,\n clips: readonly EngineMidiClipSchedule[],\n): void {\n ctx.midiClips.clear();\n for (const clip of clips) {\n const id = clip.id ?? ctx.allocateClipId();\n ctx.midiClips.set(id, { ...clip, id, events: clip.events.map((event) => ({ ...event })) });\n }\n syncMidiClips(ctx);\n}\n\nfunction syncClipsDelta(ctx: EngineClipContext, upserts: EngineClip[], removeIds: number[]): void {\n const clips = Array.from(ctx.clips.values());\n ctx.offlineEngine.setClips(clips);\n const preparedById = new Map<number, EngineClip>();\n for (const clip of clips) {\n if (clip.id === undefined) {\n continue;\n }\n const bakedChannels = ctx.offlineEngine.prebakedClipChannels(clip.id);\n preparedById.set(\n clip.id,\n bakedChannels === null\n ? clip\n : {\n ...clip,\n channels: bakedChannels,\n clipOffsetSamples: 0,\n lengthSamples: bakedChannels[0]?.length ?? 0,\n loop: false,\n warpMode: 'off',\n warpAnchors: undefined,\n },\n );\n }\n const inlineUpserts: EngineClip[] = [];\n for (const clip of upserts) {\n const prepared = clip.id === undefined ? clip : (preparedById.get(clip.id) ?? clip);\n const channels = prepared.channels;\n if (!channels && prepared.pageProvider !== undefined) {\n if (ctx.commitWorkletClipPageProvider(prepared)) {\n continue;\n }\n throw new Error('A pageProvider on SonareEngine must be created by attachOpfsClipStream().');\n }\n if (\n prepared.id === undefined ||\n prepared.warpMode !== 'off' ||\n !channels ||\n channels.length === 0 ||\n channels[0].length <= PREBAKED_CLIP_PAGE_THRESHOLD\n ) {\n inlineUpserts.push(prepared);\n continue;\n }\n const numSamples = channels[0].length;\n ctx.postSync({\n type: 'syncClipPageProvider',\n clipId: prepared.id,\n clip: { ...prepared, channels: undefined, pageProvider: undefined },\n numChannels: channels.length,\n numSamples,\n pageFrames: PREBAKED_CLIP_PAGE_FRAMES,\n });\n for (\n let start = 0, pageIndex = 0;\n start < numSamples;\n start += PREBAKED_CLIP_PAGE_FRAMES, pageIndex++\n ) {\n const page = channels.map((channel) =>\n channel.slice(start, start + PREBAKED_CLIP_PAGE_FRAMES),\n );\n ctx.postSync(\n { type: 'syncClipPage', clipId: prepared.id, pageIndex, channels: page },\n page.map((channel) => channel.buffer as Transferable),\n );\n }\n ctx.postSync({ type: 'syncClipPageCommit', clipId: prepared.id });\n }\n ctx.postSync({\n type: 'syncClipsDelta',\n upserts: inlineUpserts,\n removeIds,\n });\n}\n\nfunction syncMidiClips(ctx: EngineClipContext): void {\n const clips = Array.from(ctx.midiClips.values());\n ctx.offlineEngine.setMidiClips(clips);\n ctx.postSync({ type: 'syncMidiClips', clips });\n}\n","import type { EngineMarker, RealtimeEngine } from '../index';\nimport { resolveMarkerSet } from './engine-offline';\nimport type { SonareEngineSyncMessage } from './messages';\nimport { type SonareEngineCommandRecord, SonareEngineCommandType } from './protocol';\n\n/**\n * Collaborator surface the marker helpers need from the owning\n * {@link SonareEngine}: the marker store and id counter, the offline engine they\n * mirror into, the sync poster, the realtime command sender, and the loop setter.\n */\nexport interface EngineMarkerContext {\n readonly offlineEngine: RealtimeEngine;\n readonly markers: Map<number, EngineMarker>;\n getNextMarkerId(): number;\n setNextMarkerId(value: number): void;\n postSync(message: SonareEngineSyncMessage): void;\n sendCommand(command: SonareEngineCommandRecord): boolean;\n setLoop(startPpq: number, endPpq: number, enabled: boolean): boolean;\n}\n\nexport function addMarker(ctx: EngineMarkerContext, ppq: number, name = ''): number {\n const id = ctx.getNextMarkerId();\n ctx.setNextMarkerId(id + 1);\n ctx.markers.set(id, { id, ppq, name });\n syncMarkers(ctx);\n return id;\n}\n\n/**\n * Replaces the whole marker set in one call.\n *\n * Entries without an `id` are assigned fresh ids; entries carrying an `id`\n * keep it (ids must be positive and unique within the list). Returns the\n * resolved markers in the order given, so a caller can map its own marker\n * identities to the engine ids used by `seekMarker`/`setLoopFromMarkers`.\n *\n * @param markers The full marker list (an empty list clears all markers).\n * @returns The markers with their resolved engine ids.\n */\nexport function setMarkers(\n ctx: EngineMarkerContext,\n markers: ReadonlyArray<{ ppq: number; name?: string; id?: number }>,\n): EngineMarker[] {\n const { resolved, nextMarkerId } = resolveMarkerSet(markers, ctx.getNextMarkerId());\n ctx.setNextMarkerId(nextMarkerId);\n ctx.markers.clear();\n for (const marker of resolved) {\n ctx.markers.set(marker.id, marker);\n }\n syncMarkers(ctx);\n return resolved.map((marker) => ({ ...marker }));\n}\n\nexport function markerCount(ctx: EngineMarkerContext): number {\n return ctx.offlineEngine.markerCount();\n}\n\nexport function markerByIndex(ctx: EngineMarkerContext, index: number): EngineMarker {\n return ctx.offlineEngine.markerByIndex(index);\n}\n\nexport function marker(ctx: EngineMarkerContext, markerId: number): EngineMarker {\n return ctx.offlineEngine.marker(markerId);\n}\n\nexport function seekMarker(ctx: EngineMarkerContext, markerId: number): boolean {\n ctx.offlineEngine.seekMarker(markerId);\n // Forward to the live worklet engine. Its marker set is kept in sync via the\n // 'syncMarkers' message (see syncMarkers), so a queued kSeekMarker resolves\n // the marker id to its frame on the audio thread.\n return ctx.sendCommand({\n type: SonareEngineCommandType.SeekMarker,\n targetId: markerId,\n sampleTime: -1,\n });\n}\n\nexport function setLoopFromMarkers(\n ctx: EngineMarkerContext,\n startMarkerId: number,\n endMarkerId: number,\n): boolean {\n ctx.offlineEngine.setLoopFromMarkers(startMarkerId, endMarkerId);\n const start = ctx.offlineEngine.marker(startMarkerId);\n const end = ctx.offlineEngine.marker(endMarkerId);\n return ctx.setLoop(start.ppq, end.ppq, true);\n}\n\nfunction syncMarkers(ctx: EngineMarkerContext): void {\n const markers = Array.from(ctx.markers.values()).sort((a, b) => a.ppq - b.ppq);\n ctx.offlineEngine.setMarkers(markers);\n ctx.postSync({ type: 'syncMarkers', markers });\n}\n","import type { EngineBus, EngineTrackLane, EngineTrackSend, RealtimeEngine } from '../index';\nimport { normalizeTrackLanes } from './engine-offline';\nimport { buildMixerLanes } from './engine-sync';\nimport type { SonareEngineSyncMessage } from './messages';\nimport { ENGINE_MIXER_PARAM_FADER_DB, engineMixerBusTarget } from './protocol';\n\n/**\n * Collaborator surface the mixer/routing setters need from the owning\n * {@link SonareEngine}: the offline engine they mirror writes into, the mutable\n * routing stores (held by reference), the out-of-band sync poster, and the\n * lane/bus declaration and mixer-sync helpers.\n */\nexport interface EngineMixerContext {\n readonly offlineEngine: RealtimeEngine;\n readonly trackLaneIds: number[];\n readonly trackSends: Map<number, EngineTrackSend[]>;\n readonly trackOutputBus: Map<number, number>;\n readonly laneSidechains: Map<\n string,\n { trackId: number; insertIndex: number; sourceTrackId: number }\n >;\n readonly buses: EngineBus[];\n readonly trackStripJson: Map<number, string>;\n readonly busStripJson: Map<number, string>;\n postSync(message: SonareEngineSyncMessage): void;\n ensureTrackLane(target: string | number): number;\n ensureBus(busId: number): number;\n mixerLanes(): EngineTrackLane[];\n syncMixer(): void;\n sendSmoothedParam(paramId: number, value: number): boolean;\n getMasterStripJson(): string | undefined;\n}\n\n/** Builds the engine's track-lane descriptors from the current routing stores. */\nexport function mixerLanes(ctx: EngineMixerContext): EngineTrackLane[] {\n return buildMixerLanes(ctx.trackLaneIds, ctx.trackSends, ctx.trackOutputBus);\n}\n\n/**\n * Mirrors the current mixer routing into the offline engine and posts the full\n * mixer-sync message (lanes, buses, strip JSON, sidechains) to the worklet.\n */\nexport function syncMixer(ctx: EngineMixerContext): void {\n const lanes = mixerLanes(ctx);\n const buses = ctx.buses.map((bus) => ({ ...bus }));\n ctx.offlineEngine.setTrackBuses(buses);\n if (lanes.length > 0) {\n ctx.offlineEngine.setTrackLanes(lanes);\n }\n const trackStrips = Array.from(ctx.trackStripJson, ([trackId, sceneJson]) => ({\n trackId,\n sceneJson,\n }));\n const busStrips = Array.from(ctx.busStripJson, ([busId, sceneJson]) => ({\n busId,\n sceneJson,\n }));\n ctx.postSync({\n type: 'syncMixer',\n lanes,\n buses,\n trackStrips,\n laneSidechains: Array.from(ctx.laneSidechains.values()),\n busStrips,\n masterStripJson: ctx.getMasterStripJson(),\n });\n}\n\n/**\n * Declares the mixer track lanes in an explicit order.\n *\n * Lane indices are append-only: once a track id occupies a lane, its index\n * stays fixed for the engine's lifetime. The given list must therefore start\n * with the already-declared lane ids in their current order and may only\n * append new track ids after them. Entries carrying `sends` replace that\n * track's send list; entries without `sends` leave existing sends untouched.\n *\n * @param lanes Track ids or lane descriptors in the desired lane order.\n */\nexport function setTrackLanes(\n ctx: EngineMixerContext,\n lanes: ReadonlyArray<number | EngineTrackLane>,\n): void {\n const { entries, ids } = normalizeTrackLanes(ctx.trackLaneIds, lanes);\n for (const entry of entries) {\n if (entry.sends) {\n ctx.trackSends.set(\n entry.trackId,\n entry.sends.map((send) => ({ ...send })),\n );\n }\n if (entry.outputBusId !== undefined) {\n if (entry.outputBusId === 0) {\n ctx.trackOutputBus.delete(entry.trackId);\n } else {\n ctx.trackOutputBus.set(entry.trackId, entry.outputBusId);\n }\n }\n }\n ctx.trackLaneIds.splice(0, ctx.trackLaneIds.length, ...ids);\n ctx.syncMixer();\n}\n\n/**\n * Routes a track lane's post-fader output into a declared bus instead of\n * the master mix (group/folder routing); busId 0 restores the master mix.\n */\nexport function setTrackOutputBus(\n ctx: EngineMixerContext,\n target: string | number,\n busId: number,\n): void {\n const laneIndex = ctx.ensureTrackLane(target);\n const trackId = ctx.trackLaneIds[laneIndex];\n if (busId === 0) {\n ctx.trackOutputBus.delete(trackId);\n } else {\n ctx.trackOutputBus.set(trackId, busId);\n }\n ctx.syncMixer();\n}\n\n/**\n * Keys one insert of a lane strip from another lane's post-strip pre-fader\n * audio (ducking/sidechainRouter inserts). sourceTarget null removes the\n * binding.\n */\nexport function setLaneSidechain(\n ctx: EngineMixerContext,\n target: string | number,\n insertIndex: number,\n sourceTarget: string | number | null,\n): void {\n const laneIndex = ctx.ensureTrackLane(target);\n const trackId = ctx.trackLaneIds[laneIndex];\n const key = `${trackId}:${insertIndex}`;\n let sourceTrackId = 0;\n if (sourceTarget !== null) {\n const sourceIndex = ctx.ensureTrackLane(sourceTarget);\n sourceTrackId = ctx.trackLaneIds[sourceIndex];\n }\n if (sourceTrackId === 0) {\n ctx.laneSidechains.delete(key);\n } else {\n ctx.laneSidechains.set(key, { trackId, insertIndex, sourceTrackId });\n }\n ctx.offlineEngine.setLaneSidechain(trackId, insertIndex, sourceTrackId);\n ctx.postSync({\n type: 'syncMixer',\n lanes: ctx.mixerLanes(),\n laneSidechains: [{ trackId, insertIndex, sourceTrackId }],\n });\n}\n\nexport function setSends(\n ctx: EngineMixerContext,\n target: string | number,\n sends: EngineTrackSend[],\n): void {\n const laneIndex = ctx.ensureTrackLane(target);\n const trackId = ctx.trackLaneIds[laneIndex];\n ctx.trackSends.set(\n trackId,\n sends.map((send) => ({ ...send })),\n );\n ctx.syncMixer();\n}\n\nexport function setTrackBuses(ctx: EngineMixerContext, buses: EngineBus[]): void {\n ctx.buses.splice(0, ctx.buses.length, ...buses.map((bus) => ({ ...bus })));\n ctx.syncMixer();\n}\n\nexport function setBusGain(ctx: EngineMixerContext, busId: number, db: number): boolean {\n const busIndex = ctx.ensureBus(busId);\n ctx.buses[busIndex] = { ...ctx.buses[busIndex], busId, gainDb: db };\n ctx.offlineEngine.setTrackBuses(ctx.buses);\n return ctx.sendSmoothedParam(engineMixerBusTarget(busIndex, ENGINE_MIXER_PARAM_FADER_DB), db);\n}\n\nexport function setBusStripJson(ctx: EngineMixerContext, busId: number, sceneJson: string): void {\n ctx.ensureBus(busId);\n ctx.offlineEngine.setBusStripJson(busId, sceneJson);\n ctx.busStripJson.set(busId, sceneJson);\n ctx.syncMixer();\n}\n","import type { EngineCaptureStatus } from '../index';\nimport type {\n SonareEngineCaptureRequestMessage,\n SonareEngineCaptureResponseMessageInternal,\n SonareEngineClipPageRequestMessage,\n SonareEngineSyncMessage,\n SonareEngineTransportRequestMessage,\n SonareEngineTransportResponseMessage,\n SonareRealtimeVoiceChangerMessage,\n SonareWorkletExternalMidiMessage,\n SonareWorkletMessage,\n} from './messages';\nimport {\n isRecord,\n type SonareEngineCommandRecord,\n type SonareEngineTelemetryRecord,\n type SonareWorkletMeterSnapshot,\n} from './protocol';\n\nexport function isWorkletMessage(value: unknown): value is SonareWorkletMessage {\n if (!isRecord(value) || typeof value.type !== 'string') {\n return false;\n }\n return (\n value.type === 'scheduleInsertAutomation' ||\n value.type === 'setMeterInterval' ||\n value.type === 'destroy'\n );\n}\n\nexport function isEngineCommandRecord(value: unknown): value is SonareEngineCommandRecord {\n return isRecord(value) && typeof value.type === 'number';\n}\n\nexport function isEngineSyncMessage(value: unknown): value is SonareEngineSyncMessage {\n if (!isRecord(value) || typeof value.type !== 'string') {\n return false;\n }\n return (\n value.type === 'syncClips' ||\n value.type === 'syncClipsDelta' ||\n value.type === 'syncClipPageProvider' ||\n value.type === 'syncClipPage' ||\n value.type === 'syncClipPageClear' ||\n value.type === 'syncClipPageCommit' ||\n value.type === 'syncClipPageDestroy' ||\n value.type === 'syncMidiClips' ||\n value.type === 'syncMarkers' ||\n value.type === 'syncMetronome' ||\n value.type === 'syncAutomation' ||\n value.type === 'syncTempo' ||\n value.type === 'syncMixer' ||\n value.type === 'syncCapture' ||\n value.type === 'syncTrackStripEqBand' ||\n value.type === 'syncMasterStripEqBand' ||\n value.type === 'syncTrackStripInsertBypassed' ||\n value.type === 'syncMasterStripInsertBypassed' ||\n value.type === 'syncTrackStripInsertParamByName' ||\n value.type === 'syncMasterStripInsertParamByName' ||\n value.type === 'syncBusStripInsertParamByName' ||\n value.type === 'syncTrackStripPan' ||\n value.type === 'syncTrackStripPanLaw' ||\n value.type === 'syncTrackStripPanMode' ||\n value.type === 'syncTrackStripDualPan' ||\n value.type === 'syncTrackStripChannelDelaySamples' ||\n value.type === 'syncBuiltinInstrument' ||\n value.type === 'syncSynthInstrument' ||\n value.type === 'syncSf2Instrument' ||\n value.type === 'syncLoadSoundFont' ||\n value.type === 'syncMidiFx' ||\n value.type === 'syncClearMidiFx' ||\n value.type === 'syncMidiNoteOn' ||\n value.type === 'syncMidiNoteOff' ||\n value.type === 'syncMidiCc' ||\n value.type === 'syncMidiUmp' ||\n value.type === 'syncMidiSysex' ||\n value.type === 'syncMidiPanic' ||\n value.type === 'syncMidiDestinationExternal' ||\n value.type === 'syncExternalMidiClock' ||\n value.type === 'destroy'\n );\n}\n\nexport function isEngineCaptureRequestMessage(\n value: unknown,\n): value is SonareEngineCaptureRequestMessage {\n return (\n isRecord(value) &&\n value.type === 'captureRequest' &&\n typeof value.requestId === 'number' &&\n (value.op === 'status' || value.op === 'read' || value.op === 'reset')\n );\n}\n\nfunction isCaptureStatus(value: unknown): value is EngineCaptureStatus {\n return (\n isRecord(value) &&\n typeof value.capturedFrames === 'number' &&\n Number.isSafeInteger(value.capturedFrames) &&\n value.capturedFrames >= 0 &&\n typeof value.overflowCount === 'number' &&\n Number.isSafeInteger(value.overflowCount) &&\n value.overflowCount >= 0 &&\n typeof value.armed === 'boolean' &&\n typeof value.punchEnabled === 'boolean' &&\n (value.source === 'input' || value.source === 'output') &&\n typeof value.recordOffsetSamples === 'number' &&\n Number.isSafeInteger(value.recordOffsetSamples)\n );\n}\n\nfunction isCaptureChannel(value: unknown): value is Float32Array {\n // Capture responses are transferred out of the worklet. A typed view onto\n // the WASM heap or a SharedArrayBuffer must not cross that boundary: the\n // former can be detached by memory growth and the latter cannot be listed\n // in a transfer list. `instanceof` also rejects boxed number arrays.\n return (\n value instanceof Float32Array &&\n typeof ArrayBuffer !== 'undefined' &&\n value.buffer instanceof ArrayBuffer\n );\n}\n\nfunction isCaptureChannels(value: unknown): value is Float32Array[] {\n return Array.isArray(value) && value.every((channel) => isCaptureChannel(channel));\n}\n\nfunction hasOwn(value: Record<string, unknown>, key: string): boolean {\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Object.hasOwn is newer than the ES2020 target.\n return Object.prototype.hasOwnProperty.call(value, key);\n}\n\n/** Return a request ID even when the response payload itself is malformed. */\nexport function engineCaptureResponseRequestId(value: unknown): number | undefined {\n if (\n !isRecord(value) ||\n value.type !== 'captureResponse' ||\n typeof value.requestId !== 'number' ||\n !Number.isSafeInteger(value.requestId)\n ) {\n return undefined;\n }\n return value.requestId;\n}\n\nexport function isEngineCaptureResponseMessage(\n value: unknown,\n): value is SonareEngineCaptureResponseMessageInternal {\n const requestId = engineCaptureResponseRequestId(value);\n if (requestId === undefined || !isRecord(value)) {\n return false;\n }\n if (value.ok === false) {\n return (\n typeof value.error === 'string' && !hasOwn(value, 'status') && !hasOwn(value, 'channels')\n );\n }\n if (value.ok !== true || hasOwn(value, 'error')) {\n return false;\n }\n const hasStatus = hasOwn(value, 'status');\n const hasChannels = hasOwn(value, 'channels');\n if (hasStatus && hasChannels) {\n return false;\n }\n if (hasStatus) {\n return isCaptureStatus(value.status);\n }\n if (hasChannels) {\n return isCaptureChannels(value.channels);\n }\n return true;\n}\n\n/**\n * Check that a strict success response belongs to the requested operation.\n * Failure responses are operation-independent and are therefore valid for\n * every pending request (the node rejects them after this check).\n */\nexport function isEngineCaptureResponseForOperation(\n response: SonareEngineCaptureResponseMessageInternal,\n op: SonareEngineCaptureRequestMessage['op'],\n): boolean {\n if (!response.ok) {\n return true;\n }\n switch (op) {\n case 'status':\n return 'status' in response;\n case 'read':\n return 'channels' in response;\n case 'reset':\n return !('status' in response) && !('channels' in response);\n }\n}\n\nexport function isEngineTransportRequestMessage(\n value: unknown,\n): value is SonareEngineTransportRequestMessage {\n return (\n isRecord(value) &&\n value.type === 'transportRequest' &&\n typeof value.requestId === 'number' &&\n value.op === 'state'\n );\n}\n\nexport function isEngineTransportResponseMessage(\n value: unknown,\n): value is SonareEngineTransportResponseMessage {\n return (\n isRecord(value) &&\n value.type === 'transportResponse' &&\n typeof value.requestId === 'number' &&\n typeof value.ok === 'boolean'\n );\n}\n\nexport function isRealtimeVoiceChangerMessage(\n value: unknown,\n): value is SonareRealtimeVoiceChangerMessage {\n if (!isRecord(value) || typeof value.type !== 'string') {\n return false;\n }\n return value.type === 'setConfig' || value.type === 'reset' || value.type === 'destroy';\n}\n\nexport function isEngineTelemetryRecord(value: unknown): value is SonareEngineTelemetryRecord {\n return (\n isRecord(value) &&\n typeof value.type === 'number' &&\n typeof value.error === 'number' &&\n typeof value.renderFrame === 'number' &&\n typeof value.timelineSample === 'number' &&\n typeof value.audibleTimelineSample === 'number' &&\n typeof value.graphLatencySamplesQ8 === 'number' &&\n typeof value.value === 'number'\n );\n}\n\nexport function isExternalMidiBatchMessage(\n value: unknown,\n): value is SonareWorkletExternalMidiMessage {\n return isRecord(value) && value.type === 'externalMidi' && Array.isArray(value.events);\n}\n\nexport function isClipPageRequestMessage(\n value: unknown,\n): value is SonareEngineClipPageRequestMessage {\n return (\n isRecord(value) &&\n value.type === 'clipPageRequest' &&\n Array.isArray(value.requests) &&\n value.requests.every(\n (request) =>\n isRecord(request) &&\n typeof request.clipId === 'number' &&\n typeof request.pageIndex === 'number',\n )\n );\n}\n\nexport function isMeterSnapshot(value: unknown): value is SonareWorkletMeterSnapshot {\n return (\n isRecord(value) &&\n value.type === 'meter' &&\n typeof value.frame === 'number' &&\n typeof value.peakDbL === 'number' &&\n typeof value.peakDbR === 'number' &&\n typeof value.rmsDbL === 'number' &&\n typeof value.rmsDbR === 'number' &&\n typeof value.correlation === 'number' &&\n (typeof value.targetId === 'number' || value.targetId === undefined)\n );\n}\n","import type { EngineCaptureStatus, EngineTransportState } from '../index';\nimport { engineCapabilities } from '../index';\nimport {\n engineCaptureResponseRequestId,\n isClipPageRequestMessage,\n isEngineCaptureResponseForOperation,\n isEngineCaptureResponseMessage,\n isEngineTelemetryRecord,\n isEngineTransportResponseMessage,\n isExternalMidiBatchMessage,\n isMeterSnapshot,\n} from './guards';\nimport type {\n SonareEngineCaptureRequestMessage,\n SonareEngineCaptureResponseMessageInternal,\n SonareEngineClipPageRequestMessage,\n SonareEngineSyncErrorMessage,\n SonareEngineTransportResponseMessage,\n SonareRealtimeEngineNodeCapabilities,\n SonareRealtimeEngineNodeOptions,\n SonareRealtimeEngineWorkletProcessorOptions,\n SonareWorkletExternalMidiEvent,\n} from './messages';\nimport {\n createSonareClipPageRequestRingBuffer,\n createSonareEngineCommandRingBuffer,\n createSonareEngineTelemetryRingBuffer,\n createSonareExternalMidiRingBuffer,\n createSonareMeterRingBuffer,\n createSonareScopeRingBuffer,\n isRecord,\n pushSonareEngineCommandRingBuffer,\n readSonareClipPageRequestRingBuffer,\n readSonareEngineTelemetryRingBuffer,\n readSonareExternalMidiRingBuffer,\n readSonareMeterRingBuffer,\n readSonareScopeRingBuffer,\n type SonareClipPageRequestRingBuffer,\n type SonareEngineCommandRecord,\n type SonareEngineCommandRingBuffer,\n SonareEngineCommandType,\n type SonareEngineTelemetryRecord,\n type SonareEngineTelemetryRingBuffer,\n type SonareExternalMidiRingBuffer,\n type SonareMeterRingBuffer,\n type SonareScopeRingBuffer,\n type SonareWorkletMeterSnapshot,\n type SonareWorkletScopeSnapshot,\n} from './protocol';\n\nfunction isFiniteInteger(value: number | bigint | undefined): boolean {\n if (value === undefined) {\n return true;\n }\n return typeof value === 'bigint' || (Number.isFinite(value) && Number.isSafeInteger(value));\n}\n\nfunction isTrackMonitorMode(value: number | bigint | undefined): boolean {\n if (value === undefined) {\n return false;\n }\n const mode = typeof value === 'bigint' ? Number(value) : value;\n return typeof mode === 'number' && Number.isSafeInteger(mode) && mode >= 0 && mode <= 2;\n}\n\n/** A track-monitor command cannot infer a lane: its target is a uint32 index. */\nfunction isTrackMonitorLaneIndex(value: number | undefined): boolean {\n return (\n typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 && value <= 0xffff_ffff\n );\n}\n\nfunction isValidCommandRecord(command: SonareEngineCommandRecord): boolean {\n const type = Number(command.type);\n if (\n !Number.isSafeInteger(type) ||\n type < SonareEngineCommandType.SetParam ||\n (type > SonareEngineCommandType.SeekMarker &&\n type !== SonareEngineCommandType.SetTrackMonitorMode)\n ) {\n return false;\n }\n return (\n (command.targetId === undefined || Number.isSafeInteger(command.targetId)) &&\n (command.argFloat === undefined || Number.isFinite(command.argFloat)) &&\n isFiniteInteger(command.argInt) &&\n isFiniteInteger(command.sampleTime) &&\n (type !== SonareEngineCommandType.SetTrackMonitorMode ||\n (isTrackMonitorLaneIndex(command.targetId) && isTrackMonitorMode(command.argInt)))\n );\n}\n\nconst AUDIO_WORKLET_RENDER_QUANTUM = 128;\n\nfunction workletBlockSize(blockSize: number | undefined): number {\n const resolved = blockSize ?? AUDIO_WORKLET_RENDER_QUANTUM;\n if (!Number.isSafeInteger(resolved) || resolved < AUDIO_WORKLET_RENDER_QUANTUM) {\n throw new RangeError(\n `blockSize must be an integer of at least ${AUDIO_WORKLET_RENDER_QUANTUM} frames`,\n );\n }\n return resolved;\n}\n\nexport class SonareRealtimeEngineNode {\n readonly node: AudioWorkletNode;\n readonly capabilities: SonareRealtimeEngineNodeCapabilities;\n readonly commandRing?: SonareEngineCommandRingBuffer;\n readonly telemetryRing?: SonareEngineTelemetryRingBuffer;\n readonly meterRing?: SonareMeterRingBuffer;\n readonly scopeRing?: SonareScopeRingBuffer;\n readonly clipPageRequestRing?: SonareClipPageRequestRingBuffer;\n readonly externalMidiRing?: SonareExternalMidiRingBuffer;\n readonly ready: Promise<void>;\n private telemetryReadIndex = 0;\n private meterReadIndex = 0;\n private scopeReadIndex = 0;\n private clipPageRequestDroppedRead = 0;\n private ringPollTimer: ReturnType<typeof setInterval> | undefined;\n private telemetryListeners = new Set<(telemetry: SonareEngineTelemetryRecord) => void>();\n private meterListeners = new Set<(meter: SonareWorkletMeterSnapshot) => void>();\n private scopeListeners = new Set<(scope: SonareWorkletScopeSnapshot) => void>();\n private midiOutListeners = new Set<(events: SonareWorkletExternalMidiEvent[]) => void>();\n private clipPageRequestListeners = new Set<\n (message: SonareEngineClipPageRequestMessage) => void\n >();\n private syncErrorListeners = new Set<(message: SonareEngineSyncErrorMessage) => void>();\n private captureRequestId = 1;\n private readonly captureRequests = new Map<\n number,\n {\n op: SonareEngineCaptureRequestMessage['op'];\n resolve: (response: SonareEngineCaptureResponseMessageInternal) => void;\n reject: (reason?: unknown) => void;\n }\n >();\n private transportRequestId = 1;\n private readonly transportRequests = new Map<\n number,\n {\n resolve: (response: SonareEngineTransportResponseMessage) => void;\n reject: (reason?: unknown) => void;\n }\n >();\n private resolveReady!: () => void;\n private rejectReady!: (reason?: unknown) => void;\n private destroyed = false;\n\n private constructor(\n node: AudioWorkletNode,\n capabilities: SonareRealtimeEngineNodeCapabilities,\n commandRing?: SonareEngineCommandRingBuffer,\n telemetryRing?: SonareEngineTelemetryRingBuffer,\n meterRing?: SonareMeterRingBuffer,\n scopeRing?: SonareScopeRingBuffer,\n clipPageRequestRing?: SonareClipPageRequestRingBuffer,\n externalMidiRing?: SonareExternalMidiRingBuffer,\n ) {\n this.node = node;\n this.capabilities = capabilities;\n this.commandRing = commandRing;\n this.telemetryRing = telemetryRing;\n this.meterRing = meterRing;\n this.scopeRing = scopeRing;\n this.clipPageRequestRing = clipPageRequestRing;\n this.externalMidiRing = externalMidiRing;\n this.ready = new Promise((resolve, reject) => {\n this.resolveReady = resolve;\n this.rejectReady = reject;\n });\n if (!capabilities.readyMessage) {\n this.resolveReady();\n }\n this.node.port.onmessage = (event: MessageEvent<unknown>) => {\n const captureRequestId = engineCaptureResponseRequestId(event.data);\n if (captureRequestId !== undefined) {\n const pending = this.captureRequests.get(captureRequestId);\n if (pending) {\n this.captureRequests.delete(captureRequestId);\n if (!isEngineCaptureResponseMessage(event.data)) {\n pending.reject(new Error('Malformed capture response.'));\n } else if (!isEngineCaptureResponseForOperation(event.data, pending.op)) {\n pending.reject(new Error('Capture response does not match request operation.'));\n } else if (event.data.ok) {\n pending.resolve(event.data);\n } else {\n pending.reject(new Error(event.data.error));\n }\n }\n } else if (isEngineTransportResponseMessage(event.data)) {\n const pending = this.transportRequests.get(event.data.requestId);\n if (pending) {\n this.transportRequests.delete(event.data.requestId);\n if (event.data.ok) {\n pending.resolve(event.data);\n } else {\n pending.reject(new Error(event.data.error ?? 'Transport request failed'));\n }\n }\n } else if (isEngineTelemetryRecord(event.data)) {\n this.emitTelemetry(event.data);\n } else if (isMeterSnapshot(event.data)) {\n this.emitMeter(event.data);\n } else if (isExternalMidiBatchMessage(event.data)) {\n this.emitMidiOut(event.data.events);\n } else if (isClipPageRequestMessage(event.data)) {\n this.emitClipPageRequests(event.data);\n } else if (isRecord(event.data) && event.data.type === 'syncError') {\n const syncError: SonareEngineSyncErrorMessage = {\n type: 'syncError',\n syncType: String(event.data.syncType) as SonareEngineSyncErrorMessage['syncType'],\n message: String(event.data.message ?? 'AudioWorklet sync failed'),\n };\n for (const listener of this.syncErrorListeners) {\n listener(syncError);\n }\n } else if (isRecord(event.data) && event.data.type === 'ready') {\n this.resolveReady();\n } else if (isRecord(event.data) && event.data.type === 'error') {\n this.rejectReady(new Error(String(event.data.message ?? 'AudioWorklet error')));\n }\n };\n }\n\n /** Subscribes to control-plane sync rejections reported by the worklet. */\n onSyncError(listener: (message: SonareEngineSyncErrorMessage) => void): () => void {\n this.syncErrorListeners.add(listener);\n return () => this.syncErrorListeners.delete(listener);\n }\n\n static async create(\n context: BaseAudioContext,\n options: SonareRealtimeEngineNodeOptions = {},\n ): Promise<SonareRealtimeEngineNode> {\n const blockSize = workletBlockSize(options.blockSize);\n const processorName = options.processorName ?? 'sonare-realtime-engine-processor';\n const moduleUrl = options.moduleUrl;\n if (moduleUrl && context.audioWorklet?.addModule) {\n await context.audioWorklet.addModule(moduleUrl);\n }\n const detectedCapabilities =\n options.engineAbiVersion !== undefined\n ? {\n engineAbiVersion: options.engineAbiVersion,\n expectedEngineAbiVersion: options.expectedEngineAbiVersion ?? options.engineAbiVersion,\n abiCompatible:\n options.engineAbiVersion ===\n (options.expectedEngineAbiVersion ?? options.engineAbiVersion),\n }\n : engineCapabilities();\n if (options.requireAbiCompatible !== false && detectedCapabilities?.abiCompatible === false) {\n throw new Error(\n `Engine ABI mismatch: wasm=${detectedCapabilities.engineAbiVersion}, expected=${detectedCapabilities.expectedEngineAbiVersion}`,\n );\n }\n const sharedArrayBuffer = typeof globalThis.SharedArrayBuffer === 'function';\n const atomics = typeof globalThis.Atomics === 'object';\n const audioWorklet = typeof AudioWorkletNode !== 'undefined' || !!options.nodeFactory;\n const degradedReason =\n options.mode !== 'postMessage' && (!sharedArrayBuffer || !atomics)\n ? 'SharedArrayBuffer or Atomics unavailable; using postMessage transport.'\n : undefined;\n const mode =\n options.mode === 'postMessage' || !sharedArrayBuffer || !atomics ? 'postMessage' : 'sab';\n if (options.mode === 'sab' && mode !== 'sab') {\n throw new Error(\n 'SharedArrayBuffer mode requested but SharedArrayBuffer/Atomics are unavailable.',\n );\n }\n\n const commandRing =\n mode === 'sab'\n ? createSonareEngineCommandRingBuffer(options.commandRingCapacity ?? 128)\n : undefined;\n const telemetryRing =\n mode === 'sab'\n ? createSonareEngineTelemetryRingBuffer(options.telemetryRingCapacity ?? 128)\n : undefined;\n // Meter ring: the engine publishes meters into a SAB ring. Lock-free meter\n // delivery matches the telemetry path and keeps the audio render callback\n // allocation-free in SAB mode.\n const meterRing =\n mode === 'sab' ? createSonareMeterRingBuffer(options.meterRingCapacity ?? 128) : undefined;\n // Scope ring (FFT spectrum + goniometer): opt-in. The per-block FFT is\n // heavier than the meter path, so it is created only when the caller\n // requests scope telemetry via scopeIntervalFrames > 0.\n const scopeIntervalFrames = Math.max(0, Math.floor(options.scopeIntervalFrames ?? 0));\n const scopeRing =\n mode === 'sab' && scopeIntervalFrames > 0\n ? createSonareScopeRingBuffer(options.scopeRingCapacity ?? 64, options.scopeBands ?? 48)\n : undefined;\n // Paged-clip cache misses are a worklet-to-main-thread control signal. A\n // dedicated SPSC SAB ring keeps process() free of both embind request\n // objects and postMessage structured cloning.\n const clipPageRequestRing =\n mode === 'sab'\n ? createSonareClipPageRequestRingBuffer(options.clipPageRequestRingCapacity ?? 128)\n : undefined;\n const externalMidiRing =\n mode === 'sab'\n ? createSonareExternalMidiRingBuffer(options.externalMidiRingCapacity ?? 256)\n : undefined;\n const channelCount = Math.max(1, Math.floor(options.channelCount ?? 2));\n const cueOutput = options.cueOutput === true;\n const processorOptions: SonareRealtimeEngineWorkletProcessorOptions = {\n sampleRate: options.sampleRate ?? context.sampleRate,\n blockSize,\n channelCount,\n cueOutput,\n commandSharedBuffer: commandRing?.sharedBuffer,\n commandRingCapacity: commandRing?.capacity,\n telemetrySharedBuffer: telemetryRing?.sharedBuffer,\n telemetryRingCapacity: telemetryRing?.capacity,\n meterSharedBuffer: meterRing?.sharedBuffer,\n meterRingCapacity: meterRing?.capacity,\n scopeSharedBuffer: scopeRing?.sharedBuffer,\n scopeRingCapacity: scopeRing?.capacity,\n scopeBands: scopeRing?.bands,\n scopeIntervalFrames: scopeRing ? scopeIntervalFrames : undefined,\n clipPageRequestSharedBuffer: clipPageRequestRing?.sharedBuffer,\n clipPageRequestRingCapacity: clipPageRequestRing?.capacity,\n externalMidiSharedBuffer: externalMidiRing?.sharedBuffer,\n externalMidiRingCapacity: externalMidiRing?.capacity,\n wasmBinary: options.wasmBinary,\n initialSyncMessages: options.initialSyncMessages,\n initialCommands: options.initialCommands,\n };\n const factory =\n options.nodeFactory ??\n ((ctx: BaseAudioContext, name: string, nodeOptions: AudioWorkletNodeOptions) =>\n new AudioWorkletNode(ctx, name, nodeOptions));\n const node = factory(context, processorName, {\n numberOfInputs: 1,\n // The cue bus needs its own output; a single-output node keeps the\n // historical mix where process() folds the cue into the program.\n numberOfOutputs: cueOutput ? 2 : 1,\n outputChannelCount: cueOutput ? [channelCount, channelCount] : [channelCount],\n processorOptions,\n });\n return new SonareRealtimeEngineNode(\n node,\n {\n mode,\n runtimeTarget: 'embind',\n sharedArrayBuffer,\n atomics,\n audioWorklet,\n clipPageRequestsRealtimeSafe: mode === 'sab',\n externalMidiRealtimeSafe: mode === 'sab',\n cueOutput,\n engineAbiVersion: detectedCapabilities?.engineAbiVersion,\n expectedEngineAbiVersion: detectedCapabilities?.expectedEngineAbiVersion,\n abiCompatible: detectedCapabilities?.abiCompatible,\n degradedReason,\n // A processor posts ready/error irrespective of whether its module was\n // loaded here or registered by the host beforehand. Waiting in both\n // cases is the only way to surface a failed worklet-side WASM init.\n readyMessage: true,\n },\n commandRing,\n telemetryRing,\n meterRing,\n scopeRing,\n clipPageRequestRing,\n externalMidiRing,\n );\n }\n\n play(sampleTime = -1): boolean {\n return this.sendCommand({ type: SonareEngineCommandType.TransportPlay, sampleTime });\n }\n\n stop(sampleTime = -1): boolean {\n return this.sendCommand({ type: SonareEngineCommandType.TransportStop, sampleTime });\n }\n\n seekSample(timelineSample: number, sampleTime = -1): boolean {\n return this.sendCommand({\n type: SonareEngineCommandType.TransportSeekSample,\n sampleTime,\n argInt: timelineSample,\n });\n }\n\n seekPpq(ppq: number, sampleTime = -1): boolean {\n if (!Number.isFinite(ppq) || !Number.isSafeInteger(sampleTime)) {\n return false;\n }\n return this.sendCommand({\n type: SonareEngineCommandType.TransportSeekPpq,\n sampleTime,\n argFloat: ppq,\n });\n }\n\n sendCommand(command: SonareEngineCommandRecord): boolean {\n if (this.destroyed || !isValidCommandRecord(command)) {\n return false;\n }\n if (this.commandRing) {\n return pushSonareEngineCommandRingBuffer(this.commandRing, command);\n }\n this.node.port.postMessage(command);\n return true;\n }\n\n requestCaptureStatus(): Promise<EngineCaptureStatus> {\n return this.sendCaptureRequest('status').then((response) => {\n if (!response.ok || !('status' in response)) {\n throw new Error('Capture status response is missing status.');\n }\n return response.status;\n });\n }\n\n requestCapturedAudio(): Promise<Float32Array[]> {\n return this.sendCaptureRequest('read').then((response) => {\n if (!response.ok || !('channels' in response)) {\n throw new Error('Capture read response is missing channels.');\n }\n return response.channels;\n });\n }\n\n requestCaptureReset(): Promise<void> {\n return this.sendCaptureRequest('reset').then(() => undefined);\n }\n\n requestTransportState(): Promise<EngineTransportState> {\n return this.sendTransportRequest().then((response) => {\n if (!response.state) {\n throw new Error('Transport state response is missing state.');\n }\n return response.state;\n });\n }\n\n pollTelemetry(): SonareEngineTelemetryRecord[] {\n if (!this.telemetryRing) {\n return [];\n }\n const read = readSonareEngineTelemetryRingBuffer(this.telemetryRing, this.telemetryReadIndex);\n this.telemetryReadIndex = read.nextReadIndex;\n for (const telemetry of read.telemetry) {\n this.emitTelemetry(telemetry);\n }\n return read.telemetry;\n }\n\n // Drains any meters published into the SAB meter ring (embind SAB mode) and\n // forwards them to onMeter listeners. In postMessage mode meters arrive via\n // node.port.onmessage instead, so this is a no-op then.\n pollMeters(): SonareWorkletMeterSnapshot[] {\n if (!this.meterRing) {\n return [];\n }\n const read = readSonareMeterRingBuffer(this.meterRing, this.meterReadIndex);\n this.meterReadIndex = read.nextReadIndex;\n for (const meter of read.meters) {\n this.emitMeter(meter);\n }\n return read.meters;\n }\n\n // Drains scope telemetry (FFT spectrum + goniometer points) published into the\n // SAB scope ring and forwards each record to onScope listeners. A no-op unless\n // the node was created with scopeIntervalFrames > 0 (embind SAB mode).\n pollScope(): SonareWorkletScopeSnapshot[] {\n if (!this.scopeRing) {\n return [];\n }\n const read = readSonareScopeRingBuffer(this.scopeRing, this.scopeReadIndex);\n this.scopeReadIndex = read.nextReadIndex;\n for (const scope of read.scopes) {\n this.emitScope(scope);\n }\n return read.scopes;\n }\n\n /** Drain lowered MIDI-1 records from the SAB ring on the main thread. */\n pollMidiOut(): SonareWorkletExternalMidiEvent[] {\n if (!this.externalMidiRing) {\n return [];\n }\n const read = readSonareExternalMidiRingBuffer(this.externalMidiRing);\n const events = read.events.map((event) => {\n const bytes: number[] = [];\n for (let index = 0; index < event.byteCount; index++) {\n bytes.push((event.byteWord >>> (8 * index)) & 0xff);\n }\n return {\n destinationId: event.destinationId,\n renderFrame: event.renderFrame,\n bytes,\n };\n });\n if (events.length > 0) {\n this.emitMidiOut(events);\n }\n return events;\n }\n\n /**\n * Drains bounded paged-clip misses from the SAB ring and forwards one batch\n * to subscribers. In postMessage mode the legacy handler remains available,\n * but that degraded path is not realtime-safe for OPFS streaming.\n */\n pollClipPageRequests(): SonareEngineClipPageRequestMessage | undefined {\n if (!this.clipPageRequestRing) {\n return undefined;\n }\n const read = readSonareClipPageRequestRingBuffer(this.clipPageRequestRing);\n const dropped = (read.dropped - this.clipPageRequestDroppedRead) >>> 0;\n this.clipPageRequestDroppedRead = read.dropped;\n if (read.requests.length === 0 && dropped === 0) {\n return undefined;\n }\n const message: SonareEngineClipPageRequestMessage = {\n type: 'clipPageRequest',\n requests: read.requests,\n ...(dropped > 0 ? { dropped } : {}),\n };\n this.emitClipPageRequests(message);\n return message;\n }\n\n onTelemetry(callback: (telemetry: SonareEngineTelemetryRecord) => void): () => void {\n this.telemetryListeners.add(callback);\n this.startRingPolling();\n return () => {\n this.telemetryListeners.delete(callback);\n this.stopRingPollingIfUnused();\n };\n }\n\n onMeter(callback: (meter: SonareWorkletMeterSnapshot) => void): () => void {\n this.meterListeners.add(callback);\n this.startRingPolling();\n return () => {\n this.meterListeners.delete(callback);\n this.stopRingPollingIfUnused();\n };\n }\n\n onScope(callback: (scope: SonareWorkletScopeSnapshot) => void): () => void {\n this.scopeListeners.add(callback);\n this.startRingPolling();\n return () => {\n this.scopeListeners.delete(callback);\n this.stopRingPollingIfUnused();\n };\n }\n\n /**\n * Subscribe to external-MIDI batches drained from the engine (one call per\n * render block that produced events), already lowered to MIDI 1.0 bytes for a\n * Web MIDI output port. Returns an unsubscribe function.\n */\n onMidiOut(callback: (events: SonareWorkletExternalMidiEvent[]) => void): () => void {\n this.midiOutListeners.add(callback);\n this.startRingPolling();\n return () => {\n this.midiOutListeners.delete(callback);\n this.stopRingPollingIfUnused();\n };\n }\n\n /**\n * Subscribe to bounded batches of paged-clip misses from the worklet. The\n * callback runs on the main thread and may initiate asynchronous OPFS I/O.\n */\n onClipPageRequests(callback: (message: SonareEngineClipPageRequestMessage) => void): () => void {\n this.clipPageRequestListeners.add(callback);\n return () => {\n this.clipPageRequestListeners.delete(callback);\n };\n }\n\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n this.destroyed = true;\n if (this.ringPollTimer !== undefined) {\n clearInterval(this.ringPollTimer);\n this.ringPollTimer = undefined;\n }\n this.node.port.postMessage({ type: 'destroy' });\n this.node.disconnect();\n for (const pending of this.captureRequests.values()) {\n pending.reject(new Error('Realtime engine node is destroyed.'));\n }\n this.captureRequests.clear();\n for (const pending of this.transportRequests.values()) {\n pending.reject(new Error('Realtime engine node is destroyed.'));\n }\n this.transportRequests.clear();\n this.telemetryListeners.clear();\n this.meterListeners.clear();\n this.scopeListeners.clear();\n this.midiOutListeners.clear();\n this.clipPageRequestListeners.clear();\n }\n\n private emitTelemetry(telemetry: SonareEngineTelemetryRecord): void {\n for (const listener of this.telemetryListeners) {\n listener(telemetry);\n }\n }\n\n private startRingPolling(): void {\n if (\n this.ringPollTimer !== undefined ||\n (!this.telemetryRing && !this.meterRing && !this.scopeRing && !this.externalMidiRing)\n ) {\n return;\n }\n const poll = () => {\n if (!this.destroyed) {\n this.pollTelemetry();\n this.pollMeters();\n this.pollScope();\n this.pollMidiOut();\n }\n };\n poll();\n this.ringPollTimer = setInterval(poll, 16);\n }\n\n private stopRingPollingIfUnused(): void {\n if (\n this.ringPollTimer !== undefined &&\n this.telemetryListeners.size === 0 &&\n this.meterListeners.size === 0 &&\n this.scopeListeners.size === 0 &&\n this.midiOutListeners.size === 0\n ) {\n clearInterval(this.ringPollTimer);\n this.ringPollTimer = undefined;\n }\n }\n\n private emitMeter(meter: SonareWorkletMeterSnapshot): void {\n for (const listener of this.meterListeners) {\n listener(meter);\n }\n }\n\n private emitMidiOut(events: SonareWorkletExternalMidiEvent[]): void {\n for (const listener of this.midiOutListeners) {\n listener(events);\n }\n }\n\n private emitClipPageRequests(message: SonareEngineClipPageRequestMessage): void {\n for (const listener of this.clipPageRequestListeners) {\n listener(message);\n }\n }\n\n private emitScope(scope: SonareWorkletScopeSnapshot): void {\n for (const listener of this.scopeListeners) {\n listener(scope);\n }\n }\n\n private sendCaptureRequest(\n op: SonareEngineCaptureRequestMessage['op'],\n ): Promise<SonareEngineCaptureResponseMessageInternal> {\n if (this.destroyed) {\n return Promise.reject(new Error('Realtime engine node is destroyed.'));\n }\n const requestId = this.captureRequestId++;\n let rejectRequest!: (reason?: unknown) => void;\n const promise = new Promise<SonareEngineCaptureResponseMessageInternal>((resolve, reject) => {\n rejectRequest = reject;\n this.captureRequests.set(requestId, { op, resolve, reject });\n });\n try {\n this.node.port.postMessage({ type: 'captureRequest', requestId, op });\n } catch (error) {\n this.captureRequests.delete(requestId);\n rejectRequest(error);\n }\n return promise;\n }\n\n private sendTransportRequest(): Promise<SonareEngineTransportResponseMessage> {\n if (this.destroyed) {\n return Promise.reject(new Error('Realtime engine node is destroyed.'));\n }\n const requestId = this.transportRequestId++;\n const promise = new Promise<SonareEngineTransportResponseMessage>((resolve, reject) => {\n this.transportRequests.set(requestId, { resolve, reject });\n });\n this.node.port.postMessage({ type: 'transportRequest', requestId, op: 'state' });\n return promise;\n }\n}\n","import { trackMonitorModeCode } from '../codes';\nimport type {\n EngineAutomationPoint,\n EngineParameterInfo,\n EngineTrackMonitorMode,\n RealtimeEngine,\n} from '../index';\nimport type { SonareEngineSyncMessage } from './messages';\nimport {\n ENGINE_MIXER_PARAM_FADER_DB,\n ENGINE_MIXER_PARAM_PAN,\n engineMixerBusTarget,\n engineMixerLaneTarget,\n engineMixerMasterTarget,\n SonareEngineCommandType,\n} from './protocol';\n\n/**\n * Collaborator surface the parameter / automation-id resolution helpers need\n * from the owning {@link SonareEngine}: the offline engine they mirror into and\n * query, the realtime node they command, the lane/bus declaration helpers, and\n * the declared track-lane id store used to resolve insert-automation ids.\n */\nexport interface EngineParameterContext {\n readonly offlineEngine: RealtimeEngine;\n sendCommand(command: {\n type: SonareEngineCommandType;\n targetId?: number;\n sampleTime?: number;\n argFloat?: number;\n argInt?: number;\n }): boolean;\n postSync(message: SonareEngineSyncMessage): void;\n readonly automationLanes: Map<number, EngineAutomationPoint[]>;\n readonly trackLaneIds: number[];\n resolveParamId(nodeId: string, param: string | number): number;\n ensureTrackLane(target: string | number): number;\n ensureBus(busId: number): number;\n}\n\nexport function setParam(\n ctx: EngineParameterContext,\n nodeId: string,\n param: string | number,\n value: number,\n): boolean {\n const paramId = ctx.resolveParamId(nodeId, param);\n // Mirror the change into the offline engine so a subsequent offline render\n // reflects the live value, then push a sample-accurate command to the\n // realtime runtime (mirrors setTempo/setLoop above).\n ctx.offlineEngine.setParameter(paramId, value);\n return ctx.sendCommand({\n type: SonareEngineCommandType.SetParam,\n targetId: paramId,\n sampleTime: -1,\n argFloat: value,\n });\n}\n\nexport function setSoloMute(\n ctx: EngineParameterContext,\n target: string | number,\n solo: boolean,\n mute: boolean,\n): boolean {\n const laneIndex = ctx.ensureTrackLane(target);\n ctx.offlineEngine.setSoloMute(laneIndex, solo, mute);\n return ctx.sendCommand({\n type: SonareEngineCommandType.SetSoloMute,\n targetId: laneIndex,\n sampleTime: -1,\n argInt: (mute ? 0x1 : 0) | (solo ? 0x2 : 0),\n });\n}\n\nexport function setTrackMonitorMode(\n ctx: EngineParameterContext,\n target: string | number,\n mode: EngineTrackMonitorMode,\n renderFrame = -1,\n): boolean {\n // Resolve the mode before declaring a lane or touching either engine. This\n // keeps booleans, fractions, and unknown spellings from reaching the queue.\n const modeOrdinal = trackMonitorModeCode(mode);\n const laneIndex = ctx.ensureTrackLane(target);\n ctx.offlineEngine.setTrackMonitorMode(\n laneIndex,\n modeOrdinal as EngineTrackMonitorMode,\n renderFrame,\n );\n return ctx.sendCommand({\n type: SonareEngineCommandType.SetTrackMonitorMode,\n targetId: laneIndex,\n sampleTime: renderFrame,\n argInt: modeOrdinal,\n });\n}\n\n/**\n * Returns the automation target id for a mixer strip parameter.\n *\n * The id addresses the engine's reserved mixer namespace, so it can be fed\n * straight to setAutomationLane to automate a fader or pan without\n * registering a parameter.\n *\n * @param target Track id (declares a mixer lane on first use) or 'master'.\n * @param kind Strip parameter to address.\n * @returns Reserved engine parameter id for the strip parameter.\n */\nexport function automationParamId(\n ctx: EngineParameterContext,\n target: string | number,\n kind: 'faderDb' | 'pan',\n): number {\n const paramKind = kind === 'pan' ? ENGINE_MIXER_PARAM_PAN : ENGINE_MIXER_PARAM_FADER_DB;\n if (target === 'master') {\n return engineMixerMasterTarget(paramKind);\n }\n return engineMixerLaneTarget(ctx.ensureTrackLane(target), paramKind);\n}\n\n/**\n * Returns the automation target id for a bus fader.\n *\n * @param busId Bus id (declares the mixer bus on first use).\n * @returns Reserved engine parameter id for the bus fader gain (dB).\n */\nexport function busAutomationParamId(ctx: EngineParameterContext, busId: number): number {\n return engineMixerBusTarget(ctx.ensureBus(busId), ENGINE_MIXER_PARAM_FADER_DB);\n}\n\n/**\n * Resolves a track-lane insert parameter (JSON-key name) to the reserved\n * insert-automation id fed straight to setAutomationLane. Declares the track's\n * mixer lane first (like automationParamId) so the offline engine resolves the\n * same strip selector the realtime engine uses.\n *\n * @param target Track id (declares a mixer lane on first use).\n * @param insertIndex Index into the strip's combined insert sequence.\n * @param paramName Processor JSON-key parameter name.\n * @returns Reserved insert-automation id, or -1 when strip/insert/key unknown.\n */\nexport function resolveTrackInsertAutomationId(\n ctx: EngineParameterContext,\n target: string | number,\n insertIndex: number,\n paramName: string,\n): number {\n const laneIndex = ctx.ensureTrackLane(target);\n return ctx.offlineEngine.resolveTrackInsertAutomationId(\n ctx.trackLaneIds[laneIndex],\n insertIndex,\n paramName,\n );\n}\n\n/**\n * Resolves a master-strip insert parameter to its reserved insert-automation\n * id.\n *\n * @param insertIndex Index into the master strip's insert sequence.\n * @param paramName Processor JSON-key parameter name.\n * @returns Reserved insert-automation id, or -1 when insert/key unknown.\n */\nexport function resolveMasterInsertAutomationId(\n ctx: EngineParameterContext,\n insertIndex: number,\n paramName: string,\n): number {\n return ctx.offlineEngine.resolveMasterInsertAutomationId(insertIndex, paramName);\n}\n\n/**\n * Resolves a bus-strip insert parameter to its reserved insert-automation id.\n * Declares the mixer bus first so the offline engine resolves the same bus\n * selector.\n *\n * @param busId Bus id (declares the mixer bus on first use).\n * @param insertIndex Index into the bus strip's insert sequence.\n * @param paramName Processor JSON-key parameter name.\n * @returns Reserved insert-automation id, or -1 when bus/insert/key unknown.\n */\nexport function resolveBusInsertAutomationId(\n ctx: EngineParameterContext,\n busId: number,\n insertIndex: number,\n paramName: string,\n): number {\n ctx.ensureBus(busId);\n return ctx.offlineEngine.resolveBusInsertAutomationId(busId, insertIndex, paramName);\n}\n\n/**\n * Returns the number of automation lanes installed on the engine, including\n * lanes whose breakpoint list is currently empty.\n *\n * @returns Engine-side automation lane count.\n */\nexport function automationLaneCount(ctx: EngineParameterContext): number {\n return ctx.offlineEngine.automationLaneCount();\n}\n\nexport function listParameters(ctx: EngineParameterContext): EngineParameterInfo[] {\n const parameters: EngineParameterInfo[] = [];\n for (let index = 0; index < ctx.offlineEngine.parameterCount(); index++) {\n parameters.push(ctx.offlineEngine.parameterInfoByIndex(index));\n }\n return parameters;\n}\n\n/** Registers a parameter on both the offline mirror and live worklet engine. */\nexport function addParameter(ctx: EngineParameterContext, info: EngineParameterInfo): void {\n ctx.offlineEngine.addParameter(info);\n ctx.postSync({ type: 'syncParameters', parameters: listParameters(ctx) });\n}\n\n/** Clears registered parameters and their automation lanes on both engines. */\nexport function clearParameters(ctx: EngineParameterContext): void {\n ctx.offlineEngine.clearParameters();\n ctx.automationLanes.clear();\n ctx.postSync({ type: 'syncParameters', parameters: [] });\n}\n","import { panLawCode, panModeCode } from '../codes';\nimport type { EqBand, PanLawInput, PanMode, RealtimeEngine } from '../index';\nimport type { SonareEngineInstrumentSyncMessage, SonareEngineSyncMessage } from './messages';\n\n/**\n * Collaborator surface the strip/pan/EQ/insert/instrument/MIDI setters need from\n * the owning {@link SonareEngine}: the offline engine they mirror writes into,\n * the out-of-band sync posters, and the lane-resolution helpers.\n */\nexport interface EngineStripContext {\n readonly offlineEngine: RealtimeEngine;\n readonly trackLaneIds: number[];\n postSync(message: SonareEngineSyncMessage): void;\n postInstrumentSync(message: SonareEngineInstrumentSyncMessage): void;\n ensureTrackLane(target: string | number): number;\n resolveTargetId(target: string | number): number;\n}\n\nfunction trackIdFor(ctx: EngineStripContext, target: string | number): number {\n return ctx.trackLaneIds[ctx.ensureTrackLane(target)];\n}\n\nexport function setTrackStripJson(\n ctx: EngineStripContext,\n trackId: number,\n sceneJson: string,\n trackStripJson: Map<number, string>,\n): void {\n ctx.offlineEngine.setTrackStripJson(trackId, sceneJson);\n trackStripJson.set(trackId, sceneJson);\n}\n\nexport function setTrackStripEqBand(\n ctx: EngineStripContext,\n target: string | number,\n bandIndex: number,\n band: EqBand | string,\n): void {\n const trackId = trackIdFor(ctx, target);\n const bandJson = typeof band === 'string' ? band : JSON.stringify(band);\n ctx.offlineEngine.setTrackStripEqBandJson(trackId, bandIndex, bandJson);\n ctx.postSync({ type: 'syncTrackStripEqBand', trackId, bandIndex, bandJson });\n}\n\nexport function setTrackStripInsertBypassed(\n ctx: EngineStripContext,\n target: string | number,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass: boolean,\n): void {\n const trackId = trackIdFor(ctx, target);\n ctx.offlineEngine.setTrackStripInsertBypassed(trackId, insertIndex, bypassed, resetOnBypass);\n ctx.postSync({\n type: 'syncTrackStripInsertBypassed',\n trackId,\n insertIndex,\n bypassed,\n resetOnBypass,\n });\n}\n\nexport function setTrackStripInsertParamByName(\n ctx: EngineStripContext,\n target: string | number,\n insertIndex: number,\n paramName: string,\n value: number,\n): void {\n const trackId = trackIdFor(ctx, target);\n ctx.offlineEngine.setTrackStripInsertParamByName(trackId, insertIndex, paramName, value);\n ctx.postSync({ type: 'syncTrackStripInsertParamByName', trackId, insertIndex, paramName, value });\n}\n\nexport function setTrackStripPan(\n ctx: EngineStripContext,\n target: string | number,\n pan: number,\n): void {\n const trackId = trackIdFor(ctx, target);\n ctx.offlineEngine.setTrackStripPan(trackId, pan);\n ctx.postSync({ type: 'syncTrackStripPan', trackId, pan });\n}\n\nexport function setTrackStripPanLaw(\n ctx: EngineStripContext,\n target: string | number,\n panLaw: PanLawInput,\n): void {\n const trackId = trackIdFor(ctx, target);\n const code = panLawCode(panLaw);\n ctx.offlineEngine.setTrackStripPanLaw(trackId, code);\n ctx.postSync({ type: 'syncTrackStripPanLaw', trackId, panLaw: code });\n}\n\nexport function setTrackStripPanMode(\n ctx: EngineStripContext,\n target: string | number,\n panMode: PanMode | number,\n): void {\n const trackId = trackIdFor(ctx, target);\n const code = panModeCode(panMode);\n ctx.offlineEngine.setTrackStripPanMode(trackId, code);\n ctx.postSync({ type: 'syncTrackStripPanMode', trackId, panMode: code });\n}\n\nexport function setTrackStripDualPan(\n ctx: EngineStripContext,\n target: string | number,\n leftPan: number,\n rightPan: number,\n): void {\n const trackId = trackIdFor(ctx, target);\n ctx.offlineEngine.setTrackStripDualPan(trackId, leftPan, rightPan);\n ctx.postSync({ type: 'syncTrackStripDualPan', trackId, leftPan, rightPan });\n}\n\nexport function setTrackStripChannelDelaySamples(\n ctx: EngineStripContext,\n target: string | number,\n delaySamples: number,\n): void {\n const trackId = trackIdFor(ctx, target);\n ctx.offlineEngine.setTrackStripChannelDelaySamples(trackId, delaySamples);\n ctx.postSync({ type: 'syncTrackStripChannelDelaySamples', trackId, delaySamples });\n}\n\nexport function setMasterStripEqBand(\n ctx: EngineStripContext,\n bandIndex: number,\n band: EqBand | string,\n): void {\n const bandJson = typeof band === 'string' ? band : JSON.stringify(band);\n ctx.offlineEngine.setMasterStripEqBandJson(bandIndex, bandJson);\n ctx.postSync({ type: 'syncMasterStripEqBand', bandIndex, bandJson });\n}\n\nexport function setMasterStripInsertBypassed(\n ctx: EngineStripContext,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass: boolean,\n): void {\n ctx.offlineEngine.setMasterStripInsertBypassed(insertIndex, bypassed, resetOnBypass);\n ctx.postSync({ type: 'syncMasterStripInsertBypassed', insertIndex, bypassed, resetOnBypass });\n}\n\nexport function setMasterStripInsertParamByName(\n ctx: EngineStripContext,\n insertIndex: number,\n paramName: string,\n value: number,\n): void {\n ctx.offlineEngine.setMasterStripInsertParamByName(insertIndex, paramName, value);\n ctx.postSync({ type: 'syncMasterStripInsertParamByName', insertIndex, paramName, value });\n}\n\nexport function setBusStripInsertParamByName(\n ctx: EngineStripContext,\n busId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n): void {\n ctx.offlineEngine.setBusStripInsertParamByName(busId, insertIndex, paramName, value);\n ctx.postSync({ type: 'syncBusStripInsertParamByName', busId, insertIndex, paramName, value });\n}\n\nexport function pushMidiNoteOn(\n ctx: EngineStripContext,\n trackId: string | number,\n group: number,\n channel: number,\n note: number,\n velocity: number,\n renderFrame: number,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.pushMidiNoteOn(destinationId, group, channel, note, velocity, renderFrame);\n ctx.postSync({\n type: 'syncMidiNoteOn',\n destinationId,\n group,\n channel,\n note,\n velocity,\n renderFrame,\n });\n}\n\nexport function pushMidiNoteOff(\n ctx: EngineStripContext,\n trackId: string | number,\n group: number,\n channel: number,\n note: number,\n velocity: number,\n renderFrame: number,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.pushMidiNoteOff(destinationId, group, channel, note, velocity, renderFrame);\n ctx.postSync({\n type: 'syncMidiNoteOff',\n destinationId,\n group,\n channel,\n note,\n velocity,\n renderFrame,\n });\n}\n\nexport function pushMidiCc(\n ctx: EngineStripContext,\n trackId: string | number,\n group: number,\n channel: number,\n controller: number,\n value: number,\n renderFrame: number,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.pushMidiCc(destinationId, group, channel, controller, value, renderFrame);\n ctx.postSync({\n type: 'syncMidiCc',\n destinationId,\n group,\n channel,\n controller,\n value,\n renderFrame,\n });\n}\n\nexport function pushMidiUmp(\n ctx: EngineStripContext,\n trackId: string | number,\n word0: number,\n renderFrame: number,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.pushMidiUmp(destinationId, word0, renderFrame);\n ctx.postSync({ type: 'syncMidiUmp', destinationId, word0, renderFrame });\n}\n\nexport function setBuiltinInstrument(\n ctx: EngineStripContext,\n trackId: string | number,\n config: { destinationId?: number } & Record<string, unknown>,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.setBuiltinInstrument(config, destinationId);\n ctx.postInstrumentSync({ type: 'syncBuiltinInstrument', destinationId, config });\n}\n\nexport function setSynthInstrument(\n ctx: EngineStripContext,\n trackId: string | number,\n patch: Record<string, unknown> | string,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.setSynthInstrument(patch, destinationId);\n ctx.postInstrumentSync({ type: 'syncSynthInstrument', destinationId, patch });\n}\n\nexport function loadSoundFont(ctx: EngineStripContext, data: Uint8Array): void {\n ctx.offlineEngine.loadSoundFont(data);\n ctx.postInstrumentSync({ type: 'syncLoadSoundFont', data });\n}\n\nexport function setSf2Instrument(\n ctx: EngineStripContext,\n trackId: string | number,\n config: {\n destinationId?: number;\n gain?: number;\n polyphony?: number;\n preferModelForModeledFamilies?: boolean;\n },\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.setSf2Instrument(config, destinationId);\n ctx.postInstrumentSync({ type: 'syncSf2Instrument', destinationId, config });\n}\n\nexport function setMidiDestinationExternal(\n ctx: EngineStripContext,\n trackId: string | number,\n external: boolean,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.setMidiDestinationExternal(destinationId, external);\n ctx.postSync({ type: 'syncMidiDestinationExternal', destinationId, external });\n}\n\nexport function setExternalMidiClockEnabled(ctx: EngineStripContext, enabled: boolean): void {\n ctx.offlineEngine.setExternalMidiClockEnabled(enabled);\n ctx.postSync({ type: 'syncExternalMidiClock', enabled });\n}\n\nexport function setMidiFx(\n ctx: EngineStripContext,\n trackId: string | number,\n configJson: string,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.setMidiFx(destinationId, configJson);\n ctx.postInstrumentSync({ type: 'syncMidiFx', destinationId, configJson });\n}\n\nexport function clearMidiFx(ctx: EngineStripContext, trackId: string | number): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.clearMidiFx(destinationId);\n ctx.postInstrumentSync({ type: 'syncClearMidiFx', destinationId });\n}\n\nexport function pushMidiSysex(\n ctx: EngineStripContext,\n trackId: string | number,\n data: Uint8Array,\n renderFrame: number,\n): void {\n const destinationId = ctx.resolveTargetId(trackId);\n ctx.offlineEngine.pushMidiSysex(destinationId, data, renderFrame);\n ctx.postSync({ type: 'syncMidiSysex', destinationId, data, renderFrame });\n}\n\nexport function pushMidiPanic(ctx: EngineStripContext, renderFrame: number): void {\n ctx.offlineEngine.pushMidiPanic(renderFrame);\n ctx.postSync({ type: 'syncMidiPanic', renderFrame });\n}\n","import type {\n EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTransportState,\n RealtimeEngine,\n} from '../index';\nimport type { SonareRealtimeEngineNode } from './engine-node';\nimport { buildTempoSync } from './engine-sync';\nimport type { SonareEngineSyncMessage } from './messages';\nimport { SonareEngineCommandType } from './protocol';\n\ninterface TimeSignature {\n numerator: number;\n denominator: number;\n}\n\n/**\n * Collaborator surface the tempo / time-signature / loop / transport helpers\n * need from the owning {@link SonareEngine}: the offline engine they mirror\n * into, the realtime node they command and query, the out-of-band sync poster,\n * and getters/setters for the tempo-map and cached-transport state the engine\n * holds (so the helpers mutate it by reference).\n */\nexport interface EngineTempoContext {\n readonly offlineEngine: RealtimeEngine;\n readonly realtimeNode: SonareRealtimeEngineNode;\n sendCommand(command: {\n type: SonareEngineCommandType;\n targetId?: number;\n sampleTime?: number;\n argFloat?: number;\n argInt?: number;\n }): boolean;\n postSync(message: SonareEngineSyncMessage): void;\n getTempoBpm(): number;\n setTempoBpm(bpm: number): void;\n getTimeSignature(): TimeSignature;\n setTimeSignature(signature: TimeSignature): void;\n getTempoSegments(): EngineTempoSegment[];\n setTempoSegments(segments: EngineTempoSegment[]): void;\n getTimeSignatureSegments(): EngineTimeSignatureSegment[];\n setTimeSignatureSegments(segments: EngineTimeSignatureSegment[]): void;\n setLatestTransportState(state: EngineTransportState): void;\n getLatestTransportState(): EngineTransportState | undefined;\n}\n\n// Posts the full tempo/time-signature map to the worklet engine processor.\nexport function postTempoSync(ctx: EngineTempoContext): void {\n ctx.postSync(\n buildTempoSync(\n ctx.getTempoBpm(),\n ctx.getTimeSignature(),\n ctx.getTempoSegments(),\n ctx.getTimeSignatureSegments(),\n ),\n );\n}\n\nexport function setTempo(ctx: EngineTempoContext, bpm: number): void {\n ctx.setTempoBpm(bpm);\n ctx.setTempoSegments([{ startPpq: 0, bpm }]);\n ctx.offlineEngine.setTempo(bpm);\n postTempoSync(ctx);\n}\n\nexport function setTempoSegments(\n ctx: EngineTempoContext,\n segments: readonly EngineTempoSegment[],\n): void {\n const copied = segments.map((segment) => ({ ...segment }));\n ctx.setTempoSegments(copied);\n ctx.setTempoBpm(copied[0]?.bpm ?? ctx.getTempoBpm());\n ctx.offlineEngine.setTempoSegments(copied);\n postTempoSync(ctx);\n}\n\nexport function setTimeSignature(\n ctx: EngineTempoContext,\n numerator: number,\n denominator: number,\n): void {\n ctx.setTimeSignature({ numerator, denominator });\n ctx.setTimeSignatureSegments([{ startPpq: 0, numerator, denominator }]);\n ctx.offlineEngine.setTimeSignature(numerator, denominator);\n postTempoSync(ctx);\n}\n\nexport function setTimeSignatureSegments(\n ctx: EngineTempoContext,\n segments: readonly EngineTimeSignatureSegment[],\n): void {\n const copied = segments.map((segment) => ({ ...segment }));\n ctx.setTimeSignatureSegments(copied);\n const first = copied[0];\n if (first) {\n ctx.setTimeSignature({ numerator: first.numerator, denominator: first.denominator });\n }\n ctx.offlineEngine.setTimeSignatureSegments(copied);\n postTempoSync(ctx);\n}\n\nexport function setLoop(\n ctx: EngineTempoContext,\n startPpq: number,\n endPpq: number,\n enabled = true,\n): boolean {\n ctx.offlineEngine.setLoop(startPpq, endPpq, enabled);\n // Transport precision contract: the SAB command record carries exactly one\n // Float64 lane (argFloat) and one Int64 lane (argInt). startPpq travels in\n // argFloat with full double precision, matching the offline engine; endPpq\n // is carried as micro-PPQ (round(endPpq * 1e6)) in the integer lane and\n // divided back by 1e6 on the consumer. Loop ENDS are therefore snapped to\n // the nearest 1e-6 PPQ over the realtime transport (max 5e-7 PPQ drift),\n // while loop STARTS and the offline path stay exact. This is intentional:\n // the record has no second free Float64 lane, and a micro-PPQ grid on the\n // loop end is well below audible/sample-accurate resolution at any tempo.\n return ctx.sendCommand({\n type: SonareEngineCommandType.SetLoop,\n targetId: enabled ? 1 : 0,\n sampleTime: -1,\n argFloat: startPpq,\n argInt: Math.round(endPpq * 1_000_000),\n });\n}\n\nexport function countInEndSample(\n ctx: EngineTempoContext,\n startSample: number,\n bars: number,\n): number {\n return ctx.offlineEngine.countInEndSample(startSample, bars);\n}\n\nexport async function getTransportState(ctx: EngineTempoContext): Promise<EngineTransportState> {\n const state = await ctx.realtimeNode.requestTransportState();\n ctx.setLatestTransportState(state);\n return state;\n}\n\nexport function cachedTransportState(ctx: EngineTempoContext): EngineTransportState | undefined {\n return ctx.getLatestTransportState();\n}\n","import {\n ClipPageStreamer,\n type ClipPageStreamerRequest,\n type OpfsClipStreamOptions,\n} from '../clip_page_streamer';\nimport type {\n EngineAutomationPoint,\n EngineBus,\n EngineCaptureStatus,\n EngineClip,\n EngineMarker,\n EngineMetronomeConfig,\n EngineMidiClipSchedule,\n EngineParameterInfo,\n EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTrackLane,\n EngineTrackMonitorMode,\n EngineTrackSend,\n EngineTransportState,\n EqBand,\n MidiCcBindOptions,\n PanLaw,\n PanMode,\n} from '../index';\nimport { RealtimeEngine } from '../index';\nimport { createOpfsClipPageProvider, type OpfsClipPageProviderBinding } from '../opfs_clip_pages';\nimport type { ClipPageProvider } from '../realtime_engine';\nimport type { EngineAutomationContext } from './engine-automation';\nimport * as automation from './engine-automation';\nimport type { EngineCaptureContext } from './engine-capture-facade';\nimport * as capture from './engine-capture-facade';\nimport type { EngineClipContext } from './engine-clips';\nimport * as clips from './engine-clips';\nimport type { EngineMarkerContext } from './engine-markers';\nimport * as markers from './engine-markers';\nimport type { EngineMixerContext } from './engine-mixer-facade';\nimport * as mixer from './engine-mixer-facade';\nimport { SonareRealtimeEngineNode } from './engine-node';\nimport { buildTransportFacade, type CaptureOptions } from './engine-offline';\nimport type { SonareEngineOptions, SuspendableAudioContext } from './engine-options';\nimport type { EngineParameterContext } from './engine-parameter-facade';\nimport * as parameter from './engine-parameter-facade';\nimport type { EngineStripContext } from './engine-strips';\nimport * as strips from './engine-strips';\nimport { resolveParamId, resolveTargetId } from './engine-sync';\nimport type { EngineTempoContext } from './engine-tempo-facade';\nimport * as tempo from './engine-tempo-facade';\nimport type {\n SonareEngineInstrumentSyncMessage,\n SonareEngineSyncCaptureMessage,\n SonareEngineSyncMessage,\n SonareEngineTransportFacade,\n SonareRealtimeEngineNodeCapabilities,\n SonareWorkletExternalMidiEvent,\n} from './messages';\nimport {\n ENGINE_MIXER_PARAM_FADER_DB,\n ENGINE_MIXER_PARAM_PAN,\n engineMixerLaneTarget,\n engineMixerMasterTarget,\n SonareEngineCommandType,\n type SonareEngineTelemetryRecord,\n type SonareWorkletMeterSnapshot,\n type SonareWorkletScopeSnapshot,\n} from './protocol';\n\nconst MAX_PENDING_WORKLET_CLIP_PAGE_REQUESTS = 256;\n\nfunction transferableAudioBuffers(channels: readonly Float32Array[]): Transferable[] {\n const transfers: ArrayBuffer[] = [];\n const seen = new Set<ArrayBuffer>();\n for (const channel of channels) {\n const buffer = channel.buffer;\n // SharedArrayBuffer is cloneable but cannot appear in a transfer list. A\n // worker may intentionally return SAB-backed pages, so transfer only plain,\n // distinct ArrayBuffers and let structured clone share SABs by reference.\n if (buffer instanceof ArrayBuffer && !seen.has(buffer)) {\n seen.add(buffer);\n transfers.push(buffer);\n }\n }\n return transfers;\n}\n\nexport class SonareEngine {\n readonly node: AudioWorkletNode;\n readonly capabilities: SonareRealtimeEngineNodeCapabilities;\n readonly transport: SonareEngineTransportFacade;\n private readonly realtimeNode: SonareRealtimeEngineNode;\n private readonly offlineEngine: RealtimeEngine;\n private readonly context: SuspendableAudioContext;\n private readonly sampleRate: number;\n private readonly offlineBlockSize: number;\n private readonly offlineChannelCount: number;\n private readonly automationLanes = new Map<number, EngineAutomationPoint[]>();\n private readonly clips = new Map<number, EngineClip>();\n private readonly midiClips = new Map<number, EngineMidiClipSchedule>();\n private readonly markers = new Map<number, EngineMarker>();\n private readonly trackLaneIds: number[] = [];\n private readonly trackSends = new Map<number, EngineTrackSend[]>();\n private readonly trackOutputBus = new Map<number, number>();\n private readonly laneSidechains = new Map<\n string,\n { trackId: number; insertIndex: number; sourceTrackId: number }\n >();\n private readonly buses: EngineBus[] = [];\n private readonly trackStripJson = new Map<number, string>();\n private readonly busStripJson = new Map<number, string>();\n private masterStripJson: string | undefined;\n private captureConfig: Omit<SonareEngineSyncCaptureMessage, 'type'> | undefined;\n private tempoBpm = 120;\n private timeSignature = { numerator: 4, denominator: 4 };\n private tempoSegments: EngineTempoSegment[] = [{ startPpq: 0, bpm: 120 }];\n private timeSignatureSegments: EngineTimeSignatureSegment[] = [\n { startPpq: 0, numerator: 4, denominator: 4 },\n ];\n private latestTransportState: EngineTransportState | undefined;\n private nextClipId = 1;\n private nextMarkerId = 1;\n private transportPlaying = false;\n private readonly pendingInstrumentSync: SonareEngineInstrumentSyncMessage[] = [];\n // One latest frontier per clip is sufficient: ClipPageStreamer expands it to\n // the bounded read window. A Map both coalesces repeated page misses and\n // places a hard cap on work queued while OPFS I/O is stalled.\n private readonly workletClipPageRequests = new Map<number, ClipPageStreamerRequest>();\n private readonly workletPageProviderClipIds = new Map<number, number>();\n private workletClipStreamer: ClipPageStreamer | undefined;\n private workletClipPump: Promise<void> | undefined;\n private workletClipPagePollTimer: ReturnType<typeof setInterval> | undefined;\n private unsubscribeWorkletClipRequests: (() => void) | undefined;\n private destroyed = false;\n\n private constructor(\n context: BaseAudioContext,\n realtimeNode: SonareRealtimeEngineNode,\n offlineEngine: RealtimeEngine,\n sampleRate: number,\n offlineBlockSize: number,\n offlineChannelCount: number,\n ) {\n this.context = context;\n this.realtimeNode = realtimeNode;\n this.offlineEngine = offlineEngine;\n this.node = realtimeNode.node;\n this.capabilities = realtimeNode.capabilities;\n this.sampleRate = sampleRate;\n this.offlineBlockSize = offlineBlockSize;\n this.offlineChannelCount = offlineChannelCount;\n this.unsubscribeWorkletClipRequests = this.realtimeNode.onClipPageRequests((message) => {\n for (const request of message.requests) {\n this.enqueueWorkletClipPageRequest(request);\n }\n this.pumpWorkletClipPages();\n });\n this.transport = buildTransportFacade({\n sampleRate: this.sampleRate,\n realtimeNode: this.realtimeNode,\n offlineEngine: this.offlineEngine,\n flushOfflineMirror: () => this.flushOfflineMirror(),\n setTransportPlaying: (playing) => {\n this.transportPlaying = playing;\n },\n flushPendingInstrumentSync: () => this.flushPendingInstrumentSync(),\n setTempo: (bpm) => this.setTempo(bpm),\n setTempoSegments: (segments) => this.setTempoSegments(segments),\n setLoop: (startPpq, endPpq, enabled) => this.setLoop(startPpq, endPpq, enabled),\n });\n }\n\n static async create(\n context: BaseAudioContext,\n options: SonareEngineOptions = {},\n ): Promise<SonareEngine> {\n const sampleRate = options.sampleRate ?? context.sampleRate;\n const blockSize = options.offlineBlockSize ?? options.blockSize ?? 128;\n const channelCount = Math.max(\n 1,\n Math.floor(options.offlineChannelCount ?? options.channelCount ?? 2),\n );\n const realtimeNode = await SonareRealtimeEngineNode.create(context, options);\n try {\n // Do not expose the facade while the registered processor is still\n // buffering messages. Long clip sync must either begin after the bridge\n // is ready or fail explicitly; it may never be silently truncated.\n await realtimeNode.ready;\n } catch (error) {\n realtimeNode.destroy();\n throw error;\n }\n const offlineEngine = options.offlineEngine ?? new RealtimeEngine(sampleRate, blockSize);\n const engine = new SonareEngine(\n context,\n realtimeNode,\n offlineEngine,\n sampleRate,\n blockSize,\n channelCount,\n );\n engine.syncParameters();\n return engine;\n }\n\n async suspend(): Promise<void> {\n if (this.destroyed) {\n return;\n }\n await this.context.suspend?.();\n }\n\n async resume(): Promise<void> {\n if (this.destroyed) {\n return;\n }\n await this.context.resume?.();\n }\n\n setTempo(bpm: number): void {\n tempo.setTempo(this.tempoContext, bpm);\n }\n\n setTempoSegments(segments: readonly EngineTempoSegment[]): void {\n tempo.setTempoSegments(this.tempoContext, segments);\n }\n\n setTimeSignature(numerator: number, denominator: number): void {\n tempo.setTimeSignature(this.tempoContext, numerator, denominator);\n }\n\n setTimeSignatureSegments(segments: readonly EngineTimeSignatureSegment[]): void {\n tempo.setTimeSignatureSegments(this.tempoContext, segments);\n }\n\n setLoop(startPpq: number, endPpq: number, enabled = true): boolean {\n return tempo.setLoop(this.tempoContext, startPpq, endPpq, enabled);\n }\n\n countInEndSample(startSample: number, bars: number): number {\n return tempo.countInEndSample(this.tempoContext, startSample, bars);\n }\n\n getTransportState(): Promise<EngineTransportState> {\n return tempo.getTransportState(this.tempoContext);\n }\n\n cachedTransportState(): EngineTransportState | undefined {\n return tempo.cachedTransportState(this.tempoContext);\n }\n\n setParam(nodeId: string, param: string | number, value: number): boolean {\n return parameter.setParam(this.parameterContext, nodeId, param, value);\n }\n\n scheduleParam(\n nodeId: string,\n param: string | number,\n ppq: number,\n value: number,\n curve: number | 'linear' | 'exponential' = 'linear',\n ): void {\n automation.scheduleParam(this.automationContext, nodeId, param, ppq, value, curve);\n }\n\n addAutomationPoint(\n laneId: string | number,\n ppq: number,\n value: number,\n curve: number | 'linear' | 'exponential' = 'linear',\n ): void {\n automation.addAutomationPoint(this.automationContext, laneId, ppq, value, curve);\n }\n\n /**\n * Replaces the automation lane for `paramId` with the given breakpoints. An\n * empty array clears the lane; the points are defensively copied and sorted\n * by ppq before mirroring to the offline and live worklet engines.\n */\n setAutomationLane(paramId: number, points: ReadonlyArray<EngineAutomationPoint>): void {\n automation.setAutomationLane(this.automationContext, paramId, points);\n }\n\n /**\n * Returns the automation target id for a mixer strip parameter.\n *\n * The id addresses the engine's reserved mixer namespace, so it can be fed\n * straight to setAutomationLane to automate a fader or pan without\n * registering a parameter.\n *\n * @param target Track id (declares a mixer lane on first use) or 'master'.\n * @param kind Strip parameter to address.\n * @returns Reserved engine parameter id for the strip parameter.\n */\n automationParamId(target: string | number, kind: 'faderDb' | 'pan'): number {\n return parameter.automationParamId(this.parameterContext, target, kind);\n }\n\n /**\n * Returns the automation target id for a bus fader.\n *\n * @param busId Bus id (declares the mixer bus on first use).\n * @returns Reserved engine parameter id for the bus fader gain (dB).\n */\n busAutomationParamId(busId: number): number {\n return parameter.busAutomationParamId(this.parameterContext, busId);\n }\n\n /**\n * Resolves a track-lane insert parameter (JSON-key name) to the reserved\n * insert-automation id fed straight to setAutomationLane. Declares the track's\n * mixer lane first (like automationParamId) so the offline engine resolves the\n * same strip selector the realtime engine uses.\n *\n * @param target Track id (declares a mixer lane on first use).\n * @param insertIndex Index into the strip's combined insert sequence.\n * @param paramName Processor JSON-key parameter name.\n * @returns Reserved insert-automation id, or -1 when strip/insert/key unknown.\n */\n resolveTrackInsertAutomationId(\n target: string | number,\n insertIndex: number,\n paramName: string,\n ): number {\n return parameter.resolveTrackInsertAutomationId(\n this.parameterContext,\n target,\n insertIndex,\n paramName,\n );\n }\n\n /**\n * Resolves a master-strip insert parameter to its reserved insert-automation\n * id.\n *\n * @param insertIndex Index into the master strip's insert sequence.\n * @param paramName Processor JSON-key parameter name.\n * @returns Reserved insert-automation id, or -1 when insert/key unknown.\n */\n resolveMasterInsertAutomationId(insertIndex: number, paramName: string): number {\n return parameter.resolveMasterInsertAutomationId(this.parameterContext, insertIndex, paramName);\n }\n\n /**\n * Resolves a bus-strip insert parameter to its reserved insert-automation id.\n * Declares the mixer bus first so the offline engine resolves the same bus\n * selector.\n *\n * @param busId Bus id (declares the mixer bus on first use).\n * @param insertIndex Index into the bus strip's insert sequence.\n * @param paramName Processor JSON-key parameter name.\n * @returns Reserved insert-automation id, or -1 when bus/insert/key unknown.\n */\n resolveBusInsertAutomationId(busId: number, insertIndex: number, paramName: string): number {\n return parameter.resolveBusInsertAutomationId(\n this.parameterContext,\n busId,\n insertIndex,\n paramName,\n );\n }\n\n /**\n * Returns the number of automation lanes installed on the engine, including\n * lanes whose breakpoint list is currently empty.\n *\n * @returns Engine-side automation lane count.\n */\n automationLaneCount(): number {\n return parameter.automationLaneCount(this.parameterContext);\n }\n\n listParameters(): EngineParameterInfo[] {\n return parameter.listParameters(this.parameterContext);\n }\n\n /** Registers a custom parameter on the offline mirror and worklet engine. */\n addParameter(info: EngineParameterInfo): void {\n parameter.addParameter(this.parameterContext, info);\n }\n\n /** Clears custom parameters and their automation lanes on both engines. */\n clearParameters(): void {\n parameter.clearParameters(this.parameterContext);\n }\n\n setSoloMute(target: string | number, solo: boolean, mute: boolean): boolean {\n return parameter.setSoloMute(this.parameterContext, target, solo, mute);\n }\n\n /** Queues a per-track PFL/AFL monitor tap mode change. */\n setTrackMonitorMode(\n target: string | number,\n mode: EngineTrackMonitorMode,\n renderFrame = -1,\n ): boolean {\n return parameter.setTrackMonitorMode(this.parameterContext, target, mode, renderFrame);\n }\n\n setStripGain(target: string | number, db: number): boolean {\n return this.sendSmoothedParam(this.stripParamId(target, ENGINE_MIXER_PARAM_FADER_DB), db);\n }\n\n setStripPan(target: string | number, pan: number): boolean {\n return this.sendSmoothedParam(this.stripParamId(target, ENGINE_MIXER_PARAM_PAN), pan);\n }\n\n /**\n * Declares the mixer track lanes in an explicit order.\n *\n * Lane indices are append-only: once a track id occupies a lane, its index\n * stays fixed for the engine's lifetime. The given list must therefore start\n * with the already-declared lane ids in their current order and may only\n * append new track ids after them. Entries carrying `sends` replace that\n * track's send list; entries without `sends` leave existing sends untouched.\n *\n * @param lanes Track ids or lane descriptors in the desired lane order.\n */\n setTrackLanes(lanes: ReadonlyArray<number | EngineTrackLane>): void {\n mixer.setTrackLanes(this.mixerContext, lanes);\n }\n\n /**\n * Routes a track lane's post-fader output into a declared bus instead of\n * the master mix (group/folder routing); busId 0 restores the master mix.\n */\n setTrackOutputBus(target: string | number, busId: number): void {\n mixer.setTrackOutputBus(this.mixerContext, target, busId);\n }\n\n /**\n * Keys one insert of a lane strip from another lane's post-strip pre-fader\n * audio (ducking/sidechainRouter inserts). sourceTarget null removes the\n * binding.\n */\n setLaneSidechain(\n target: string | number,\n insertIndex: number,\n sourceTarget: string | number | null,\n ): void {\n mixer.setLaneSidechain(this.mixerContext, target, insertIndex, sourceTarget);\n }\n\n setSends(target: string | number, sends: EngineTrackSend[]): void {\n mixer.setSends(this.mixerContext, target, sends);\n }\n\n setTrackBuses(buses: EngineBus[]): void {\n mixer.setTrackBuses(this.mixerContext, buses);\n }\n\n setBusGain(busId: number, db: number): boolean {\n return mixer.setBusGain(this.mixerContext, busId, db);\n }\n\n setTrackStripJson(target: string | number, sceneJson: string): void {\n const laneIndex = this.ensureTrackLane(target);\n const trackId = this.trackLaneIds[laneIndex];\n strips.setTrackStripJson(this.stripContext, trackId, sceneJson, this.trackStripJson);\n this.syncMixer();\n }\n\n setTrackStripEqBand(target: string | number, bandIndex: number, band: EqBand | string): void {\n strips.setTrackStripEqBand(this.stripContext, target, bandIndex, band);\n }\n\n setTrackStripInsertBypassed(\n target: string | number,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n strips.setTrackStripInsertBypassed(\n this.stripContext,\n target,\n insertIndex,\n bypassed,\n resetOnBypass,\n );\n }\n\n setTrackStripInsertParamByName(\n target: string | number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n strips.setTrackStripInsertParamByName(this.stripContext, target, insertIndex, paramName, value);\n }\n\n setTrackStripPan(target: string | number, pan: number): void {\n strips.setTrackStripPan(this.stripContext, target, pan);\n }\n\n setTrackStripPanLaw(target: string | number, panLaw: PanLaw | number): void {\n strips.setTrackStripPanLaw(this.stripContext, target, panLaw);\n }\n\n setTrackStripPanMode(target: string | number, panMode: PanMode | number): void {\n strips.setTrackStripPanMode(this.stripContext, target, panMode);\n }\n\n setTrackStripDualPan(target: string | number, leftPan: number, rightPan: number): void {\n strips.setTrackStripDualPan(this.stripContext, target, leftPan, rightPan);\n }\n\n setTrackStripChannelDelaySamples(target: string | number, delaySamples: number): void {\n strips.setTrackStripChannelDelaySamples(this.stripContext, target, delaySamples);\n }\n\n setStripEq(target: string | number, bandIndex: number, band: EqBand | string): void {\n if (target === 'master') {\n this.setMasterStripEqBand(bandIndex, band);\n return;\n }\n this.setTrackStripEqBand(target, bandIndex, band);\n }\n\n setStripInsertBypassed(\n target: string | number,\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n if (target === 'master') {\n this.setMasterStripInsertBypassed(insertIndex, bypassed, resetOnBypass);\n return;\n }\n this.setTrackStripInsertBypassed(target, insertIndex, bypassed, resetOnBypass);\n }\n\n setStripInserts(target: string | number, sceneJson: string): void {\n if (target === 'master') {\n this.setMasterStripJson(sceneJson);\n return;\n }\n this.setTrackStripJson(target, sceneJson);\n }\n\n setBusStripJson(busId: number, sceneJson: string): void {\n mixer.setBusStripJson(this.mixerContext, busId, sceneJson);\n }\n\n setMasterStripJson(sceneJson: string): void {\n this.offlineEngine.setMasterStripJson(sceneJson);\n this.masterStripJson = sceneJson;\n this.syncMixer();\n }\n\n setMasterStripEqBand(bandIndex: number, band: EqBand | string): void {\n strips.setMasterStripEqBand(this.stripContext, bandIndex, band);\n }\n\n setMasterStripInsertBypassed(\n insertIndex: number,\n bypassed: boolean,\n resetOnBypass = false,\n ): void {\n strips.setMasterStripInsertBypassed(this.stripContext, insertIndex, bypassed, resetOnBypass);\n }\n\n setMasterStripInsertParamByName(insertIndex: number, paramName: string, value: number): void {\n strips.setMasterStripInsertParamByName(this.stripContext, insertIndex, paramName, value);\n }\n\n setBusStripInsertParamByName(\n busId: number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n this.ensureBus(busId);\n strips.setBusStripInsertParamByName(this.stripContext, busId, insertIndex, paramName, value);\n }\n\n setStripInsertParamByName(\n target: string | number,\n insertIndex: number,\n paramName: string,\n value: number,\n ): void {\n if (target === 'master') {\n this.setMasterStripInsertParamByName(insertIndex, paramName, value);\n return;\n }\n this.setTrackStripInsertParamByName(target, insertIndex, paramName, value);\n }\n\n setMasterChain(sceneJson: string): void {\n this.setMasterStripJson(sceneJson);\n }\n\n /**\n * Creates and primes an OPFS-backed page provider for this live worklet\n * engine. Pass the returned `provider` to {@link addClip} in place of a\n * `Float32Array[]`; the `clipId` in `options` must equal that clip's explicit\n * `opts.id`. Subsequent cache misses are fetched on the main thread and\n * supplied back to the worklet through its bounded pull protocol.\n */\n async attachOpfsClipStream(\n options: OpfsClipStreamOptions,\n ): Promise<{ binding: OpfsClipPageProviderBinding; provider: ClipPageProvider }> {\n if (this.destroyed) {\n throw new Error('SonareEngine is destroyed.');\n }\n if (!this.capabilities.clipPageRequestsRealtimeSafe) {\n throw new Error(\n 'OPFS clip streaming requires SharedArrayBuffer clip-page requests; the postMessage fallback is not realtime-safe.',\n );\n }\n const { clipId, primePages = 1, ...providerOptions } = options;\n if ([...this.workletPageProviderClipIds.values()].includes(clipId)) {\n throw new Error(`An OPFS stream is already attached for clip ${clipId}.`);\n }\n const streamer = this.ensureWorkletClipStreamer();\n // Allocate the worklet-owned provider before priming: port message order\n // ensures every prime page is adopted before addClip commits its schedule.\n this.postSync({\n type: 'syncClipPageProvider',\n clipId,\n numChannels: providerOptions.numChannels,\n numSamples: providerOptions.numSamples,\n pageFrames: providerOptions.pageFrames,\n });\n let binding: OpfsClipPageProviderBinding;\n binding = createOpfsClipPageProvider(this.offlineEngine, {\n ...providerOptions,\n onPageSupplied: (pageIndex, channels) => {\n this.postSync(\n { type: 'syncClipPage', clipId, pageIndex, channels },\n transferableAudioBuffers(channels),\n );\n },\n onPageCleared: (pageIndex) => {\n this.postSync({ type: 'syncClipPageClear', clipId, pageIndex });\n },\n onClose: () => {\n this.workletPageProviderClipIds.delete(binding.provider.id);\n this.postSync({ type: 'syncClipPageDestroy', clipId });\n },\n });\n this.workletPageProviderClipIds.set(binding.provider.id, clipId);\n const lastPage = Math.ceil(providerOptions.numSamples / providerOptions.pageFrames) - 1;\n const primed: number[] = [];\n try {\n for (let page = 0; page < primePages && page <= lastPage; ++page) {\n if (await binding.supplyPage(page)) {\n primed.push(page);\n }\n }\n streamer.addSource(\n {\n clipId,\n binding,\n pageFrames: providerOptions.pageFrames,\n numSamples: providerOptions.numSamples,\n },\n primed,\n );\n this.startWorkletClipPagePolling();\n } catch (error) {\n binding.close();\n throw error;\n }\n return { binding, provider: binding.provider };\n }\n\n addClip(\n trackId: string | number,\n buffer: Float32Array[] | ClipPageProvider,\n startPpq: number,\n opts: Partial<Omit<EngineClip, 'channels' | 'pageProvider' | 'startPpq'>> = {},\n ): number {\n return clips.addClip(this.clipContext, trackId, buffer, startPpq, opts);\n }\n\n removeClip(clipId: number): void {\n clips.removeClip(this.clipContext, clipId);\n }\n\n setMidiClips(schedules: readonly EngineMidiClipSchedule[]): void {\n clips.setMidiClips(this.clipContext, schedules);\n }\n\n setBuiltinInstrument(\n trackId: string | number,\n config: { destinationId?: number } & Record<string, unknown> = {},\n ): void {\n strips.setBuiltinInstrument(this.stripContext, trackId, config);\n }\n\n setSynthInstrument(trackId: string | number, patch: Record<string, unknown> | string = {}): void {\n strips.setSynthInstrument(this.stripContext, trackId, patch);\n }\n\n loadSoundFont(data: Uint8Array): void {\n strips.loadSoundFont(this.stripContext, data);\n }\n\n setSf2Instrument(\n trackId: string | number,\n config: {\n destinationId?: number;\n gain?: number;\n polyphony?: number;\n preferModelForModeledFamilies?: boolean;\n } = {},\n ): void {\n strips.setSf2Instrument(this.stripContext, trackId, config);\n }\n\n /**\n * Route a track's MIDI to the external output (drained via {@link onMidiOut})\n * instead of an internal instrument, so the track plays an external device.\n * Pass `external=false` to restore internal-synth playback.\n */\n setMidiDestinationExternal(trackId: string | number, external: boolean): void {\n strips.setMidiDestinationExternal(this.stripContext, trackId, external);\n }\n\n /**\n * Enable/disable forwarding MIDI clock + transport (start/continue/stop) to\n * the external output so external gear tracks the transport tempo. The bytes\n * arrive through {@link onMidiOut} tagged with the transport destination.\n */\n setExternalMidiClockEnabled(enabled: boolean): void {\n strips.setExternalMidiClockEnabled(this.stripContext, enabled);\n }\n\n /**\n * Install or replace a live, non-destructive MIDI-FX insert for one\n * destination. The insert transforms the destination's MIDI before\n * synthesis (transpose, quantize, velocity shaping, humanize, harmonize,\n * arpeggiate) without rewriting any stored notes, so it can be bypassed by\n * {@link clearMidiFx}. The config JSON is the flat object the engine's\n * MIDI-FX accepts (the same schema as the offline `Project.bakeMidiFx`).\n */\n setMidiFx(trackId: string | number, configJson: string): void {\n strips.setMidiFx(this.stripContext, trackId, configJson);\n }\n\n /** Remove the live MIDI-FX insert from one destination (a no-op when none). */\n clearMidiFx(trackId: string | number): void {\n strips.clearMidiFx(this.stripContext, trackId);\n }\n\n pushMidiNoteOn(\n trackId: string | number,\n group: number,\n channel: number,\n note: number,\n velocity: number,\n renderFrame = -1,\n ): void {\n strips.pushMidiNoteOn(this.stripContext, trackId, group, channel, note, velocity, renderFrame);\n }\n\n pushMidiNoteOff(\n trackId: string | number,\n group: number,\n channel: number,\n note: number,\n velocity = 0,\n renderFrame = -1,\n ): void {\n strips.pushMidiNoteOff(this.stripContext, trackId, group, channel, note, velocity, renderFrame);\n }\n\n pushMidiCc(\n trackId: string | number,\n group: number,\n channel: number,\n controller: number,\n value: number,\n renderFrame = -1,\n ): void {\n strips.pushMidiCc(this.stripContext, trackId, group, channel, controller, value, renderFrame);\n }\n\n pushMidiUmp(trackId: string | number, word0: number, renderFrame = -1): void {\n strips.pushMidiUmp(this.stripContext, trackId, word0, renderFrame);\n }\n\n pushMidiSysex(trackId: string | number, data: Uint8Array, renderFrame = -1): void {\n strips.pushMidiSysex(this.stripContext, trackId, data, renderFrame);\n }\n\n bindMidiCc(\n channel: number,\n controller: number,\n paramId: number,\n options: MidiCcBindOptions = {},\n ): void {\n const minValue = options.minValue ?? 0;\n const maxValue = options.maxValue ?? 1;\n this.offlineEngine.bindMidiCc(channel, controller, paramId, { minValue, maxValue });\n this.postSync({ type: 'syncMidiCcBinding', channel, controller, paramId, minValue, maxValue });\n }\n\n setMidiInputSource(destinationId = 0): void {\n this.offlineEngine.setMidiInputSource(destinationId);\n this.postSync({ type: 'syncMidiInputSource', destinationId });\n }\n\n clearMidiInputSource(): void {\n this.offlineEngine.clearMidiInputSource();\n this.postSync({ type: 'syncClearMidiInputSource' });\n }\n\n pushMidiInputNoteOn(\n group: number,\n channel: number,\n note: number,\n velocity: number,\n portTimeSamples = 0,\n ): void {\n this.offlineEngine.pushMidiInputNoteOn(group, channel, note, velocity, portTimeSamples);\n this.postSync({\n type: 'syncMidiInputNoteOn',\n group,\n channel,\n data0: note,\n data1: velocity,\n portTimeSamples,\n });\n }\n\n pushMidiInputNoteOff(\n group: number,\n channel: number,\n note: number,\n velocity = 0,\n portTimeSamples = 0,\n ): void {\n this.offlineEngine.pushMidiInputNoteOff(group, channel, note, velocity, portTimeSamples);\n this.postSync({\n type: 'syncMidiInputNoteOff',\n group,\n channel,\n data0: note,\n data1: velocity,\n portTimeSamples,\n });\n }\n\n pushMidiInputCc(\n group: number,\n channel: number,\n controller: number,\n value: number,\n portTimeSamples = 0,\n ): void {\n this.offlineEngine.pushMidiInputCc(group, channel, controller, value, portTimeSamples);\n this.postSync({\n type: 'syncMidiInputCc',\n group,\n channel,\n data0: controller,\n data1: value,\n portTimeSamples,\n });\n }\n\n pushMidiPanic(renderFrame = -1): void {\n this.offlineEngine.pushMidiPanic(renderFrame);\n this.postSync({ type: 'syncMidiPanic', renderFrame });\n }\n\n configureCapture(options: CaptureOptions): void {\n capture.configureCapture(this.captureContext, options);\n }\n\n /**\n * Arms the engine-global capture path. `trackId` is retained for source\n * compatibility and must be `0`; per-track capture is not implemented.\n */\n armRecord(trackId: string | number, enabled: boolean): boolean {\n return capture.armRecord(this.captureContext, trackId, enabled);\n }\n\n punch(inPpq: number, outPpq: number): boolean {\n return capture.punch(this.captureContext, inPpq, outPpq);\n }\n\n captureStatus(): Promise<EngineCaptureStatus> {\n return capture.captureStatus(this.captureContext);\n }\n\n capturedAudio(): Promise<Float32Array[]> {\n return capture.capturedAudio(this.captureContext);\n }\n\n async resetCapture(): Promise<void> {\n return capture.resetCapture(this.captureContext);\n }\n\n setMetronome(opts: EngineMetronomeConfig): void {\n this.offlineEngine.setMetronome(opts);\n // The full config (beatGain/accentGain/clickSamples/clickSeconds) cannot fit\n // the fixed-size SAB command record, so it is delivered out-of-band; the\n // SetMetronome command then toggles enabled state on the audio thread.\n this.postSync({ type: 'syncMetronome', config: opts });\n this.sendMirroredCommand({\n type: SonareEngineCommandType.SetMetronome,\n sampleTime: -1,\n argInt: opts.enabled ? 1 : 0,\n });\n }\n\n addMarker(ppq: number, name = ''): number {\n return markers.addMarker(this.markerContext, ppq, name);\n }\n\n /**\n * Replaces the whole marker set in one call. Entries without an `id` are\n * assigned fresh ids; entries carrying an `id` keep it. Returns the resolved\n * markers in the order given.\n */\n setMarkers(entries: ReadonlyArray<{ ppq: number; name?: string; id?: number }>): EngineMarker[] {\n return markers.setMarkers(this.markerContext, entries);\n }\n\n markerCount(): number {\n return markers.markerCount(this.markerContext);\n }\n\n markerByIndex(index: number): EngineMarker {\n return markers.markerByIndex(this.markerContext, index);\n }\n\n marker(markerId: number): EngineMarker {\n return markers.marker(this.markerContext, markerId);\n }\n\n seekMarker(markerId: number): boolean {\n return markers.seekMarker(this.markerContext, markerId);\n }\n\n setLoopFromMarkers(startMarkerId: number, endMarkerId: number): boolean {\n return markers.setLoopFromMarkers(this.markerContext, startMarkerId, endMarkerId);\n }\n\n async renderOffline(totalFrames: number): Promise<Float32Array[]> {\n const frames = Math.max(0, Math.floor(totalFrames));\n const inputs: Float32Array[] = [];\n for (let ch = 0; ch < this.offlineChannelCount; ch++) {\n inputs.push(new Float32Array(frames));\n }\n return this.offlineEngine.renderOffline(inputs, this.offlineBlockSize);\n }\n\n /**\n * Subscribe to external-MIDI batches (already lowered to MIDI 1.0 bytes) for\n * delivery to Web MIDI output ports. Fires once per render block that\n * produced events. Returns an unsubscribe function.\n */\n onMidiOut(callback: (events: SonareWorkletExternalMidiEvent[]) => void): () => void {\n return this.realtimeNode.onMidiOut(callback);\n }\n\n onMeter(callback: (meter: SonareWorkletMeterSnapshot) => void): () => void {\n return this.realtimeNode.onMeter(callback);\n }\n\n onScope(callback: (scope: SonareWorkletScopeSnapshot) => void): () => void {\n return this.realtimeNode.onScope(callback);\n }\n\n onTelemetry(callback: (telemetry: SonareEngineTelemetryRecord) => void): () => void {\n return this.realtimeNode.onTelemetry(callback);\n }\n\n pollTelemetry(): SonareEngineTelemetryRecord[] {\n return this.realtimeNode.pollTelemetry();\n }\n\n pollMeters(): SonareWorkletMeterSnapshot[] {\n return this.realtimeNode.pollMeters();\n }\n\n pollScope(): SonareWorkletScopeSnapshot[] {\n return this.realtimeNode.pollScope();\n }\n\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n this.unsubscribeWorkletClipRequests?.();\n this.unsubscribeWorkletClipRequests = undefined;\n this.workletClipStreamer?.close();\n this.workletClipStreamer = undefined;\n if (this.workletClipPagePollTimer !== undefined) {\n clearInterval(this.workletClipPagePollTimer);\n this.workletClipPagePollTimer = undefined;\n }\n this.workletClipPageRequests.clear();\n this.destroyed = true;\n this.transport.stop();\n this.realtimeNode.pollTelemetry();\n this.realtimeNode.destroy();\n this.offlineEngine.destroy();\n }\n\n private ensureWorkletClipStreamer(): ClipPageStreamer {\n if (!this.workletClipStreamer) {\n this.workletClipStreamer = new ClipPageStreamer({\n popClipPageRequest: () => this.popWorkletClipPageRequest(),\n });\n }\n return this.workletClipStreamer;\n }\n\n /**\n * SAB requests have no postMessage wake-up by design. Polling on the main\n * thread is therefore intentionally outside the audio callback; 8 ms keeps\n * the bounded OPFS prefetch frontier responsive without adding worklet GC.\n */\n private startWorkletClipPagePolling(): void {\n if (this.workletClipPagePollTimer !== undefined) {\n return;\n }\n const poll = () => {\n if (!this.destroyed) {\n this.realtimeNode.pollClipPageRequests();\n }\n };\n poll();\n this.workletClipPagePollTimer = setInterval(poll, 8);\n }\n\n private pumpWorkletClipPages(): void {\n const streamer = this.workletClipStreamer;\n if (!streamer || this.workletClipPump) {\n return;\n }\n this.workletClipPump = streamer\n .pump()\n .catch((error: unknown) => {\n // The worklet keeps rendering silence for an unavailable page. Surface\n // I/O failures without converting them into an AudioWorklet exception.\n // biome-ignore lint/suspicious/noConsole: asynchronous OPFS diagnostic.\n console.error('Sonare OPFS clip-page supply failed:', error);\n })\n .finally(() => {\n this.workletClipPump = undefined;\n if (this.workletClipPageRequests.size > 0) {\n this.pumpWorkletClipPages();\n }\n });\n }\n\n private enqueueWorkletClipPageRequest(request: ClipPageStreamerRequest): void {\n if (\n !Number.isInteger(request.clipId) ||\n request.clipId < 0 ||\n !Number.isInteger(request.pageIndex) ||\n (request.pageIndex ?? -1) < 0\n ) {\n return;\n }\n // Reinsert an existing id so iteration order represents newest frontiers.\n this.workletClipPageRequests.delete(request.clipId);\n if (this.workletClipPageRequests.size >= MAX_PENDING_WORKLET_CLIP_PAGE_REQUESTS) {\n const oldest = this.workletClipPageRequests.keys().next().value;\n if (oldest !== undefined) {\n this.workletClipPageRequests.delete(oldest);\n }\n }\n this.workletClipPageRequests.set(request.clipId, request);\n }\n\n private popWorkletClipPageRequest(): ClipPageStreamerRequest | null {\n const entry = this.workletClipPageRequests.entries().next().value;\n if (!entry) {\n return null;\n }\n const [clipId, request] = entry;\n this.workletClipPageRequests.delete(clipId);\n return request;\n }\n\n private commitWorkletClipPageProvider(clip: EngineClip): boolean {\n const providerId =\n typeof clip.pageProvider === 'object' && clip.pageProvider !== null\n ? clip.pageProvider.id\n : clip.pageProvider;\n if (providerId === undefined) {\n return false;\n }\n const clipId = this.workletPageProviderClipIds.get(providerId);\n if (clipId === undefined) {\n return false;\n }\n if (clip.id !== clipId) {\n throw new Error(`OPFS stream clipId ${clipId} must match addClip(..., { id: ${clipId} }).`);\n }\n this.postSync({\n type: 'syncClipPageCommit',\n clipId,\n clip: { ...clip, channels: undefined, pageProvider: undefined },\n });\n return true;\n }\n\n private mixerLanes(): EngineTrackLane[] {\n return mixer.mixerLanes(this.mixerContext);\n }\n\n private syncMixer(): void {\n mixer.syncMixer(this.mixerContext);\n }\n\n private postInstrumentSync(message: SonareEngineInstrumentSyncMessage): void {\n if (this.destroyed) {\n return;\n }\n if (this.transportPlaying) {\n this.pendingInstrumentSync.push(message);\n return;\n }\n this.postSync(message);\n }\n\n private flushPendingInstrumentSync(): void {\n if (this.destroyed || this.pendingInstrumentSync.length === 0) {\n return;\n }\n const pending = this.pendingInstrumentSync.splice(0);\n for (const message of pending) {\n this.postSync(message);\n }\n }\n\n // Posts an out-of-band control-sync message to the worklet engine processor.\n // Sync messages use a string `type` so the worklet's message handler routes\n // them to receiveSync() (numeric `type` is reserved for SonareEngineCommandRecord).\n private postSync(message: SonareEngineSyncMessage, transfer?: Transferable[]): void {\n if (this.destroyed) {\n return;\n }\n try {\n if (transfer && transfer.length > 0) {\n this.realtimeNode.node.port.postMessage(message, transfer);\n } else {\n this.realtimeNode.node.port.postMessage(message);\n }\n } finally {\n this.flushOfflineMirror();\n }\n }\n\n // The offline engine is a control-thread mirror. It has no render loop to\n // drain its command ring, so drain it after each control operation. Never\n // call this from the worklet/audio path: it is intentionally control-only.\n private flushOfflineMirror(): void {\n this.offlineEngine.flushControlCommands();\n }\n\n private sendMirroredCommand(\n command: Parameters<SonareRealtimeEngineNode['sendCommand']>[0],\n ): boolean {\n const accepted = this.realtimeNode.sendCommand(command);\n this.flushOfflineMirror();\n return accepted;\n }\n\n // Collaborator surface handed to the mixer/routing free functions so they can\n // mutate the routing stores (held by reference), mirror into the offline\n // engine, post mixer-sync messages, and declare lanes/buses without a\n // back-reference to the whole engine.\n private get mixerContext(): EngineMixerContext {\n return {\n offlineEngine: this.offlineEngine,\n trackLaneIds: this.trackLaneIds,\n trackSends: this.trackSends,\n trackOutputBus: this.trackOutputBus,\n laneSidechains: this.laneSidechains,\n buses: this.buses,\n trackStripJson: this.trackStripJson,\n busStripJson: this.busStripJson,\n postSync: (message) => this.postSync(message),\n ensureTrackLane: (target) => this.ensureTrackLane(target),\n ensureBus: (busId) => this.ensureBus(busId),\n mixerLanes: () => this.mixerLanes(),\n syncMixer: () => this.syncMixer(),\n sendSmoothedParam: (paramId, value) => this.sendSmoothedParam(paramId, value),\n getMasterStripJson: () => this.masterStripJson,\n };\n }\n\n // Collaborator surface handed to the strip/pan/EQ/insert/MIDI free functions\n // so they can mirror into the offline engine, post sync messages, and resolve\n // lanes without each holding a back-reference to the whole engine.\n private get stripContext(): EngineStripContext {\n return {\n offlineEngine: this.offlineEngine,\n trackLaneIds: this.trackLaneIds,\n postSync: (message) => this.postSync(message),\n postInstrumentSync: (message) => this.postInstrumentSync(message),\n ensureTrackLane: (target) => this.ensureTrackLane(target),\n resolveTargetId: (target) => this.resolveTargetId(target),\n };\n }\n\n // Collaborator surface handed to the automation-lane free functions so they\n // can mutate the lane store, mirror into the offline engine, and post\n // automation-sync messages without holding a back-reference.\n private get automationContext(): EngineAutomationContext {\n return {\n offlineEngine: this.offlineEngine,\n automationLanes: this.automationLanes,\n postSync: (message) => this.postSync(message),\n resolveParamId: (nodeId, param) => this.resolveParamId(nodeId, param),\n };\n }\n\n // Collaborator surface handed to the capture/record/punch free functions so\n // they can mirror into and query the offline engine, command the realtime\n // node, and read/write the capture config without a back-reference.\n private get captureContext(): EngineCaptureContext {\n return {\n offlineEngine: this.offlineEngine,\n realtimeNode: this.realtimeNode,\n sendCommand: (command) => this.sendMirroredCommand(command),\n offlineChannelCount: this.offlineChannelCount,\n postSync: (message) => this.postSync(message),\n getCaptureConfig: () => this.captureConfig,\n setCaptureConfig: (config) => {\n this.captureConfig = config;\n },\n };\n }\n\n // Collaborator surface handed to the parameter / automation-id resolution\n // free functions so they can mirror into and query the offline engine,\n // command the realtime node, and declare lanes/buses without holding a\n // back-reference to the whole engine.\n private get parameterContext(): EngineParameterContext {\n return {\n offlineEngine: this.offlineEngine,\n sendCommand: (command) => this.sendMirroredCommand(command),\n postSync: (message) => this.postSync(message),\n automationLanes: this.automationLanes,\n trackLaneIds: this.trackLaneIds,\n resolveParamId: (nodeId, param) => this.resolveParamId(nodeId, param),\n ensureTrackLane: (target) => this.ensureTrackLane(target),\n ensureBus: (busId) => this.ensureBus(busId),\n };\n }\n\n // Collaborator surface handed to the tempo / time-signature free functions so\n // they can mirror into the offline engine, command the realtime node, post\n // tempo-sync messages, and mutate the engine's tempo-map state by reference.\n private get tempoContext(): EngineTempoContext {\n return {\n offlineEngine: this.offlineEngine,\n realtimeNode: this.realtimeNode,\n sendCommand: (command) => this.sendMirroredCommand(command),\n postSync: (message) => this.postSync(message),\n getTempoBpm: () => this.tempoBpm,\n setTempoBpm: (bpm) => {\n this.tempoBpm = bpm;\n },\n getTimeSignature: () => this.timeSignature,\n setTimeSignature: (signature) => {\n this.timeSignature = signature;\n },\n getTempoSegments: () => this.tempoSegments,\n setTempoSegments: (segments) => {\n this.tempoSegments = segments;\n },\n getTimeSignatureSegments: () => this.timeSignatureSegments,\n setTimeSignatureSegments: (segments) => {\n this.timeSignatureSegments = segments;\n },\n setLatestTransportState: (state) => {\n this.latestTransportState = state;\n },\n getLatestTransportState: () => this.latestTransportState,\n };\n }\n\n // Collaborator surface handed to the audio/MIDI clip scheduling free\n // functions so they can mutate the clip stores, mirror into the offline\n // engine, and post clip-sync messages without holding a back-reference.\n private get clipContext(): EngineClipContext {\n return {\n offlineEngine: this.offlineEngine,\n clips: this.clips,\n midiClips: this.midiClips,\n allocateClipId: () => this.nextClipId++,\n postSync: (message, transfer) => this.postSync(message, transfer),\n ensureTrackLane: (target) => this.ensureTrackLane(target),\n resolveTargetId: (target) => this.resolveTargetId(target),\n commitWorkletClipPageProvider: (clip) => this.commitWorkletClipPageProvider(clip),\n };\n }\n\n // Collaborator surface handed to the marker free functions so they can mutate\n // the marker store and id counter, mirror into the offline engine, post\n // marker-sync messages, and drive transport without a back-reference.\n private get markerContext(): EngineMarkerContext {\n return {\n offlineEngine: this.offlineEngine,\n markers: this.markers,\n getNextMarkerId: () => this.nextMarkerId,\n setNextMarkerId: (value) => {\n this.nextMarkerId = value;\n },\n postSync: (message) => this.postSync(message),\n sendCommand: (command) => this.sendMirroredCommand(command),\n setLoop: (startPpq, endPpq, enabled) => this.setLoop(startPpq, endPpq, enabled),\n };\n }\n\n // Resolves the reserved mixer parameter id for a fader/pan target, declaring a\n // track lane on first use; 'master' addresses the master strip namespace.\n private stripParamId(target: string | number, paramKind: number): number {\n if (target === 'master') {\n return engineMixerMasterTarget(paramKind);\n }\n return engineMixerLaneTarget(this.ensureTrackLane(target), paramKind);\n }\n\n // Mirrors a smoothed parameter into the offline engine and pushes a\n // sample-accurate smoothed-param command to the realtime runtime.\n private sendSmoothedParam(paramId: number, value: number): boolean {\n this.offlineEngine.setParameter(paramId, value);\n return this.sendMirroredCommand({\n type: SonareEngineCommandType.SetParamSmoothed,\n targetId: paramId,\n sampleTime: -1,\n argFloat: value,\n });\n }\n\n private resolveParamId(nodeId: string, param: string | number): number {\n return resolveParamId(this.listParameters(), nodeId, param);\n }\n\n private syncParameters(): void {\n const parameters = this.listParameters();\n if (parameters.length > 0) {\n this.postSync({ type: 'syncParameters', parameters });\n }\n }\n\n private resolveTargetId(target: string | number): number {\n return resolveTargetId(target);\n }\n\n private ensureTrackLane(target: string | number): number {\n const trackId = this.resolveTargetId(target);\n if (!Number.isInteger(trackId) || trackId <= 0) {\n throw new Error(`Invalid track id for mixer lane: ${String(target)}`);\n }\n const existing = this.trackLaneIds.indexOf(trackId);\n if (existing >= 0) {\n return existing;\n }\n this.trackLaneIds.push(trackId);\n this.syncMixer();\n return this.trackLaneIds.length - 1;\n }\n\n private ensureBus(busId: number): number {\n const resolved = Math.trunc(busId);\n if (!Number.isInteger(resolved) || resolved <= 0) {\n throw new Error(`Invalid bus id for mixer bus: ${String(busId)}`);\n }\n const existing = this.buses.findIndex((bus) => bus.busId === resolved);\n if (existing >= 0) {\n return existing;\n }\n this.buses.push({ busId: resolved });\n this.syncMixer();\n return this.buses.length - 1;\n }\n}\n","import type {\n EngineAutomationPoint,\n EngineBus,\n EngineCaptureStatus,\n EngineClip,\n EngineMarker,\n EngineMetronomeConfig,\n EngineMidiClipSchedule,\n EngineParameterInfo,\n EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTrackLane,\n EngineTransportState,\n RealtimeVoiceChangerConfigInput,\n RealtimeVoiceChangerPodConfig,\n} from '../index';\nimport type { AutomationCurve } from '../public_types';\nimport type {\n SonareEngineCommandRecord,\n SonareEngineTelemetryRecord,\n SonareWorkletMeterSnapshot,\n SonareWorkletSpectrumSnapshot,\n} from './protocol';\n\nexport interface SonareWorkletProcessorOptions {\n sceneJson: string;\n sampleRate?: number;\n blockSize?: number;\n stripCount?: number;\n meterIntervalFrames?: number;\n meterSharedBuffer?: SharedArrayBuffer;\n meterRingCapacity?: number;\n spectrumIntervalFrames?: number;\n spectrumBands?: number;\n spectrumSharedBuffer?: SharedArrayBuffer;\n spectrumRingCapacity?: number;\n}\n\nexport interface SonareRealtimeEngineWorkletProcessorOptions {\n wasmBinary?: ArrayBuffer | Uint8Array;\n initialSyncMessages?: SonareEngineSyncMessage[];\n initialCommands?: SonareEngineCommandRecord[];\n sampleRate?: number;\n blockSize?: number;\n channelCount?: number;\n meterIntervalFrames?: number;\n commandSharedBuffer?: SharedArrayBuffer;\n commandRingCapacity?: number;\n telemetrySharedBuffer?: SharedArrayBuffer;\n telemetryRingCapacity?: number;\n meterSharedBuffer?: SharedArrayBuffer;\n meterRingCapacity?: number;\n // Scope telemetry (FFT spectrum + goniometer): opt-in. The ring is created\n // only when scopeIntervalFrames > 0, since the per-block FFT is heavier than\n // the meter path. scopeBands selects the linear band resolution.\n scopeIntervalFrames?: number;\n scopeBands?: number;\n scopeSharedBuffer?: SharedArrayBuffer;\n scopeRingCapacity?: number;\n /**\n * Lock-free SPSC queue for clip-page cache misses. Supplying this is required\n * for realtime-safe OPFS streaming: it avoids both embind object creation and\n * postMessage structured cloning from AudioWorklet process().\n */\n clipPageRequestSharedBuffer?: SharedArrayBuffer;\n clipPageRequestRingCapacity?: number;\n /** Lock-free worklet-to-main-thread MIDI-1 output ring. */\n externalMidiSharedBuffer?: SharedArrayBuffer;\n externalMidiRingCapacity?: number;\n /**\n * Route the PFL/AFL cue bus to the processor's SECOND output instead of\n * folding it into the program output. Off by default, so an existing\n * single-output host keeps its current mix sample for sample. The node must\n * be constructed with two outputs for the cue to be audible.\n */\n cueOutput?: boolean;\n}\n\nexport interface SonareRealtimeVoiceChangerWorkletProcessorOptions {\n preset?: RealtimeVoiceChangerConfigInput;\n sampleRate?: number;\n blockSize?: number;\n channelCount?: number;\n}\n\nexport interface SonareRealtimeVoiceChangerSetConfigMessage {\n type: 'setConfig';\n /** Pre-normalized by the main thread; never JSON parsed in the worklet. */\n config: RealtimeVoiceChangerPodConfig;\n}\n\nexport interface SonareRealtimeVoiceChangerResetMessage {\n type: 'reset';\n}\n\nexport interface SonareRealtimeVoiceChangerDestroyMessage {\n type: 'destroy';\n}\n\nexport type SonareRealtimeVoiceChangerMessage =\n | SonareRealtimeVoiceChangerSetConfigMessage\n | SonareRealtimeVoiceChangerResetMessage\n | SonareRealtimeVoiceChangerDestroyMessage;\n\nexport interface SonareRealtimeEngineNodeCapabilities {\n mode: 'sab' | 'postMessage';\n runtimeTarget: 'embind';\n sharedArrayBuffer: boolean;\n atomics: boolean;\n audioWorklet: boolean;\n /** True only when clip-page misses use the bounded SAB ring. */\n clipPageRequestsRealtimeSafe: boolean;\n /** True when external MIDI uses the SAB output ring rather than postMessage. */\n externalMidiRealtimeSafe: boolean;\n /**\n * True when the node carries a second output fed by the PFL/AFL cue bus. When\n * false the cue is folded into the program output, as it always was.\n */\n cueOutput: boolean;\n engineAbiVersion?: number;\n expectedEngineAbiVersion?: number;\n abiCompatible?: boolean;\n degradedReason?: string;\n readyMessage?: boolean;\n}\n\nexport interface SonareRealtimeEngineNodeOptions\n extends SonareRealtimeEngineWorkletProcessorOptions {\n processorName?: string;\n moduleUrl?: string | URL;\n mode?: 'auto' | 'sab' | 'postMessage';\n engineAbiVersion?: number;\n expectedEngineAbiVersion?: number;\n requireAbiCompatible?: boolean;\n nodeFactory?: (\n context: BaseAudioContext,\n processorName: string,\n options: AudioWorkletNodeOptions,\n ) => AudioWorkletNode;\n}\n\nexport interface SonareEngineTransportFacade {\n play(sampleTime?: number): boolean;\n stop(sampleTime?: number): boolean;\n seekPpq(ppq: number, sampleTime?: number): boolean;\n seekSeconds(seconds: number, sampleTime?: number): boolean;\n setTempo(bpm: number): void;\n setTempoSegments(segments: readonly EngineTempoSegment[]): void;\n setLoop(startPpq: number, endPpq: number, enabled?: boolean): boolean;\n}\n\nexport interface SonareWorkletScheduleInsertAutomationMessage {\n type: 'scheduleInsertAutomation';\n stripIndex: number;\n insertIndex: number;\n paramId: number;\n value: number;\n samplePos?: number;\n curve?: AutomationCurve;\n}\n\nexport interface SonareWorkletSetMeterIntervalMessage {\n type: 'setMeterInterval';\n frames: number;\n}\n\nexport interface SonareWorkletDestroyMessage {\n type: 'destroy';\n}\n\nexport type SonareWorkletMessage =\n | SonareWorkletScheduleInsertAutomationMessage\n | SonareWorkletSetMeterIntervalMessage\n | SonareWorkletDestroyMessage;\n\n/** One external-MIDI event delivered to the main thread, lowered to MIDI 1.0\n * bytes ready for a Web MIDI output port. */\nexport interface SonareWorkletExternalMidiEvent {\n /** Originating track lane, or 0xFFFFFFFF for transport/clock bytes. */\n destinationId: number;\n /** Sample position within the producing block. */\n renderFrame: number;\n /** MIDI 1.0 status + data bytes (1..3 entries). */\n bytes: number[];\n}\n\n/** Batch of external-MIDI events posted from the worklet once per render block. */\nexport interface SonareWorkletExternalMidiMessage {\n type: 'externalMidi';\n events: SonareWorkletExternalMidiEvent[];\n}\n\n/** A control-plane sync message that the worklet rejected without crashing. */\nexport interface SonareEngineSyncErrorMessage {\n type: 'syncError';\n syncType: SonareEngineSyncMessage['type'];\n message: string;\n}\n\nexport type SonareWorkletTransportMessage =\n | SonareWorkletMeterSnapshot\n | SonareWorkletSpectrumSnapshot\n | SonareWorkletExternalMidiMessage\n | SonareEngineClipPageRequestMessage\n | SonareEngineTelemetryRecord;\n\nexport interface WorkletTransport {\n postMessage?: (\n message:\n | SonareWorkletTransportMessage\n | SonareEngineCaptureResponseMessageInternal\n | SonareEngineTransportResponseMessage\n | SonareEngineSyncErrorMessage,\n transfer?: Transferable[],\n ) => void;\n onMeter?: (meter: SonareWorkletMeterSnapshot) => void;\n onSpectrum?: (spectrum: SonareWorkletSpectrumSnapshot) => void;\n}\n\nexport interface ResolvedMetronomeConfig {\n beatGain: number;\n accentGain: number;\n clickSamples: number;\n clickSeconds: number;\n}\n\n// Fallback metronome gains/click length used by the worklet consumer until the\n// host posts a 'syncMetronome' config. Aligned with the embind setMetronome\n// defaults (src/wasm/bindings.cpp) so offline and realtime metronomes match.\nexport const DEFAULT_METRONOME_CONFIG: ResolvedMetronomeConfig = {\n beatGain: 0.35,\n accentGain: 0.7,\n clickSamples: 0,\n clickSeconds: 0,\n};\n\nexport function resolveMetronomeConfig(config: EngineMetronomeConfig): ResolvedMetronomeConfig {\n const resolved = {\n beatGain: config.beatGain ?? DEFAULT_METRONOME_CONFIG.beatGain,\n accentGain: config.accentGain ?? DEFAULT_METRONOME_CONFIG.accentGain,\n clickSamples: config.clickSamples ?? DEFAULT_METRONOME_CONFIG.clickSamples,\n clickSeconds: config.clickSeconds ?? DEFAULT_METRONOME_CONFIG.clickSeconds,\n };\n if (\n !Number.isFinite(resolved.beatGain) ||\n resolved.beatGain < 0 ||\n !Number.isFinite(resolved.accentGain) ||\n resolved.accentGain < 0 ||\n !Number.isInteger(resolved.clickSamples) ||\n resolved.clickSamples < 0 ||\n !Number.isFinite(resolved.clickSeconds) ||\n resolved.clickSeconds < 0 ||\n resolved.clickSamples > 384000 ||\n (config.clickSeconds !== undefined &&\n (!Number.isFinite(config.clickSeconds) || config.clickSeconds < 0 || config.clickSeconds > 1))\n ) {\n throw new RangeError('invalid metronome gains or click length');\n }\n return resolved;\n}\n\n// Out-of-band control messages posted from the main-thread SonareEngine facade\n// to the worklet engine processor over node.port. Unlike SonareEngineCommandRecord\n// (a small POD POSTed/ringed every block) these carry bulk/structured payloads\n// (clip audio buffers, marker lists, metronome config) that cannot fit the\n// fixed-size SAB command record. Their port handlers still execute on the\n// AudioWorklet rendering thread, so consumers must validate them without\n// allocation and publish bounded snapshots for process() to consume.\nexport interface SonareEngineSyncClipsMessage {\n type: 'syncClips';\n clips: EngineClip[];\n}\n\nexport interface SonareEngineSyncClipsDeltaMessage {\n type: 'syncClipsDelta';\n upserts: EngineClip[];\n removeIds: number[];\n}\n\n/** Begins a paged, pre-baked clip transfer. PCM pages follow in FIFO order. */\nexport interface SonareEngineSyncClipPageProviderMessage {\n type: 'syncClipPageProvider';\n clipId: number;\n /** Omitted when an OPFS stream is primed before its clip is scheduled. */\n clip?: EngineClip;\n numChannels: number;\n numSamples: number;\n pageFrames: number;\n}\n\n/** Supplies one bounded PCM page for a pending pre-baked clip transfer. */\nexport interface SonareEngineSyncClipPageMessage {\n type: 'syncClipPage';\n clipId: number;\n pageIndex: number;\n channels: Float32Array[];\n}\n\n/** Evicts one page after the main-thread sliding window advances. */\nexport interface SonareEngineSyncClipPageClearMessage {\n type: 'syncClipPageClear';\n clipId: number;\n pageIndex: number;\n}\n\n/** Releases a provider whose clip was removed or whose stream was closed. */\nexport interface SonareEngineSyncClipPageDestroyMessage {\n type: 'syncClipPageDestroy';\n clipId: number;\n}\n\n/** Makes a fully supplied paged clip visible to the audio engine. */\nexport interface SonareEngineSyncClipPageCommitMessage {\n type: 'syncClipPageCommit';\n clipId: number;\n /**\n * Clip schedule to publish with a provider that was primed before its\n * schedule was known. The original pre-baked push path supplies it on the\n * provider message instead.\n */\n clip?: EngineClip;\n}\n\n/**\n * A bounded batch of page misses emitted by the AudioWorklet. The main thread\n * resolves these from OPFS and responds with `syncClipPage`; a missing page is\n * silent until that response arrives.\n */\nexport interface SonareEngineClipPageRequestMessage {\n type: 'clipPageRequest';\n requests: Array<{ clipId: number; pageIndex: number }>;\n /** Number of misses dropped because a bounded native or SAB request queue was full. */\n dropped?: number;\n}\n\nexport interface SonareEngineSyncMidiClipsMessage {\n type: 'syncMidiClips';\n clips: EngineMidiClipSchedule[];\n}\n\nexport interface SonareEngineSyncMarkersMessage {\n type: 'syncMarkers';\n markers: EngineMarker[];\n}\n\nexport interface SonareEngineSyncMetronomeMessage {\n type: 'syncMetronome';\n config: EngineMetronomeConfig;\n}\n\nexport interface SonareEngineSyncAutomationMessage {\n type: 'syncAutomation';\n paramId: number;\n points: EngineAutomationPoint[];\n}\n\n/** Replaces the live engine's registered custom-parameter set. */\nexport interface SonareEngineSyncParametersMessage {\n type: 'syncParameters';\n parameters: EngineParameterInfo[];\n}\n\nexport interface SonareEngineSyncTempoMessage {\n type: 'syncTempo';\n bpm: number;\n timeSignature: { numerator: number; denominator: number };\n tempoSegments?: EngineTempoSegment[];\n timeSignatureSegments?: EngineTimeSignatureSegment[];\n}\n\nexport interface SonareEngineSyncMixerMessage {\n type: 'syncMixer';\n lanes: EngineTrackLane[];\n buses?: EngineBus[];\n trackStrips?: Array<{ trackId: number; sceneJson: string }>;\n busStrips?: Array<{ busId: number; sceneJson: string }>;\n masterStripJson?: string;\n /** Lane insert sidechain bindings (replayed after lanes/strips). */\n laneSidechains?: Array<{ trackId: number; insertIndex: number; sourceTrackId: number }>;\n}\n\nexport interface SonareEngineSyncCaptureMessage {\n type: 'syncCapture';\n bufferFrames: number;\n channels: number;\n source: EngineCaptureStatus['source'];\n recordOffsetSamples: number;\n inputMonitor: { enabled: boolean; gain: number };\n}\n\nexport interface SonareEngineSyncTrackStripEqBandMessage {\n type: 'syncTrackStripEqBand';\n trackId: number;\n bandIndex: number;\n bandJson: string;\n}\n\nexport interface SonareEngineSyncMasterStripEqBandMessage {\n type: 'syncMasterStripEqBand';\n bandIndex: number;\n bandJson: string;\n}\n\nexport interface SonareEngineSyncTrackStripInsertBypassedMessage {\n type: 'syncTrackStripInsertBypassed';\n trackId: number;\n insertIndex: number;\n bypassed: boolean;\n resetOnBypass: boolean;\n}\n\nexport interface SonareEngineSyncMasterStripInsertBypassedMessage {\n type: 'syncMasterStripInsertBypassed';\n insertIndex: number;\n bypassed: boolean;\n resetOnBypass: boolean;\n}\n\nexport interface SonareEngineSyncTrackStripInsertParamByNameMessage {\n type: 'syncTrackStripInsertParamByName';\n trackId: number;\n insertIndex: number;\n paramName: string;\n value: number;\n}\n\nexport interface SonareEngineSyncMasterStripInsertParamByNameMessage {\n type: 'syncMasterStripInsertParamByName';\n insertIndex: number;\n paramName: string;\n value: number;\n}\n\nexport interface SonareEngineSyncBusStripInsertParamByNameMessage {\n type: 'syncBusStripInsertParamByName';\n busId: number;\n insertIndex: number;\n paramName: string;\n value: number;\n}\n\nexport interface SonareEngineSyncTrackStripPanMessage {\n type: 'syncTrackStripPan';\n trackId: number;\n pan: number;\n}\n\nexport interface SonareEngineSyncTrackStripPanLawMessage {\n type: 'syncTrackStripPanLaw';\n trackId: number;\n panLaw: number;\n}\n\nexport interface SonareEngineSyncTrackStripPanModeMessage {\n type: 'syncTrackStripPanMode';\n trackId: number;\n panMode: number;\n}\n\nexport interface SonareEngineSyncTrackStripDualPanMessage {\n type: 'syncTrackStripDualPan';\n trackId: number;\n leftPan: number;\n rightPan: number;\n}\n\nexport interface SonareEngineSyncTrackStripChannelDelaySamplesMessage {\n type: 'syncTrackStripChannelDelaySamples';\n trackId: number;\n delaySamples: number;\n}\n\nexport interface SonareEngineSyncBuiltinInstrumentMessage {\n type: 'syncBuiltinInstrument';\n destinationId: number;\n config: { destinationId?: number } & Record<string, unknown>;\n}\n\nexport interface SonareEngineSyncSynthInstrumentMessage {\n type: 'syncSynthInstrument';\n destinationId: number;\n patch: Record<string, unknown> | string;\n}\n\nexport interface SonareEngineSyncSf2InstrumentMessage {\n type: 'syncSf2Instrument';\n destinationId: number;\n config: {\n destinationId?: number;\n gain?: number;\n polyphony?: number;\n preferModelForModeledFamilies?: boolean;\n };\n}\n\nexport interface SonareEngineSyncLoadSoundFontMessage {\n type: 'syncLoadSoundFont';\n data: Uint8Array;\n}\n\nexport interface SonareEngineSyncMidiFxMessage {\n type: 'syncMidiFx' | 'syncClearMidiFx';\n destinationId: number;\n /** Engine MIDI-FX config JSON; present for 'syncMidiFx', absent for a clear. */\n configJson?: string;\n}\n\nexport interface SonareEngineSyncMidiNoteMessage {\n type: 'syncMidiNoteOn' | 'syncMidiNoteOff';\n destinationId: number;\n group: number;\n channel: number;\n note: number;\n velocity: number;\n renderFrame: number;\n}\n\nexport interface SonareEngineSyncMidiCcMessage {\n type: 'syncMidiCc';\n destinationId: number;\n group: number;\n channel: number;\n controller: number;\n value: number;\n renderFrame: number;\n}\n\nexport interface SonareEngineSyncMidiUmpMessage {\n type: 'syncMidiUmp';\n destinationId: number;\n word0: number;\n renderFrame: number;\n}\n\nexport interface SonareEngineSyncMidiSysexMessage {\n type: 'syncMidiSysex';\n destinationId: number;\n data: Uint8Array;\n renderFrame: number;\n}\n\nexport interface SonareEngineSyncMidiPanicMessage {\n type: 'syncMidiPanic';\n renderFrame: number;\n}\n\nexport interface SonareEngineSyncMidiDestinationExternalMessage {\n type: 'syncMidiDestinationExternal';\n destinationId: number;\n external: boolean;\n}\n\nexport interface SonareEngineSyncExternalMidiClockMessage {\n type: 'syncExternalMidiClock';\n enabled: boolean;\n}\n\nexport interface SonareEngineSyncMidiInputSourceMessage {\n type: 'syncMidiInputSource' | 'syncClearMidiInputSource';\n destinationId?: number;\n}\n\nexport interface SonareEngineSyncMidiCcBindingMessage {\n type: 'syncMidiCcBinding';\n channel: number;\n controller: number;\n paramId: number;\n minValue: number;\n maxValue: number;\n}\n\nexport interface SonareEngineSyncMidiInputEventMessage {\n type: 'syncMidiInputNoteOn' | 'syncMidiInputNoteOff' | 'syncMidiInputCc';\n group: number;\n channel: number;\n data0: number;\n data1: number;\n portTimeSamples: number;\n}\n\n/** Releases the realtime engine and all worklet-owned clip buffers. */\nexport interface SonareEngineDestroyMessage {\n type: 'destroy';\n}\n\nexport type SonareEngineInstrumentSyncMessage =\n | SonareEngineSyncBuiltinInstrumentMessage\n | SonareEngineSyncSynthInstrumentMessage\n | SonareEngineSyncSf2InstrumentMessage\n | SonareEngineSyncLoadSoundFontMessage\n | SonareEngineSyncMidiFxMessage;\n\nexport type SonareEngineSyncMessage =\n | SonareEngineSyncClipsMessage\n | SonareEngineSyncClipsDeltaMessage\n | SonareEngineSyncClipPageProviderMessage\n | SonareEngineSyncClipPageMessage\n | SonareEngineSyncClipPageClearMessage\n | SonareEngineSyncClipPageCommitMessage\n | SonareEngineSyncClipPageDestroyMessage\n | SonareEngineSyncMidiClipsMessage\n | SonareEngineSyncMarkersMessage\n | SonareEngineSyncMetronomeMessage\n | SonareEngineSyncAutomationMessage\n | SonareEngineSyncParametersMessage\n | SonareEngineSyncTempoMessage\n | SonareEngineSyncMixerMessage\n | SonareEngineSyncCaptureMessage\n | SonareEngineSyncTrackStripEqBandMessage\n | SonareEngineSyncMasterStripEqBandMessage\n | SonareEngineSyncTrackStripInsertBypassedMessage\n | SonareEngineSyncMasterStripInsertBypassedMessage\n | SonareEngineSyncTrackStripInsertParamByNameMessage\n | SonareEngineSyncMasterStripInsertParamByNameMessage\n | SonareEngineSyncBusStripInsertParamByNameMessage\n | SonareEngineSyncTrackStripPanMessage\n | SonareEngineSyncTrackStripPanLawMessage\n | SonareEngineSyncTrackStripPanModeMessage\n | SonareEngineSyncTrackStripDualPanMessage\n | SonareEngineSyncTrackStripChannelDelaySamplesMessage\n | SonareEngineSyncBuiltinInstrumentMessage\n | SonareEngineSyncSynthInstrumentMessage\n | SonareEngineSyncSf2InstrumentMessage\n | SonareEngineSyncLoadSoundFontMessage\n | SonareEngineSyncMidiFxMessage\n | SonareEngineSyncMidiNoteMessage\n | SonareEngineSyncMidiCcMessage\n | SonareEngineSyncMidiUmpMessage\n | SonareEngineSyncMidiSysexMessage\n | SonareEngineSyncMidiPanicMessage\n | SonareEngineSyncMidiDestinationExternalMessage\n | SonareEngineSyncExternalMidiClockMessage\n | SonareEngineSyncMidiInputSourceMessage\n | SonareEngineSyncMidiCcBindingMessage\n | SonareEngineSyncMidiInputEventMessage\n | SonareEngineDestroyMessage;\n\nexport interface WorkletPort {\n postMessage?: (message: unknown, transfer?: Transferable[]) => void;\n onmessage?: (event: { data: unknown }) => void;\n addEventListener?: (type: 'message', listener: (event: { data: unknown }) => void) => void;\n start?: () => void;\n}\n\nexport interface SonareEngineCaptureRequestMessage {\n type: 'captureRequest';\n requestId: number;\n op: 'status' | 'read' | 'reset';\n}\n\n/**\n * Public capture response shape retained for source compatibility.\n *\n * The worklet wire protocol is stricter than this legacy structural type; use\n * `SonareEngineCaptureResponseMessageInternal` inside the implementation.\n */\nexport interface SonareEngineCaptureResponseMessage {\n type: 'captureResponse';\n requestId: number;\n ok: boolean;\n status?: EngineCaptureStatus;\n channels?: Float32Array[] | number[][];\n error?: string;\n}\n\ninterface SonareEngineCaptureStatusResponseMessageInternal {\n type: 'captureResponse';\n requestId: number;\n ok: true;\n status: EngineCaptureStatus;\n}\n\ninterface SonareEngineCaptureReadResponseMessageInternal {\n type: 'captureResponse';\n requestId: number;\n ok: true;\n channels: Float32Array[];\n}\n\ninterface SonareEngineCaptureResetResponseMessageInternal {\n type: 'captureResponse';\n requestId: number;\n ok: true;\n}\n\ninterface SonareEngineCaptureErrorResponseMessageInternal {\n type: 'captureResponse';\n requestId: number;\n ok: false;\n error: string;\n}\n\n/** Strict wire response type used only by the worklet implementation. */\nexport type SonareEngineCaptureResponseMessageInternal =\n | SonareEngineCaptureStatusResponseMessageInternal\n | SonareEngineCaptureReadResponseMessageInternal\n | SonareEngineCaptureResetResponseMessageInternal\n | SonareEngineCaptureErrorResponseMessageInternal;\n\nexport interface SonareEngineTransportRequestMessage {\n type: 'transportRequest';\n requestId: number;\n op: 'state';\n}\n\nexport interface SonareEngineTransportResponseMessage {\n type: 'transportResponse';\n requestId: number;\n ok: boolean;\n state?: EngineTransportState;\n error?: string;\n}\n","import type { EngineClip } from '../index';\nimport { RealtimeEngine } from '../index';\nimport type { WorkletInput, WorkletOutput } from './audio_types';\nimport {\n DEFAULT_METRONOME_CONFIG,\n type ResolvedMetronomeConfig,\n resolveMetronomeConfig,\n type SonareEngineCaptureRequestMessage,\n type SonareEngineCaptureResponseMessageInternal,\n type SonareEngineSyncMessage,\n type SonareEngineTransportRequestMessage,\n type SonareEngineTransportResponseMessage,\n type SonareRealtimeEngineWorkletProcessorOptions,\n type WorkletTransport,\n} from './messages';\nimport {\n clipPageRequestRingFromSharedBuffer,\n encodeFrameHi,\n encodeFrameLo,\n engineRingFromSharedBuffer,\n externalMidiRingFromSharedBuffer,\n meterFromEngine,\n meterRingFromSharedBuffer,\n popSonareEngineCommandRingBuffer,\n pushSonareClipPageRequestRingBuffer,\n pushSonareExternalMidiRingBuffer,\n type SharedClipPageRequestRingWriter,\n type SharedExternalMidiRingWriter,\n type SharedMeterRingWriter,\n type SharedScopeRingWriter,\n SONARE_ENGINE_COMMAND_RECORD_BYTES,\n SONARE_ENGINE_TELEMETRY_RECORD_BYTES,\n SONARE_METER_RING_RECORD_FLOATS,\n SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS,\n type SonareEngineCommandRecord,\n type SonareEngineCommandRingBuffer,\n SonareEngineCommandType,\n SonareEngineTelemetryError,\n type SonareEngineTelemetryRecord,\n type SonareEngineTelemetryRingBuffer,\n SonareEngineTelemetryType,\n type SonareWorkletMeterSnapshot,\n scopeRingFromSharedBuffer,\n telemetryFromEngine,\n writeInt64Words,\n writeSonareEngineTelemetryRingBuffer,\n} from './protocol';\n\n/**\n * Copies one plane per output channel, zero-filling the tail past `frames` and\n * any channel the source does not cover. Shared by the program and cue outputs\n * so the two cannot drift in their padding behaviour. Allocation-free.\n */\nfunction copyPlanesToOutput(\n output: Float32Array[],\n planes: readonly Float32Array[],\n frames: number,\n): void {\n for (let ch = 0; ch < output.length; ch++) {\n const target = output[ch];\n const source = planes[ch] ?? planes[0];\n if (source) {\n target.set(source.subarray(0, Math.min(target.length, frames)));\n if (target.length > frames) {\n target.fill(0, frames);\n }\n } else {\n target.fill(0);\n }\n }\n}\n\nfunction captureTransferList(channels: readonly Float32Array[]): Transferable[] {\n const transfers: ArrayBuffer[] = [];\n const seen = new Set<ArrayBuffer>();\n for (const channel of channels) {\n const buffer = channel.buffer;\n if (!(buffer instanceof ArrayBuffer)) {\n throw new TypeError('capture response channels must use plain ArrayBuffers');\n }\n if (!seen.has(buffer)) {\n seen.add(buffer);\n transfers.push(buffer);\n }\n }\n return transfers;\n}\n\n/**\n * AudioWorklet-style bridge for the DAW realtime engine facade.\n *\n * Backed by the `sonare.wasm` embind facade.\n */\nexport class SonareRealtimeEngineWorkletProcessor {\n private static warnedChannelScratchOverflow = false;\n readonly sampleRate: number;\n readonly blockSize: number;\n readonly channelCount: number;\n private engine: RealtimeEngine;\n private closed = false;\n private commandRing?: SonareEngineCommandRingBuffer;\n private telemetryRing?: SonareEngineTelemetryRingBuffer;\n private meterRing?: SharedMeterRingWriter;\n private scopeRing?: SharedScopeRingWriter;\n private clipPageRequestRing?: SharedClipPageRequestRingWriter;\n private externalMidiRing?: SharedExternalMidiRingWriter;\n private transport?: WorkletTransport;\n private meterIntervalFrames: number;\n private lastMeterFrame = Number.NEGATIVE_INFINITY;\n // Latest metronome gains/click length pushed via 'syncMetronome'. The\n // SetMetronome command only toggles enabled state; the config arrives here.\n private metronomeConfig: ResolvedMetronomeConfig = { ...DEFAULT_METRONOME_CONFIG };\n // Zero-copy prepared realtime path: persistent per-channel views onto the\n // engine's WASM-heap scratch (acquired once on the main thread via\n // getChannelBuffer). process() writes the AudioWorklet input straight into\n // these views, calls engine.processPrepared(frames) which runs the engine IN\n // PLACE, then reads the same views back — no std::vector or JS Float32Array is\n // allocated per render quantum (the old engine.process() round-tripped fresh\n // arrays on both heaps every block, an RT-safety hazard).\n private channelBuffers: Float32Array[];\n // Cue-bus plane, allocated only when the host asked for a separate PFL/AFL\n // output. Empty otherwise, so a single-output host pays no heap and keeps the\n // historical behaviour where process() folds the cue into the program mix.\n private monitorBuffers: Float32Array[] = [];\n private readonly cueOutput: boolean;\n private readonly liveClips = new Map<number, EngineClip>();\n private readonly pagedClipProviders = new Map<number, number>();\n private readonly pagedClipPageFrames = new Map<number, number>();\n private readonly pendingPagedClips = new Map<number, EngineClip>();\n // The worklet drains at most this many distinct page misses per render\n // quantum. The fixed scalar buffers avoid retaining an unbounded queue on\n // the audio thread; any remaining native requests stay queued for the next\n // quantum and render silence meanwhile.\n private readonly clipPageRequestClipIds = new Float64Array(64);\n private readonly clipPageRequestPageIndices = new Float64Array(64);\n private clipPageRequestOverflowReported = 0;\n\n constructor(\n options: SonareRealtimeEngineWorkletProcessorOptions = {},\n transport?: WorkletTransport,\n ) {\n this.sampleRate = options.sampleRate ?? 48000;\n this.blockSize = options.blockSize ?? 128;\n this.channelCount = Math.max(1, Math.floor(options.channelCount ?? 2));\n this.transport = transport;\n this.meterIntervalFrames = Math.max(0, Math.floor(options.meterIntervalFrames ?? 2048));\n this.commandRing = options.commandSharedBuffer\n ? this.commandRingFromSharedBuffer(options.commandSharedBuffer, options.commandRingCapacity)\n : undefined;\n this.telemetryRing = options.telemetrySharedBuffer\n ? this.telemetryRingFromSharedBuffer(\n options.telemetrySharedBuffer,\n options.telemetryRingCapacity,\n )\n : undefined;\n this.meterRing = options.meterSharedBuffer\n ? meterRingFromSharedBuffer(options.meterSharedBuffer, options.meterRingCapacity)\n : undefined;\n this.scopeRing = options.scopeSharedBuffer\n ? scopeRingFromSharedBuffer(\n options.scopeSharedBuffer,\n options.scopeRingCapacity,\n options.scopeBands,\n )\n : undefined;\n this.clipPageRequestRing = options.clipPageRequestSharedBuffer\n ? clipPageRequestRingFromSharedBuffer(\n options.clipPageRequestSharedBuffer,\n options.clipPageRequestRingCapacity,\n )\n : undefined;\n this.externalMidiRing = options.externalMidiSharedBuffer\n ? externalMidiRingFromSharedBuffer(\n options.externalMidiSharedBuffer,\n options.externalMidiRingCapacity,\n )\n : undefined;\n this.engine = new RealtimeEngine(\n this.sampleRate,\n this.blockSize,\n 1024,\n 1024,\n this.channelCount,\n );\n // Allocate persistent WASM-heap scratch (worst case: channelCount channels x\n // blockSize frames) and acquire the per-channel heap views once.\n this.engine.prepareChannels(this.channelCount, this.blockSize);\n this.channelBuffers = new Array(this.channelCount);\n for (let ch = 0; ch < this.channelCount; ch++) {\n this.channelBuffers[ch] = this.engine.getChannelBuffer(ch, this.blockSize);\n }\n this.cueOutput = options.cueOutput === true;\n if (this.cueOutput) {\n this.engine.prepareMonitorChannels(this.channelCount, this.blockSize);\n this.monitorBuffers = new Array(this.channelCount);\n for (let ch = 0; ch < this.channelCount; ch++) {\n this.monitorBuffers[ch] = this.engine.getMonitorChannelBuffer(ch, this.blockSize);\n }\n }\n // Arm the engine's scope producer only when a scope ring was provided. The\n // band count follows the ring's record layout so writeScopeRing never\n // overruns its slot.\n if (this.scopeRing) {\n const interval = Math.max(1, Math.floor(options.scopeIntervalFrames ?? this.blockSize));\n this.engine.configureScopeTelemetry(interval, this.scopeRing.bands);\n }\n }\n\n process(inputs: WorkletInput, outputs: WorkletOutput): boolean {\n if (this.closed) {\n return false;\n }\n const output = outputs[0];\n const firstOutput = output?.[0];\n if (!firstOutput) {\n return true;\n }\n const frames = firstOutput.length;\n if (frames > this.blockSize) {\n for (const channel of output ?? []) {\n channel.fill(0);\n }\n this.publishTelemetry();\n return true;\n }\n\n this.drainCommands();\n\n // Clamp `frames` to the pre-allocated scratch capacity. The earlier\n // `frames > this.blockSize` branch already returns early, so this is\n // defensive — but we warn once if it ever fires so the contract violation\n // is visible.\n let usableFrames = frames;\n if (usableFrames > this.blockSize) {\n if (!SonareRealtimeEngineWorkletProcessor.warnedChannelScratchOverflow) {\n SonareRealtimeEngineWorkletProcessor.warnedChannelScratchOverflow = true;\n // biome-ignore lint/suspicious/noConsole: realtime-safety diagnostic.\n console.warn(\n `SonareRealtimeEngineWorkletProcessor: requested ${usableFrames} frames ` +\n `exceeds pre-allocated capacity ${this.blockSize}; clamping.`,\n );\n }\n usableFrames = this.blockSize;\n }\n\n // Defend against WASM linear-memory growth detaching the cached heap views:\n // if any view's backing ArrayBuffer has been detached (byteLength === 0),\n // re-acquire all of them. This is a control-flow check (no allocation in the\n // common case where memory did not grow).\n if ((this.channelBuffers[0]?.byteLength ?? 0) === 0) {\n this.reacquireChannelBuffers();\n }\n if (this.cueOutput && (this.monitorBuffers[0]?.byteLength ?? 0) === 0) {\n this.reacquireMonitorBuffers();\n }\n\n const input = inputs[0];\n // Write the AudioWorklet input straight into the engine's WASM-heap views;\n // no per-block heap allocation.\n for (let ch = 0; ch < this.channelCount; ch++) {\n const dst = this.channelBuffers[ch];\n const source = input?.[ch];\n if (source && source.length === usableFrames) {\n dst.set(source.subarray(0, usableFrames));\n } else {\n dst.fill(0, 0, usableFrames);\n }\n }\n\n // Run the engine in place over the prepared scratch (allocation-free). The\n // monitor variant keeps the cue bus out of the program planes so it can go\n // to its own output; the plain call folds it in, as it always has.\n if (this.cueOutput) {\n this.engine.processPreparedWithMonitor(usableFrames);\n } else {\n this.engine.processPrepared(usableFrames);\n }\n\n copyPlanesToOutput(output, this.channelBuffers, usableFrames);\n if (this.cueOutput) {\n const cue = outputs[1];\n if (cue) {\n copyPlanesToOutput(cue, this.monitorBuffers, usableFrames);\n }\n }\n this.publishClipPageRequests();\n this.publishTelemetry();\n this.publishMeters();\n this.publishScope();\n this.publishExternalMidi();\n return true;\n }\n\n private reacquireChannelBuffers(): void {\n for (let ch = 0; ch < this.channelCount; ch++) {\n this.channelBuffers[ch] = this.engine.getChannelBuffer(ch, this.blockSize);\n }\n }\n\n private reacquireMonitorBuffers(): void {\n for (let ch = 0; ch < this.channelCount; ch++) {\n this.monitorBuffers[ch] = this.engine.getMonitorChannelBuffer(ch, this.blockSize);\n }\n }\n\n receiveCommand(command: SonareEngineCommandRecord): void {\n if (!this.closed) {\n this.safeApplyCommand(command);\n }\n }\n\n // Applies an out-of-band control-plane sync message on the AudioWorklet\n // thread. These handlers must remain bounded: expensive clip transforms are\n // performed on the main-thread mirror, and long pre-baked PCM arrives in\n // small pages before the final lightweight clip schedule is committed.\n receiveSync(message: SonareEngineSyncMessage): void {\n if (this.closed) {\n return;\n }\n try {\n this.applySync(message);\n } catch (error) {\n this.transport?.postMessage?.({\n type: 'syncError',\n syncType: message.type,\n message: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n private applySync(message: SonareEngineSyncMessage): void {\n switch (message.type) {\n case 'destroy':\n this.destroy();\n return;\n case 'syncClips': {\n // Commit native state before touching the worklet-side mirrors. A\n // rejected embind call must leave a later delta based on the previous\n // clip set, not on a half-applied replacement.\n this.engine.setClips(message.clips);\n this.clearPagedClipProviders();\n this.liveClips.clear();\n for (const clip of message.clips) {\n if (clip.id !== undefined) {\n this.liveClips.set(clip.id, clip);\n }\n }\n break;\n }\n case 'syncClipsDelta': {\n const nextClips = new Map(this.liveClips);\n for (const clipId of message.removeIds) {\n nextClips.delete(clipId);\n }\n for (const clip of message.upserts) {\n if (clip.id !== undefined) {\n nextClips.set(clip.id, clip);\n }\n }\n this.engine.setClips(Array.from(nextClips.values()));\n for (const clipId of message.removeIds) {\n this.removePagedClipProvider(clipId);\n }\n this.liveClips.clear();\n for (const [clipId, clip] of nextClips) {\n this.liveClips.set(clipId, clip);\n }\n break;\n }\n case 'syncClipPageProvider': {\n const provider = this.engine.createClipPageProvider(\n message.numChannels,\n message.numSamples,\n message.pageFrames,\n );\n this.removePagedClipProvider(message.clipId);\n this.pagedClipProviders.set(message.clipId, provider.id);\n this.pagedClipPageFrames.set(message.clipId, message.pageFrames);\n if (message.clip) {\n this.pendingPagedClips.set(message.clipId, message.clip);\n }\n break;\n }\n case 'syncClipPage': {\n const providerId = this.pagedClipProviders.get(message.clipId);\n if (providerId !== undefined) {\n this.engine.supplyClipPage(providerId, message.pageIndex, message.channels);\n }\n break;\n }\n case 'syncClipPageClear': {\n const providerId = this.pagedClipProviders.get(message.clipId);\n if (providerId !== undefined) {\n this.engine.clearClipPage(providerId, message.pageIndex);\n }\n break;\n }\n case 'syncClipPageCommit': {\n const providerId = this.pagedClipProviders.get(message.clipId);\n const clip = message.clip ?? this.pendingPagedClips.get(message.clipId);\n if (providerId !== undefined && clip) {\n const nextClip = { ...clip, pageProvider: providerId };\n const nextClips = new Map(this.liveClips);\n nextClips.set(message.clipId, nextClip);\n this.engine.setClips(Array.from(nextClips.values()));\n this.liveClips.set(message.clipId, nextClip);\n this.pendingPagedClips.delete(message.clipId);\n }\n break;\n }\n case 'syncClipPageDestroy': {\n const nextClips = new Map(this.liveClips);\n nextClips.delete(message.clipId);\n this.engine.setClips(Array.from(nextClips.values()));\n this.liveClips.delete(message.clipId);\n this.removePagedClipProvider(message.clipId);\n break;\n }\n case 'syncMidiClips':\n this.engine.setMidiClips(message.clips);\n break;\n case 'syncMarkers':\n this.engine.setMarkers(message.markers);\n break;\n case 'syncMetronome':\n // Do not publish the cached config until the native engine accepted it.\n // Otherwise a rejected sync would corrupt the command-side fallback.\n {\n const config = resolveMetronomeConfig(message.config);\n this.engine.setMetronome(message.config);\n this.metronomeConfig = config;\n }\n break;\n case 'syncAutomation':\n this.engine.setAutomationLane(message.paramId, message.points);\n break;\n case 'syncParameters':\n this.engine.clearParameters();\n for (const info of message.parameters) {\n this.engine.addParameter(info);\n }\n break;\n case 'syncTempo':\n if (message.tempoSegments) {\n this.engine.setTempoSegments(message.tempoSegments);\n } else {\n this.engine.setTempo(message.bpm);\n }\n if (message.timeSignatureSegments) {\n this.engine.setTimeSignatureSegments(message.timeSignatureSegments);\n } else {\n this.engine.setTimeSignature(\n message.timeSignature.numerator,\n message.timeSignature.denominator,\n );\n }\n break;\n case 'syncMixer':\n if (message.buses) {\n this.engine.setTrackBuses(message.buses);\n }\n this.engine.setTrackLanes(message.lanes);\n for (const strip of message.trackStrips ?? []) {\n this.engine.setTrackStripJson(strip.trackId, strip.sceneJson);\n }\n for (const strip of message.busStrips ?? []) {\n this.engine.setBusStripJson(strip.busId, strip.sceneJson);\n }\n if (message.masterStripJson) {\n this.engine.setMasterStripJson(message.masterStripJson);\n }\n for (const binding of message.laneSidechains ?? []) {\n this.engine.setLaneSidechain(binding.trackId, binding.insertIndex, binding.sourceTrackId);\n }\n break;\n case 'syncCapture':\n this.engine.setCaptureBuffer(message.channels, message.bufferFrames);\n this.engine.setCaptureSource(message.source);\n this.engine.setRecordOffsetSamples(message.recordOffsetSamples);\n this.engine.setInputMonitor(message.inputMonitor.enabled, message.inputMonitor.gain);\n break;\n case 'syncTrackStripEqBand':\n this.engine.setTrackStripEqBandJson(message.trackId, message.bandIndex, message.bandJson);\n break;\n case 'syncMasterStripEqBand':\n this.engine.setMasterStripEqBandJson(message.bandIndex, message.bandJson);\n break;\n case 'syncTrackStripInsertBypassed':\n this.engine.setTrackStripInsertBypassed(\n message.trackId,\n message.insertIndex,\n message.bypassed,\n message.resetOnBypass,\n );\n break;\n case 'syncMasterStripInsertBypassed':\n this.engine.setMasterStripInsertBypassed(\n message.insertIndex,\n message.bypassed,\n message.resetOnBypass,\n );\n break;\n case 'syncTrackStripInsertParamByName':\n this.engine.setTrackStripInsertParamByName(\n message.trackId,\n message.insertIndex,\n message.paramName,\n message.value,\n );\n break;\n case 'syncMasterStripInsertParamByName':\n this.engine.setMasterStripInsertParamByName(\n message.insertIndex,\n message.paramName,\n message.value,\n );\n break;\n case 'syncBusStripInsertParamByName':\n this.engine.setBusStripInsertParamByName(\n message.busId,\n message.insertIndex,\n message.paramName,\n message.value,\n );\n break;\n case 'syncTrackStripPan':\n this.engine.setTrackStripPan(message.trackId, message.pan);\n break;\n case 'syncTrackStripPanLaw':\n this.engine.setTrackStripPanLaw(message.trackId, message.panLaw);\n break;\n case 'syncTrackStripPanMode':\n this.engine.setTrackStripPanMode(message.trackId, message.panMode);\n break;\n case 'syncTrackStripDualPan':\n this.engine.setTrackStripDualPan(message.trackId, message.leftPan, message.rightPan);\n break;\n case 'syncTrackStripChannelDelaySamples':\n this.engine.setTrackStripChannelDelaySamples(message.trackId, message.delaySamples);\n break;\n case 'syncBuiltinInstrument':\n this.engine.setBuiltinInstrument(message.config, message.destinationId);\n break;\n case 'syncSynthInstrument':\n this.engine.setSynthInstrument(message.patch, message.destinationId);\n break;\n case 'syncLoadSoundFont':\n this.engine.loadSoundFont(message.data);\n break;\n case 'syncSf2Instrument':\n this.engine.setSf2Instrument(message.config, message.destinationId);\n break;\n case 'syncMidiFx':\n this.engine.setMidiFx(message.destinationId, message.configJson ?? '');\n break;\n case 'syncClearMidiFx':\n this.engine.clearMidiFx(message.destinationId);\n break;\n case 'syncMidiNoteOn':\n this.engine.pushMidiNoteOn(\n message.destinationId,\n message.group,\n message.channel,\n message.note,\n message.velocity,\n message.renderFrame,\n );\n break;\n case 'syncMidiNoteOff':\n this.engine.pushMidiNoteOff(\n message.destinationId,\n message.group,\n message.channel,\n message.note,\n message.velocity,\n message.renderFrame,\n );\n break;\n case 'syncMidiCc':\n this.engine.pushMidiCc(\n message.destinationId,\n message.group,\n message.channel,\n message.controller,\n message.value,\n message.renderFrame,\n );\n break;\n case 'syncMidiUmp':\n this.engine.pushMidiUmp(message.destinationId, message.word0, message.renderFrame);\n break;\n case 'syncMidiSysex':\n this.engine.pushMidiSysex(message.destinationId, message.data, message.renderFrame);\n break;\n case 'syncMidiPanic':\n this.engine.pushMidiPanic(message.renderFrame);\n break;\n case 'syncMidiDestinationExternal':\n this.engine.setMidiDestinationExternal(message.destinationId, message.external);\n break;\n case 'syncExternalMidiClock':\n this.engine.setExternalMidiClockEnabled(message.enabled);\n break;\n case 'syncMidiInputSource':\n this.engine.setMidiInputSource(message.destinationId ?? 0);\n break;\n case 'syncClearMidiInputSource':\n this.engine.clearMidiInputSource();\n break;\n case 'syncMidiCcBinding':\n this.engine.bindMidiCc(message.channel, message.controller, message.paramId, {\n minValue: message.minValue,\n maxValue: message.maxValue,\n });\n break;\n case 'syncMidiInputNoteOn':\n this.engine.pushMidiInputNoteOn(\n message.group,\n message.channel,\n message.data0,\n message.data1,\n message.portTimeSamples,\n );\n break;\n case 'syncMidiInputNoteOff':\n this.engine.pushMidiInputNoteOff(\n message.group,\n message.channel,\n message.data0,\n message.data1,\n message.portTimeSamples,\n );\n break;\n case 'syncMidiInputCc':\n this.engine.pushMidiInputCc(\n message.group,\n message.channel,\n message.data0,\n message.data1,\n message.portTimeSamples,\n );\n break;\n }\n }\n\n receiveCaptureRequest(message: SonareEngineCaptureRequestMessage): void {\n if (this.closed) {\n return;\n }\n try {\n if (message.op === 'status') {\n const status = this.engine.captureStatus();\n this.transport?.postMessage?.({\n type: 'captureResponse',\n requestId: message.requestId,\n ok: true,\n status: {\n capturedFrames: status.capturedFrames,\n overflowCount: status.overflowCount,\n armed: status.armed,\n punchEnabled: status.punchEnabled,\n source: status.source,\n recordOffsetSamples: status.recordOffsetSamples,\n },\n } satisfies SonareEngineCaptureResponseMessageInternal);\n return;\n }\n if (message.op === 'read') {\n // Embind's outer val::array is array-like but not structured-cloneable\n // in every host. Copy only that tiny container; keep each native\n // Float32Array intact so the channel payload remains transferable.\n const channels = Array.from(this.engine.capturedAudio());\n const transfer = captureTransferList(channels);\n this.transport?.postMessage?.(\n {\n type: 'captureResponse',\n requestId: message.requestId,\n ok: true,\n channels,\n } satisfies SonareEngineCaptureResponseMessageInternal,\n transfer,\n );\n return;\n }\n this.engine.resetCapture();\n this.transport?.postMessage?.({\n type: 'captureResponse',\n requestId: message.requestId,\n ok: true,\n } satisfies SonareEngineCaptureResponseMessageInternal);\n } catch (error) {\n this.transport?.postMessage?.({\n type: 'captureResponse',\n requestId: message.requestId,\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n } satisfies SonareEngineCaptureResponseMessageInternal);\n }\n }\n\n receiveTransportRequest(message: SonareEngineTransportRequestMessage): void {\n if (this.closed) {\n return;\n }\n try {\n this.transport?.postMessage?.({\n type: 'transportResponse',\n requestId: message.requestId,\n ok: true,\n state: this.engine.getTransportState(),\n } satisfies SonareEngineTransportResponseMessage);\n } catch (error) {\n this.transport?.postMessage?.({\n type: 'transportResponse',\n requestId: message.requestId,\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n } satisfies SonareEngineTransportResponseMessage);\n }\n }\n\n destroy(): void {\n if (!this.closed) {\n this.clearPagedClipProviders();\n this.engine.destroy();\n this.closed = true;\n }\n }\n\n private drainCommands(): void {\n if (!this.commandRing) {\n return;\n }\n for (let i = 0; i < 64; i++) {\n const command = popSonareEngineCommandRingBuffer(this.commandRing);\n if (!command) {\n return;\n }\n this.safeApplyCommand(command);\n }\n }\n\n private safeApplyCommand(command: SonareEngineCommandRecord): void {\n try {\n this.applyCommand(command);\n } catch {\n // A malformed control command must never escape AudioWorklet.process():\n // Web Audio permanently stops invoking a processor that throws there.\n this.publishTelemetryRecord({\n type: SonareEngineTelemetryType.Error,\n error: SonareEngineTelemetryError.InvalidCommand,\n renderFrame: 0,\n timelineSample: 0,\n audibleTimelineSample: 0,\n graphLatencySamplesQ8: 0,\n value: Number(command.type),\n });\n }\n }\n\n private applyCommand(command: SonareEngineCommandRecord): void {\n const sampleTime = Number(command.sampleTime ?? -1);\n switch (command.type) {\n case SonareEngineCommandType.SetParam:\n // paramId is carried in targetId, the new value in argFloat (matches the\n // SonareEngine.setParam producer). sampleTime is the render frame.\n this.engine.setParameter(\n Math.trunc(Number(command.targetId ?? 0)),\n Number(command.argFloat ?? 0),\n sampleTime,\n );\n break;\n case SonareEngineCommandType.SetParamSmoothed:\n this.engine.setParameterSmoothed(\n Math.trunc(Number(command.targetId ?? 0)),\n Number(command.argFloat ?? 0),\n sampleTime,\n );\n break;\n case SonareEngineCommandType.TransportPlay:\n this.engine.play(sampleTime);\n break;\n case SonareEngineCommandType.TransportStop:\n this.engine.stop(sampleTime);\n break;\n case SonareEngineCommandType.TransportSeekSample:\n this.engine.seekSample(Number(command.argInt ?? 0), sampleTime);\n break;\n case SonareEngineCommandType.TransportSeekPpq:\n this.engine.seekPpq(Number(command.argFloat ?? 0), sampleTime);\n break;\n case SonareEngineCommandType.SetLoop:\n this.engine.setLoop(\n Number(command.argFloat ?? 0),\n Number(command.argInt ?? 0) / 1_000_000,\n command.targetId !== 0,\n );\n break;\n case SonareEngineCommandType.ArmRecord:\n this.engine.armCapture(Boolean(command.argInt));\n break;\n case SonareEngineCommandType.Punch:\n // Both endpoints already arrive as samples (see SonareEngine.punch);\n // do NOT re-scale by sampleRate.\n this.engine.setCapturePunch(\n Number(command.argInt ?? 0),\n Math.max(0, Math.round(Number(command.argFloat ?? 0))),\n true,\n );\n break;\n case SonareEngineCommandType.SetMetronome:\n // Metronome config (beatGain/accentGain/clickSamples/clickSeconds) is\n // delivered out-of-band via the 'syncMetronome' message so it carries\n // the caller's full config; the command only toggles enabled state as a\n // sample-aligned fallback.\n this.engine.setMetronome({\n enabled: Boolean(command.argInt),\n beatGain: this.metronomeConfig.beatGain,\n accentGain: this.metronomeConfig.accentGain,\n clickSamples: this.metronomeConfig.clickSamples,\n clickSeconds: this.metronomeConfig.clickSeconds,\n });\n break;\n case SonareEngineCommandType.SeekMarker:\n // The realtime engine's markers are kept in sync via 'syncMarkers'\n // (RtPublisher-style swap), so a queued kSeekMarker resolves correctly.\n this.engine.seekMarker(Math.trunc(Number(command.targetId ?? 0)), sampleTime);\n break;\n case SonareEngineCommandType.SetSoloMute:\n this.engine.setSoloMute(\n Math.trunc(Number(command.targetId ?? 0)),\n Boolean((Number(command.argInt ?? 0) & 0x2) !== 0),\n Boolean((Number(command.argInt ?? 0) & 0x1) !== 0),\n sampleTime,\n );\n break;\n case SonareEngineCommandType.SetTrackMonitorMode: {\n const rawMode = command.argInt;\n const mode = typeof rawMode === 'bigint' ? Number(rawMode) : rawMode;\n if (typeof mode !== 'number' || !Number.isSafeInteger(mode) || mode < 0 || mode > 2) {\n throw new RangeError(`Invalid track monitor mode: ${String(rawMode)}`);\n }\n const laneIndex = command.targetId;\n if (\n typeof laneIndex !== 'number' ||\n !Number.isSafeInteger(laneIndex) ||\n laneIndex < 0 ||\n laneIndex > 0xffff_ffff\n ) {\n throw new RangeError(`Invalid track monitor lane index: ${String(laneIndex)}`);\n }\n this.engine.setTrackMonitorMode(laneIndex, mode as 0 | 1 | 2, sampleTime);\n break;\n }\n default:\n this.publishTelemetryRecord({\n type: SonareEngineTelemetryType.Error,\n error: SonareEngineTelemetryError.UnknownTarget,\n renderFrame: 0,\n timelineSample: 0,\n audibleTimelineSample: 0,\n graphLatencySamplesQ8: 0,\n value: Number(command.type),\n });\n break;\n }\n }\n\n private publishTelemetry(): void {\n const ring = this.telemetryRing;\n if (ring) {\n for (let count = 0; count < 64 && this.engine.popTelemetryToScratch(); count++) {\n this.writeTelemetryScratch(ring);\n }\n return;\n }\n for (const item of this.engine.drainTelemetry(64)) {\n this.publishTelemetryRecord(telemetryFromEngine(item));\n }\n }\n\n private writeTelemetryScratch(ring: SonareEngineTelemetryRingBuffer): void {\n const writeIndex = Atomics.load(ring.header, 0);\n const offset = (writeIndex % ring.capacity) * SONARE_ENGINE_TELEMETRY_RECORD_BYTES;\n ring.view.setUint32(offset, this.engine.telemetryScratchType(), true);\n ring.view.setUint32(offset + 4, this.engine.telemetryScratchError(), true);\n writeInt64Words(ring.view, offset + 8, this.engine.telemetryScratchRenderFrame());\n writeInt64Words(ring.view, offset + 16, this.engine.telemetryScratchTimelineSample());\n writeInt64Words(ring.view, offset + 24, this.engine.telemetryScratchAudibleTimelineSample());\n ring.view.setInt32(offset + 32, this.engine.telemetryScratchGraphLatencySamplesQ8(), true);\n ring.view.setUint32(offset + 36, this.engine.telemetryScratchValue(), true);\n ring.view.setUint32(offset + 40, 0, true);\n ring.view.setUint32(offset + 44, 0, true);\n Atomics.store(ring.header, 0, writeIndex + 1);\n if (writeIndex + 1 > ring.capacity) {\n Atomics.store(ring.header, 4, writeIndex + 1 - ring.capacity);\n }\n }\n\n private publishTelemetryRecord(record: SonareEngineTelemetryRecord): void {\n if (this.telemetryRing) {\n writeSonareEngineTelemetryRingBuffer(this.telemetryRing, record);\n return;\n }\n this.transport?.postMessage?.(record);\n }\n\n // Drains the engine meter telemetry queue into the stereo meter ring / transport.\n //\n // Shared-queue contract: `drainMeterTelemetry` and `drainMeterTelemetryWide`\n // pop the SAME single-consumer telemetry queue, so exactly ONE of them may run\n // per engine. The live worklet path owns the queue via the stereo drain below;\n // the worklet meter ring (SONARE_METER_RING_RECORD_FLOATS) is a fixed stereo\n // layout carrying planes 0/1 plus the correlation/LUFS summary. Per-plane\n // surround meters are NOT delivered over the live worklet ring — a host that\n // needs them must use the offline `drainMeterTelemetryWide()` API on a\n // non-worklet engine instance (do not also call it on a worklet-driven engine,\n // or the two drains will starve each other).\n private publishMeters(): void {\n if (this.meterIntervalFrames <= 0 || (!this.transport && !this.meterRing)) {\n return;\n }\n if (this.meterRing) {\n for (let count = 0; count < 64 && this.engine.popMeterTelemetryToScratch(); count++) {\n const frame = this.engine.meterScratchRenderFrame();\n if (\n frame !== this.lastMeterFrame &&\n frame - this.lastMeterFrame < this.meterIntervalFrames\n ) {\n continue;\n }\n if (frame !== this.lastMeterFrame) {\n this.lastMeterFrame = frame;\n }\n this.writeMeterScratch(this.meterRing);\n }\n return;\n }\n for (const item of this.engine.drainMeterTelemetry(64)) {\n const meter = meterFromEngine(item);\n if (\n meter.frame !== this.lastMeterFrame &&\n meter.frame - this.lastMeterFrame < this.meterIntervalFrames\n ) {\n continue;\n }\n if (meter.frame !== this.lastMeterFrame) {\n this.lastMeterFrame = meter.frame;\n }\n // Prefer the lock-free SAB meter ring (matching the telemetry path and\n // SonareWorkletProcessor); only fall back to structured-clone postMessage\n // when no ring was provided, so we do not allocate/post from the audio\n // render callback in SAB mode.\n if (this.meterRing) {\n this.writeMeterRing(meter);\n } else {\n this.transport?.onMeter?.(meter);\n this.transport?.postMessage?.(meter);\n }\n }\n }\n\n private writeMeterScratch(ring: SharedMeterRingWriter): void {\n const writeIndex = Atomics.load(ring.header, 0);\n const offset = (writeIndex % ring.capacity) * SONARE_METER_RING_RECORD_FLOATS;\n const frame = Number(this.engine.meterScratchRenderFrame());\n ring.records[offset] = encodeFrameLo(frame);\n ring.records[offset + 1] = encodeFrameHi(frame);\n ring.records[offset + 2] = this.engine.meterScratchTargetId();\n for (let field = 0; field < 11; field++) {\n ring.records[offset + 3 + field] = this.engine.meterScratchValue(field);\n }\n Atomics.store(ring.header, 0, writeIndex + 1);\n }\n\n private writeMeterRing(meter: SonareWorkletMeterSnapshot): void {\n const ring = this.meterRing;\n if (!ring) {\n return;\n }\n const writeIndex = Atomics.load(ring.header, 0);\n const offset = (writeIndex % ring.capacity) * SONARE_METER_RING_RECORD_FLOATS;\n ring.records[offset] = encodeFrameLo(meter.frame);\n ring.records[offset + 1] = encodeFrameHi(meter.frame);\n ring.records[offset + 2] = meter.targetId;\n ring.records[offset + 3] = meter.peakDbL;\n ring.records[offset + 4] = meter.peakDbR;\n ring.records[offset + 5] = meter.rmsDbL;\n ring.records[offset + 6] = meter.rmsDbR;\n ring.records[offset + 7] = meter.correlation;\n ring.records[offset + 8] = meter.truePeakDbL;\n ring.records[offset + 9] = meter.truePeakDbR;\n ring.records[offset + 10] = meter.momentaryLufs;\n ring.records[offset + 11] = meter.shortTermLufs;\n ring.records[offset + 12] = meter.integratedLufs;\n ring.records[offset + 13] = meter.gainReductionDb;\n Atomics.store(ring.header, 0, writeIndex + 1);\n // writeIndex is a free-running monotonic counter, so an overflow guard here\n // would fire on essentially every write past the first `capacity` records\n // and store an ever-growing value, not a dropped-record count. Readers\n // already detect silent overrun via firstReadable = max(readIndex,\n // writeIndex - capacity), so header slot 3 is left at its initial 0.\n }\n\n // Drains the engine's scope producer (FFT spectrum + goniometer points) into\n // the lock-free SAB scope ring. No allocation on the render path: records are\n // written field-by-field into the ring.\n private publishScope(): void {\n const ring = this.scopeRing;\n if (!ring) {\n return;\n }\n for (let count = 0; count < 64 && this.engine.popScopeTelemetryToScratch(); count++) {\n this.writeScopeScratch(ring);\n }\n }\n\n private writeScopeScratch(ring: SharedScopeRingWriter): void {\n const writeIndex = Atomics.load(ring.header, 0);\n const base = (writeIndex % ring.capacity) * ring.recordFloats;\n const frame = Number(this.engine.scopeScratchRenderFrame());\n ring.records[base] = encodeFrameLo(frame);\n ring.records[base + 1] = encodeFrameHi(frame);\n ring.records[base + 2] = this.engine.scopeScratchTargetId();\n const bandCount = Math.min(ring.bands, this.engine.scopeScratchBandCount());\n ring.records[base + 3] = bandCount;\n const pointCount = Math.min(ring.maxPoints, this.engine.scopeScratchPointCount());\n ring.records[base + 4] = pointCount;\n const bandsBase = base + SONARE_SCOPE_RING_RECORD_PREFIX_FLOATS;\n for (let i = 0; i < bandCount; i++) {\n ring.records[bandsBase + i] = this.engine.scopeScratchBand(i);\n }\n const pointsBase = bandsBase + ring.bands;\n for (let i = 0; i < pointCount; i++) {\n ring.records[pointsBase + 2 * i] = this.engine.scopeScratchPointLeft(i);\n ring.records[pointsBase + 2 * i + 1] = this.engine.scopeScratchPointRight(i);\n }\n Atomics.store(ring.header, 0, writeIndex + 1);\n }\n\n // Drains queued external-MIDI events (already lowered to MIDI 1.0 bytes) and\n // forwards them to the main thread for delivery to Web MIDI output ports.\n // One batch per render block; skipped entirely when nothing is queued, so an\n // all-internal project never allocates or posts here.\n private publishExternalMidi(): void {\n const ring = this.externalMidiRing;\n if (ring) {\n for (let count = 0; count < 256 && this.engine.popExternalMidiToScratch(); count++) {\n pushSonareExternalMidiRingBuffer(\n ring,\n this.engine.externalMidiScratchDestinationId(),\n this.engine.externalMidiScratchRenderFrame(),\n this.engine.externalMidiScratchByteWord(),\n this.engine.externalMidiScratchByteCount(),\n );\n this.engine.consumeExternalMidiScratch();\n }\n return;\n }\n if (!this.transport?.postMessage) {\n return;\n }\n if (this.engine.externalMidiPendingCount() === 0) {\n return;\n }\n const events = this.engine.drainExternalMidi(256);\n if (events.length === 0) {\n return;\n }\n this.transport.postMessage({ type: 'externalMidi', events });\n }\n\n /**\n * Forward a bounded batch of native page misses to the main thread. This\n * deliberately runs after audio rendering: a cache miss is silence for this\n * block, and OPFS I/O must never delay `process()`.\n */\n private publishClipPageRequests(): void {\n const ring = this.clipPageRequestRing;\n const transport = this.transport;\n if (!ring && !transport?.postMessage) {\n return;\n }\n let count = 0;\n let drained = 0;\n while (drained < this.clipPageRequestClipIds.length) {\n drained += 1;\n let clipId: number;\n let sample: number;\n if (ring) {\n // This scalar scratch API is intentionally used only on the SAB path:\n // it avoids embind materialising one JS object for every page miss in\n // AudioWorklet process().\n if (!this.engine.popClipPageRequestToScratch()) {\n break;\n }\n clipId = this.engine.clipPageRequestScratchClipId();\n sample = this.engine.clipPageRequestScratchSample();\n } else {\n // postMessage fallback is explicitly non-RT-safe; retain the public\n // object-returning API only for that degraded control-plane path.\n const request = this.engine.popClipPageRequest();\n if (!request) {\n break;\n }\n clipId = request.clipId;\n sample = request.sample;\n }\n const pageFrames = this.pagedClipPageFrames.get(clipId);\n if (!pageFrames) {\n continue;\n }\n const pageIndex = Math.floor(sample / pageFrames);\n let duplicate = false;\n for (let i = 0; i < count; ++i) {\n if (\n this.clipPageRequestClipIds[i] === clipId &&\n this.clipPageRequestPageIndices[i] === pageIndex\n ) {\n duplicate = true;\n break;\n }\n }\n if (!duplicate) {\n this.clipPageRequestClipIds[count] = clipId;\n this.clipPageRequestPageIndices[count] = pageIndex;\n count += 1;\n }\n }\n const overflowCount = this.engine.clipPageRequestOverflowCount();\n // The native counter is uint32_t; preserve a correct delta across its\n // defined unsigned wraparound instead of emitting a negative count.\n const dropped = (overflowCount - this.clipPageRequestOverflowReported) >>> 0;\n this.clipPageRequestOverflowReported = overflowCount;\n if (ring) {\n // Preserve native-queue loss in the same cumulative counter used for a\n // full SAB request ring. No object, structured clone, or postMessage is\n // created on this path.\n if (dropped > 0) {\n Atomics.add(ring.header, 4, dropped);\n }\n for (let i = 0; i < count; ++i) {\n pushSonareClipPageRequestRingBuffer(\n ring,\n this.clipPageRequestClipIds[i],\n this.clipPageRequestPageIndices[i],\n );\n }\n return;\n }\n if (count === 0 && dropped === 0) {\n return;\n }\n if (!transport?.postMessage) {\n return;\n }\n // A message is necessarily allocated by postMessage; the hot path's\n // resident queue remains fixed-size and no message is built without a miss.\n const requests = new Array<{ clipId: number; pageIndex: number }>(count);\n for (let i = 0; i < count; ++i) {\n requests[i] = {\n clipId: this.clipPageRequestClipIds[i],\n pageIndex: this.clipPageRequestPageIndices[i],\n };\n }\n transport.postMessage({\n type: 'clipPageRequest',\n requests,\n ...(dropped > 0 ? { dropped } : {}),\n });\n }\n\n private removePagedClipProvider(clipId: number): void {\n const providerId = this.pagedClipProviders.get(clipId);\n if (providerId !== undefined) {\n this.engine.destroyClipPageProvider(providerId);\n }\n this.pagedClipProviders.delete(clipId);\n this.pagedClipPageFrames.delete(clipId);\n this.pendingPagedClips.delete(clipId);\n }\n\n private clearPagedClipProviders(): void {\n for (const clipId of this.pagedClipProviders.keys()) {\n this.removePagedClipProvider(clipId);\n }\n }\n\n private commandRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n fallbackCapacity?: number,\n ): SonareEngineCommandRingBuffer {\n const ring = engineRingFromSharedBuffer(\n sharedBuffer,\n SONARE_ENGINE_COMMAND_RECORD_BYTES,\n fallbackCapacity,\n );\n return { sharedBuffer, header: ring.header, view: ring.view, capacity: ring.capacity };\n }\n\n private telemetryRingFromSharedBuffer(\n sharedBuffer: SharedArrayBuffer,\n fallbackCapacity?: number,\n ): SonareEngineTelemetryRingBuffer {\n const ring = engineRingFromSharedBuffer(\n sharedBuffer,\n SONARE_ENGINE_TELEMETRY_RECORD_BYTES,\n fallbackCapacity,\n );\n return { sharedBuffer, header: ring.header, view: ring.view, capacity: ring.capacity };\n }\n}\n","import { init as initSonareModule, isInitialized } from '../index';\nimport type { SonareModule } from '../sonare.js';\nimport type { WorkletInput, WorkletOutput } from './audio_types';\nimport { SonareRealtimeEngineWorkletProcessor } from './engine-processor';\nimport {\n isEngineCaptureRequestMessage,\n isEngineCommandRecord,\n isEngineSyncMessage,\n isEngineTransportRequestMessage,\n} from './guards';\nimport type { SonareRealtimeEngineWorkletProcessorOptions, WorkletPort } from './messages';\n\nexport function registerSonareRealtimeEngineWorkletProcessor(\n name = 'sonare-realtime-engine-processor',\n): void {\n const scope = globalThis as unknown as {\n AudioWorkletProcessor?: new () => object;\n registerProcessor?: (processorName: string, processorCtor: unknown) => void;\n };\n if (!scope.AudioWorkletProcessor || !scope.registerProcessor) {\n throw new Error('AudioWorkletProcessor is not available in this context.');\n }\n const Base = scope.AudioWorkletProcessor;\n class RegisteredSonareRealtimeEngineWorkletProcessor extends Base {\n private bridge?: SonareRealtimeEngineWorkletProcessor;\n private readonly pendingMessages: unknown[] = [];\n private pendingMessagesOverflowed = false;\n readonly port?: WorkletPort;\n\n constructor(options?: { processorOptions?: SonareRealtimeEngineWorkletProcessorOptions }) {\n super();\n const port = this.port;\n const processorOptions = options?.processorOptions ?? {};\n void this.initializeEmbind(processorOptions, port);\n const onMessage = (event: { data: unknown }) => {\n if (!this.bridge) {\n if (this.pendingMessages.length < 1024) {\n this.pendingMessages.push(event.data);\n } else {\n // A long sync before embind initialization must fail visibly rather\n // than drop a provider/page/commit message and leave silent audio.\n this.pendingMessagesOverflowed = true;\n }\n return;\n }\n if (isEngineCommandRecord(event.data)) {\n this.bridge.receiveCommand(event.data);\n } else if (isEngineSyncMessage(event.data)) {\n this.bridge.receiveSync(event.data);\n } else if (isEngineCaptureRequestMessage(event.data)) {\n this.bridge.receiveCaptureRequest(event.data);\n } else if (isEngineTransportRequestMessage(event.data)) {\n this.bridge.receiveTransportRequest(event.data);\n }\n };\n if (port?.addEventListener) {\n port.addEventListener('message', onMessage);\n port.start?.();\n } else if (port) {\n port.onmessage = onMessage;\n }\n }\n\n process(inputs: WorkletInput, outputs: WorkletOutput): boolean {\n if (this.bridge) {\n return this.bridge.process(inputs, outputs);\n }\n const output = outputs[0];\n for (const channel of output ?? []) {\n channel.fill(0);\n }\n return true;\n }\n\n private replayPendingMessages(): void {\n const messages = this.pendingMessages.splice(0);\n for (const data of messages) {\n if (isEngineCommandRecord(data)) {\n this.bridge?.receiveCommand(data);\n } else if (isEngineSyncMessage(data)) {\n this.bridge?.receiveSync(data);\n } else if (isEngineCaptureRequestMessage(data)) {\n this.bridge?.receiveCaptureRequest(data);\n } else if (isEngineTransportRequestMessage(data)) {\n this.bridge?.receiveTransportRequest(data);\n }\n }\n }\n\n private async initializeEmbind(\n options: SonareRealtimeEngineWorkletProcessorOptions,\n port?: WorkletPort,\n ): Promise<void> {\n try {\n const initPromise = (\n globalThis as typeof globalThis & { SonareEmbindInitPromise?: Promise<void> }\n ).SonareEmbindInitPromise;\n if (initPromise) {\n await initPromise;\n }\n if (!isInitialized()) {\n type EmbindModuleFactory = (options?: {\n locateFile?: (path: string, prefix: string) => string;\n wasmBinary?: ArrayBuffer | Uint8Array;\n }) => Promise<SonareModule>;\n const moduleFactory = (\n globalThis as typeof globalThis & {\n SonareEmbindModuleFactory?: EmbindModuleFactory;\n }\n ).SonareEmbindModuleFactory;\n if (!moduleFactory) {\n throw new Error('embind realtime engine module is not initialized.');\n }\n await initSonareModule({\n locateFile: (path) => path,\n wasmBinary: options.wasmBinary,\n moduleFactory,\n });\n }\n if (this.pendingMessagesOverflowed) {\n throw new Error('AudioWorklet initialization message buffer overflowed.');\n }\n this.bridge = new SonareRealtimeEngineWorkletProcessor(options, {\n postMessage: (message, transfer) => port?.postMessage?.(message, transfer),\n onMeter: (meter) => port?.postMessage?.(meter),\n });\n for (const message of options.initialSyncMessages ?? []) {\n this.bridge.receiveSync(message);\n }\n for (const command of options.initialCommands ?? []) {\n this.bridge.receiveCommand(command);\n }\n this.replayPendingMessages();\n port?.postMessage?.({ type: 'ready', runtimeTarget: 'embind' });\n } catch (error) {\n port?.postMessage?.({\n type: 'error',\n message: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n scope.registerProcessor(name, RegisteredSonareRealtimeEngineWorkletProcessor);\n}\n","import type { MixerRealtimeBuffer } from '../index';\nimport { Mixer } from '../index';\nimport type { WorkletInput, WorkletOutput } from './audio_types';\nimport { isWorkletMessage } from './guards';\nimport type {\n SonareWorkletMessage,\n SonareWorkletProcessorOptions,\n WorkletPort,\n WorkletTransport,\n} from './messages';\nimport {\n encodeFrameHi,\n encodeFrameLo,\n magnitudeToDb,\n meterRingFromSharedBuffer,\n type SharedMeterRingWriter,\n type SharedSpectrumRingWriter,\n SONARE_METER_RING_RECORD_FLOATS,\n type SonareWorkletMeterSnapshot,\n type SonareWorkletSpectrumSnapshot,\n spectrumRingFromSharedBuffer,\n toDb,\n} from './protocol';\n\n/**\n * AudioWorklet-style mixer bridge backed by the package's single `sonare.wasm`.\n *\n * The WASM module must already be initialized via `init()` before constructing\n * this bridge. Each AudioWorklet input is treated as one stereo strip:\n * `inputs[strip][0]` is left and `inputs[strip][1]` is right. Missing channels\n * are replaced with preallocated silence.\n */\nexport class SonareWorkletProcessor {\n readonly sampleRate: number;\n readonly blockSize: number;\n private mixer: Mixer;\n private realtime: MixerRealtimeBuffer;\n private closed = false;\n private processedFrames = 0;\n private lastMeterFrame = 0;\n private meterIntervalFrames: number;\n private spectrumIntervalFrames: number;\n private lastSpectrumFrame = 0;\n private transport?: WorkletTransport;\n private meterRing?: SharedMeterRingWriter;\n private spectrumRing?: SharedSpectrumRingWriter;\n private spectrumBands: Float32Array;\n\n constructor(options: SonareWorkletProcessorOptions, transport?: WorkletTransport) {\n if (!options.sceneJson) {\n throw new Error('sceneJson is required.');\n }\n this.sampleRate = options.sampleRate ?? 48000;\n this.blockSize = options.blockSize ?? 128;\n this.meterIntervalFrames = Math.max(0, Math.floor(options.meterIntervalFrames ?? 2048));\n this.spectrumIntervalFrames = Math.max(0, Math.floor(options.spectrumIntervalFrames ?? 0));\n this.transport = transport;\n this.meterIntervalFrames = Math.max(0, Math.floor(options.meterIntervalFrames ?? 2048));\n this.meterRing = options.meterSharedBuffer\n ? meterRingFromSharedBuffer(options.meterSharedBuffer, options.meterRingCapacity)\n : undefined;\n this.spectrumRing = options.spectrumSharedBuffer\n ? spectrumRingFromSharedBuffer(\n options.spectrumSharedBuffer,\n options.spectrumRingCapacity,\n options.spectrumBands,\n )\n : undefined;\n const spectrumBandCount = this.spectrumRing?.bands ?? Math.max(1, options.spectrumBands ?? 16);\n this.spectrumBands = new Float32Array(spectrumBandCount);\n this.mixer = Mixer.fromSceneJson(options.sceneJson, this.sampleRate, this.blockSize);\n this.mixer.compile();\n const sceneStripCount = this.mixer.stripCount();\n const stripCount = options.stripCount ?? sceneStripCount;\n if (stripCount !== sceneStripCount) {\n throw new Error('stripCount must match the scene strip count.');\n }\n this.realtime = this.mixer.createRealtimeBuffer();\n }\n\n process(inputs: WorkletInput, outputs: WorkletOutput): boolean {\n if (this.closed) {\n return false;\n }\n const output = outputs[0];\n const leftOut = output?.[0];\n const rightOut = output?.[1];\n if (!leftOut) {\n return true;\n }\n const frames = leftOut.length;\n // The mixer's realtime heap buffers are sized to blockSize. A render quantum\n // that differs from blockSize (e.g. a future browser using a quantum other\n // than 128, or a misconfigured blockSize) must NOT return false here:\n // returning false permanently terminates the AudioWorkletProcessor and\n // silently kills the node mid-stream. Instead degrade gracefully by\n // processing min(frames, blockSize) and zero-filling any remainder.\n const usable = Math.min(frames, this.blockSize);\n\n for (let strip = 0; strip < this.realtime.leftInputs.length; strip++) {\n const input = inputs[strip];\n const left = input?.[0];\n const right = input?.[1];\n const leftTarget = this.realtime.leftInputs[strip];\n const rightTarget = this.realtime.rightInputs[strip];\n if (left && left.length >= usable) {\n leftTarget.set(left.subarray(0, usable));\n if (right && right.length >= usable) {\n rightTarget.set(right.subarray(0, usable));\n } else {\n rightTarget.set(left.subarray(0, usable));\n }\n } else {\n leftTarget.fill(0);\n rightTarget.fill(0);\n }\n }\n\n this.realtime.process(usable);\n if (usable === frames) {\n leftOut.set(this.realtime.outLeft.subarray(0, usable));\n if (rightOut) {\n rightOut.set(this.realtime.outRight.subarray(0, usable));\n }\n } else {\n // frames > blockSize: fill the produced part and zero the remaining tail.\n leftOut.fill(0);\n leftOut.set(this.realtime.outLeft.subarray(0, usable));\n if (rightOut) {\n rightOut.fill(0);\n rightOut.set(this.realtime.outRight.subarray(0, usable));\n }\n }\n this.processedFrames += usable;\n this.publishMeter(\n this.realtime.outLeft.subarray(0, usable),\n this.realtime.outRight.subarray(0, usable),\n );\n this.publishSpectrum(\n this.realtime.outLeft.subarray(0, usable),\n this.realtime.outRight.subarray(0, usable),\n );\n return true;\n }\n\n receiveMessage(message: SonareWorkletMessage): void {\n if (this.closed) {\n return;\n }\n if (message.type === 'destroy') {\n this.destroy();\n return;\n }\n if (message.type === 'setMeterInterval') {\n this.meterIntervalFrames = Math.max(0, Math.floor(message.frames));\n return;\n }\n if (message.type === 'scheduleInsertAutomation') {\n this.mixer.scheduleInsertAutomation(\n message.stripIndex,\n message.insertIndex,\n message.paramId,\n message.samplePos ?? this.processedFrames,\n message.value,\n message.curve ?? 'linear',\n );\n }\n }\n\n destroy(): void {\n if (!this.closed) {\n this.mixer.delete();\n this.closed = true;\n }\n }\n\n private publishMeter(left: Float32Array, right: Float32Array): void {\n if (!this.transport || this.meterIntervalFrames <= 0) {\n return;\n }\n if (this.processedFrames - this.lastMeterFrame < this.meterIntervalFrames) {\n return;\n }\n this.lastMeterFrame = this.processedFrames;\n\n let peakL = 0;\n let peakR = 0;\n let sumL = 0;\n let sumR = 0;\n let sumLR = 0;\n for (let i = 0; i < left.length; i++) {\n const l = left[i] ?? 0;\n const r = right[i] ?? 0;\n const absL = Math.abs(l);\n const absR = Math.abs(r);\n if (absL > peakL) {\n peakL = absL;\n }\n if (absR > peakR) {\n peakR = absR;\n }\n sumL += l * l;\n sumR += r * r;\n sumLR += l * r;\n }\n const rmsL = Math.sqrt(sumL / Math.max(1, left.length));\n const rmsR = Math.sqrt(sumR / Math.max(1, right.length));\n const denominator = Math.sqrt(sumL * sumR);\n const meter: SonareWorkletMeterSnapshot = {\n type: 'meter',\n targetId: 0,\n frame: this.processedFrames,\n peakDbL: toDb(peakL),\n peakDbR: toDb(peakR),\n rmsDbL: toDb(rmsL),\n rmsDbR: toDb(rmsR),\n correlation: denominator > 0 ? sumLR / denominator : 0,\n truePeakDbL: toDb(peakL),\n truePeakDbR: toDb(peakR),\n momentaryLufs: Number.NaN,\n shortTermLufs: Number.NaN,\n integratedLufs: Number.NaN,\n gainReductionDb: Number.NaN,\n };\n this.transport.onMeter?.(meter);\n if (this.meterRing) {\n this.writeMeterRing(meter);\n } else {\n this.transport.postMessage?.(meter);\n }\n }\n\n private writeMeterRing(meter: SonareWorkletMeterSnapshot): void {\n const ring = this.meterRing;\n if (!ring) {\n return;\n }\n const writeIndex = Atomics.load(ring.header, 0);\n const offset = (writeIndex % ring.capacity) * SONARE_METER_RING_RECORD_FLOATS;\n ring.records[offset] = encodeFrameLo(meter.frame);\n ring.records[offset + 1] = encodeFrameHi(meter.frame);\n ring.records[offset + 2] = meter.targetId;\n ring.records[offset + 3] = meter.peakDbL;\n ring.records[offset + 4] = meter.peakDbR;\n ring.records[offset + 5] = meter.rmsDbL;\n ring.records[offset + 6] = meter.rmsDbR;\n ring.records[offset + 7] = meter.correlation;\n ring.records[offset + 8] = meter.truePeakDbL;\n ring.records[offset + 9] = meter.truePeakDbR;\n ring.records[offset + 10] = meter.momentaryLufs;\n ring.records[offset + 11] = meter.shortTermLufs;\n ring.records[offset + 12] = meter.integratedLufs;\n ring.records[offset + 13] = meter.gainReductionDb;\n Atomics.store(ring.header, 0, writeIndex + 1);\n // writeIndex is a free-running monotonic counter, so an overflow guard here\n // would fire on essentially every write past the first `capacity` records\n // and store an ever-growing value, not a dropped-record count. Readers\n // already detect silent overrun via firstReadable = max(readIndex,\n // writeIndex - capacity), so header slot 3 is left at its initial 0.\n }\n\n private publishSpectrum(left: Float32Array, right: Float32Array): void {\n if (this.spectrumIntervalFrames <= 0) {\n return;\n }\n if (this.processedFrames - this.lastSpectrumFrame < this.spectrumIntervalFrames) {\n return;\n }\n this.lastSpectrumFrame = this.processedFrames;\n this.computeSpectrum(left, right);\n if (this.spectrumRing) {\n this.writeSpectrumRing(this.processedFrames, this.spectrumBands);\n return;\n }\n const spectrum: SonareWorkletSpectrumSnapshot = {\n type: 'spectrum',\n frame: this.processedFrames,\n bands: new Float32Array(this.spectrumBands),\n };\n this.transport?.onSpectrum?.(spectrum);\n this.transport?.postMessage?.(spectrum);\n }\n\n private computeSpectrum(left: Float32Array, right: Float32Array): void {\n // Coarse per-render-quantum band energy, NOT a full FFT analyzer: each band\n // is a single-bin DFT (bin = band + 1) evaluated over the current block of n\n // samples. Bins at or above the block Nyquist (band + 1 > floor(n / 2))\n // alias, so the evaluated band count is clamped to floor(n / 2) and any\n // higher bands are pinned to the silence floor. Bin resolution is therefore\n // tied to the render quantum (typically 128 samples); treat the output as a\n // rough spectral tilt, not a precise spectrum.\n const n = Math.max(1, Math.min(left.length, right.length));\n const maxBand = Math.floor(n / 2);\n for (let band = 0; band < this.spectrumBands.length; band++) {\n if (band >= maxBand) {\n this.spectrumBands[band] = magnitudeToDb(0);\n continue;\n }\n const bin = band + 1;\n let real = 0;\n let imag = 0;\n for (let i = 0; i < n; i++) {\n const sample = 0.5 * ((left[i] ?? 0) + (right[i] ?? 0));\n const phase = (-2 * Math.PI * bin * i) / n;\n real += sample * Math.cos(phase);\n imag += sample * Math.sin(phase);\n }\n this.spectrumBands[band] = magnitudeToDb((2 * Math.hypot(real, imag)) / n);\n }\n }\n\n private writeSpectrumRing(frame: number, bands: Float32Array): void {\n const ring = this.spectrumRing;\n if (!ring) {\n return;\n }\n const writeIndex = Atomics.load(ring.header, 0);\n const offset = (writeIndex % ring.capacity) * ring.recordFloats;\n ring.records[offset] = encodeFrameLo(frame);\n ring.records[offset + 1] = encodeFrameHi(frame);\n ring.records[offset + 2] = bands.length;\n ring.records.set(bands.subarray(0, ring.bands), offset + 3);\n Atomics.store(ring.header, 0, writeIndex + 1);\n // See writeMeterRing: header slot 4 (the spectrum-ring overflow slot) is\n // left at its initial 0; readers detect silent overrun via the\n // firstReadable = max(readIndex, writeIndex - capacity) clamp. (Slot 3 here\n // holds the band count and is still written at ring creation.)\n }\n}\n\nexport function registerSonareWorkletProcessor(name = 'sonare-worklet-processor'): void {\n const scope = globalThis as unknown as {\n AudioWorkletProcessor?: new () => object;\n registerProcessor?: (processorName: string, processorCtor: unknown) => void;\n };\n if (!scope.AudioWorkletProcessor || !scope.registerProcessor) {\n throw new Error('AudioWorkletProcessor is not available in this context.');\n }\n const Base = scope.AudioWorkletProcessor;\n class RegisteredSonareWorkletProcessor extends Base {\n private bridge: SonareWorkletProcessor;\n readonly port?: WorkletPort;\n\n constructor(options?: { processorOptions?: SonareWorkletProcessorOptions }) {\n super();\n const port = this.port;\n this.bridge = new SonareWorkletProcessor(options?.processorOptions ?? { sceneJson: '' }, {\n postMessage: (message) => port?.postMessage?.(message),\n });\n const onMessage = (event: { data: unknown }) => {\n if (isWorkletMessage(event.data)) {\n this.bridge.receiveMessage(event.data);\n }\n };\n if (port?.addEventListener) {\n port.addEventListener('message', onMessage);\n port.start?.();\n } else if (port) {\n port.onmessage = onMessage;\n }\n }\n\n process(inputs: WorkletInput, outputs: WorkletOutput): boolean {\n return this.bridge.process(inputs, outputs);\n }\n }\n scope.registerProcessor(name, RegisteredSonareWorkletProcessor);\n}\n","import { RealtimeVoiceChanger } from '../index';\nimport type { WorkletInput, WorkletOutput } from './audio_types';\nimport { isRealtimeVoiceChangerMessage } from './guards';\nimport type {\n SonareRealtimeVoiceChangerMessage,\n SonareRealtimeVoiceChangerWorkletProcessorOptions,\n WorkletPort,\n} from './messages';\n\nexport class SonareRealtimeVoiceChangerWorkletProcessor {\n private static warnedMonoOverflow = false;\n private static warnedInterleavedOverflow = false;\n private changer: RealtimeVoiceChanger;\n private readonly sampleRate: number;\n private readonly blockSize: number;\n private readonly channelCount: number;\n // WASM-heap typed-memory views, sized to the worst case (blockSize *\n // channelCount). Acquired on the main thread (constructor) so the\n // audio-thread process() never crosses an allocation boundary.\n private monoInput: Float32Array;\n private monoOutput: Float32Array;\n private bufferGeneration: number;\n // Planar heap-backed views (one Float32Array per channel) used by the\n // multi-channel path. AudioWorklet inputs/outputs are already planar\n // Float32Arrays, so this avoids the per-sample interleave/deinterleave\n // passes that the older interleaved path needed.\n private planarChannels: Float32Array[];\n private destroyed = false;\n\n constructor(options: SonareRealtimeVoiceChangerWorkletProcessorOptions = {}) {\n this.sampleRate = options.sampleRate ?? 48000;\n this.blockSize = options.blockSize ?? 128;\n this.channelCount = Math.max(1, Math.floor(options.channelCount ?? 1));\n this.changer = new RealtimeVoiceChanger(options.preset ?? 'neutral-monitor');\n this.changer.prepare(this.sampleRate, this.blockSize, this.channelCount);\n // Acquire WASM-heap views once, sized to the worst case. These are alive\n // for the lifetime of the changer; if the host requests more frames per\n // process() than blockSize, we clamp (see ensure*Capacity).\n this.monoInput = this.changer.getMonoInputBuffer(this.blockSize);\n this.monoOutput = this.changer.getMonoOutputBuffer(this.blockSize);\n this.bufferGeneration = this.changer.bufferGeneration();\n this.planarChannels = [];\n if (this.channelCount > 1) {\n for (let ch = 0; ch < this.channelCount; ch++) {\n this.planarChannels.push(this.changer.getPlanarChannelBuffer(ch, this.blockSize));\n }\n }\n }\n\n /**\n * Handles a control-plane message from the main thread. AudioWorklet port\n * handlers run on the same audio rendering thread as `process()`: this path\n * therefore accepts only a pre-normalized POD and never parses JSON.\n */\n receiveMessage(message: SonareRealtimeVoiceChangerMessage): void {\n if (this.destroyed) {\n return;\n }\n if (message.type === 'setConfig') {\n this.changer.setPodConfig(message.config);\n } else if (message.type === 'reset') {\n this.changer.reset();\n } else if (message.type === 'destroy') {\n this.destroy();\n }\n }\n\n process(inputs: WorkletInput, outputs: WorkletOutput): boolean {\n const output = outputs[0];\n if (this.destroyed || !output || output.length === 0) {\n return !this.destroyed;\n }\n\n // The cached heap views can detach if WASM linear memory grows (the embind\n // module is built ALLOW_MEMORY_GROWTH). Re-acquire them if detached\n // (byteLength === 0) before touching them; in the common no-growth case this\n // is a cheap branch with no allocation.\n if (\n this.bufferGeneration !== this.changer.bufferGeneration() ||\n this.monoInput.byteLength === 0\n ) {\n this.reacquireBuffers();\n }\n\n const input = inputs[0];\n const requestedFrames = output[0]?.length ?? 0;\n const requestedChannels = Math.min(this.channelCount, output.length);\n if (requestedFrames === 0 || requestedChannels === 0) {\n return true;\n }\n\n if (requestedChannels === 1) {\n // Clamp to the pre-allocated capacity; warn (once) if the host violated\n // the contract. We never reallocate on the audio thread.\n const frames = this.ensureMonoCapacity(requestedFrames);\n const source = input?.[0];\n if (source) {\n this.monoInput.set(source.subarray(0, frames));\n } else {\n this.monoInput.fill(0, 0, frames);\n }\n this.changer.processPreparedMono(frames);\n output[0].set(this.monoOutput.subarray(0, frames));\n return true;\n }\n\n const frames = this.ensureInterleavedCapacity(requestedFrames, requestedChannels);\n const channels = requestedChannels;\n // Planar zero-copy path: AudioWorklet's input[ch] is already a\n // Float32Array per channel, so we set() straight into the heap-backed\n // planar view and processPreparedPlanar runs in place.\n for (let ch = 0; ch < channels; ch++) {\n const src = input?.[ch];\n const dst = this.planarChannels[ch];\n if (!dst) {\n continue;\n }\n if (src) {\n dst.set(src.subarray(0, frames));\n } else {\n dst.fill(0, 0, frames);\n }\n }\n this.changer.processPreparedPlanar(frames);\n for (let ch = 0; ch < channels; ch++) {\n const src = this.planarChannels[ch];\n if (src) {\n output[ch].set(src.subarray(0, frames));\n }\n // No `for frame` inner loop needed; output[ch] is a Float32Array.\n }\n return true;\n }\n\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n this.destroyed = true;\n this.changer.delete();\n }\n\n // Re-acquires the cached WASM-heap views after a memory-growth detachment.\n // The underlying C++ vectors are pre-warmed (ensure_*_capacity ran at prepare\n // time), so getMono*/getPlanar* return fresh views onto the SAME storage\n // without reallocating it.\n private reacquireBuffers(): void {\n this.monoInput = this.changer.getMonoInputBuffer(this.blockSize);\n this.monoOutput = this.changer.getMonoOutputBuffer(this.blockSize);\n if (this.channelCount > 1) {\n for (let ch = 0; ch < this.channelCount; ch++) {\n this.planarChannels[ch] = this.changer.getPlanarChannelBuffer(ch, this.blockSize);\n }\n }\n this.bufferGeneration = this.changer.bufferGeneration();\n }\n\n /**\n * Returns the number of frames we can actually process given the\n * pre-allocated capacity. If the host requests more frames than the\n * worst-case block size declared at construction time, we clamp to the\n * available capacity and warn once — we MUST NOT reallocate on the\n * realtime audio thread.\n */\n private ensureMonoCapacity(frames: number): number {\n const capacity = this.monoInput.length;\n if (frames <= capacity) {\n return frames;\n }\n if (!SonareRealtimeVoiceChangerWorkletProcessor.warnedMonoOverflow) {\n SonareRealtimeVoiceChangerWorkletProcessor.warnedMonoOverflow = true;\n // biome-ignore lint/suspicious/noConsole: realtime-safety diagnostic.\n console.warn(\n `SonareRealtimeVoiceChangerWorkletProcessor: requested ${frames} mono frames ` +\n `exceeds pre-allocated capacity ${capacity}; clamping. ` +\n 'Increase blockSize at construction time to avoid this.',\n );\n }\n return capacity;\n }\n\n /**\n * Same contract as ensureMonoCapacity but for the planar per-channel\n * scratch. Returns the number of frames that fit in the available capacity.\n */\n private ensureInterleavedCapacity(frames: number, channels: number): number {\n const capacity = this.planarChannels[0]?.length ?? 0;\n if (frames <= capacity) {\n return frames;\n }\n if (!SonareRealtimeVoiceChangerWorkletProcessor.warnedInterleavedOverflow) {\n SonareRealtimeVoiceChangerWorkletProcessor.warnedInterleavedOverflow = true;\n // biome-ignore lint/suspicious/noConsole: realtime-safety diagnostic.\n console.warn(\n `SonareRealtimeVoiceChangerWorkletProcessor: requested ${frames}x${channels} ` +\n `planar frames exceeds pre-allocated capacity ${capacity}; clamping. ` +\n 'Increase blockSize or channelCount at construction time to avoid this.',\n );\n }\n return capacity;\n }\n}\n\nexport function registerSonareRealtimeVoiceChangerWorkletProcessor(\n name = 'sonare-realtime-voice-changer-processor',\n): void {\n const scope = globalThis as unknown as {\n AudioWorkletProcessor?: new () => object;\n registerProcessor?: (processorName: string, processorCtor: unknown) => void;\n };\n if (!scope.AudioWorkletProcessor || !scope.registerProcessor) {\n throw new Error('AudioWorkletProcessor is not available in this context.');\n }\n const Base = scope.AudioWorkletProcessor;\n class RegisteredSonareRealtimeVoiceChangerWorkletProcessor extends Base {\n private bridge: SonareRealtimeVoiceChangerWorkletProcessor;\n readonly port?: WorkletPort;\n\n constructor(options?: {\n processorOptions?: SonareRealtimeVoiceChangerWorkletProcessorOptions;\n }) {\n super();\n const port = this.port;\n this.bridge = new SonareRealtimeVoiceChangerWorkletProcessor(options?.processorOptions ?? {});\n const onMessage = (event: { data: unknown }) => {\n if (isRealtimeVoiceChangerMessage(event.data)) {\n this.bridge.receiveMessage(event.data);\n }\n };\n if (port?.addEventListener) {\n port.addEventListener('message', onMessage);\n port.start?.();\n } else if (port) {\n port.onmessage = onMessage;\n }\n }\n\n process(inputs: WorkletInput, outputs: WorkletOutput): boolean {\n return this.bridge.process(inputs, outputs);\n }\n }\n scope.registerProcessor(name, RegisteredSonareRealtimeVoiceChangerWorkletProcessor);\n}\n"],"mappings":"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","names":["module","module","module","module","module","marker","SonareEngineCommandType","SonareEngineTelemetryType","SonareEngineTelemetryError","marker","initPromise","frames"]}