@libraz/libsonare 1.5.2 → 1.5.3

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.
Files changed (46) hide show
  1. package/README.md +18 -3
  2. package/dist/index.d.ts +1147 -181
  3. package/dist/index.js +4826 -3941
  4. package/dist/index.js.map +1 -1
  5. package/dist/sonare.js +1 -1
  6. package/dist/sonare.wasm +0 -0
  7. package/dist/worklet.d.ts +29 -1
  8. package/dist/worklet.js +1067 -973
  9. package/dist/worklet.js.map +1 -1
  10. package/package.json +2 -1
  11. package/src/_chain_config.ts +46 -0
  12. package/src/audio.ts +24 -4
  13. package/src/effects_mastering.ts +25 -1
  14. package/src/effects_transform.ts +283 -43
  15. package/src/effects_voice_change.ts +46 -53
  16. package/src/feature_core.ts +316 -12
  17. package/src/feature_music.ts +357 -0
  18. package/src/feature_pitch.ts +61 -0
  19. package/src/feature_resample.ts +17 -2
  20. package/src/feature_spectral.ts +349 -2
  21. package/src/feature_spectrogram.ts +336 -0
  22. package/src/index.ts +130 -1
  23. package/src/mastering_chain.ts +305 -50
  24. package/src/mastering_core.ts +232 -16
  25. package/src/mastering_dynamics.ts +66 -10
  26. package/src/mastering_repair.ts +119 -7
  27. package/src/metering.ts +366 -81
  28. package/src/mixer.ts +9 -2
  29. package/src/mixing_oneshot.ts +25 -5
  30. package/src/module_state.ts +1 -1
  31. package/src/project_class.ts +17 -6
  32. package/src/project_internal.ts +10 -2
  33. package/src/project_types.ts +25 -2
  34. package/src/public_types_mastering.ts +114 -4
  35. package/src/public_types_spectral.ts +7 -0
  36. package/src/quick_analysis.ts +325 -117
  37. package/src/realtime_engine.ts +8 -0
  38. package/src/sonare.js.d.ts +31 -0
  39. package/src/stream_analyzer.ts +20 -1
  40. package/src/stream_types.ts +12 -1
  41. package/src/validation.ts +17 -2
  42. package/src/worklet/engine-clips.ts +67 -2
  43. package/src/worklet/engine-processor.ts +33 -5
  44. package/src/worklet/engine.ts +7 -3
  45. package/src/worklet/guards.ts +3 -0
  46. package/src/worklet/messages.ts +27 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/module_state.ts","../src/codes.ts","../src/mixer.ts","../src/realtime_voice_changer.ts","../src/realtime_engine.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":["/**\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 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));\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, PanLaw, PanMode, SendTiming } from './public_types';\n\nexport function automationCurveCode(curve: AutomationCurve): number {\n switch (curve) {\n case 'linear':\n return 0;\n case 'exponential':\n return 1;\n case 'hold':\n return 2;\n case 's-curve':\n return 3;\n default:\n throw new Error(`Invalid automation curve: ${curve}`);\n }\n}\n\nexport function panLawCode(panLaw: PanLaw | number): number {\n if (typeof panLaw === 'number') {\n return panLaw;\n }\n switch (panLaw) {\n case 'const4.5dB':\n return 1;\n case 'const6dB':\n return 2;\n case 'linear0dB':\n return 3;\n default:\n return 0;\n }\n}\n\nexport function panModeCode(panMode: PanMode | number): number {\n if (typeof panMode === 'number') {\n return panMode;\n }\n switch (panMode) {\n case 'stereoPan':\n case 'stereo-pan':\n return 1;\n case 'dualPan':\n case 'dual-pan':\n return 2;\n default:\n return 0;\n }\n}\n\nexport function meterTapCode(tap: MeterTap | number): number {\n return tap === 'preFader' || tap === 0 ? 0 : 1;\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 if (typeof timing === 'number') {\n return timing;\n }\n return timing === 'preFader' ? 1 : 0;\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 PanLaw,\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\n private constructor(mixer: import('./sonare.js').WasmMixer) {\n this.mixer = mixer;\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));\n }\n\n /** Rebuild and compile the routing graph from the current scene topology. */\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 /** 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. */\n setPanLaw(stripIndex: number, panLaw: PanLaw | number): 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 /**\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 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 { RealtimeVoiceChangerConfigInput, VoicePresetId } 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 constructor(config: RealtimeVoiceChangerConfigInput = 'neutral-monitor') {\n const module = getSonareModule();\n this.changer = module.createRealtimeVoiceChanger(config as Record<string, unknown> | string);\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): void {\n this.changer.setConfig(config as Record<string, unknown> | string);\n }\n\n configJson(): string {\n return this.changer.configJson();\n }\n\n latencySamples(): number {\n return this.changer.latencySamples();\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 // 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 (input.byteLength === 0 || output.byteLength === 0) {\n input = this.getMonoInputBuffer(numSamples);\n output = this.getMonoOutputBuffer(numSamples);\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 // Re-acquire detached views after WASM memory growth (see\n // createRealtimeMonoBuffer for rationale).\n const reacquireIfDetached = (): void => {\n if (input.byteLength === 0 || output.byteLength === 0) {\n input = this.getInterleavedInputBuffer(numFrames, numChannels);\n output = this.getInterleavedOutputBuffer(numFrames, numChannels);\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 const acquire = (): void => {\n channels = [];\n for (let ch = 0; ch < numChannels; ch++) {\n channels.push(this.getPlanarChannelBuffer(ch, numFrames));\n }\n };\n acquire();\n // Re-acquire detached views after WASM memory growth (see\n // createRealtimeMonoBuffer for rationale).\n const reacquireIfDetached = (): void => {\n if ((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 { panLawCode, panModeCode, sendTimingCode } from './codes';\nimport { ErrorCode, SonareError } from './errors';\nimport { getSonareModule } from './module_state';\nimport type { SynthPatch } from './project';\nimport type { EqBand, PanLaw, 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 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\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 ) {\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 );\n }\n\n prepare(\n sampleRate: number,\n maxBlockSize: number,\n commandCapacity = 1024,\n telemetryCapacity = 1024,\n ): void {\n this.native.prepare(sampleRate, maxBlockSize, commandCapacity, telemetryCapacity);\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 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: { destinationId?: number; gain?: number; polyphony?: number } = {},\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 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 /**\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 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 /**\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 seekPpq(ppq: number, renderFrame = -1): void {\n this.native.seekPpq(ppq, renderFrame);\n }\n\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 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 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: PanLaw | number): 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 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: EngineCaptureStatus['source']): void {\n this.native.setCaptureSource(source);\n }\n\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 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 * 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 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 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","/**\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 { RealtimeVoiceChangerPodConfig, VoicePresetId } 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 ClipPageStreamSource,\n OpfsClipStream,\n OpfsClipStreamOptions,\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 MasteringInsertParamInfo,\n MasteringProcessorCatalogEntry,\n TransientShaperOptions,\n TrimSilenceMode,\n TrimSilenceOptions,\n VoiceChangeOptions,\n VoiceChangeRealtimeOptions,\n} from './effects_mastering';\nexport {\n harmonic,\n hpss,\n masterAudio,\n masterAudioStereo,\n masterAudioStereoWithProgress,\n masterAudioWithProgress,\n mastering,\n masteringAssistantSuggest,\n masteringAudioProfile,\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 mixingScenePresetJson,\n mixingScenePresetNames,\n mixStereo,\n normalize,\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 { ErrorCode, isSonareError, SonareError } from './errors';\nexport type { MelodyOptions } from './feature_music';\nexport {\n amplitudeToDb,\n analyzeMelody,\n analyzeSections,\n bassChroma,\n chroma,\n chromaCens,\n chromaCqt,\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 hpssWithResidual,\n hybridCqt,\n hzToMel,\n hzToMidi,\n hzToNote,\n lufs,\n lufsInterleaved,\n melSpectrogram,\n melToAudio,\n melToHz,\n melToStft,\n mfcc,\n mfccToAudio,\n mfccToMel,\n midiToHz,\n momentaryLufs,\n nnFilter,\n nnlsChroma,\n noteToHz,\n onsetEnvelope,\n onsetStrengthMulti,\n padCenter,\n pcen,\n peakPick,\n phaseVocoder,\n pitchPyin,\n pitchTuning,\n pitchYin,\n plp,\n polyFeatures,\n powerToDb,\n preemphasis,\n pseudoCqt,\n remix,\n resample,\n rmsEnergy,\n samplesToFrames,\n shortTermLufs,\n spectralBandwidth,\n spectralCentroid,\n spectralContrast,\n spectralFlatness,\n spectralRolloff,\n splitSilence,\n stft,\n stftDb,\n tempogram,\n tempogramRatio,\n timeToFrames,\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 ClippingRegion,\n ClippingReport,\n DynamicRangeReport,\n MeteringDetectClippingOptions,\n MeteringDynamicRangeOptions,\n PhaseScopeReport,\n SpectrumOptions,\n SpectrumReport,\n VectorscopeReport,\n WaveformPeakPyramidOptions,\n WaveformPeaksOptions,\n WaveformPeaksReport,\n} from './metering';\nexport {\n meteringCrestFactorDb,\n meteringDcOffset,\n meteringDetectClipping,\n meteringDynamicRange,\n meteringPeakDb,\n meteringPhaseScope,\n meteringPhaseScopeDecimated,\n meteringRmsDb,\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 MidiCcLearnOptions,\n ProjectAssistSidecar,\n ProjectAutomationCurve,\n ProjectAutomationLaneDesc,\n ProjectAutomationPoint,\n ProjectBounceOptions,\n ProjectChordSymbol,\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 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 EXPECTED_PROJECT_ABI_VERSION,\n MarkerKind,\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 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 MasteringOptions,\n MasteringPreset,\n MasteringProcessorParams,\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 NoteStretchOptions,\n PairAnalysis,\n PairProcessor,\n PanLaw,\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 SendTiming,\n SoloProcessor,\n SpectralEditMode,\n SpectralEditOptions,\n SpectralEditWindow,\n SpectralRegionOp,\n StereoAnalysis,\n StftPowerResult,\n StftResult,\n StreamingEqualizerConfig,\n StreamingMasteringChainConfig,\n StreamingPlatform,\n StreamingRetuneConfig,\n TempogramMode,\n Timbre,\n TimeSignature,\n VoicePresetId,\n} from './public_types';\nexport {\n ChordQuality,\n KeyProfile,\n Mode,\n PitchClass,\n SectionType,\n} from './public_types';\nexport type {\n BpmAnalysisResult,\n BpmCandidate,\n DynamicsAnalysisResult,\n RhythmAnalysisResult,\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 EngineAutomationPoint,\n EngineBounceOptions,\n EngineBounceResult,\n EngineBus,\n EngineCapabilities,\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 EngineTrackSend,\n EngineTransportState,\n ExternalMidiEvent,\n MidiCcBindOptions,\n} from './realtime_engine';\nexport { EXPECTED_ENGINE_ABI_VERSION, engineCapabilities, RealtimeEngine } 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';\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 * 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 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'`). Returns `null` for an out-of-range ordinal.\n */\nexport function voiceCharacterPresetId(preset: VoicePresetId | number): string | null {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.voiceCharacterPresetId(resolveVoicePresetOrdinal(preset));\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. Returns `null` for an out-of-range ordinal.\n */\nexport function realtimeVoiceChangerPresetConfig(\n preset: VoicePresetId | number,\n): RealtimeVoiceChangerPodConfig | null {\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/**\n * Resolves a parameter id from a name or numeric id. Numeric params pass\n * through; named params are matched against the parameter list, then fall back\n * to a target-id resolution of the name (or the node id).\n */\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 return resolveTargetId(param || 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 applied outside 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 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 return ctx.realtimeNode.seekPpq(ppq, sampleTime);\n },\n seekSeconds: (seconds, sampleTime = -1) => {\n const timelineSample = Math.max(0, Math.round(seconds * ctx.sampleRate));\n ctx.offlineEngine.seekSample(timelineSample, sampleTime);\n return ctx.realtimeNode.seekSample(timelineSample, sampleTime);\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\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}\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}\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 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 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 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\nfunction recordOffset(index: number, capacity: number, recordBytes: number): number {\n return (index % capacity) * recordBytes;\n}\n\nexport function toBigInt64(value: number | bigint | undefined, fallback: bigint): bigint {\n if (typeof value === 'bigint') {\n return value;\n }\n if (typeof value === 'number') {\n return BigInt(Math.trunc(value));\n }\n return fallback;\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 view.setBigInt64(offset + 8, toBigInt64(command.sampleTime, -1n), true);\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 view.setBigInt64(offset + 24, toBigInt64(command.argInt, 0n), true);\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: Number(view.getBigInt64(offset + 8, true)),\n argFloat: view.getFloat64(offset + 16, true),\n argInt: Number(view.getBigInt64(offset + 24, true)),\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 view.setBigInt64(offset + 8, BigInt(Math.trunc(telemetry.renderFrame)), true);\n view.setBigInt64(offset + 16, BigInt(Math.trunc(telemetry.timelineSample)), true);\n view.setBigInt64(offset + 24, BigInt(Math.trunc(telemetry.audibleTimelineSample)), true);\n view.setInt32(offset + 32, telemetry.graphLatencySamplesQ8, true);\n view.setUint32(offset + 36, telemetry.value, true);\n view.setBigInt64(offset + 40, 0n, 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: Number(view.getBigInt64(offset + 8, true)),\n timelineSample: Number(view.getBigInt64(offset + 16, true)),\n audibleTimelineSample: Number(view.getBigInt64(offset + 24, true)),\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 readonly offlineChannelCount: number;\n postSync(message: SonareEngineSyncMessage): void;\n getCaptureConfig(): CaptureConfig | undefined;\n setCaptureConfig(config: CaptureConfig): void;\n resolveTargetId(target: string | number): number;\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 (enabled && !ctx.getCaptureConfig()) {\n throw new Error('Capture buffer is not configured');\n }\n ctx.offlineEngine.armCapture(enabled);\n return ctx.realtimeNode.sendCommand({\n type: SonareEngineCommandType.ArmRecord,\n targetId: ctx.resolveTargetId(trackId),\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.realtimeNode.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 { 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): void;\n resolveTargetId(target: string | number): number;\n ensureTrackLane(target: string | number): number;\n}\n\nexport function addClip(\n ctx: EngineClipContext,\n trackId: string | number,\n buffer: Float32Array[],\n startPpq: number,\n opts: Partial<Omit<EngineClip, 'channels' | 'startPpq'>> = {},\n): number {\n const id = opts.id ?? ctx.allocateClipId();\n const clip: EngineClip = {\n ...opts,\n id,\n channels: 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 ctx.postSync({\n type: 'syncClipsDelta',\n upserts,\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 {\n SonareEngineCaptureRequestMessage,\n SonareEngineCaptureResponseMessage,\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 === '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 === 'syncMidiSysex' ||\n value.type === 'syncMidiPanic' ||\n value.type === 'syncMidiDestinationExternal' ||\n value.type === 'syncExternalMidiClock'\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\nexport function isEngineCaptureResponseMessage(\n value: unknown,\n): value is SonareEngineCaptureResponseMessage {\n return (\n isRecord(value) &&\n value.type === 'captureResponse' &&\n typeof value.requestId === 'number' &&\n typeof value.ok === 'boolean'\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 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 isEngineCaptureResponseMessage,\n isEngineTelemetryRecord,\n isEngineTransportResponseMessage,\n isExternalMidiBatchMessage,\n isMeterSnapshot,\n} from './guards';\nimport type {\n SonareEngineCaptureRequestMessage,\n SonareEngineCaptureResponseMessage,\n SonareEngineTransportResponseMessage,\n SonareRealtimeEngineNodeCapabilities,\n SonareRealtimeEngineNodeOptions,\n SonareRealtimeEngineWorkletProcessorOptions,\n SonareWorkletExternalMidiEvent,\n} from './messages';\nimport {\n createSonareEngineCommandRingBuffer,\n createSonareEngineTelemetryRingBuffer,\n createSonareMeterRingBuffer,\n createSonareScopeRingBuffer,\n isRecord,\n pushSonareEngineCommandRingBuffer,\n readSonareEngineTelemetryRingBuffer,\n readSonareMeterRingBuffer,\n readSonareScopeRingBuffer,\n type SonareEngineCommandRecord,\n type SonareEngineCommandRingBuffer,\n SonareEngineCommandType,\n type SonareEngineTelemetryRecord,\n type SonareEngineTelemetryRingBuffer,\n type SonareMeterRingBuffer,\n type SonareScopeRingBuffer,\n type SonareWorkletMeterSnapshot,\n type SonareWorkletScopeSnapshot,\n} from './protocol';\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 ready: Promise<void>;\n private telemetryReadIndex = 0;\n private meterReadIndex = 0;\n private scopeReadIndex = 0;\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 captureRequestId = 1;\n private readonly captureRequests = new Map<\n number,\n {\n resolve: (response: SonareEngineCaptureResponseMessage) => 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 ) {\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.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 if (isEngineCaptureResponseMessage(event.data)) {\n const pending = this.captureRequests.get(event.data.requestId);\n if (pending) {\n this.captureRequests.delete(event.data.requestId);\n if (event.data.ok) {\n pending.resolve(event.data);\n } else {\n pending.reject(new Error(event.data.error ?? 'Capture request failed'));\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 (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 static async create(\n context: BaseAudioContext,\n options: SonareRealtimeEngineNodeOptions = {},\n ): Promise<SonareRealtimeEngineNode> {\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 const channelCount = Math.max(1, Math.floor(options.channelCount ?? 2));\n const processorOptions: SonareRealtimeEngineWorkletProcessorOptions = {\n sampleRate: options.sampleRate ?? context.sampleRate,\n blockSize: options.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 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 engineAbiVersion: detectedCapabilities?.engineAbiVersion,\n expectedEngineAbiVersion: detectedCapabilities?.expectedEngineAbiVersion,\n abiCompatible: detectedCapabilities?.abiCompatible,\n degradedReason,\n readyMessage: moduleUrl !== undefined && !options.nodeFactory,\n },\n commandRing,\n telemetryRing,\n meterRing,\n scopeRing,\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 return this.sendCommand({\n type: SonareEngineCommandType.TransportSeekPpq,\n sampleTime,\n argFloat: ppq,\n });\n }\n\n sendCommand(command: SonareEngineCommandRecord): boolean {\n if (this.destroyed) {\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.status) {\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 (response.channels ?? []).map((channel) =>\n channel instanceof Float32Array ? channel : new Float32Array(channel),\n ),\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 onTelemetry(callback: (telemetry: SonareEngineTelemetryRecord) => void): () => void {\n this.telemetryListeners.add(callback);\n return () => {\n this.telemetryListeners.delete(callback);\n };\n }\n\n onMeter(callback: (meter: SonareWorkletMeterSnapshot) => void): () => void {\n this.meterListeners.add(callback);\n return () => {\n this.meterListeners.delete(callback);\n };\n }\n\n onScope(callback: (scope: SonareWorkletScopeSnapshot) => void): () => void {\n this.scopeListeners.add(callback);\n return () => {\n this.scopeListeners.delete(callback);\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 return () => {\n this.midiOutListeners.delete(callback);\n };\n }\n\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n this.destroyed = true;\n this.node.port.postMessage({ type: SonareEngineCommandType.TransportStop, sampleTime: -1 });\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 }\n\n private emitTelemetry(telemetry: SonareEngineTelemetryRecord): void {\n for (const listener of this.telemetryListeners) {\n listener(telemetry);\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 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<SonareEngineCaptureResponseMessage> {\n if (this.destroyed) {\n return Promise.reject(new Error('Realtime engine node is destroyed.'));\n }\n const requestId = this.captureRequestId++;\n const promise = new Promise<SonareEngineCaptureResponseMessage>((resolve, reject) => {\n this.captureRequests.set(requestId, { resolve, reject });\n });\n this.node.port.postMessage({ type: 'captureRequest', requestId, op });\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 type { EngineParameterInfo, RealtimeEngine } from '../index';\nimport type { SonareRealtimeEngineNode } from './engine-node';\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 readonly realtimeNode: SonareRealtimeEngineNode;\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.realtimeNode.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.realtimeNode.sendCommand({\n type: SonareEngineCommandType.SetSoloMute,\n targetId: laneIndex,\n sampleTime: -1,\n argInt: (mute ? 0x1 : 0) | (solo ? 0x2 : 0),\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","import { panLawCode, panModeCode } from '../codes';\nimport type { EqBand, PanLaw, 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: PanLaw | number,\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 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: { destinationId?: number; gain?: number; polyphony?: number },\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 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 ctx.realtimeNode.sendCommand({\n type: SonareEngineCommandType.SetTempoMap,\n sampleTime: -1,\n argFloat: bpm,\n });\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.realtimeNode.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 type {\n EngineAutomationPoint,\n EngineBus,\n EngineCaptureStatus,\n EngineClip,\n EngineMarker,\n EngineMetronomeConfig,\n EngineMidiClipSchedule,\n EngineParameterInfo,\n EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTrackLane,\n EngineTrackSend,\n EngineTransportState,\n EqBand,\n PanLaw,\n PanMode,\n} from '../index';\nimport { RealtimeEngine } from '../index';\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\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 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.transport = buildTransportFacade({\n sampleRate: this.sampleRate,\n realtimeNode: this.realtimeNode,\n offlineEngine: this.offlineEngine,\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 const offlineEngine = options.offlineEngine ?? new RealtimeEngine(sampleRate, blockSize);\n return new SonareEngine(\n context,\n realtimeNode,\n offlineEngine,\n sampleRate,\n blockSize,\n channelCount,\n );\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 setSoloMute(target: string | number, solo: boolean, mute: boolean): boolean {\n return parameter.setSoloMute(this.parameterContext, target, solo, mute);\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 addClip(\n trackId: string | number,\n buffer: Float32Array[],\n startPpq: number,\n opts: Partial<Omit<EngineClip, 'channels' | '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: { destinationId?: number; gain?: number; polyphony?: number } = {},\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 pushMidiSysex(trackId: string | number, data: Uint8Array, renderFrame = -1): void {\n strips.pushMidiSysex(this.stripContext, trackId, data, renderFrame);\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 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.realtimeNode.sendCommand({\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.destroyed = true;\n this.transport.stop();\n this.realtimeNode.pollTelemetry();\n this.realtimeNode.destroy();\n this.offlineEngine.destroy();\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): void {\n if (this.destroyed) {\n return;\n }\n this.realtimeNode.node.port.postMessage(message);\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 offlineChannelCount: this.offlineChannelCount,\n postSync: (message) => this.postSync(message),\n getCaptureConfig: () => this.captureConfig,\n setCaptureConfig: (config) => {\n this.captureConfig = config;\n },\n resolveTargetId: (target) => this.resolveTargetId(target),\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 realtimeNode: this.realtimeNode,\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 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) => this.postSync(message),\n ensureTrackLane: (target) => this.ensureTrackLane(target),\n resolveTargetId: (target) => this.resolveTargetId(target),\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.realtimeNode.sendCommand(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.realtimeNode.sendCommand({\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 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 EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTrackLane,\n EngineTransportState,\n RealtimeVoiceChangerConfigInput,\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\nexport interface SonareRealtimeVoiceChangerWorkletProcessorOptions {\n preset?: RealtimeVoiceChangerConfigInput;\n sampleRate?: number;\n blockSize?: number;\n channelCount?: number;\n}\n\nexport interface SonareRealtimeVoiceChangerSetConfigMessage {\n type: 'setConfig';\n preset: RealtimeVoiceChangerConfigInput;\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 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\nexport type SonareWorkletTransportMessage =\n | SonareWorkletMeterSnapshot\n | SonareWorkletSpectrumSnapshot\n | SonareWorkletExternalMidiMessage\n | SonareEngineTelemetryRecord;\n\nexport interface WorkletTransport {\n postMessage?: (\n message:\n | SonareWorkletTransportMessage\n | SonareEngineCaptureResponseMessage\n | SonareEngineTransportResponseMessage,\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}\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: 96,\n};\n\nexport function resolveMetronomeConfig(config: EngineMetronomeConfig): ResolvedMetronomeConfig {\n return {\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 };\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, so they are applied OUTSIDE process() — the\n// audio-thread equivalent of the engine's control-thread RtPublisher setters.\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\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\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: { destinationId?: number; gain?: number; polyphony?: number };\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 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 type SonareEngineInstrumentSyncMessage =\n | SonareEngineSyncBuiltinInstrumentMessage\n | SonareEngineSyncSynthInstrumentMessage\n | SonareEngineSyncSf2InstrumentMessage\n | SonareEngineSyncLoadSoundFontMessage\n | SonareEngineSyncMidiFxMessage;\n\nexport type SonareEngineSyncMessage =\n | SonareEngineSyncClipsMessage\n | SonareEngineSyncClipsDeltaMessage\n | SonareEngineSyncMidiClipsMessage\n | SonareEngineSyncMarkersMessage\n | SonareEngineSyncMetronomeMessage\n | SonareEngineSyncAutomationMessage\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 | SonareEngineSyncMidiSysexMessage\n | SonareEngineSyncMidiPanicMessage\n | SonareEngineSyncMidiDestinationExternalMessage\n | SonareEngineSyncExternalMidiClockMessage;\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\nexport interface SonareEngineCaptureResponseMessage {\n type: 'captureResponse';\n requestId: number;\n ok: boolean;\n status?: EngineCaptureStatus;\n channels?: Float32Array[] | number[][];\n error?: string;\n}\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, EngineScopeTelemetry } 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 SonareEngineCaptureResponseMessage,\n type SonareEngineSyncMessage,\n type SonareEngineTransportRequestMessage,\n type SonareEngineTransportResponseMessage,\n type SonareRealtimeEngineWorkletProcessorOptions,\n type WorkletTransport,\n} from './messages';\nimport {\n encodeFrameHi,\n encodeFrameLo,\n engineRingFromSharedBuffer,\n meterFromEngine,\n meterRingFromSharedBuffer,\n popSonareEngineCommandRingBuffer,\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 writeSonareEngineTelemetryRingBuffer,\n} from './protocol';\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 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\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.engine = new RealtimeEngine(this.sampleRate, this.blockSize);\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.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.applyCommand(command);\n }\n }\n\n // Applies an out-of-band control-plane sync message. Runs on the AudioWorklet\n // global scope but OUTSIDE process() (the message-port callback), so the\n // bulk/allocating engine setters (setClips/setMarkers) are safe here — they\n // never run on the realtime render path. This is the audio-thread equivalent\n // of the engine's control-thread RtPublisher setters.\n receiveSync(message: SonareEngineSyncMessage): void {\n if (this.closed) {\n return;\n }\n switch (message.type) {\n case 'syncClips':\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 this.engine.setClips(message.clips);\n break;\n case 'syncClipsDelta':\n for (const clipId of message.removeIds) {\n this.liveClips.delete(clipId);\n }\n for (const clip of message.upserts) {\n if (clip.id !== undefined) {\n this.liveClips.set(clip.id, clip);\n }\n }\n this.engine.setClips(Array.from(this.liveClips.values()));\n break;\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 this.metronomeConfig = resolveMetronomeConfig(message.config);\n this.engine.setMetronome(message.config);\n break;\n case 'syncAutomation':\n this.engine.setAutomationLane(message.paramId, message.points);\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 '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 }\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 SonareEngineCaptureResponseMessage);\n return;\n }\n if (message.op === 'read') {\n const captured = this.engine.capturedAudio();\n const channels: number[][] = [];\n for (let ch = 0; ch < captured.length; ch++) {\n const source = captured[ch];\n const copy: number[] = [];\n for (let i = 0; i < source.length; i++) {\n copy.push(Number(source[i]));\n }\n channels.push(copy);\n }\n this.transport?.postMessage?.({\n type: 'captureResponse',\n requestId: message.requestId,\n ok: true,\n channels,\n } satisfies SonareEngineCaptureResponseMessage);\n return;\n }\n this.engine.resetCapture();\n this.transport?.postMessage?.({\n type: 'captureResponse',\n requestId: message.requestId,\n ok: true,\n } satisfies SonareEngineCaptureResponseMessage);\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 SonareEngineCaptureResponseMessage);\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.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.applyCommand(command);\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.SetTempoMap:\n this.engine.setTempo(Number(command.argFloat ?? 120));\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 });\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 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 for (const item of this.engine.drainTelemetry(64)) {\n this.publishTelemetryRecord(telemetryFromEngine(item));\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 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 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 (const item of this.engine.drainScopeTelemetry(64)) {\n this.writeScopeRing(ring, item);\n }\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 if (!this.transport?.postMessage) {\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 private writeScopeRing(ring: SharedScopeRingWriter, record: EngineScopeTelemetry): void {\n const writeIndex = Atomics.load(ring.header, 0);\n const base = (writeIndex % ring.capacity) * ring.recordFloats;\n ring.records[base] = encodeFrameLo(record.renderFrame);\n ring.records[base + 1] = encodeFrameHi(record.renderFrame);\n ring.records[base + 2] = record.targetId;\n const bandCount = Math.min(ring.bands, record.bands.length);\n ring.records[base + 3] = bandCount;\n const pointCount = Math.min(ring.maxPoints, record.points.length);\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] = record.bands[i];\n }\n const pointsBase = bandsBase + ring.bands;\n for (let i = 0; i < pointCount; i++) {\n const point = record.points[i];\n ring.records[pointsBase + 2 * i] = point.left;\n ring.records[pointsBase + 2 * i + 1] = point.right;\n }\n Atomics.store(ring.header, 0, writeIndex + 1);\n // Like writeMeterRing, writeIndex is a free-running monotonic counter; the\n // reader detects silent overrun via firstReadable, so the overflow slot\n // (header[5]) stays at its initial 0.\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 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 }\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 this.bridge = new SonareRealtimeEngineWorkletProcessor(options, {\n postMessage: (message) => port?.postMessage?.(message),\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 // 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.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. Runs on the\n * AudioWorklet global scope but OUTSIDE of `process()` (i.e. outside the\n * realtime audio callback), so it is safe to perform JSON parsing and\n * DSP coefficient recomputation here. `setConfig` MUST NOT be deferred\n * into `process()` because that would block the audio thread for longer\n * than one render quantum (e.g. 128 samples / 44.1 kHz = ~2.9 ms).\n */\n receiveMessage(message: SonareRealtimeVoiceChangerMessage): void {\n if (this.destroyed) {\n return;\n }\n if (message.type === 'setConfig') {\n // Apply synchronously on the message-handler thread. `setConfig` may\n // allocate and parse JSON internally; doing it here keeps `process()`\n // realtime-safe.\n this.changer.setConfig(message.preset);\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 (this.monoInput.byteLength === 0) {\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.processMonoInto(\n this.monoInput.subarray(0, frames),\n this.monoOutput.subarray(0, frames),\n );\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 }\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/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":["/**\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 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, PanLaw, PanMode, SendTiming } from './public_types';\n\nexport function automationCurveCode(curve: AutomationCurve): number {\n switch (curve) {\n case 'linear':\n return 0;\n case 'exponential':\n return 1;\n case 'hold':\n return 2;\n case 's-curve':\n return 3;\n default:\n throw new Error(`Invalid automation curve: ${curve}`);\n }\n}\n\nexport function panLawCode(panLaw: PanLaw | number): number {\n if (typeof panLaw === 'number') {\n return panLaw;\n }\n switch (panLaw) {\n case 'const4.5dB':\n return 1;\n case 'const6dB':\n return 2;\n case 'linear0dB':\n return 3;\n default:\n return 0;\n }\n}\n\nexport function panModeCode(panMode: PanMode | number): number {\n if (typeof panMode === 'number') {\n return panMode;\n }\n switch (panMode) {\n case 'stereoPan':\n case 'stereo-pan':\n return 1;\n case 'dualPan':\n case 'dual-pan':\n return 2;\n default:\n return 0;\n }\n}\n\nexport function meterTapCode(tap: MeterTap | number): number {\n return tap === 'preFader' || tap === 0 ? 0 : 1;\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 if (typeof timing === 'number') {\n return timing;\n }\n return timing === 'preFader' ? 1 : 0;\n}\n","import { panLawCode, panModeCode, sendTimingCode } from './codes';\nimport { ErrorCode, SonareError } from './errors';\nimport { getSonareModule } from './module_state';\nimport type { SynthPatch } from './project';\nimport type { EqBand, PanLaw, 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 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\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 ) {\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 );\n }\n\n prepare(\n sampleRate: number,\n maxBlockSize: number,\n commandCapacity = 1024,\n telemetryCapacity = 1024,\n ): void {\n this.native.prepare(sampleRate, maxBlockSize, commandCapacity, telemetryCapacity);\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 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: { destinationId?: number; gain?: number; polyphony?: number } = {},\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 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 /**\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 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 /**\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 seekPpq(ppq: number, renderFrame = -1): void {\n this.native.seekPpq(ppq, renderFrame);\n }\n\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 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: PanLaw | number): 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 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: EngineCaptureStatus['source']): void {\n this.native.setCaptureSource(source);\n }\n\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 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 * 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 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 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 PanLaw,\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 /** Rebuild and compile the routing graph from the current scene topology. */\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 /** 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. */\n setPanLaw(stripIndex: number, panLaw: PanLaw | number): 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 /**\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 { RealtimeVoiceChangerConfigInput, VoicePresetId } 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 constructor(config: RealtimeVoiceChangerConfigInput = 'neutral-monitor') {\n const module = getSonareModule();\n this.changer = module.createRealtimeVoiceChanger(config as Record<string, unknown> | string);\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): void {\n this.changer.setConfig(config as Record<string, unknown> | string);\n }\n\n configJson(): string {\n return this.changer.configJson();\n }\n\n latencySamples(): number {\n return this.changer.latencySamples();\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 // 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 (input.byteLength === 0 || output.byteLength === 0) {\n input = this.getMonoInputBuffer(numSamples);\n output = this.getMonoOutputBuffer(numSamples);\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 // Re-acquire detached views after WASM memory growth (see\n // createRealtimeMonoBuffer for rationale).\n const reacquireIfDetached = (): void => {\n if (input.byteLength === 0 || output.byteLength === 0) {\n input = this.getInterleavedInputBuffer(numFrames, numChannels);\n output = this.getInterleavedOutputBuffer(numFrames, numChannels);\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 const acquire = (): void => {\n channels = [];\n for (let ch = 0; ch < numChannels; ch++) {\n channels.push(this.getPlanarChannelBuffer(ch, numFrames));\n }\n };\n acquire();\n // Re-acquire detached views after WASM memory growth (see\n // createRealtimeMonoBuffer for rationale).\n const reacquireIfDetached = (): void => {\n if ((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 { RealtimeVoiceChangerPodConfig, VoicePresetId } 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 ClipPageStreamSource,\n OpfsClipStream,\n OpfsClipStreamOptions,\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 MasteringRepairDeclickRequest,\n MasteringRepairDeclipRequest,\n MasteringRepairDecrackleRequest,\n MasteringRepairDehumRequest,\n MasteringRepairDenoiseClassicalRequest,\n MasteringRepairDereverbClassicalRequest,\n MasteringRepairTrimSilenceRequest,\n MasteringSamplesParamsRequest,\n MasteringStereoAnalyzeRequest,\n MasteringStreamingPreviewRequest,\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 masteringAudioProfile,\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 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 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 CyclicTempogramRequest,\n DbConversionRequest,\n EmphasisRequest,\n FixFramesRequest,\n FixLengthRequest,\n FrameSignalRequest,\n PadCenterRequest,\n PcenRequest,\n PeakPickRequest,\n PlpRequest,\n SilenceRequest,\n TempogramRequest,\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 { PitchPyinRequest, PitchYinRequest } 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 SpectralContrastRequest,\n SpectralFrameRequest,\n SpectralRolloffRequest,\n ZeroCrossingRateRequest,\n ZeroCrossingsRequest,\n} from './feature_spectral';\nexport type {\n ChromaSpectrogramRequest,\n MelSpectrogramRequest,\n MelToAudioRequest,\n MelToStftRequest,\n MfccRequest,\n MfccToAudioRequest,\n MfccToMelRequest,\n SpectrogramRequest,\n TrimRequest,\n} from './feature_spectrogram';\nexport {\n amplitudeToDb,\n analyzeMelody,\n analyzeSections,\n bassChroma,\n chroma,\n chromaCens,\n chromaCqt,\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 hpssWithResidual,\n hybridCqt,\n hzToMel,\n hzToMidi,\n hzToNote,\n lufs,\n lufsInterleaved,\n melSpectrogram,\n melToAudio,\n melToHz,\n melToStft,\n mfcc,\n mfccToAudio,\n mfccToMel,\n midiToHz,\n momentaryLufs,\n nnFilter,\n nnlsChroma,\n noteToHz,\n onsetEnvelope,\n onsetStrengthMulti,\n padCenter,\n pcen,\n peakPick,\n phaseVocoder,\n pitchPyin,\n pitchTuning,\n pitchYin,\n plp,\n polyFeatures,\n powerToDb,\n preemphasis,\n pseudoCqt,\n remix,\n resample,\n rmsEnergy,\n samplesToFrames,\n shortTermLufs,\n spectralBandwidth,\n spectralCentroid,\n spectralContrast,\n spectralFlatness,\n spectralRolloff,\n splitSilence,\n stft,\n stftDb,\n tempogram,\n tempogramRatio,\n timeToFrames,\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 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 meteringDcOffset,\n meteringDetectClipping,\n meteringDynamicRange,\n meteringPeakDb,\n meteringPhaseScope,\n meteringPhaseScopeDecimated,\n meteringRmsDb,\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 MidiCcLearnOptions,\n ProjectAssistSidecar,\n ProjectAutomationCurve,\n ProjectAutomationLaneDesc,\n ProjectAutomationPoint,\n ProjectBounceOptions,\n ProjectChordSymbol,\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 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 EXPECTED_PROJECT_ABI_VERSION,\n MarkerKind,\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 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 MasteringOptions,\n MasteringPreset,\n MasteringProcessorParams,\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 NoteStretchOptions,\n PairAnalysis,\n PairProcessor,\n PanLaw,\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 SendTiming,\n SoloProcessor,\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 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 DynamicsAnalysisResult,\n EstimateRoomRequest,\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 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 EngineTrackSend,\n EngineTransportState,\n ExternalMidiEvent,\n MidiCcBindOptions,\n} from './realtime_engine';\nexport { EXPECTED_ENGINE_ABI_VERSION, engineCapabilities, RealtimeEngine } 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';\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 * 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 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'`). Returns `null` for an out-of-range ordinal.\n */\nexport function voiceCharacterPresetId(preset: VoicePresetId | number): string | null {\n if (!module) {\n throw new Error('Module not initialized. Call init() first.');\n }\n return module.voiceCharacterPresetId(resolveVoicePresetOrdinal(preset));\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. Returns `null` for an out-of-range ordinal.\n */\nexport function realtimeVoiceChangerPresetConfig(\n preset: VoicePresetId | number,\n): RealtimeVoiceChangerPodConfig | null {\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/**\n * Resolves a parameter id from a name or numeric id. Numeric params pass\n * through; named params are matched against the parameter list, then fall back\n * to a target-id resolution of the name (or the node id).\n */\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 return resolveTargetId(param || 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 applied outside 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 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 return ctx.realtimeNode.seekPpq(ppq, sampleTime);\n },\n seekSeconds: (seconds, sampleTime = -1) => {\n const timelineSample = Math.max(0, Math.round(seconds * ctx.sampleRate));\n ctx.offlineEngine.seekSample(timelineSample, sampleTime);\n return ctx.realtimeNode.seekSample(timelineSample, sampleTime);\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\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}\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}\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 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 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 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\nfunction recordOffset(index: number, capacity: number, recordBytes: number): number {\n return (index % capacity) * recordBytes;\n}\n\nexport function toBigInt64(value: number | bigint | undefined, fallback: bigint): bigint {\n if (typeof value === 'bigint') {\n return value;\n }\n if (typeof value === 'number') {\n return BigInt(Math.trunc(value));\n }\n return fallback;\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 view.setBigInt64(offset + 8, toBigInt64(command.sampleTime, -1n), true);\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 view.setBigInt64(offset + 24, toBigInt64(command.argInt, 0n), true);\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: Number(view.getBigInt64(offset + 8, true)),\n argFloat: view.getFloat64(offset + 16, true),\n argInt: Number(view.getBigInt64(offset + 24, true)),\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 view.setBigInt64(offset + 8, BigInt(Math.trunc(telemetry.renderFrame)), true);\n view.setBigInt64(offset + 16, BigInt(Math.trunc(telemetry.timelineSample)), true);\n view.setBigInt64(offset + 24, BigInt(Math.trunc(telemetry.audibleTimelineSample)), true);\n view.setInt32(offset + 32, telemetry.graphLatencySamplesQ8, true);\n view.setUint32(offset + 36, telemetry.value, true);\n view.setBigInt64(offset + 40, 0n, 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: Number(view.getBigInt64(offset + 8, true)),\n timelineSample: Number(view.getBigInt64(offset + 16, true)),\n audibleTimelineSample: Number(view.getBigInt64(offset + 24, true)),\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 readonly offlineChannelCount: number;\n postSync(message: SonareEngineSyncMessage): void;\n getCaptureConfig(): CaptureConfig | undefined;\n setCaptureConfig(config: CaptureConfig): void;\n resolveTargetId(target: string | number): number;\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 (enabled && !ctx.getCaptureConfig()) {\n throw new Error('Capture buffer is not configured');\n }\n ctx.offlineEngine.armCapture(enabled);\n return ctx.realtimeNode.sendCommand({\n type: SonareEngineCommandType.ArmRecord,\n targetId: ctx.resolveTargetId(trackId),\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.realtimeNode.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 { 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}\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[],\n startPpq: number,\n opts: Partial<Omit<EngineClip, 'channels' | 'startPpq'>> = {},\n): number {\n const id = opts.id ?? ctx.allocateClipId();\n const clip: EngineClip = {\n ...opts,\n id,\n channels: 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 (\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 {\n SonareEngineCaptureRequestMessage,\n SonareEngineCaptureResponseMessage,\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 === 'syncClipPageCommit' ||\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 === 'syncMidiSysex' ||\n value.type === 'syncMidiPanic' ||\n value.type === 'syncMidiDestinationExternal' ||\n value.type === 'syncExternalMidiClock'\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\nexport function isEngineCaptureResponseMessage(\n value: unknown,\n): value is SonareEngineCaptureResponseMessage {\n return (\n isRecord(value) &&\n value.type === 'captureResponse' &&\n typeof value.requestId === 'number' &&\n typeof value.ok === 'boolean'\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 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 isEngineCaptureResponseMessage,\n isEngineTelemetryRecord,\n isEngineTransportResponseMessage,\n isExternalMidiBatchMessage,\n isMeterSnapshot,\n} from './guards';\nimport type {\n SonareEngineCaptureRequestMessage,\n SonareEngineCaptureResponseMessage,\n SonareEngineTransportResponseMessage,\n SonareRealtimeEngineNodeCapabilities,\n SonareRealtimeEngineNodeOptions,\n SonareRealtimeEngineWorkletProcessorOptions,\n SonareWorkletExternalMidiEvent,\n} from './messages';\nimport {\n createSonareEngineCommandRingBuffer,\n createSonareEngineTelemetryRingBuffer,\n createSonareMeterRingBuffer,\n createSonareScopeRingBuffer,\n isRecord,\n pushSonareEngineCommandRingBuffer,\n readSonareEngineTelemetryRingBuffer,\n readSonareMeterRingBuffer,\n readSonareScopeRingBuffer,\n type SonareEngineCommandRecord,\n type SonareEngineCommandRingBuffer,\n SonareEngineCommandType,\n type SonareEngineTelemetryRecord,\n type SonareEngineTelemetryRingBuffer,\n type SonareMeterRingBuffer,\n type SonareScopeRingBuffer,\n type SonareWorkletMeterSnapshot,\n type SonareWorkletScopeSnapshot,\n} from './protocol';\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 ready: Promise<void>;\n private telemetryReadIndex = 0;\n private meterReadIndex = 0;\n private scopeReadIndex = 0;\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 captureRequestId = 1;\n private readonly captureRequests = new Map<\n number,\n {\n resolve: (response: SonareEngineCaptureResponseMessage) => 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 ) {\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.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 if (isEngineCaptureResponseMessage(event.data)) {\n const pending = this.captureRequests.get(event.data.requestId);\n if (pending) {\n this.captureRequests.delete(event.data.requestId);\n if (event.data.ok) {\n pending.resolve(event.data);\n } else {\n pending.reject(new Error(event.data.error ?? 'Capture request failed'));\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 (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 static async create(\n context: BaseAudioContext,\n options: SonareRealtimeEngineNodeOptions = {},\n ): Promise<SonareRealtimeEngineNode> {\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 const channelCount = Math.max(1, Math.floor(options.channelCount ?? 2));\n const processorOptions: SonareRealtimeEngineWorkletProcessorOptions = {\n sampleRate: options.sampleRate ?? context.sampleRate,\n blockSize: options.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 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 engineAbiVersion: detectedCapabilities?.engineAbiVersion,\n expectedEngineAbiVersion: detectedCapabilities?.expectedEngineAbiVersion,\n abiCompatible: detectedCapabilities?.abiCompatible,\n degradedReason,\n readyMessage: moduleUrl !== undefined && !options.nodeFactory,\n },\n commandRing,\n telemetryRing,\n meterRing,\n scopeRing,\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 return this.sendCommand({\n type: SonareEngineCommandType.TransportSeekPpq,\n sampleTime,\n argFloat: ppq,\n });\n }\n\n sendCommand(command: SonareEngineCommandRecord): boolean {\n if (this.destroyed) {\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.status) {\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 (response.channels ?? []).map((channel) =>\n channel instanceof Float32Array ? channel : new Float32Array(channel),\n ),\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 onTelemetry(callback: (telemetry: SonareEngineTelemetryRecord) => void): () => void {\n this.telemetryListeners.add(callback);\n return () => {\n this.telemetryListeners.delete(callback);\n };\n }\n\n onMeter(callback: (meter: SonareWorkletMeterSnapshot) => void): () => void {\n this.meterListeners.add(callback);\n return () => {\n this.meterListeners.delete(callback);\n };\n }\n\n onScope(callback: (scope: SonareWorkletScopeSnapshot) => void): () => void {\n this.scopeListeners.add(callback);\n return () => {\n this.scopeListeners.delete(callback);\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 return () => {\n this.midiOutListeners.delete(callback);\n };\n }\n\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n this.destroyed = true;\n this.node.port.postMessage({ type: SonareEngineCommandType.TransportStop, sampleTime: -1 });\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 }\n\n private emitTelemetry(telemetry: SonareEngineTelemetryRecord): void {\n for (const listener of this.telemetryListeners) {\n listener(telemetry);\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 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<SonareEngineCaptureResponseMessage> {\n if (this.destroyed) {\n return Promise.reject(new Error('Realtime engine node is destroyed.'));\n }\n const requestId = this.captureRequestId++;\n const promise = new Promise<SonareEngineCaptureResponseMessage>((resolve, reject) => {\n this.captureRequests.set(requestId, { resolve, reject });\n });\n this.node.port.postMessage({ type: 'captureRequest', requestId, op });\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 type { EngineParameterInfo, RealtimeEngine } from '../index';\nimport type { SonareRealtimeEngineNode } from './engine-node';\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 readonly realtimeNode: SonareRealtimeEngineNode;\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.realtimeNode.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.realtimeNode.sendCommand({\n type: SonareEngineCommandType.SetSoloMute,\n targetId: laneIndex,\n sampleTime: -1,\n argInt: (mute ? 0x1 : 0) | (solo ? 0x2 : 0),\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","import { panLawCode, panModeCode } from '../codes';\nimport type { EqBand, PanLaw, 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: PanLaw | number,\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 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: { destinationId?: number; gain?: number; polyphony?: number },\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 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 ctx.realtimeNode.sendCommand({\n type: SonareEngineCommandType.SetTempoMap,\n sampleTime: -1,\n argFloat: bpm,\n });\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.realtimeNode.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 type {\n EngineAutomationPoint,\n EngineBus,\n EngineCaptureStatus,\n EngineClip,\n EngineMarker,\n EngineMetronomeConfig,\n EngineMidiClipSchedule,\n EngineParameterInfo,\n EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTrackLane,\n EngineTrackSend,\n EngineTransportState,\n EqBand,\n PanLaw,\n PanMode,\n} from '../index';\nimport { RealtimeEngine } from '../index';\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\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 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.transport = buildTransportFacade({\n sampleRate: this.sampleRate,\n realtimeNode: this.realtimeNode,\n offlineEngine: this.offlineEngine,\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 const offlineEngine = options.offlineEngine ?? new RealtimeEngine(sampleRate, blockSize);\n return new SonareEngine(\n context,\n realtimeNode,\n offlineEngine,\n sampleRate,\n blockSize,\n channelCount,\n );\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 setSoloMute(target: string | number, solo: boolean, mute: boolean): boolean {\n return parameter.setSoloMute(this.parameterContext, target, solo, mute);\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 addClip(\n trackId: string | number,\n buffer: Float32Array[],\n startPpq: number,\n opts: Partial<Omit<EngineClip, 'channels' | '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: { destinationId?: number; gain?: number; polyphony?: number } = {},\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 pushMidiSysex(trackId: string | number, data: Uint8Array, renderFrame = -1): void {\n strips.pushMidiSysex(this.stripContext, trackId, data, renderFrame);\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 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.realtimeNode.sendCommand({\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.destroyed = true;\n this.transport.stop();\n this.realtimeNode.pollTelemetry();\n this.realtimeNode.destroy();\n this.offlineEngine.destroy();\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 if (transfer && transfer.length > 0) {\n this.realtimeNode.node.port.postMessage(message, transfer);\n } else {\n this.realtimeNode.node.port.postMessage(message);\n }\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 offlineChannelCount: this.offlineChannelCount,\n postSync: (message) => this.postSync(message),\n getCaptureConfig: () => this.captureConfig,\n setCaptureConfig: (config) => {\n this.captureConfig = config;\n },\n resolveTargetId: (target) => this.resolveTargetId(target),\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 realtimeNode: this.realtimeNode,\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 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 };\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.realtimeNode.sendCommand(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.realtimeNode.sendCommand({\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 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 EngineTempoSegment,\n EngineTimeSignatureSegment,\n EngineTrackLane,\n EngineTransportState,\n RealtimeVoiceChangerConfigInput,\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\nexport interface SonareRealtimeVoiceChangerWorkletProcessorOptions {\n preset?: RealtimeVoiceChangerConfigInput;\n sampleRate?: number;\n blockSize?: number;\n channelCount?: number;\n}\n\nexport interface SonareRealtimeVoiceChangerSetConfigMessage {\n type: 'setConfig';\n preset: RealtimeVoiceChangerConfigInput;\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 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\nexport type SonareWorkletTransportMessage =\n | SonareWorkletMeterSnapshot\n | SonareWorkletSpectrumSnapshot\n | SonareWorkletExternalMidiMessage\n | SonareEngineTelemetryRecord;\n\nexport interface WorkletTransport {\n postMessage?: (\n message:\n | SonareWorkletTransportMessage\n | SonareEngineCaptureResponseMessage\n | SonareEngineTransportResponseMessage,\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}\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: 96,\n};\n\nexport function resolveMetronomeConfig(config: EngineMetronomeConfig): ResolvedMetronomeConfig {\n return {\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 };\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, so they are applied OUTSIDE process() — the\n// audio-thread equivalent of the engine's control-thread RtPublisher setters.\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 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/** Makes a fully supplied paged clip visible to the audio engine. */\nexport interface SonareEngineSyncClipPageCommitMessage {\n type: 'syncClipPageCommit';\n clipId: 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\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: { destinationId?: number; gain?: number; polyphony?: number };\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 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 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 | SonareEngineSyncClipPageCommitMessage\n | SonareEngineSyncMidiClipsMessage\n | SonareEngineSyncMarkersMessage\n | SonareEngineSyncMetronomeMessage\n | SonareEngineSyncAutomationMessage\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 | SonareEngineSyncMidiSysexMessage\n | SonareEngineSyncMidiPanicMessage\n | SonareEngineSyncMidiDestinationExternalMessage\n | SonareEngineSyncExternalMidiClockMessage;\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\nexport interface SonareEngineCaptureResponseMessage {\n type: 'captureResponse';\n requestId: number;\n ok: boolean;\n status?: EngineCaptureStatus;\n channels?: Float32Array[] | number[][];\n error?: string;\n}\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, EngineScopeTelemetry } 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 SonareEngineCaptureResponseMessage,\n type SonareEngineSyncMessage,\n type SonareEngineTransportRequestMessage,\n type SonareEngineTransportResponseMessage,\n type SonareRealtimeEngineWorkletProcessorOptions,\n type WorkletTransport,\n} from './messages';\nimport {\n encodeFrameHi,\n encodeFrameLo,\n engineRingFromSharedBuffer,\n meterFromEngine,\n meterRingFromSharedBuffer,\n popSonareEngineCommandRingBuffer,\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 writeSonareEngineTelemetryRingBuffer,\n} from './protocol';\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 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 pendingPagedClips = new Map<number, EngineClip>();\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.engine = new RealtimeEngine(this.sampleRate, this.blockSize);\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.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.applyCommand(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 switch (message.type) {\n case 'syncClips':\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 this.engine.setClips(message.clips);\n break;\n case 'syncClipsDelta':\n for (const clipId of message.removeIds) {\n this.liveClips.delete(clipId);\n }\n for (const clip of message.upserts) {\n if (clip.id !== undefined) {\n this.liveClips.set(clip.id, clip);\n }\n }\n this.engine.setClips(Array.from(this.liveClips.values()));\n break;\n case 'syncClipPageProvider': {\n const provider = this.engine.createClipPageProvider(\n message.numChannels,\n message.numSamples,\n message.pageFrames,\n );\n this.pagedClipProviders.set(message.clipId, provider.id);\n this.pendingPagedClips.set(message.clipId, message.clip);\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 'syncClipPageCommit': {\n const providerId = this.pagedClipProviders.get(message.clipId);\n const clip = this.pendingPagedClips.get(message.clipId);\n if (providerId !== undefined && clip) {\n this.liveClips.set(message.clipId, { ...clip, pageProvider: providerId });\n this.pendingPagedClips.delete(message.clipId);\n this.engine.setClips(Array.from(this.liveClips.values()));\n }\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 this.metronomeConfig = resolveMetronomeConfig(message.config);\n this.engine.setMetronome(message.config);\n break;\n case 'syncAutomation':\n this.engine.setAutomationLane(message.paramId, message.points);\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 '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 }\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 SonareEngineCaptureResponseMessage);\n return;\n }\n if (message.op === 'read') {\n const captured = this.engine.capturedAudio();\n const channels: number[][] = [];\n for (let ch = 0; ch < captured.length; ch++) {\n const source = captured[ch];\n const copy: number[] = [];\n for (let i = 0; i < source.length; i++) {\n copy.push(Number(source[i]));\n }\n channels.push(copy);\n }\n this.transport?.postMessage?.({\n type: 'captureResponse',\n requestId: message.requestId,\n ok: true,\n channels,\n } satisfies SonareEngineCaptureResponseMessage);\n return;\n }\n this.engine.resetCapture();\n this.transport?.postMessage?.({\n type: 'captureResponse',\n requestId: message.requestId,\n ok: true,\n } satisfies SonareEngineCaptureResponseMessage);\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 SonareEngineCaptureResponseMessage);\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.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.applyCommand(command);\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.SetTempoMap:\n this.engine.setTempo(Number(command.argFloat ?? 120));\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 });\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 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 for (const item of this.engine.drainTelemetry(64)) {\n this.publishTelemetryRecord(telemetryFromEngine(item));\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 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 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 (const item of this.engine.drainScopeTelemetry(64)) {\n this.writeScopeRing(ring, item);\n }\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 if (!this.transport?.postMessage) {\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 private writeScopeRing(ring: SharedScopeRingWriter, record: EngineScopeTelemetry): void {\n const writeIndex = Atomics.load(ring.header, 0);\n const base = (writeIndex % ring.capacity) * ring.recordFloats;\n ring.records[base] = encodeFrameLo(record.renderFrame);\n ring.records[base + 1] = encodeFrameHi(record.renderFrame);\n ring.records[base + 2] = record.targetId;\n const bandCount = Math.min(ring.bands, record.bands.length);\n ring.records[base + 3] = bandCount;\n const pointCount = Math.min(ring.maxPoints, record.points.length);\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] = record.bands[i];\n }\n const pointsBase = bandsBase + ring.bands;\n for (let i = 0; i < pointCount; i++) {\n const point = record.points[i];\n ring.records[pointsBase + 2 * i] = point.left;\n ring.records[pointsBase + 2 * i + 1] = point.right;\n }\n Atomics.store(ring.header, 0, writeIndex + 1);\n // Like writeMeterRing, writeIndex is a free-running monotonic counter; the\n // reader detects silent overrun via firstReadable, so the overflow slot\n // (header[5]) stays at its initial 0.\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 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 }\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 this.bridge = new SonareRealtimeEngineWorkletProcessor(options, {\n postMessage: (message) => port?.postMessage?.(message),\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 // 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.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. Runs on the\n * AudioWorklet global scope but OUTSIDE of `process()` (i.e. outside the\n * realtime audio callback), so it is safe to perform JSON parsing and\n * DSP coefficient recomputation here. `setConfig` MUST NOT be deferred\n * into `process()` because that would block the audio thread for longer\n * than one render quantum (e.g. 128 samples / 44.1 kHz = ~2.9 ms).\n */\n receiveMessage(message: SonareRealtimeVoiceChangerMessage): void {\n if (this.destroyed) {\n return;\n }\n if (message.type === 'setConfig') {\n // Apply synchronously on the message-handler thread. `setConfig` may\n // allocate and parse JSON internally; doing it here keeps `process()`\n // realtime-safe.\n this.changer.setConfig(message.preset);\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 (this.monoInput.byteLength === 0) {\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.processMonoInto(\n this.monoInput.subarray(0, frames),\n this.monoOutput.subarray(0, frames),\n );\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 }\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":";AAsBO,IAAM,cAAN,cAA0B,MAAM;AAAA,EAMrC,YAAY,MAAc,UAAkB,SAAiB;AAC3D,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,WAAW;AAAA,EAClB;AACF;;;AC/BA,IAAI,gBAAqC;AAqBzC,SAAS,mBAAmB,OAA+B;AACzD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,MAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;AAC/C,UAAM,MAAO,MAA+B;AAC5C,QAAI,OAAO,QAAQ,UAAU;AAC3B,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAOA,SAAS,gBAAgB,KAAmB,QAA6B;AACvE,MAAI;AACJ,MAAI,WAAW;AACf,MAAI,UAAU,+BAA+B,MAAM;AACnD,MAAI;AACF,UAAM,OACJ,IACA,sBAAsB,MAAM;AAC9B,QAAI,MAAM;AACR,aAAO,KAAK,QAAQ;AACpB,iBAAW,KAAK,YAAY;AAC5B,gBAAU,KAAK,WAAW;AAAA,IAC5B;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO,IAAI,YAAY,MAAM,UAAU,OAAO;AAChD;AAUA,SAAS,iBAAiB,KAAiC;AACzD,QAAM,QAAQ,oBAAI,IAA0B;AAC5C,QAAM,cAAc,oBAAI,QAAyB;AACjD,QAAM,UAAU,CAAC,UAA0B;AACzC,UAAM,MAAM,mBAAmB,KAAK;AACpC,QAAI,QAAQ,MAAM;AAChB,YAAM,gBAAgB,KAAK,GAAG;AAAA,IAChC;AACA,UAAM;AAAA,EACR;AAEA,QAAM,mBAAmB,CAAC,UAA4B;AACpD,QAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;AAC/C,aAAO;AAAA,IACT;AACA,QAAI,YAAY,OAAO,KAAK,KAAK,iBAAiB,eAAe,iBAAiB,SAAS;AACzF,aAAO;AAAA,IACT;AACA,UAAM,cAAc;AACpB,UAAM,SAAS,YAAY,IAAI,WAAW;AAC1C,QAAI,QAAQ;AACV,aAAO;AAAA,IACT;AACA,UAAM,cAAc,oBAAI,IAA0B;AAClD,UAAM,UAAU,IAAI,MAAM,aAAa;AAAA,MACrC,IAAI,QAAQ,MAAM,UAAU;AAC1B,cAAM,SAAS,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AACjD,YAAI,OAAO,WAAW,YAAY;AAChC,iBAAO;AAAA,QACT;AACA,cAAM,eAAe,YAAY,IAAI,IAAI;AACzC,YAAI,cAAc;AAChB,iBAAO;AAAA,QACT;AACA,cAAM,SAAS;AACf,cAAM,gBAAgB,IAAI,SAAoB;AAC5C,cAAI;AACF,mBAAO,iBAAiB,QAAQ,MAAM,QAAQ,QAAQ,IAAI,CAAC;AAAA,UAC7D,SAAS,OAAO;AACd,mBAAO,QAAQ,KAAK;AAAA,UACtB;AAAA,QACF;AACA,oBAAY,IAAI,MAAM,aAAa;AACnC,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AACD,gBAAY,IAAI,aAAa,OAAO;AACpC,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,CAAC,UAAiD;AACrE,UAAM,UAAU,oBAAI,IAA0B;AAC9C,WAAO,IAAI,MAAM,OAAO;AAAA,MACtB,IAAI,QAAQ,MAAM,UAAU;AAC1B,cAAM,SAAS,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AACjD,YAAI,OAAO,WAAW,YAAY;AAChC,iBAAO;AAAA,QACT;AACA,cAAM,eAAe,QAAQ,IAAI,IAAI;AACrC,YAAI,cAAc;AAChB,iBAAO;AAAA,QACT;AACA,cAAM,KAAK;AACX,cAAM,gBAAgB,IAAI,SAAoB;AAC5C,cAAI;AACF,mBAAO,iBAAiB,QAAQ,MAAM,IAAI,QAAQ,IAAI,CAAC;AAAA,UACzD,SAAS,OAAO;AACd,mBAAO,QAAQ,KAAK;AAAA,UACtB;AAAA,QACF;AACA,gBAAQ,IAAI,MAAM,aAAa;AAC/B,eAAO;AAAA,MACT;AAAA,MACA,MAAM,GAAG,SAAS,MAAM;AACtB,YAAI;AACF,iBAAO,iBAAiB,QAAQ,MAAM,GAAG,SAAS,IAAiB,CAAC;AAAA,QACtE,SAAS,OAAO;AACd,iBAAO,QAAQ,KAAK;AAAA,QACtB;AAAA,MACF;AAAA,MACA,UAAU,GAAG,MAAM,WAAW;AAC5B,YAAI;AACF,iBAAO,iBAAiB,QAAQ,UAAU,GAAG,MAAmB,SAAS,CAAC;AAAA,QAC5E,SAAS,OAAO;AACd,iBAAO,QAAQ,KAAK;AAAA,QACtB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO,IAAI,MAAM,KAAK;AAAA,IACpB,IAAI,QAAQ,MAAM,UAAU;AAC1B,YAAM,QAAQ,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AAChD,UAAI,OAAO,UAAU,YAAY;AAC/B,eAAO;AAAA,MACT;AACA,YAAM,SAAS,MAAM,IAAI,IAAI;AAC7B,UAAI,QAAQ;AACV,eAAO;AAAA,MACT;AAIA,YAAM,UAAU,aAAa,KAAqC;AAClE,YAAM,IAAI,MAAM,OAAO;AACvB,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAEO,SAAS,gBAAgBA,SAA4B;AAC1D,kBAAgB,iBAAiBA,OAAM;AACzC;AAEO,SAAS,kBAAgC;AAC9C,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AACA,SAAO;AACT;;;AC1LO,SAAS,oBAAoB,OAAgC;AAClE,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,YAAM,IAAI,MAAM,6BAA6B,KAAK,EAAE;AAAA,EACxD;AACF;AAEO,SAAS,WAAW,QAAiC;AAC1D,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO;AAAA,EACT;AACA,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,YAAY,SAAmC;AAC7D,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO;AAAA,EACT;AACA,UAAQ,SAAS;AAAA,IACf,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,aAAa,KAAgC;AAC3D,SAAO,QAAQ,cAAc,QAAQ,IAAI,IAAI;AAC/C;AAEO,SAAS,eAAe,QAAqC;AAGlE,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO;AAAA,EACT;AACA,SAAO,WAAW,aAAa,IAAI;AACrC;;;ACwDO,IAAM,8BAA8B;AAoBpC,SAAS,qBAAyC;AACvD,QAAM,aAAa,gBAAgB,EAAE,iBAAiB;AACtD,QAAM,oBAAoB,OAAO,WAAW,sBAAsB;AAClE,QAAM,UAAU,OAAO,WAAW,YAAY;AAC9C,QAAM,eACJ,OAAO,qBAAqB,eAC5B,OAAQ,WACL,0BAA0B;AAC/B,SAAO;AAAA,IACL,kBAAkB;AAAA,IAClB,0BAA0B;AAAA,IAC1B,eAAe,eAAe;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,qBAAqB,UAAU,QAAQ;AAAA,EAC/C;AACF;AAEO,IAAM,iBAAN,MAAqB;AAAA,EAG1B,YACE,aAAa,MACb,eAAe,KACf,kBAAkB,MAClB,oBAAoB,MACpB;AACA,UAAMC,UAAS,gBAAgB;AAC/B,UAAM,eAAe,mBAAmB;AACxC,QAAI,CAAC,aAAa,eAAe;AAC/B,YAAM,IAAI;AAAA,QACR,6BAA6B,aAAa,gBAAgB,cAAc,aAAa,wBAAwB;AAAA,MAC/G;AAAA,IACF;AACA,SAAK,SAAS,IAAIA,QAAO;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,QACE,YACA,cACA,kBAAkB,MAClB,oBAAoB,MACd;AACN,SAAK,OAAO,QAAQ,YAAY,cAAc,iBAAiB,iBAAiB;AAAA,EAClF;AAAA;AAAA,EAGA,aAAa,SAAiB,OAAe,cAAc,IAAU;AACnE,SAAK,OAAO,aAAa,SAAS,OAAO,WAAW;AAAA,EACtD;AAAA;AAAA,EAGA,qBAAqB,SAAiB,OAAe,cAAc,IAAU;AAC3E,SAAK,OAAO,qBAAqB,SAAS,OAAO,WAAW;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,oBAAoB,aAA2B;AAC7C,SAAK,OAAO,oBAAoB,WAAW;AAAA,EAC7C;AAAA,EAEA,YAAY,WAAmB,MAAe,MAAe,cAAc,IAAU;AACnF,SAAK,OAAO,YAAY,WAAW,MAAM,MAAM,WAAW;AAAA,EAC5D;AAAA,EAEA,aAAa,OAAgD;AAC3D,SAAK,OAAO,aAAa,KAAK;AAAA,EAChC;AAAA,EAEA,qBACE,SAA+D,CAAC,GAChE,gBAAgB,OAAO,iBAAiB,GAClC;AACN,SAAK,OAAO,qBAAqB,eAAe,MAAM;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,mBACE,QAA6B,CAAC,GAC9B,iBAAiB,OAAO,UAAU,WAAW,MAAM,gBAAgB,WAAc,GAC3E;AACN,SAAK,OAAO,mBAAmB,eAAe,KAAK;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cAAc,MAAwB;AACpC,SAAK,OAAO,cAAc,IAAI;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,iBACE,SAAwE,CAAC,GACzE,gBAAgB,OAAO,iBAAiB,GAClC;AACN,SAAK,OAAO,iBAAiB,eAAe,MAAM;AAAA,EACpD;AAAA,EAEA,oBAAoB,gBAAgB,GAAS;AAC3C,SAAK,OAAO,oBAAoB,aAAa;AAAA,EAC/C;AAAA,EAEA,sBAA8B;AAC5B,WAAO,KAAK,OAAO,oBAAoB;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WACE,SACA,YACA,SACA,UAA6B,CAAC,GACxB;AACN,SAAK,OAAO;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,YAAY;AAAA,MACpB,QAAQ,YAAY;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,sBAA4B;AAC1B,SAAK,OAAO,oBAAoB;AAAA,EAClC;AAAA,EAEA,qBAA6B;AAC3B,WAAO,KAAK,OAAO,mBAAmB;AAAA,EACxC;AAAA;AAAA,EAGA,UAAU,eAAuB,YAA0B;AACzD,SAAK,OAAO,UAAU,eAAe,UAAU;AAAA,EACjD;AAAA,EAEA,YAAY,gBAAgB,GAAS;AACnC,SAAK,OAAO,YAAY,aAAa;AAAA,EACvC;AAAA;AAAA,EAGA,mBAAmB,gBAAgB,GAAS;AAC1C,SAAK,OAAO,mBAAmB,aAAa;AAAA,EAC9C;AAAA,EAEA,uBAA6B;AAC3B,SAAK,OAAO,qBAAqB;AAAA,EACnC;AAAA,EAEA,wBAAgC;AAC9B,WAAO,KAAK,OAAO,sBAAsB;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,2BAA2B,eAAuB,UAAyB;AACzE,SAAK,OAAO,2BAA2B,eAAe,QAAQ;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,4BAA4B,SAAwB;AAClD,SAAK,OAAO,4BAA4B,OAAO;AAAA,EACjD;AAAA;AAAA,EAGA,2BAAmC;AACjC,WAAO,KAAK,OAAO,yBAAyB;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,kBAAkB,aAAa,MAA+B;AAC5D,WAAO,KAAK,OAAO,kBAAkB,UAAU;AAAA,EACjD;AAAA,EAEA,oBACE,OACA,SACA,MACA,UACA,kBAAkB,GACZ;AACN,SAAK,OAAO,oBAAoB,OAAO,SAAS,MAAM,UAAU,eAAe;AAAA,EACjF;AAAA,EAEA,qBACE,OACA,SACA,MACA,WAAW,GACX,kBAAkB,GACZ;AACN,SAAK,OAAO,qBAAqB,OAAO,SAAS,MAAM,UAAU,eAAe;AAAA,EAClF;AAAA,EAEA,gBACE,OACA,SACA,YACA,OACA,kBAAkB,GACZ;AACN,SAAK,OAAO,gBAAgB,OAAO,SAAS,YAAY,OAAO,eAAe;AAAA,EAChF;AAAA,EAEA,eACE,eACA,OACA,SACA,MACA,UACA,cAAc,IACR;AACN,SAAK,OAAO,eAAe,eAAe,OAAO,SAAS,MAAM,UAAU,WAAW;AAAA,EACvF;AAAA,EAEA,gBACE,eACA,OACA,SACA,MACA,WAAW,GACX,cAAc,IACR;AACN,SAAK,OAAO,gBAAgB,eAAe,OAAO,SAAS,MAAM,UAAU,WAAW;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WACE,eACA,OACA,SACA,YACA,OACA,cAAc,IACR;AACN,SAAK,OAAO,WAAW,eAAe,OAAO,SAAS,YAAY,OAAO,WAAW;AAAA,EACtF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cAAc,eAAuB,MAAkB,cAAc,IAAU;AAC7E,SAAK,OAAO,cAAc,eAAe,MAAM,WAAW;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,cAAc,IAAU;AACpC,SAAK,OAAO,cAAc,WAAW;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAwB;AACtB,SAAK,OAAO,gBAAgB;AAAA,EAC9B;AAAA;AAAA,EAGA,oBAA0C;AACxC,WAAO,KAAK,OAAO,kBAAkB;AAAA,EACvC;AAAA,EAEA,KAAK,cAAc,IAAU;AAC3B,SAAK,OAAO,KAAK,WAAW;AAAA,EAC9B;AAAA,EAEA,KAAK,cAAc,IAAU;AAC3B,SAAK,OAAO,KAAK,WAAW;AAAA,EAC9B;AAAA,EAEA,WAAW,gBAAwB,cAAc,IAAU;AACzD,SAAK,OAAO,WAAW,gBAAgB,WAAW;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,mBAAyB;AACvB,SAAK,OAAO,iBAAiB;AAAA,EAC/B;AAAA,EAEA,QAAQ,KAAa,cAAc,IAAU;AAC3C,SAAK,OAAO,QAAQ,KAAK,WAAW;AAAA,EACtC;AAAA,EAEA,SAAS,KAAmB;AAC1B,SAAK,OAAO,SAAS,GAAG;AAAA,EAC1B;AAAA,EAEA,iBAAiB,UAA+C;AAC9D,SAAK,OAAO,iBAAiB,CAAC,GAAG,QAAQ,CAAC;AAAA,EAC5C;AAAA,EAEA,iBAAiB,WAAmB,aAA2B;AAC7D,SAAK,OAAO,iBAAiB,WAAW,WAAW;AAAA,EACrD;AAAA,EAEA,yBAAyB,UAAuD;AAC9E,SAAK,OAAO,yBAAyB,CAAC,GAAG,QAAQ,CAAC;AAAA,EACpD;AAAA,EAEA,YAAY,KAAqB;AAC/B,WAAO,OAAO,KAAK,OAAO,YAAY,GAAG,CAAC;AAAA,EAC5C;AAAA,EAEA,QAAQ,UAAkB,QAAgB,UAAU,MAAY;AAC9D,SAAK,OAAO,QAAQ,UAAU,QAAQ,OAAO;AAAA,EAC/C;AAAA,EAEA,aAAa,MAAiC;AAC5C,SAAK,OAAO,aAAa,IAAI;AAAA,EAC/B;AAAA,EAEA,iBAAyB;AACvB,WAAO,KAAK,OAAO,eAAe;AAAA,EACpC;AAAA,EAEA,qBAAqB,OAAoC;AACvD,WAAO,KAAK,OAAO,qBAAqB,KAAK;AAAA,EAC/C;AAAA,EAEA,cAAc,IAAiC;AAC7C,WAAO,KAAK,OAAO,cAAc,EAAE;AAAA,EACrC;AAAA,EAEA,kBAAkB,SAAiB,QAAuC;AACxE,SAAK,OAAO,kBAAkB,SAAS,MAAM;AAAA,EAC/C;AAAA,EAEA,sBAA8B;AAC5B,WAAO,KAAK,OAAO,oBAAoB;AAAA,EACzC;AAAA,EAEA,WAAW,SAA+B;AACxC,SAAK,OAAO,WAAW,OAAO;AAAA,EAChC;AAAA,EAEA,cAAsB;AACpB,WAAO,KAAK,OAAO,YAAY;AAAA,EACjC;AAAA,EAEA,cAAc,OAA6B;AACzC,WAAO,KAAK,OAAO,cAAc,KAAK;AAAA,EACxC;AAAA,EAEA,OAAO,IAA0B;AAC/B,WAAO,KAAK,OAAO,OAAO,EAAE;AAAA,EAC9B;AAAA,EAEA,WAAW,UAAkB,cAAc,IAAU;AACnD,SAAK,OAAO,WAAW,UAAU,WAAW;AAAA,EAC9C;AAAA,EAEA,mBAAmB,eAAuB,aAA2B;AACnE,SAAK,OAAO,mBAAmB,eAAe,WAAW;AAAA,EAC3D;AAAA,EAEA,aAAa,QAAqC;AAChD,SAAK,OAAO,aAAa,MAAM;AAAA,EACjC;AAAA,EAEA,YAA6C;AAC3C,WAAO,KAAK,OAAO,UAAU;AAAA,EAC/B;AAAA,EAEA,iBAAiB,aAAqB,MAAsB;AAC1D,WAAO,OAAO,KAAK,OAAO,iBAAiB,aAAa,IAAI,CAAC;AAAA,EAC/D;AAAA,EAEA,SAAS,MAA6B;AACpC,SAAK,OAAO,SAAS,IAAI;AAAA,EAC3B;AAAA,EAEA,iBAAyB;AACvB,WAAO,KAAK,OAAO,eAAe;AAAA,EACpC;AAAA,EAEA,uBAA+B;AAC7B,WAAO,KAAK,OAAO,qBAAqB;AAAA,EAC1C;AAAA,EAEA,SAAS,OAA2B;AAClC,SAAK,OAAO;AAAA,MACV,MAAM,IAAI,CAAC,UAAU;AAAA,QACnB,GAAG;AAAA,QACH,cACE,OAAO,KAAK,iBAAiB,YAAY,KAAK,iBAAiB,OAC3D,KAAK,aAAa,KAClB,KAAK;AAAA,MACb,EAAE;AAAA,IACJ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAAqB,QAAuC;AAC1D,WAAO,KAAK,OAAO,qBAAqB,MAAM;AAAA,EAChD;AAAA,EAEA,YAAoB;AAClB,WAAO,KAAK,OAAO,UAAU;AAAA,EAC/B;AAAA,EAEA,cAAc,OAA8C;AAC1D,SAAK,OAAO;AAAA,MACV,MAAM,IAAI,CAAC,SAAS;AAClB,YAAI,OAAO,SAAS,UAAU;AAC5B,iBAAO,EAAE,SAAS,KAAK;AAAA,QACzB;AACA,YAAI,CAAC,KAAK,OAAO;AACf,iBAAO;AAAA,QACT;AAGA,eAAO;AAAA,UACL,GAAG;AAAA,UACH,OAAO,KAAK,MAAM,IAAI,CAAC,UAAU;AAAA,YAC/B,GAAG;AAAA;AAAA,YAEH,YAAY,KAAK,eAAe,SAAY,IAAI,eAAe,KAAK,UAAU;AAAA,UAChF,EAAE;AAAA,QACJ;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAiB,SAAiB,aAAqB,eAA6B;AAClF,SAAK,OAAO,iBAAiB,SAAS,aAAa,aAAa;AAAA,EAClE;AAAA,EAEA,cAAc,OAA0B;AACtC,SAAK,OAAO,cAAc,KAAK;AAAA,EACjC;AAAA,EAEA,gBAAgB,OAAe,WAAyB;AACtD,QAAI;AACF,WAAK,MAAM,SAAS;AAAA,IACtB,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,YAAM,IAAI,mCAAqC,iBAAiB,OAAO;AAAA,IACzE;AACA,SAAK,OAAO,gBAAgB,OAAO,SAAS;AAAA,EAC9C;AAAA,EAEA,kBAAkB,SAAiB,WAAyB;AAC1D,QAAI;AACF,WAAK,MAAM,SAAS;AAAA,IACtB,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,YAAM,IAAI,mCAAqC,iBAAiB,OAAO;AAAA,IACzE;AACA,SAAK,OAAO,kBAAkB,SAAS,SAAS;AAAA,EAClD;AAAA,EAEA,oBAAoB,SAAiB,WAAmB,MAA6B;AACnF,SAAK,OAAO;AAAA,MACV;AAAA,MACA;AAAA,MACA,OAAO,SAAS,WAAW,OAAO,KAAK,UAAU,IAAI;AAAA,IACvD;AAAA,EACF;AAAA,EAEA,wBAAwB,SAAiB,WAAmB,UAAwB;AAClF,SAAK,OAAO,wBAAwB,SAAS,WAAW,QAAQ;AAAA,EAClE;AAAA,EAEA,4BACE,SACA,aACA,UACA,gBAAgB,OACV;AACN,SAAK,OAAO,4BAA4B,SAAS,aAAa,UAAU,aAAa;AAAA,EACvF;AAAA,EAEA,mBAAmB,WAAyB;AAC1C,QAAI;AACF,WAAK,MAAM,SAAS;AAAA,IACtB,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,YAAM,IAAI,mCAAqC,iBAAiB,OAAO;AAAA,IACzE;AACA,SAAK,OAAO,mBAAmB,SAAS;AAAA,EAC1C;AAAA,EAEA,qBAAqB,WAAmB,MAA6B;AACnE,SAAK,OAAO;AAAA,MACV;AAAA,MACA,OAAO,SAAS,WAAW,OAAO,KAAK,UAAU,IAAI;AAAA,IACvD;AAAA,EACF;AAAA,EAEA,yBAAyB,WAAmB,UAAwB;AAClE,SAAK,OAAO,yBAAyB,WAAW,QAAQ;AAAA,EAC1D;AAAA,EAEA,6BACE,aACA,UACA,gBAAgB,OACV;AACN,SAAK,OAAO,6BAA6B,aAAa,UAAU,aAAa;AAAA,EAC/E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,+BACE,SACA,aACA,WACA,OACM;AACN,SAAK,OAAO,+BAA+B,SAAS,aAAa,WAAW,KAAK;AAAA,EACnF;AAAA;AAAA,EAGA,gCAAgC,aAAqB,WAAmB,OAAqB;AAC3F,SAAK,OAAO,gCAAgC,aAAa,WAAW,KAAK;AAAA,EAC3E;AAAA;AAAA,EAGA,6BACE,OACA,aACA,WACA,OACM;AACN,SAAK,OAAO,6BAA6B,OAAO,aAAa,WAAW,KAAK;AAAA,EAC/E;AAAA;AAAA,EAGA,0BACE,OACA,aACA,UACA,gBAAgB,OACV;AACN,SAAK,OAAO,0BAA0B,OAAO,aAAa,UAAU,aAAa;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,+BAA+B,SAAiB,aAAqB,WAA2B;AAC9F,WAAO,KAAK,OAAO,+BAA+B,SAAS,aAAa,SAAS;AAAA,EACnF;AAAA,EAEA,gCAAgC,aAAqB,WAA2B;AAC9E,WAAO,KAAK,OAAO,gCAAgC,aAAa,SAAS;AAAA,EAC3E;AAAA,EAEA,6BAA6B,OAAe,aAAqB,WAA2B;AAC1F,WAAO,KAAK,OAAO,6BAA6B,OAAO,aAAa,SAAS;AAAA,EAC/E;AAAA;AAAA,EAGA,iBAAiB,SAAiB,KAAmB;AACnD,SAAK,OAAO,iBAAiB,SAAS,GAAG;AAAA,EAC3C;AAAA;AAAA,EAGA,oBAAoB,SAAiB,QAA+B;AAClE,SAAK,OAAO,oBAAoB,SAAS,WAAW,MAAM,CAAC;AAAA,EAC7D;AAAA;AAAA,EAGA,qBAAqB,SAAiB,SAAiC;AACrE,SAAK,OAAO,qBAAqB,SAAS,YAAY,OAAO,CAAC;AAAA,EAChE;AAAA;AAAA,EAGA,qBAAqB,SAAiB,SAAiB,UAAwB;AAC7E,SAAK,OAAO,qBAAqB,SAAS,SAAS,QAAQ;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iCAAiC,SAAiB,cAA4B;AAC5E,SAAK,OAAO,iCAAiC,SAAS,YAAY;AAAA,EACpE;AAAA,EAEA,uBACE,aACA,YACA,YACkB;AAClB,UAAM,KAAK,KAAK,OAAO,uBAAuB,aAAa,YAAY,UAAU;AACjF,WAAO,IAAI,iBAAiB,MAAM,EAAE;AAAA,EACtC;AAAA,EAEA,eAAe,YAAoB,WAAmB,UAAgC;AACpF,SAAK,OAAO,eAAe,YAAY,WAAW,QAAQ;AAAA,EAC5D;AAAA,EAEA,cAAc,YAAoB,WAAyB;AACzD,SAAK,OAAO,cAAc,YAAY,SAAS;AAAA,EACjD;AAAA,EAEA,wBAAwB,YAA0B;AAChD,SAAK,OAAO,wBAAwB,UAAU;AAAA,EAChD;AAAA,EAEA,qBAA6C;AAC3C,WAAO,KAAK,OAAO,mBAAmB;AAAA,EACxC;AAAA,EAEA,iBAAiB,aAAqB,gBAA8B;AAClE,SAAK,OAAO,iBAAiB,aAAa,cAAc;AAAA,EAC1D;AAAA,EAEA,WAAW,QAAQ,MAAY;AAC7B,SAAK,OAAO,WAAW,KAAK;AAAA,EAC9B;AAAA,EAEA,gBAAgB,aAAqB,WAAmB,UAAU,MAAY;AAC5E,SAAK,OAAO,gBAAgB,aAAa,WAAW,OAAO;AAAA,EAC7D;AAAA,EAEA,iBAAiB,QAA6C;AAC5D,SAAK,OAAO,iBAAiB,MAAM;AAAA,EACrC;AAAA,EAEA,uBAAuB,eAA6B;AAClD,SAAK,OAAO,uBAAuB,aAAa;AAAA,EAClD;AAAA,EAEA,gBAAgB,SAAkB,OAAO,GAAS;AAChD,SAAK,OAAO,gBAAgB,SAAS,IAAI;AAAA,EAC3C;AAAA,EAEA,eAAqB;AACnB,SAAK,OAAO,aAAa;AAAA,EAC3B;AAAA,EAEA,gBAAqC;AACnC,WAAO,KAAK,OAAO,cAAc;AAAA,EACnC;AAAA,EAEA,gBAAgC;AAC9B,WAAO,KAAK,OAAO,cAAc;AAAA,EACnC;AAAA,EAEA,QAAQ,UAA0C;AAChD,WAAO,KAAK,OAAO,QAAQ,QAAQ;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBAAgB,aAAqB,WAAyB;AAC5D,SAAK,OAAO,gBAAgB,aAAa,SAAS;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiB,SAAiB,WAAiC;AACjE,WAAO,KAAK,OAAO,iBAAiB,SAAS,SAAS;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAgB,WAAyB;AACvC,SAAK,OAAO,gBAAgB,SAAS;AAAA,EACvC;AAAA,EAEA,mBAAmB,UAA8D;AAC/E,WAAO,KAAK,OAAO,mBAAmB,QAAQ;AAAA,EAChD;AAAA,EAEA,cAAc,UAA0B,YAAY,KAAqB;AACvE,WAAO,KAAK,OAAO,cAAc,UAAU,SAAS;AAAA,EACtD;AAAA,EAEA,cAAc,SAAkD;AAC9D,WAAO,KAAK,OAAO,cAAc,OAAO;AAAA,EAC1C;AAAA,EAEA,cAAc,SAAkD;AAC9D,WAAO,KAAK,OAAO,cAAc,OAAO;AAAA,EAC1C;AAAA,EAEA,eAAe,aAAa,MAAyB;AACnD,WAAO,KAAK,OAAO,eAAe,UAAU;AAAA,EAC9C;AAAA,EAEA,oBAAoB,aAAa,MAA8B;AAC7D,WAAO,KAAK,OAAO,oBAAoB,UAAU;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,wBAAwB,aAAa,MAAkC;AACrE,WAAO,KAAK,OAAO,wBAAwB,UAAU;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,wBAAwB,gBAAwB,WAA2B;AACzE,WAAO,KAAK,OAAO,wBAAwB,gBAAgB,SAAS;AAAA,EACtE;AAAA;AAAA,EAGA,oBAAoB,aAAa,MAA8B;AAC7D,WAAO,KAAK,OAAO,oBAAoB,UAAU;AAAA,EACnD;AAAA,EAEA,UAAgB;AACd,SAAK,OAAO,OAAO;AAAA,EACrB;AACF;AAEO,IAAM,mBAAN,MAAuB;AAAA,EAG5B,YACmB,QACR,IACT;AAFiB;AACR;AAJX,SAAQ,WAAW;AAAA,EAKhB;AAAA,EAEH,OAAO,WAAmB,UAAgC;AACxD,QAAI,KAAK,UAAU;AACjB,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACjD;AACA,SAAK,OAAO,eAAe,KAAK,IAAI,WAAW,QAAQ;AAAA,EACzD;AAAA,EAEA,MAAM,WAAyB;AAC7B,QAAI,KAAK,UAAU;AACjB;AAAA,IACF;AACA,SAAK,OAAO,cAAc,KAAK,IAAI,SAAS;AAAA,EAC9C;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,UAAU;AACjB;AAAA,IACF;AACA,SAAK,WAAW;AAChB,SAAK,OAAO,wBAAwB,KAAK,EAAE;AAAA,EAC7C;AACF;;;ACr5BO,IAAM,QAAN,MAAM,OAAM;AAAA,EAIT,YAAY,OAAwC,WAAmB;AAC7E,SAAK,QAAQ;AACb,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,cAAc,MAAc,aAAa,MAAO,YAAY,KAAY;AAC7E,UAAMC,UAAS,gBAAgB;AAC/B,WAAO,IAAI,OAAMA,QAAO,yBAAyB,MAAM,YAAY,SAAS,GAAG,SAAS;AAAA,EAC1F;AAAA;AAAA,EAGA,UAAgB;AACd,SAAK,MAAM,QAAQ;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,gBAA0B;AACxB,WAAO,KAAK,MAAM,cAAc;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,cAAc,cAA8B,eAAmD;AAC7F,QAAI,aAAa,WAAW,cAAc,QAAQ;AAChD,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC7E;AACA,WAAO,KAAK,MAAM,cAAc,cAAc,aAAa;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,kBACE,cACA,eACA,SACA,UACM;AACN,QAAI,aAAa,WAAW,cAAc,QAAQ;AAChD,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC7E;AACA,QAAI,QAAQ,WAAW,SAAS,QAAQ;AACtC,YAAM,IAAI,MAAM,iDAAiD;AAAA,IACnE;AACA,SAAK,MAAM,kBAAkB,cAAc,eAAe,SAAS,QAAQ;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,uBAA4C;AAC1C,UAAM,aAAa,KAAK,WAAW;AACnC,QAAI,aAA6B,CAAC;AAClC,QAAI,cAA8B,CAAC;AACnC,QAAI,UAAU,KAAK,MAAM,eAAe;AACxC,QAAI,WAAW,KAAK,MAAM,gBAAgB;AAC1C,UAAM,UAAU,MAAY;AAC1B,mBAAa,CAAC;AACd,oBAAc,CAAC;AACf,eAAS,QAAQ,GAAG,QAAQ,YAAY,SAAS;AAC/C,mBAAW,KAAK,KAAK,MAAM,cAAc,KAAK,CAAC;AAC/C,oBAAY,KAAK,KAAK,MAAM,eAAe,KAAK,CAAC;AAAA,MACnD;AACA,gBAAU,KAAK,MAAM,eAAe;AACpC,iBAAW,KAAK,MAAM,gBAAgB;AAAA,IACxC;AACA,YAAQ;AAIR,UAAM,sBAAsB,MAAY;AACtC,UAAI,QAAQ,eAAe,MAAM,WAAW,CAAC,GAAG,cAAc,OAAO,GAAG;AACtE,gBAAQ;AAAA,MACV;AAAA,IACF;AACA,WAAO;AAAA,MACL,IAAI,aAA6B;AAC/B,4BAAoB;AACpB,eAAO;AAAA,MACT;AAAA,MACA,IAAI,cAA8B;AAChC,4BAAoB;AACpB,eAAO;AAAA,MACT;AAAA,MACA,IAAI,UAAwB;AAC1B,4BAAoB;AACpB,eAAO;AAAA,MACT;AAAA,MACA,IAAI,WAAyB;AAC3B,4BAAoB;AACpB,eAAO;AAAA,MACT;AAAA,MACA,SAAS,CAAC,aAAa,QAAQ,WAAW;AACxC,4BAAoB;AACpB,aAAK,MAAM,sBAAsB,UAAU;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,aAAqB;AACnB,WAAO,KAAK,MAAM,WAAW;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,yBACE,YACA,aACA,SACA,WACA,OACA,QAAyB,UACnB;AACN,SAAK,MAAM;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,oBAAoB,KAAK;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,IAA2B;AACnC,UAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,WAAO,QAAQ,IAAI,OAAO;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,IAAY,OAAO,OAAa;AACrC,SAAK,MAAM,OAAO,IAAI,IAAI;AAAA,EAC5B;AAAA;AAAA,EAGA,UAAU,IAAkB;AAC1B,SAAK,MAAM,UAAU,EAAE;AAAA,EACzB;AAAA;AAAA,EAGA,WAAmB;AACjB,WAAO,KAAK,MAAM,SAAS;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,IAAY,SAAS,GAAK,UAAoB,CAAC,GAAS;AAClE,SAAK,MAAM,YAAY,IAAI,QAAQ,OAAO;AAAA,EAC5C;AAAA;AAAA,EAGA,kBAAkB,IAAY,QAAsB;AAClD,SAAK,MAAM,kBAAkB,IAAI,MAAM;AAAA,EACzC;AAAA;AAAA,EAGA,eAAe,IAAkB;AAC/B,SAAK,MAAM,eAAe,EAAE;AAAA,EAC9B;AAAA;AAAA,EAGA,gBAAwB;AACtB,WAAO,KAAK,MAAM,cAAc;AAAA,EAClC;AAAA;AAAA,EAGA,eAAe,YAAoB,IAAkB;AACnD,SAAK,MAAM,eAAe,YAAY,EAAE;AAAA,EAC1C;AAAA;AAAA,EAGA,WAAW,YAAoB,IAAkB;AAC/C,SAAK,MAAM,WAAW,YAAY,EAAE;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAAO,YAAoB,KAAa,SAAkC;AAExE,UAAM,OAAO,YAAY,SAAY,KAAK,YAAY,OAAO;AAC7D,SAAK,MAAM,OAAO,YAAY,KAAK,IAAI;AAAA,EACzC;AAAA;AAAA,EAGA,SAAS,YAAoB,OAAqB;AAChD,SAAK,MAAM,SAAS,YAAY,KAAK;AAAA,EACvC;AAAA;AAAA,EAGA,SAAS,YAAoB,OAAsB;AACjD,SAAK,MAAM,SAAS,YAAY,KAAK;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,YAAoB,QAAuB;AACnD,SAAK,MAAM,UAAU,YAAY,MAAM;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,YAAoB,UAAyB;AACvD,SAAK,MAAM,YAAY,YAAY,QAAQ;AAAA,EAC7C;AAAA;AAAA,EAGA,kBAAkB,YAAoB,YAAqB,aAA4B;AACrF,SAAK,MAAM,kBAAkB,YAAY,YAAY,WAAW;AAAA,EAClE;AAAA;AAAA,EAGA,UAAU,YAAoB,QAA+B;AAC3D,SAAK,MAAM,UAAU,YAAY,WAAW,MAAM,CAAC;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,uBAAuB,YAAoB,cAA4B;AACrE,SAAK,MAAM,uBAAuB,YAAY,YAAY;AAAA,EAC5D;AAAA;AAAA,EAGA,eAAe,YAAoB,UAAwB;AACzD,SAAK,MAAM,eAAe,YAAY,QAAQ;AAAA,EAChD;AAAA;AAAA,EAGA,WAAW,YAAoB,SAAiB,UAAwB;AACtE,SAAK,MAAM,WAAW,YAAY,SAAS,QAAQ;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAe,YAAoB,KAAwB;AACzD,SAAK,MAAM,eAAe,YAAY,GAAG;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,QACE,YACA,IACA,kBACA,SAAS,GACT,SAA8B,aACtB;AACR,WAAO,KAAK,MAAM,QAAQ,YAAY,IAAI,kBAAkB,QAAQ,eAAe,MAAM,CAAC;AAAA,EAC5F;AAAA;AAAA,EAGA,UAAU,YAAoB,WAAmB,QAAsB;AACrE,SAAK,MAAM,UAAU,YAAY,WAAW,MAAM;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,WAAW,YAAoB,WAAyB;AACtD,SAAK,MAAM,WAAW,YAAY,SAAS;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAS,YAAoB,MAAgB,aAA+B;AAC1E,WAAO,KAAK,MAAM,SAAS,YAAY,aAAa,GAAG,CAAC;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,WAAW,YAAoB,KAA2C;AACxE,QAAI,QAAQ,QAAW;AACrB,aAAO,KAAK,MAAM,WAAW,UAAU;AAAA,IACzC;AACA,WAAO,KAAK,MAAM,SAAS,YAAY,aAAa,GAAG,CAAC;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,wBACE,YACA,WACA,SACA,QAAyB,UACnB;AACN,SAAK,MAAM,wBAAwB,YAAY,WAAW,SAAS,oBAAoB,KAAK,CAAC;AAAA,EAC/F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,sBACE,YACA,WACA,KACA,QAAyB,UACnB;AACN,SAAK,MAAM,sBAAsB,YAAY,WAAW,KAAK,oBAAoB,KAAK,CAAC;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,wBACE,YACA,WACA,OACA,QAAyB,UACnB;AACN,SAAK,MAAM,wBAAwB,YAAY,WAAW,OAAO,oBAAoB,KAAK,CAAC;AAAA,EAC7F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,uBACE,YACA,WACA,WACA,IACA,QAAyB,UACnB;AACN,SAAK,MAAM;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,oBAAoB,KAAK;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAAqB,YAAoB,WAAsC;AAC7E,WAAO,KAAK,MAAM,qBAAqB,YAAY,SAAS;AAAA,EAC9D;AAAA;AAAA,EAGA,cAAsB;AACpB,WAAO,KAAK,MAAM,YAAY;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAsB;AACpB,WAAO,KAAK,MAAM,YAAY;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAyB;AACvB,WAAO,KAAK,MAAM,eAAe;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAgB,YAAwC;AACtD,QAAI,CAAC,OAAO,cAAc,UAAU,KAAK,cAAc,KAAK,aAAa,KAAK,WAAW;AACvF,YAAM,IAAI;AAAA,QACR,+DAA+D,KAAK,SAAS;AAAA,MAC/E;AAAA,IACF;AACA,WAAO,KAAK,MAAM,gBAAgB,UAAU;AAAA,EAC9C;AAAA;AAAA,EAGA,SAAe;AACb,SAAK,MAAM,OAAO;AAAA,EACpB;AAAA;AAAA,EAGA,UAAgB;AACd,SAAK,OAAO;AAAA,EACd;AACF;;;ACjgBO,IAAM,uBAAN,MAA2B;AAAA,EAGhC,YAAY,SAA0C,mBAAmB;AACvE,UAAMC,UAAS,gBAAgB;AAC/B,SAAK,UAAUA,QAAO,2BAA2B,MAA0C;AAAA,EAC7F;AAAA,EAEA,QAAQ,YAAoB,eAAe,KAAK,WAAW,GAAS;AAClE,SAAK,QAAQ,QAAQ,YAAY,cAAc,QAAQ;AAAA,EACzD;AAAA,EAEA,QAAc;AACZ,SAAK,QAAQ,MAAM;AAAA,EACrB;AAAA,EAEA,UAAU,QAA+C;AACvD,SAAK,QAAQ,UAAU,MAA0C;AAAA,EACnE;AAAA,EAEA,aAAqB;AACnB,WAAO,KAAK,QAAQ,WAAW;AAAA,EACjC;AAAA,EAEA,iBAAyB;AACvB,WAAO,KAAK,QAAQ,eAAe;AAAA,EACrC;AAAA,EAEA,YAAY,SAAqC;AAC/C,WAAO,KAAK,QAAQ,YAAY,OAAO;AAAA,EACzC;AAAA,EAEA,gBAAgB,SAAuB,QAA4B;AACjE,SAAK,QAAQ,gBAAgB,SAAS,MAAM;AAAA,EAC9C;AAAA,EAEA,mBAAmB,SAAuB,UAAgC;AACxE,WAAO,KAAK,QAAQ,mBAAmB,SAAS,QAAQ;AAAA,EAC1D;AAAA,EAEA,uBAAuB,SAAuB,UAAkB,QAA4B;AAC1F,SAAK,QAAQ,uBAAuB,SAAS,UAAU,MAAM;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,mBAAmB,YAAkC;AACnD,WAAO,KAAK,QAAQ,mBAAmB,UAAU;AAAA,EACnD;AAAA;AAAA,EAGA,oBAAoB,YAAkC;AACpD,WAAO,KAAK,QAAQ,oBAAoB,UAAU;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,oBAAoB,YAA0B;AAC5C,SAAK,QAAQ,oBAAoB,UAAU;AAAA,EAC7C;AAAA;AAAA,EAGA,0BAA0B,WAAmB,aAAmC;AAC9E,WAAO,KAAK,QAAQ,0BAA0B,WAAW,WAAW;AAAA,EACtE;AAAA;AAAA,EAGA,2BAA2B,WAAmB,aAAmC;AAC/E,WAAO,KAAK,QAAQ,2BAA2B,WAAW,WAAW;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,2BAA2B,WAAmB,aAA2B;AACvE,SAAK,QAAQ,2BAA2B,WAAW,WAAW;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,uBAAuB,SAAiB,WAAiC;AACvE,WAAO,KAAK,QAAQ,uBAAuB,SAAS,SAAS;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,sBAAsB,WAAyB;AAC7C,SAAK,QAAQ,sBAAsB,SAAS;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,yBAAyB,YAAoD;AAC3E,QAAI,QAAQ,KAAK,mBAAmB,UAAU;AAC9C,QAAI,SAAS,KAAK,oBAAoB,UAAU;AAKhD,UAAM,sBAAsB,MAAY;AACtC,UAAI,MAAM,eAAe,KAAK,OAAO,eAAe,GAAG;AACrD,gBAAQ,KAAK,mBAAmB,UAAU;AAC1C,iBAAS,KAAK,oBAAoB,UAAU;AAAA,MAC9C;AAAA,IACF;AACA,WAAO;AAAA,MACL,IAAI,QAAsB;AACxB,4BAAoB;AACpB,eAAO;AAAA,MACT;AAAA,MACA,IAAI,SAAuB;AACzB,4BAAoB;AACpB,eAAO;AAAA,MACT;AAAA,MACA,SAAS,MAAM;AACb,4BAAoB;AACpB,aAAK,oBAAoB,UAAU;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,gCACE,WACA,aACuC;AACvC,QAAI,QAAQ,KAAK,0BAA0B,WAAW,WAAW;AACjE,QAAI,SAAS,KAAK,2BAA2B,WAAW,WAAW;AAGnE,UAAM,sBAAsB,MAAY;AACtC,UAAI,MAAM,eAAe,KAAK,OAAO,eAAe,GAAG;AACrD,gBAAQ,KAAK,0BAA0B,WAAW,WAAW;AAC7D,iBAAS,KAAK,2BAA2B,WAAW,WAAW;AAAA,MACjE;AAAA,IACF;AACA,WAAO;AAAA,MACL,IAAI,QAAsB;AACxB,4BAAoB;AACpB,eAAO;AAAA,MACT;AAAA,MACA,IAAI,SAAuB;AACzB,4BAAoB;AACpB,eAAO;AAAA,MACT;AAAA,MACA,UAAU;AAAA,MACV,SAAS,MAAM;AACb,4BAAoB;AACpB,aAAK,2BAA2B,WAAW,WAAW;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,2BACE,WACA,aACkC;AAClC,QAAI,WAA2B,CAAC;AAChC,UAAM,UAAU,MAAY;AAC1B,iBAAW,CAAC;AACZ,eAAS,KAAK,GAAG,KAAK,aAAa,MAAM;AACvC,iBAAS,KAAK,KAAK,uBAAuB,IAAI,SAAS,CAAC;AAAA,MAC1D;AAAA,IACF;AACA,YAAQ;AAGR,UAAM,sBAAsB,MAAY;AACtC,WAAK,SAAS,CAAC,GAAG,cAAc,OAAO,GAAG;AACxC,gBAAQ;AAAA,MACV;AAAA,IACF;AACA,WAAO;AAAA,MACL,IAAI,WAA2B;AAC7B,4BAAoB;AACpB,eAAO;AAAA,MACT;AAAA,MACA,SAAS,MAAM;AACb,4BAAoB;AACpB,aAAK,sBAAsB,SAAS;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,SAAe;AACb,SAAK,QAAQ,OAAO;AAAA,EACtB;AACF;;;ACwXA,IAAI,SAA8B;AAClC,IAAI,cAAoC;AAaxC,eAAsB,KAAK,SAOT;AAChB,MAAI,QAAQ;AACV;AAAA,EACF;AAEA,MAAI,aAAa;AACf,WAAO;AAAA,EACT;AAEA,iBAAe,YAAY;AACzB,QAAI;AACF,YAAM,eAAe,SAAS,kBAAkB,MAAM,OAAO,aAAa,GAAG;AAC7E,eAAS,MAAM,aAAa,OAAO;AACnC,sBAAgB,MAAM;AAAA,IACxB,SAAS,OAAO;AACd,oBAAc;AACd,YAAM;AAAA,IACR;AAAA,EACF,GAAG;AAEH,SAAO;AACT;AAKO,SAAS,gBAAyB;AACvC,SAAO,WAAW;AACpB;;;ACvpBO,SAAS,gBACd,cACA,YACA,gBACmB;AACnB,SAAO,aAAa,IAAI,CAAC,YAAY;AACnC,UAAM,QAAQ,WAAW,IAAI,OAAO;AACpC,UAAM,cAAc,eAAe,IAAI,OAAO;AAC9C,WAAO;AAAA,MACL;AAAA,MACA,GAAI,SAAS,MAAM,SAAS,IAAI,EAAE,OAAO,MAAM,IAAI,CAAC,UAAU,EAAE,GAAG,KAAK,EAAE,EAAE,IAAI,CAAC;AAAA,MACjF,GAAI,gBAAgB,SAAY,EAAE,YAAY,IAAI,CAAC;AAAA,IACrD;AAAA,EACF,CAAC;AACH;AAMO,SAAS,eACd,UACA,eACA,eACA,uBAC8B;AAC9B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,eAAe,EAAE,GAAG,cAAc;AAAA,IAClC,eAAe,cAAc,IAAI,CAAC,aAAa,EAAE,GAAG,QAAQ,EAAE;AAAA,IAC9D,uBAAuB,sBAAsB,IAAI,CAAC,aAAa,EAAE,GAAG,QAAQ,EAAE;AAAA,EAChF;AACF;AAMO,SAAS,gBAAgB,QAAiC;AAC/D,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO;AAAA,EACT;AACA,QAAM,SAAS,OAAO,SAAS,QAAQ,EAAE;AACzC,SAAO,OAAO,SAAS,MAAM,IAAI,SAAS;AAC5C;AAOO,SAAS,eACd,YACA,QACA,OACQ;AACR,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,SAAS,WAAW,KAAK,CAAC,SAAS,KAAK,SAAS,KAAK;AAC5D,MAAI,QAAQ;AACV,WAAO,OAAO;AAAA,EAChB;AACA,SAAO,gBAAgB,SAAS,MAAM;AACxC;AAGO,SAAS,UAAU,OAAkD;AAC1E,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,SAAO,UAAU,gBAAgB,IAAI;AACvC;;;AC7EO,SAAS,cACd,KACA,QACA,OACA,KACA,OACA,QAA2C,UACrC;AACN,QAAM,UAAU,IAAI,eAAe,QAAQ,KAAK;AAChD,QAAM,OAAO,IAAI,gBAAgB,IAAI,OAAO,KAAK,CAAC;AAClD,OAAK,KAAK,EAAE,KAAK,OAAO,aAAa,UAAU,KAAK,EAAE,CAAC;AACvD,OAAK,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG;AACjC,MAAI,gBAAgB,IAAI,SAAS,IAAI;AACrC,MAAI,cAAc,kBAAkB,SAAS,IAAI;AAKjD,MAAI,SAAS,EAAE,MAAM,kBAAkB,SAAS,QAAQ,KAAK,CAAC;AAChE;AAEO,SAAS,mBACd,KACA,QACA,KACA,OACA,QAA2C,UACrC;AACN,gBAAc,KAAK,IAAI,QAAQ,KAAK,OAAO,KAAK;AAClD;AAcO,SAAS,kBACd,KACA,SACA,QACM;AACN,QAAM,SAAS,OAAO,IAAI,CAAC,WAAW,EAAE,GAAG,MAAM,EAAE,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG;AACjF,MAAI,OAAO,WAAW,GAAG;AACvB,QAAI,gBAAgB,OAAO,OAAO;AAAA,EACpC,OAAO;AACL,QAAI,gBAAgB,IAAI,SAAS,MAAM;AAAA,EACzC;AACA,MAAI,cAAc,kBAAkB,SAAS,MAAM;AACnD,MAAI,SAAS,EAAE,MAAM,kBAAkB,SAAS,QAAQ,OAAO,CAAC;AAClE;;;ACrDO,SAAS,mBACd,SACA,iBAC8C;AAC9C,SAAO;AAAA,IACL,cAAc,KAAK,MAAM,QAAQ,YAAY;AAAA,IAC7C,UAAU,KAAK,MAAM,QAAQ,YAAY,eAAe;AAAA,IACxD,QAAQ,QAAQ,UAAU;AAAA,IAC1B,qBAAqB,KAAK,MAAM,QAAQ,uBAAuB,CAAC;AAAA,IAChE,cAAc;AAAA,MACZ,SAAS,QAAQ,QAAQ,cAAc,OAAO;AAAA,MAC9C,MAAM,QAAQ,cAAc,QAAQ;AAAA,IACtC;AAAA,EACF;AACF;AAwBO,SAAS,qBAAqB,KAA0D;AAC7F,SAAO;AAAA,IACL,MAAM,CAAC,aAAa,OAAO;AACzB,YAAM,KAAK,IAAI,aAAa,KAAK,UAAU;AAC3C,UAAI,IAAI;AACN,YAAI,oBAAoB,IAAI;AAAA,MAC9B;AACA,aAAO;AAAA,IACT;AAAA,IACA,MAAM,CAAC,aAAa,OAAO;AACzB,YAAM,KAAK,IAAI,aAAa,KAAK,UAAU;AAC3C,UAAI,IAAI;AACN,YAAI,oBAAoB,KAAK;AAC7B,YAAI,2BAA2B;AAAA,MACjC;AACA,aAAO;AAAA,IACT;AAAA,IACA,SAAS,CAAC,KAAK,aAAa,OAAO;AACjC,UAAI,cAAc,QAAQ,KAAK,UAAU;AACzC,aAAO,IAAI,aAAa,QAAQ,KAAK,UAAU;AAAA,IACjD;AAAA,IACA,aAAa,CAAC,SAAS,aAAa,OAAO;AACzC,YAAM,iBAAiB,KAAK,IAAI,GAAG,KAAK,MAAM,UAAU,IAAI,UAAU,CAAC;AACvE,UAAI,cAAc,WAAW,gBAAgB,UAAU;AACvD,aAAO,IAAI,aAAa,WAAW,gBAAgB,UAAU;AAAA,IAC/D;AAAA,IACA,UAAU,CAAC,QAAQ,IAAI,SAAS,GAAG;AAAA,IACnC,kBAAkB,CAAC,aAAa,IAAI,iBAAiB,QAAQ;AAAA,IAC7D,SAAS,CAAC,UAAU,QAAQ,UAAU,SAAS,IAAI,QAAQ,UAAU,QAAQ,OAAO;AAAA,EACtF;AACF;AAaO,SAAS,oBACd,UACA,OAC+C;AAC/C,QAAM,UAAU,MAAM,IAAI,CAAC,SAAU,OAAO,SAAS,WAAW,EAAE,SAAS,KAAK,IAAI,IAAK;AACzF,QAAM,MAAgB,CAAC;AACvB,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,OAAO,UAAU,MAAM,OAAO,KAAK,MAAM,WAAW,GAAG;AAC1D,YAAM,IAAI,MAAM,oCAAoC,OAAO,MAAM,OAAO,CAAC,EAAE;AAAA,IAC7E;AACA,QAAI,KAAK,MAAM,OAAO;AAAA,EACxB;AACA,MAAI,IAAI,IAAI,GAAG,EAAE,SAAS,IAAI,QAAQ;AACpC,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACzD;AACA,WAAS,QAAQ,GAAG,QAAQ,SAAS,QAAQ,SAAS;AACpD,QAAI,IAAI,KAAK,MAAM,SAAS,KAAK,GAAG;AAClC,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,SAAS,IAAI;AACxB;AAWO,SAAS,iBACd,SACA,cACoD;AACpD,QAAM,WAA2B,CAAC;AAClC,QAAM,OAAO,oBAAI,IAAY;AAC7B,MAAI,UAAU;AACd,aAAWC,WAAU,SAAS;AAC5B,QAAI,CAAC,OAAO,SAASA,QAAO,GAAG,GAAG;AAChC,YAAM,IAAI,MAAM,uBAAuB,OAAOA,QAAO,GAAG,CAAC,EAAE;AAAA,IAC7D;AACA,QAAIA,QAAO,OAAO,QAAW;AAC3B,UAAI,CAAC,OAAO,UAAUA,QAAO,EAAE,KAAKA,QAAO,MAAM,GAAG;AAClD,cAAM,IAAI,MAAM,sBAAsB,OAAOA,QAAO,EAAE,CAAC,EAAE;AAAA,MAC3D;AACA,UAAI,KAAK,IAAIA,QAAO,EAAE,GAAG;AACvB,cAAM,IAAI,MAAM,wBAAwBA,QAAO,EAAE,EAAE;AAAA,MACrD;AAAA,IACF;AACA,UAAM,KAAKA,QAAO,MAAM;AACxB,SAAK,IAAI,EAAE;AACX,QAAI,MAAM,SAAS;AACjB,gBAAU,KAAK;AAAA,IACjB;AACA,aAAS,KAAK,EAAE,IAAI,KAAKA,QAAO,KAAK,MAAMA,QAAO,QAAQ,GAAG,CAAC;AAAA,EAChE;AACA,SAAO,EAAE,UAAU,cAAc,QAAQ;AAC3C;;;AC/JA,IAAM,2BAA2B;AAC1B,IAAM,8BAA8B;AACpC,IAAM,yBAAyB;AAE/B,SAAS,sBAAsB,WAAmB,WAA2B;AAClF,SAAO,4BAA6B,YAAY,QAAS,IAAM,YAAY;AAC7E;AAEO,SAAS,qBAAqB,UAAkB,WAA2B;AAChF,SAAO,4BAA8B,MAAO,WAAY,QAAS,IAAM,YAAY;AACrF;AAEO,SAAS,wBAAwB,WAA2B;AACjE,SAAO,2BAA4B,OAAQ,IAAM,YAAY;AAC/D;AAyBO,IAAM,gCAAgC;AAQtC,IAAM,kCAAkC;AACxC,IAAM,mCAAmC;AAIzC,IAAM,gCAAgC;AACtC,IAAM,yCAAyC;AAGtD,IAAM,yBAAyB;AAGxB,SAAS,cAAc,OAAuB;AACnD,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC;AACvC,SAAO,IAAI;AACb;AAGO,SAAS,cAAc,OAAuB;AACnD,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC;AACvC,SAAO,KAAK,MAAM,IAAI,sBAAsB;AAC9C;AAGO,SAAS,YAAY,IAAY,IAAoB;AAC1D,SAAO,KAAK,yBAAyB;AACvC;AACO,IAAM,iCAAiC;AACvC,IAAM,qCAAqC;AAC3C,IAAM,uCAAuC;AAE7C,IAAK,0BAAL,kBAAKC,6BAAL;AACL,EAAAA,kDAAA,cAAW,KAAX;AACA,EAAAA,kDAAA,sBAAmB,KAAnB;AACA,EAAAA,kDAAA,mBAAgB,KAAhB;AACA,EAAAA,kDAAA,mBAAgB,KAAhB;AACA,EAAAA,kDAAA,yBAAsB,KAAtB;AACA,EAAAA,kDAAA,sBAAmB,KAAnB;AACA,EAAAA,kDAAA,iBAAc,KAAd;AACA,EAAAA,kDAAA,aAAU,KAAV;AACA,EAAAA,kDAAA,eAAY,KAAZ;AACA,EAAAA,kDAAA,oBAAiB,KAAjB;AACA,EAAAA,kDAAA,iBAAc,MAAd;AACA,EAAAA,kDAAA,aAAU,MAAV;AACA,EAAAA,kDAAA,gBAAa,MAAb;AACA,EAAAA,kDAAA,eAAY,MAAZ;AACA,EAAAA,kDAAA,WAAQ,MAAR;AACA,EAAAA,kDAAA,kBAAe,MAAf;AACA,EAAAA,kDAAA,eAAY,MAAZ;AACA,EAAAA,kDAAA,gBAAa,MAAb;AAlBU,SAAAA;AAAA,GAAA;AAqBL,IAAK,4BAAL,kBAAKC,+BAAL;AACL,EAAAA,sDAAA,kBAAe,KAAf;AACA,EAAAA,sDAAA,WAAQ,KAAR;AAFU,SAAAA;AAAA,GAAA;AAKL,IAAK,6BAAL,kBAAKC,gCAAL;AACL,EAAAA,wDAAA,UAAO,KAAP;AACA,EAAAA,wDAAA,0BAAuB,KAAvB;AACA,EAAAA,wDAAA,4BAAyB,KAAzB;AACA,EAAAA,wDAAA,sBAAmB,KAAnB;AACA,EAAAA,wDAAA,uBAAoB,KAApB;AACA,EAAAA,wDAAA,qBAAkB,KAAlB;AACA,EAAAA,wDAAA,sBAAmB,KAAnB;AACA,EAAAA,wDAAA,mBAAgB,KAAhB;AACA,EAAAA,wDAAA,8BAA2B,KAA3B;AACA,EAAAA,wDAAA,iBAAc,KAAd;AACA,EAAAA,wDAAA,yBAAsB,MAAtB;AACA,EAAAA,wDAAA,kCAA+B,MAA/B;AACA,EAAAA,wDAAA,0BAAuB,MAAvB;AACA,EAAAA,wDAAA,+BAA4B,MAA5B;AACA,EAAAA,wDAAA,4BAAyB,MAAzB;AACA,EAAAA,wDAAA,sBAAmB,MAAnB;AACA,EAAAA,wDAAA,8BAA2B,MAA3B;AAjBU,SAAAA;AAAA,GAAA;AAwIL,SAAS,KAAK,OAAuB;AAC1C,SAAO,QAAQ,IAAI,KAAK,KAAK,MAAM,KAAK,IAAI,OAAO;AACrD;AAEO,SAAS,SAAS,OAAkD;AACzE,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEO,SAAS,gCAAgC,UAA0B;AACxE,QAAM,kBAAkB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,CAAC;AACxD,SACE,gCAAgC,WAAW,oBAC3C,kBAAkB,kCAAkC,aAAa;AAErE;AAEO,SAAS,4BAA4B,WAAW,KAA4B;AACjF,QAAM,kBAAkB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,CAAC;AACxD,QAAM,eAAe,IAAI,kBAAkB,gCAAgC,eAAe,CAAC;AAC3F,QAAM,OAAO,0BAA0B,cAAc,eAAe;AACpE,UAAQ,MAAM,KAAK,QAAQ,GAAG,CAAC;AAC/B,UAAQ,MAAM,KAAK,QAAQ,GAAG,eAAe;AAC7C,UAAQ,MAAM,KAAK,QAAQ,GAAG,+BAA+B;AAC7D,UAAQ,MAAM,KAAK,QAAQ,GAAG,CAAC;AAC/B,SAAO,EAAE,cAAc,QAAQ,KAAK,QAAQ,SAAS,KAAK,SAAS,UAAU,KAAK,SAAS;AAC7F;AAEO,SAAS,0BACd,MACA,YAAY,GACe;AAC3B,QAAM,aAAa,QAAQ,KAAK,KAAK,QAAQ,CAAC;AAC9C,QAAM,eAAe,QAAQ,KAAK,KAAK,QAAQ,CAAC,KAAK;AACrD,QAAM,gBAAgB,KAAK,IAAI,GAAG,KAAK,IAAI,WAAW,UAAU,CAAC;AACjE,QAAM,gBAAgB,KAAK,IAAI,eAAe,aAAa,KAAK,QAAQ;AACxE,QAAM,SAAuC,CAAC;AAC9C,WAAS,QAAQ,eAAe,QAAQ,YAAY,SAAS;AAC3D,UAAM,SAAU,QAAQ,KAAK,WAAY;AACzC,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,OAAO,YAAY,KAAK,QAAQ,MAAM,GAAG,KAAK,QAAQ,SAAS,CAAC,CAAC;AAAA,MACjE,UAAU,KAAK,QAAQ,SAAS,CAAC;AAAA,MACjC,SAAS,KAAK,QAAQ,SAAS,CAAC;AAAA,MAChC,SAAS,KAAK,QAAQ,SAAS,CAAC;AAAA,MAChC,QAAQ,KAAK,QAAQ,SAAS,CAAC;AAAA,MAC/B,QAAQ,KAAK,QAAQ,SAAS,CAAC;AAAA,MAC/B,aAAa,KAAK,QAAQ,SAAS,CAAC;AAAA,MACpC,aAAa,KAAK,QAAQ,SAAS,CAAC;AAAA,MACpC,aAAa,KAAK,QAAQ,SAAS,CAAC;AAAA,MACpC,eAAe,KAAK,QAAQ,SAAS,EAAE;AAAA,MACvC,eAAe,KAAK,QAAQ,SAAS,EAAE;AAAA,MACvC,gBAAgB,KAAK,QAAQ,SAAS,EAAE;AAAA,MACxC,iBAAiB,KAAK,QAAQ,SAAS,EAAE;AAAA,IAC3C,CAAC;AAAA,EACH;AACA,SAAO,EAAE,eAAe,YAAY,OAAO;AAC7C;AAEO,SAAS,mCAAmC,UAAkB,QAAQ,IAAY;AACvF,QAAM,kBAAkB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,CAAC;AACxD,QAAM,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC;AAGlD,SACE,mCAAmC,WAAW,oBAC9C,mBAAmB,IAAI,gBAAgB,aAAa;AAExD;AAEO,SAAS,+BACd,WAAW,KACX,QAAQ,IACkB;AAC1B,QAAM,kBAAkB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,CAAC;AACxD,QAAM,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC;AAClD,QAAM,eAAe,IAAI;AAAA,IACvB,mCAAmC,iBAAiB,YAAY;AAAA,EAClE;AACA,QAAM,OAAO,6BAA6B,cAAc,iBAAiB,YAAY;AACrF,UAAQ,MAAM,KAAK,QAAQ,GAAG,CAAC;AAC/B,UAAQ,MAAM,KAAK,QAAQ,GAAG,eAAe;AAC7C,UAAQ,MAAM,KAAK,QAAQ,GAAG,KAAK,YAAY;AAC/C,UAAQ,MAAM,KAAK,QAAQ,GAAG,YAAY;AAC1C,UAAQ,MAAM,KAAK,QAAQ,GAAG,CAAC;AAC/B,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,KAAK;AAAA,IACb,SAAS,KAAK;AAAA,IACd,UAAU,KAAK;AAAA,IACf,OAAO,KAAK;AAAA,EACd;AACF;AAEO,SAAS,6BACd,MACA,YAAY,GACkB;AAC9B,QAAM,aAAa,QAAQ,KAAK,KAAK,QAAQ,CAAC;AAC9C,QAAM,eAAe,QAAQ,KAAK,KAAK,QAAQ,CAAC,KAAK,IAAI,KAAK;AAC9D,QAAM,QAAQ,QAAQ,KAAK,KAAK,QAAQ,CAAC,KAAK,KAAK;AACnD,QAAM,gBAAgB,KAAK,IAAI,GAAG,KAAK,IAAI,WAAW,UAAU,CAAC;AACjE,QAAM,gBAAgB,KAAK,IAAI,eAAe,aAAa,KAAK,QAAQ;AACxE,QAAM,UAA2C,CAAC;AAClD,WAAS,QAAQ,eAAe,QAAQ,YAAY,SAAS;AAC3D,UAAM,SAAU,QAAQ,KAAK,WAAY;AACzC,UAAM,SAAS,IAAI,aAAa,KAAK;AACrC,WAAO,IAAI,KAAK,QAAQ,SAAS,SAAS,GAAG,SAAS,IAAI,KAAK,CAAC;AAChE,YAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,OAAO,YAAY,KAAK,QAAQ,MAAM,GAAG,KAAK,QAAQ,SAAS,CAAC,CAAC;AAAA,MACjE,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AACA,SAAO,EAAE,eAAe,YAAY,QAAQ;AAC9C;AAEO,SAAS,4BAA4B,OAAe,WAA2B;AACpF,SAAO,yCAAyC,QAAQ,IAAI;AAC9D;AAEO,SAAS,gCACd,UACA,QAAQ,IACR,YAAY,IACJ;AACR,QAAM,kBAAkB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,CAAC;AACxD,QAAM,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC;AAClD,QAAM,gBAAgB,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,CAAC;AACvD,SACE,gCAAgC,WAAW,oBAC3C,kBACE,4BAA4B,cAAc,aAAa,IACvD,aAAa;AAEnB;AAEO,SAAS,4BACd,WAAW,IACX,QAAQ,IACR,YAAY,IACW;AACvB,QAAM,kBAAkB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,CAAC;AACxD,QAAM,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC;AAClD,QAAM,gBAAgB,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,CAAC;AACvD,QAAM,eAAe,IAAI;AAAA,IACvB,gCAAgC,iBAAiB,cAAc,aAAa;AAAA,EAC9E;AACA,QAAM,OAAO;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,UAAQ,MAAM,KAAK,QAAQ,GAAG,CAAC;AAC/B,UAAQ,MAAM,KAAK,QAAQ,GAAG,eAAe;AAC7C,UAAQ,MAAM,KAAK,QAAQ,GAAG,KAAK,YAAY;AAC/C,UAAQ,MAAM,KAAK,QAAQ,GAAG,YAAY;AAC1C,UAAQ,MAAM,KAAK,QAAQ,GAAG,aAAa;AAC3C,UAAQ,MAAM,KAAK,QAAQ,GAAG,CAAC;AAC/B,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,KAAK;AAAA,IACb,SAAS,KAAK;AAAA,IACd,UAAU,KAAK;AAAA,IACf,OAAO,KAAK;AAAA,IACZ,WAAW,KAAK;AAAA,EAClB;AACF;AAEO,SAAS,0BACd,MACA,YAAY,GACe;AAC3B,QAAM,aAAa,QAAQ,KAAK,KAAK,QAAQ,CAAC;AAC9C,QAAM,QAAQ,QAAQ,KAAK,KAAK,QAAQ,CAAC,KAAK,KAAK;AACnD,QAAM,YAAY,QAAQ,KAAK,KAAK,QAAQ,CAAC;AAC7C,QAAM,eACJ,QAAQ,KAAK,KAAK,QAAQ,CAAC,KAAK,4BAA4B,OAAO,SAAS;AAC9E,QAAM,gBAAgB,KAAK,IAAI,GAAG,KAAK,IAAI,WAAW,UAAU,CAAC;AACjE,QAAM,gBAAgB,KAAK,IAAI,eAAe,aAAa,KAAK,QAAQ;AACxE,QAAM,SAAuC,CAAC;AAC9C,WAAS,QAAQ,eAAe,QAAQ,YAAY,SAAS;AAC3D,UAAM,SAAU,QAAQ,KAAK,WAAY;AACzC,UAAM,YAAY,KAAK,IAAI,OAAO,KAAK,IAAI,GAAG,KAAK,QAAQ,SAAS,CAAC,CAAC,CAAC;AACvE,UAAM,aAAa,KAAK,IAAI,WAAW,KAAK,IAAI,GAAG,KAAK,QAAQ,SAAS,CAAC,CAAC,CAAC;AAC5E,UAAM,YAAY,IAAI,aAAa,SAAS;AAC5C,cAAU;AAAA,MACR,KAAK,QAAQ;AAAA,QACX,SAAS;AAAA,QACT,SAAS,yCAAyC;AAAA,MACpD;AAAA,IACF;AACA,UAAM,aAAa,SAAS,yCAAyC;AACrE,UAAM,aAAa,IAAI,aAAa,aAAa,CAAC;AAClD,eAAW,IAAI,KAAK,QAAQ,SAAS,YAAY,aAAa,aAAa,CAAC,CAAC;AAC7E,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,OAAO,YAAY,KAAK,QAAQ,MAAM,GAAG,KAAK,QAAQ,SAAS,CAAC,CAAC;AAAA,MACjE,UAAU,KAAK,QAAQ,SAAS,CAAC;AAAA,MACjC,OAAO;AAAA,MACP,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AACA,SAAO,EAAE,eAAe,YAAY,OAAO;AAC7C;AAEO,SAAS,0BACd,cACA,kBACA,eACA,mBACuB;AACvB,QAAM,cAAc,gCAAgC,WAAW;AAC/D,QAAM,SAAS,IAAI,WAAW,cAAc,GAAG,6BAA6B;AAC5E,QAAM,mBAAmB,QAAQ,KAAK,QAAQ,CAAC;AAC/C,QAAM,gBAAgB,QAAQ,KAAK,QAAQ,CAAC;AAC5C,QAAM,oBAAoB,QAAQ,KAAK,QAAQ,CAAC;AAChD,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,MAAM,oBAAoB,oBAAoB,CAAC,CAAC;AAClF,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,iBAAiB,iBAAiB,EAAE,CAAC;AAC1E,QAAM,YAAY,KAAK,IAAI,GAAG,KAAK,MAAM,sBAAsB,qBAAqB,GAAG,CAAC;AACxF,QAAM,eAAe,4BAA4B,OAAO,SAAS;AACjE,QAAM,WAAW,gCAAgC,UAAU,OAAO,SAAS;AAC3E,MAAI,aAAa,aAAa,UAAU;AACtC,UAAM,IAAI,MAAM,iEAAiE;AAAA,EACnF;AACA,UAAQ,MAAM,QAAQ,GAAG,QAAQ;AACjC,UAAQ,MAAM,QAAQ,GAAG,YAAY;AACrC,UAAQ,MAAM,QAAQ,GAAG,KAAK;AAC9B,UAAQ,MAAM,QAAQ,GAAG,SAAS;AAClC,SAAO;AAAA,IACL;AAAA,IACA,SAAS,IAAI,aAAa,cAAc,aAAa,WAAW,YAAY;AAAA,IAC5E;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,wCAAwC,UAA0B;AAChF,QAAM,kBAAkB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,CAAC;AACxD,SACE,iCAAiC,WAAW,oBAC5C,kBAAkB;AAEtB;AAEO,SAAS,0CAA0C,UAA0B;AAClF,QAAM,kBAAkB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,CAAC;AACxD,SACE,iCAAiC,WAAW,oBAC5C,kBAAkB;AAEtB;AAEO,SAAS,oCAAoC,WAAW,KAAoC;AACjG,QAAM,kBAAkB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,CAAC;AACxD,QAAM,eAAe,IAAI;AAAA,IACvB,wCAAwC,eAAe;AAAA,EACzD;AACA,QAAM,OAAO;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,SAAO,EAAE,cAAc,QAAQ,KAAK,QAAQ,MAAM,KAAK,MAAM,UAAU,KAAK,SAAS;AACvF;AAEO,SAAS,sCACd,WAAW,KACsB;AACjC,QAAM,kBAAkB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,CAAC;AACxD,QAAM,eAAe,IAAI;AAAA,IACvB,0CAA0C,eAAe;AAAA,EAC3D;AACA,QAAM,OAAO;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,SAAO,EAAE,cAAc,QAAQ,KAAK,QAAQ,MAAM,KAAK,MAAM,UAAU,KAAK,SAAS;AACvF;AAEO,SAAS,kCACd,MACA,SACS;AACT,QAAM,aAAa,QAAQ,KAAK,KAAK,QAAQ,CAAC;AAC9C,QAAM,YAAY,QAAQ,KAAK,KAAK,QAAQ,CAAC;AAC7C,MAAI,aAAa,aAAa,KAAK,UAAU;AAC3C,YAAQ,IAAI,KAAK,QAAQ,GAAG,CAAC;AAC7B,WAAO;AAAA,EACT;AACA;AAAA,IACE,KAAK;AAAA,IACL,aAAa,YAAY,KAAK,UAAU,kCAAkC;AAAA,IAC1E;AAAA,EACF;AACA,UAAQ,MAAM,KAAK,QAAQ,GAAG,aAAa,CAAC;AAC5C,SAAO;AACT;AAEO,SAAS,iCACd,MACkC;AAClC,QAAM,YAAY,QAAQ,KAAK,KAAK,QAAQ,CAAC;AAC7C,QAAM,aAAa,QAAQ,KAAK,KAAK,QAAQ,CAAC;AAC9C,MAAI,aAAa,YAAY;AAC3B,WAAO;AAAA,EACT;AACA,QAAM,UAAU;AAAA,IACd,KAAK;AAAA,IACL,aAAa,WAAW,KAAK,UAAU,kCAAkC;AAAA,EAC3E;AACA,UAAQ,MAAM,KAAK,QAAQ,GAAG,YAAY,CAAC;AAC3C,SAAO;AACT;AAEO,SAAS,qCACd,MACA,WACM;AACN,QAAM,aAAa,QAAQ,KAAK,KAAK,QAAQ,CAAC;AAC9C;AAAA,IACE,KAAK;AAAA,IACL,aAAa,YAAY,KAAK,UAAU,oCAAoC;AAAA,IAC5E;AAAA,EACF;AACA,UAAQ,MAAM,KAAK,QAAQ,GAAG,aAAa,CAAC;AAC5C,MAAI,aAAa,IAAI,KAAK,UAAU;AAClC,YAAQ,MAAM,KAAK,QAAQ,GAAG,aAAa,IAAI,KAAK,QAAQ;AAAA,EAC9D;AACF;AAEO,SAAS,oCACd,MACA,YAAY,GACyB;AACrC,QAAM,aAAa,QAAQ,KAAK,KAAK,QAAQ,CAAC;AAC9C,QAAM,gBAAgB,KAAK,IAAI,GAAG,KAAK,IAAI,WAAW,UAAU,CAAC;AACjE,QAAM,gBAAgB,KAAK,IAAI,eAAe,aAAa,KAAK,QAAQ;AACxE,QAAM,YAA2C,CAAC;AAClD,WAAS,QAAQ,eAAe,QAAQ,YAAY,SAAS;AAC3D,cAAU;AAAA,MACR;AAAA,QACE,KAAK;AAAA,QACL,aAAa,OAAO,KAAK,UAAU,oCAAoC;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,eAAe,YAAY,UAAU;AAChD;AAEO,SAAS,0BACd,cACA,kBACuB;AACvB,QAAM,cAAc,gCAAgC,WAAW;AAC/D,QAAM,SAAS,IAAI,WAAW,cAAc,GAAG,6BAA6B;AAC5E,QAAM,mBAAmB,QAAQ,KAAK,QAAQ,CAAC;AAC/C,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,MAAM,oBAAoB,oBAAoB,CAAC,CAAC;AAClF,QAAM,WAAW,gCAAgC,QAAQ;AACzD,MAAI,aAAa,aAAa,UAAU;AACtC,UAAM,IAAI,MAAM,iEAAiE;AAAA,EACnF;AACA,UAAQ,MAAM,QAAQ,GAAG,QAAQ;AACjC,UAAQ,MAAM,QAAQ,GAAG,+BAA+B;AACxD,SAAO;AAAA,IACL;AAAA,IACA,SAAS,IAAI;AAAA,MACX;AAAA,MACA;AAAA,MACA,WAAW;AAAA,IACb;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,6BACd,cACA,kBACA,eAC0B;AAC1B,QAAM,cAAc,mCAAmC,WAAW;AAClE,QAAM,SAAS,IAAI,WAAW,cAAc,GAAG,gCAAgC;AAC/E,QAAM,mBAAmB,QAAQ,KAAK,QAAQ,CAAC;AAC/C,QAAM,gBAAgB,QAAQ,KAAK,QAAQ,CAAC;AAC5C,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,MAAM,oBAAoB,oBAAoB,CAAC,CAAC;AAClF,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,iBAAiB,iBAAiB,EAAE,CAAC;AAC1E,QAAM,eAAe,IAAI;AACzB,QAAM,WAAW,mCAAmC,UAAU,KAAK;AACnE,MAAI,aAAa,aAAa,UAAU;AACtC,UAAM,IAAI,MAAM,oEAAoE;AAAA,EACtF;AACA,UAAQ,MAAM,QAAQ,GAAG,QAAQ;AACjC,UAAQ,MAAM,QAAQ,GAAG,YAAY;AACrC,UAAQ,MAAM,QAAQ,GAAG,KAAK;AAC9B,SAAO;AAAA,IACL;AAAA,IACA,SAAS,IAAI,aAAa,cAAc,aAAa,WAAW,YAAY;AAAA,IAC5E;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,2BACd,cACA,aACA,kBAC0D;AAC1D,QAAM,cAAc,iCAAiC,WAAW;AAChE,QAAM,SAAS,IAAI,WAAW,cAAc,GAAG,8BAA8B;AAC7E,QAAM,mBAAmB,QAAQ,KAAK,QAAQ,CAAC;AAC/C,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,MAAM,oBAAoB,oBAAoB,CAAC,CAAC;AAClF,QAAM,WAAW,cAAc,WAAW;AAC1C,MAAI,aAAa,aAAa,UAAU;AACtC,UAAM,IAAI,MAAM,wEAAwE;AAAA,EAC1F;AACA,UAAQ,MAAM,QAAQ,GAAG,QAAQ;AACjC,UAAQ,MAAM,QAAQ,GAAG,WAAW;AACpC,SAAO;AAAA,IACL;AAAA,IACA,MAAM,IAAI,SAAS,cAAc,aAAa,WAAW,WAAW;AAAA,IACpE;AAAA,EACF;AACF;AAEA,SAAS,aAAa,OAAe,UAAkB,aAA6B;AAClF,SAAQ,QAAQ,WAAY;AAC9B;AAEO,SAAS,WAAW,OAAoC,UAA0B;AACvF,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,OAAO,KAAK,MAAM,KAAK,CAAC;AAAA,EACjC;AACA,SAAO;AACT;AAEA,SAAS,yBACP,MACA,QACA,SACM;AACN,OAAK,UAAU,QAAQ,QAAQ,MAAM,IAAI;AACzC,OAAK,UAAU,SAAS,GAAG,QAAQ,YAAY,GAAG,IAAI;AACtD,OAAK,YAAY,SAAS,GAAG,WAAW,QAAQ,YAAY,CAAC,EAAE,GAAG,IAAI;AAItE,OAAK,WAAW,SAAS,IAAI,QAAQ,YAAY,GAAG,IAAI;AACxD,OAAK,YAAY,SAAS,IAAI,WAAW,QAAQ,QAAQ,EAAE,GAAG,IAAI;AACpE;AAEA,SAAS,wBAAwB,MAAgB,QAA2C;AAC1F,SAAO;AAAA,IACL,MAAM,KAAK,UAAU,QAAQ,IAAI;AAAA,IACjC,UAAU,KAAK,UAAU,SAAS,GAAG,IAAI;AAAA,IACzC,YAAY,OAAO,KAAK,YAAY,SAAS,GAAG,IAAI,CAAC;AAAA,IACrD,UAAU,KAAK,WAAW,SAAS,IAAI,IAAI;AAAA,IAC3C,QAAQ,OAAO,KAAK,YAAY,SAAS,IAAI,IAAI,CAAC;AAAA,EACpD;AACF;AAEA,SAAS,2BACP,MACA,QACA,WACM;AACN,OAAK,UAAU,QAAQ,UAAU,MAAM,IAAI;AAC3C,OAAK,UAAU,SAAS,GAAG,UAAU,OAAO,IAAI;AAChD,OAAK,YAAY,SAAS,GAAG,OAAO,KAAK,MAAM,UAAU,WAAW,CAAC,GAAG,IAAI;AAC5E,OAAK,YAAY,SAAS,IAAI,OAAO,KAAK,MAAM,UAAU,cAAc,CAAC,GAAG,IAAI;AAChF,OAAK,YAAY,SAAS,IAAI,OAAO,KAAK,MAAM,UAAU,qBAAqB,CAAC,GAAG,IAAI;AACvF,OAAK,SAAS,SAAS,IAAI,UAAU,uBAAuB,IAAI;AAChE,OAAK,UAAU,SAAS,IAAI,UAAU,OAAO,IAAI;AACjD,OAAK,YAAY,SAAS,IAAI,IAAI,IAAI;AACxC;AAEA,SAAS,0BAA0B,MAAgB,QAA6C;AAC9F,SAAO;AAAA,IACL,MAAM,KAAK,UAAU,QAAQ,IAAI;AAAA,IACjC,OAAO,KAAK,UAAU,SAAS,GAAG,IAAI;AAAA,IACtC,aAAa,OAAO,KAAK,YAAY,SAAS,GAAG,IAAI,CAAC;AAAA,IACtD,gBAAgB,OAAO,KAAK,YAAY,SAAS,IAAI,IAAI,CAAC;AAAA,IAC1D,uBAAuB,OAAO,KAAK,YAAY,SAAS,IAAI,IAAI,CAAC;AAAA,IACjE,uBAAuB,KAAK,SAAS,SAAS,IAAI,IAAI;AAAA,IACtD,OAAO,KAAK,UAAU,SAAS,IAAI,IAAI;AAAA,EACzC;AACF;AAEO,SAAS,oBAAoB,WAAyD;AAC3F,SAAO;AAAA,IACL,MAAM,UAAU;AAAA,IAChB,OAAO,UAAU;AAAA,IACjB,aAAa,UAAU;AAAA,IACvB,gBAAgB,UAAU;AAAA,IAC1B,uBAAuB,UAAU;AAAA,IACjC,uBAAuB,UAAU;AAAA,IACjC,OAAO,UAAU;AAAA,EACnB;AACF;AAEO,SAAS,gBAAgB,OAAyD;AACvF,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU,MAAM;AAAA,IAChB,OAAO,MAAM;AAAA,IACb,SAAS,MAAM;AAAA,IACf,SAAS,MAAM;AAAA,IACf,QAAQ,MAAM;AAAA,IACd,QAAQ,MAAM;AAAA,IACd,aAAa,MAAM;AAAA,IACnB,aAAa,MAAM;AAAA,IACnB,aAAa,MAAM;AAAA,IACnB,eAAe,MAAM;AAAA,IACrB,eAAe,MAAM;AAAA,IACrB,gBAAgB,MAAM;AAAA,IACtB,iBAAiB,MAAM;AAAA,EACzB;AACF;AAEO,SAAS,cAAc,OAAuB;AACnD,SAAO,QAAQ,QAAU,KAAK,KAAK,MAAM,KAAK,IAAI;AACpD;;;ACzuBO,SAAS,iBAAiB,KAA2B,SAA+B;AACzF,QAAM,SAAS,mBAAmB,SAAS,IAAI,mBAAmB;AAClE,MAAI,cAAc,iBAAiB,OAAO,UAAU,OAAO,YAAY;AACvE,MAAI,cAAc,iBAAiB,OAAO,MAAM;AAChD,MAAI,cAAc,uBAAuB,OAAO,mBAAmB;AACnE,MAAI,cAAc,gBAAgB,OAAO,aAAa,SAAS,OAAO,aAAa,IAAI;AACvF,MAAI,iBAAiB,MAAM;AAC3B,MAAI,SAAS,EAAE,MAAM,eAAe,GAAG,OAAO,CAAC;AACjD;AAEO,SAAS,UACd,KACA,SACA,SACS;AACT,MAAI,WAAW,CAAC,IAAI,iBAAiB,GAAG;AACtC,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD;AACA,MAAI,cAAc,WAAW,OAAO;AACpC,SAAO,IAAI,aAAa,YAAY;AAAA,IAClC;AAAA,IACA,UAAU,IAAI,gBAAgB,OAAO;AAAA,IACrC,YAAY;AAAA,IACZ,QAAQ,UAAU,IAAI;AAAA,EACxB,CAAC;AACH;AAEO,SAAS,MAAM,KAA2B,OAAe,QAAyB;AACvF,QAAM,WAAW,IAAI,cAAc,YAAY,KAAK;AACpD,QAAM,YAAY,IAAI,cAAc,YAAY,MAAM;AACtD,MAAI,cAAc,gBAAgB,UAAU,WAAW,IAAI;AAM3D,SAAO,IAAI,aAAa,YAAY;AAAA,IAClC;AAAA,IACA,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ,CAAC;AACH;AAEO,SAAS,cAAc,KAAyD;AACrF,SAAO,IAAI,aAAa,qBAAqB;AAC/C;AAEO,SAAS,cAAc,KAAoD;AAChF,SAAO,IAAI,aAAa,qBAAqB;AAC/C;AAEA,eAAsB,aAAa,KAA0C;AAC3E,MAAI,cAAc,aAAa;AAC/B,QAAM,IAAI,aAAa,oBAAoB;AAC7C;;;AC1DA,IAAM,+BAA+B;AACrC,IAAM,4BAA4B;AAE3B,SAAS,QACd,KACA,SACA,QACA,UACA,OAA2D,CAAC,GACpD;AACR,QAAM,KAAK,KAAK,MAAM,IAAI,eAAe;AACzC,QAAM,OAAmB;AAAA,IACvB,GAAG;AAAA,IACH;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,SAAS,IAAI,gBAAgB,OAAO;AAAA,EACtC;AACA,MAAI,gBAAgB,OAAO;AAC3B,MAAI,MAAM,IAAI,IAAI,IAAI;AACtB,iBAAe,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;AAC9B,SAAO;AACT;AAEO,SAAS,WAAW,KAAwB,QAAsB;AACvE,MAAI,MAAM,OAAO,MAAM;AACvB,iBAAe,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;AAClC;AAEO,SAAS,aACd,KACA,OACM;AACN,MAAI,UAAU,MAAM;AACpB,aAAW,QAAQ,OAAO;AACxB,UAAM,KAAK,KAAK,MAAM,IAAI,eAAe;AACzC,QAAI,UAAU,IAAI,IAAI,EAAE,GAAG,MAAM,IAAI,QAAQ,KAAK,OAAO,IAAI,CAAC,WAAW,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC;AAAA,EAC3F;AACA,gBAAc,GAAG;AACnB;AAEA,SAAS,eAAe,KAAwB,SAAuB,WAA2B;AAChG,QAAM,QAAQ,MAAM,KAAK,IAAI,MAAM,OAAO,CAAC;AAC3C,MAAI,cAAc,SAAS,KAAK;AAChC,QAAM,eAAe,oBAAI,IAAwB;AACjD,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,OAAO,QAAW;AACzB;AAAA,IACF;AACA,UAAM,gBAAgB,IAAI,cAAc,qBAAqB,KAAK,EAAE;AACpE,iBAAa;AAAA,MACX,KAAK;AAAA,MACL,kBAAkB,OACd,OACA;AAAA,QACE,GAAG;AAAA,QACH,UAAU;AAAA,QACV,mBAAmB;AAAA,QACnB,eAAe,cAAc,CAAC,GAAG,UAAU;AAAA,QAC3C,MAAM;AAAA,QACN,UAAU;AAAA,QACV,aAAa;AAAA,MACf;AAAA,IACN;AAAA,EACF;AACA,QAAM,gBAA8B,CAAC;AACrC,aAAW,QAAQ,SAAS;AAC1B,UAAM,WAAW,KAAK,OAAO,SAAY,OAAQ,aAAa,IAAI,KAAK,EAAE,KAAK;AAC9E,UAAM,WAAW,SAAS;AAC1B,QACE,SAAS,OAAO,UAChB,SAAS,aAAa,SACtB,CAAC,YACD,SAAS,WAAW,KACpB,SAAS,CAAC,EAAE,UAAU,8BACtB;AACA,oBAAc,KAAK,QAAQ;AAC3B;AAAA,IACF;AACA,UAAM,aAAa,SAAS,CAAC,EAAE;AAC/B,QAAI,SAAS;AAAA,MACX,MAAM;AAAA,MACN,QAAQ,SAAS;AAAA,MACjB,MAAM,EAAE,GAAG,UAAU,UAAU,QAAW,cAAc,OAAU;AAAA,MAClE,aAAa,SAAS;AAAA,MACtB;AAAA,MACA,YAAY;AAAA,IACd,CAAC;AACD,aACM,QAAQ,GAAG,YAAY,GAC3B,QAAQ,YACR,SAAS,2BAA2B,aACpC;AACA,YAAM,OAAO,SAAS;AAAA,QAAI,CAAC,YACzB,QAAQ,MAAM,OAAO,QAAQ,yBAAyB;AAAA,MACxD;AACA,UAAI;AAAA,QACF,EAAE,MAAM,gBAAgB,QAAQ,SAAS,IAAI,WAAW,UAAU,KAAK;AAAA,QACvE,KAAK,IAAI,CAAC,YAAY,QAAQ,MAAsB;AAAA,MACtD;AAAA,IACF;AACA,QAAI,SAAS,EAAE,MAAM,sBAAsB,QAAQ,SAAS,GAAG,CAAC;AAAA,EAClE;AACA,MAAI,SAAS;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAEA,SAAS,cAAc,KAA8B;AACnD,QAAM,QAAQ,MAAM,KAAK,IAAI,UAAU,OAAO,CAAC;AAC/C,MAAI,cAAc,aAAa,KAAK;AACpC,MAAI,SAAS,EAAE,MAAM,iBAAiB,MAAM,CAAC;AAC/C;;;ACnHO,SAAS,UAAU,KAA0B,KAAa,OAAO,IAAY;AAClF,QAAM,KAAK,IAAI,gBAAgB;AAC/B,MAAI,gBAAgB,KAAK,CAAC;AAC1B,MAAI,QAAQ,IAAI,IAAI,EAAE,IAAI,KAAK,KAAK,CAAC;AACrC,cAAY,GAAG;AACf,SAAO;AACT;AAaO,SAAS,WACd,KACA,SACgB;AAChB,QAAM,EAAE,UAAU,aAAa,IAAI,iBAAiB,SAAS,IAAI,gBAAgB,CAAC;AAClF,MAAI,gBAAgB,YAAY;AAChC,MAAI,QAAQ,MAAM;AAClB,aAAWC,WAAU,UAAU;AAC7B,QAAI,QAAQ,IAAIA,QAAO,IAAIA,OAAM;AAAA,EACnC;AACA,cAAY,GAAG;AACf,SAAO,SAAS,IAAI,CAACA,aAAY,EAAE,GAAGA,QAAO,EAAE;AACjD;AAEO,SAAS,YAAY,KAAkC;AAC5D,SAAO,IAAI,cAAc,YAAY;AACvC;AAEO,SAAS,cAAc,KAA0B,OAA6B;AACnF,SAAO,IAAI,cAAc,cAAc,KAAK;AAC9C;AAEO,SAAS,OAAO,KAA0B,UAAgC;AAC/E,SAAO,IAAI,cAAc,OAAO,QAAQ;AAC1C;AAEO,SAAS,WAAW,KAA0B,UAA2B;AAC9E,MAAI,cAAc,WAAW,QAAQ;AAIrC,SAAO,IAAI,YAAY;AAAA,IACrB;AAAA,IACA,UAAU;AAAA,IACV,YAAY;AAAA,EACd,CAAC;AACH;AAEO,SAAS,mBACd,KACA,eACA,aACS;AACT,MAAI,cAAc,mBAAmB,eAAe,WAAW;AAC/D,QAAM,QAAQ,IAAI,cAAc,OAAO,aAAa;AACpD,QAAM,MAAM,IAAI,cAAc,OAAO,WAAW;AAChD,SAAO,IAAI,QAAQ,MAAM,KAAK,IAAI,KAAK,IAAI;AAC7C;AAEA,SAAS,YAAY,KAAgC;AACnD,QAAM,UAAU,MAAM,KAAK,IAAI,QAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG;AAC7E,MAAI,cAAc,WAAW,OAAO;AACpC,MAAI,SAAS,EAAE,MAAM,eAAe,QAAQ,CAAC;AAC/C;;;AC1DO,SAAS,WAAW,KAA4C;AACrE,SAAO,gBAAgB,IAAI,cAAc,IAAI,YAAY,IAAI,cAAc;AAC7E;AAMO,SAAS,UAAU,KAA+B;AACvD,QAAM,QAAQ,WAAW,GAAG;AAC5B,QAAM,QAAQ,IAAI,MAAM,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,EAAE;AACjD,MAAI,cAAc,cAAc,KAAK;AACrC,MAAI,MAAM,SAAS,GAAG;AACpB,QAAI,cAAc,cAAc,KAAK;AAAA,EACvC;AACA,QAAM,cAAc,MAAM,KAAK,IAAI,gBAAgB,CAAC,CAAC,SAAS,SAAS,OAAO;AAAA,IAC5E;AAAA,IACA;AAAA,EACF,EAAE;AACF,QAAM,YAAY,MAAM,KAAK,IAAI,cAAc,CAAC,CAAC,OAAO,SAAS,OAAO;AAAA,IACtE;AAAA,IACA;AAAA,EACF,EAAE;AACF,MAAI,SAAS;AAAA,IACX,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB,MAAM,KAAK,IAAI,eAAe,OAAO,CAAC;AAAA,IACtD;AAAA,IACA,iBAAiB,IAAI,mBAAmB;AAAA,EAC1C,CAAC;AACH;AAaO,SAAS,cACd,KACA,OACM;AACN,QAAM,EAAE,SAAS,IAAI,IAAI,oBAAoB,IAAI,cAAc,KAAK;AACpE,aAAW,SAAS,SAAS;AAC3B,QAAI,MAAM,OAAO;AACf,UAAI,WAAW;AAAA,QACb,MAAM;AAAA,QACN,MAAM,MAAM,IAAI,CAAC,UAAU,EAAE,GAAG,KAAK,EAAE;AAAA,MACzC;AAAA,IACF;AACA,QAAI,MAAM,gBAAgB,QAAW;AACnC,UAAI,MAAM,gBAAgB,GAAG;AAC3B,YAAI,eAAe,OAAO,MAAM,OAAO;AAAA,MACzC,OAAO;AACL,YAAI,eAAe,IAAI,MAAM,SAAS,MAAM,WAAW;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AACA,MAAI,aAAa,OAAO,GAAG,IAAI,aAAa,QAAQ,GAAG,GAAG;AAC1D,MAAI,UAAU;AAChB;AAMO,SAAS,kBACd,KACA,QACA,OACM;AACN,QAAM,YAAY,IAAI,gBAAgB,MAAM;AAC5C,QAAM,UAAU,IAAI,aAAa,SAAS;AAC1C,MAAI,UAAU,GAAG;AACf,QAAI,eAAe,OAAO,OAAO;AAAA,EACnC,OAAO;AACL,QAAI,eAAe,IAAI,SAAS,KAAK;AAAA,EACvC;AACA,MAAI,UAAU;AAChB;AAOO,SAAS,iBACd,KACA,QACA,aACA,cACM;AACN,QAAM,YAAY,IAAI,gBAAgB,MAAM;AAC5C,QAAM,UAAU,IAAI,aAAa,SAAS;AAC1C,QAAM,MAAM,GAAG,OAAO,IAAI,WAAW;AACrC,MAAI,gBAAgB;AACpB,MAAI,iBAAiB,MAAM;AACzB,UAAM,cAAc,IAAI,gBAAgB,YAAY;AACpD,oBAAgB,IAAI,aAAa,WAAW;AAAA,EAC9C;AACA,MAAI,kBAAkB,GAAG;AACvB,QAAI,eAAe,OAAO,GAAG;AAAA,EAC/B,OAAO;AACL,QAAI,eAAe,IAAI,KAAK,EAAE,SAAS,aAAa,cAAc,CAAC;AAAA,EACrE;AACA,MAAI,cAAc,iBAAiB,SAAS,aAAa,aAAa;AACtE,MAAI,SAAS;AAAA,IACX,MAAM;AAAA,IACN,OAAO,IAAI,WAAW;AAAA,IACtB,gBAAgB,CAAC,EAAE,SAAS,aAAa,cAAc,CAAC;AAAA,EAC1D,CAAC;AACH;AAEO,SAAS,SACd,KACA,QACA,OACM;AACN,QAAM,YAAY,IAAI,gBAAgB,MAAM;AAC5C,QAAM,UAAU,IAAI,aAAa,SAAS;AAC1C,MAAI,WAAW;AAAA,IACb;AAAA,IACA,MAAM,IAAI,CAAC,UAAU,EAAE,GAAG,KAAK,EAAE;AAAA,EACnC;AACA,MAAI,UAAU;AAChB;AAEO,SAAS,cAAc,KAAyB,OAA0B;AAC/E,MAAI,MAAM,OAAO,GAAG,IAAI,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,EAAE,CAAC;AACzE,MAAI,UAAU;AAChB;AAEO,SAAS,WAAW,KAAyB,OAAe,IAAqB;AACtF,QAAM,WAAW,IAAI,UAAU,KAAK;AACpC,MAAI,MAAM,QAAQ,IAAI,EAAE,GAAG,IAAI,MAAM,QAAQ,GAAG,OAAO,QAAQ,GAAG;AAClE,MAAI,cAAc,cAAc,IAAI,KAAK;AACzC,SAAO,IAAI,kBAAkB,qBAAqB,UAAU,2BAA2B,GAAG,EAAE;AAC9F;AAEO,SAAS,gBAAgB,KAAyB,OAAe,WAAyB;AAC/F,MAAI,UAAU,KAAK;AACnB,MAAI,cAAc,gBAAgB,OAAO,SAAS;AAClD,MAAI,aAAa,IAAI,OAAO,SAAS;AACrC,MAAI,UAAU;AAChB;;;ACxKO,SAAS,iBAAiB,OAA+C;AAC9E,MAAI,CAAC,SAAS,KAAK,KAAK,OAAO,MAAM,SAAS,UAAU;AACtD,WAAO;AAAA,EACT;AACA,SACE,MAAM,SAAS,8BACf,MAAM,SAAS,sBACf,MAAM,SAAS;AAEnB;AAEO,SAAS,sBAAsB,OAAoD;AACxF,SAAO,SAAS,KAAK,KAAK,OAAO,MAAM,SAAS;AAClD;AAEO,SAAS,oBAAoB,OAAkD;AACpF,MAAI,CAAC,SAAS,KAAK,KAAK,OAAO,MAAM,SAAS,UAAU;AACtD,WAAO;AAAA,EACT;AACA,SACE,MAAM,SAAS,eACf,MAAM,SAAS,oBACf,MAAM,SAAS,0BACf,MAAM,SAAS,kBACf,MAAM,SAAS,wBACf,MAAM,SAAS,mBACf,MAAM,SAAS,iBACf,MAAM,SAAS,mBACf,MAAM,SAAS,oBACf,MAAM,SAAS,eACf,MAAM,SAAS,eACf,MAAM,SAAS,iBACf,MAAM,SAAS,0BACf,MAAM,SAAS,2BACf,MAAM,SAAS,kCACf,MAAM,SAAS,mCACf,MAAM,SAAS,qCACf,MAAM,SAAS,sCACf,MAAM,SAAS,mCACf,MAAM,SAAS,uBACf,MAAM,SAAS,0BACf,MAAM,SAAS,2BACf,MAAM,SAAS,2BACf,MAAM,SAAS,uCACf,MAAM,SAAS,2BACf,MAAM,SAAS,yBACf,MAAM,SAAS,uBACf,MAAM,SAAS,uBACf,MAAM,SAAS,gBACf,MAAM,SAAS,qBACf,MAAM,SAAS,oBACf,MAAM,SAAS,qBACf,MAAM,SAAS,gBACf,MAAM,SAAS,mBACf,MAAM,SAAS,mBACf,MAAM,SAAS,iCACf,MAAM,SAAS;AAEnB;AAEO,SAAS,8BACd,OAC4C;AAC5C,SACE,SAAS,KAAK,KACd,MAAM,SAAS,oBACf,OAAO,MAAM,cAAc,aAC1B,MAAM,OAAO,YAAY,MAAM,OAAO,UAAU,MAAM,OAAO;AAElE;AAEO,SAAS,+BACd,OAC6C;AAC7C,SACE,SAAS,KAAK,KACd,MAAM,SAAS,qBACf,OAAO,MAAM,cAAc,YAC3B,OAAO,MAAM,OAAO;AAExB;AAEO,SAAS,gCACd,OAC8C;AAC9C,SACE,SAAS,KAAK,KACd,MAAM,SAAS,sBACf,OAAO,MAAM,cAAc,YAC3B,MAAM,OAAO;AAEjB;AAEO,SAAS,iCACd,OAC+C;AAC/C,SACE,SAAS,KAAK,KACd,MAAM,SAAS,uBACf,OAAO,MAAM,cAAc,YAC3B,OAAO,MAAM,OAAO;AAExB;AAEO,SAAS,8BACd,OAC4C;AAC5C,MAAI,CAAC,SAAS,KAAK,KAAK,OAAO,MAAM,SAAS,UAAU;AACtD,WAAO;AAAA,EACT;AACA,SAAO,MAAM,SAAS,eAAe,MAAM,SAAS,WAAW,MAAM,SAAS;AAChF;AAEO,SAAS,wBAAwB,OAAsD;AAC5F,SACE,SAAS,KAAK,KACd,OAAO,MAAM,SAAS,YACtB,OAAO,MAAM,UAAU,YACvB,OAAO,MAAM,gBAAgB,YAC7B,OAAO,MAAM,mBAAmB,YAChC,OAAO,MAAM,0BAA0B,YACvC,OAAO,MAAM,0BAA0B,YACvC,OAAO,MAAM,UAAU;AAE3B;AAEO,SAAS,2BACd,OAC2C;AAC3C,SAAO,SAAS,KAAK,KAAK,MAAM,SAAS,kBAAkB,MAAM,QAAQ,MAAM,MAAM;AACvF;AAEO,SAAS,gBAAgB,OAAqD;AACnF,SACE,SAAS,KAAK,KACd,MAAM,SAAS,WACf,OAAO,MAAM,UAAU,YACvB,OAAO,MAAM,YAAY,YACzB,OAAO,MAAM,YAAY,YACzB,OAAO,MAAM,WAAW,YACxB,OAAO,MAAM,WAAW,YACxB,OAAO,MAAM,gBAAgB,aAC5B,OAAO,MAAM,aAAa,YAAY,MAAM,aAAa;AAE9D;;;AC1HO,IAAM,2BAAN,MAAM,0BAAyB;AAAA,EAmC5B,YACN,MACA,cACA,aACA,eACA,WACA,WACA;AAlCF,SAAQ,qBAAqB;AAC7B,SAAQ,iBAAiB;AACzB,SAAQ,iBAAiB;AACzB,SAAQ,qBAAqB,oBAAI,IAAsD;AACvF,SAAQ,iBAAiB,oBAAI,IAAiD;AAC9E,SAAQ,iBAAiB,oBAAI,IAAiD;AAC9E,SAAQ,mBAAmB,oBAAI,IAAwD;AACvF,SAAQ,mBAAmB;AAC3B,SAAiB,kBAAkB,oBAAI,IAMrC;AACF,SAAQ,qBAAqB;AAC7B,SAAiB,oBAAoB,oBAAI,IAMvC;AAGF,SAAQ,YAAY;AAUlB,SAAK,OAAO;AACZ,SAAK,eAAe;AACpB,SAAK,cAAc;AACnB,SAAK,gBAAgB;AACrB,SAAK,YAAY;AACjB,SAAK,YAAY;AACjB,SAAK,QAAQ,IAAI,QAAQ,CAAC,SAAS,WAAW;AAC5C,WAAK,eAAe;AACpB,WAAK,cAAc;AAAA,IACrB,CAAC;AACD,QAAI,CAAC,aAAa,cAAc;AAC9B,WAAK,aAAa;AAAA,IACpB;AACA,SAAK,KAAK,KAAK,YAAY,CAAC,UAAiC;AAC3D,UAAI,+BAA+B,MAAM,IAAI,GAAG;AAC9C,cAAM,UAAU,KAAK,gBAAgB,IAAI,MAAM,KAAK,SAAS;AAC7D,YAAI,SAAS;AACX,eAAK,gBAAgB,OAAO,MAAM,KAAK,SAAS;AAChD,cAAI,MAAM,KAAK,IAAI;AACjB,oBAAQ,QAAQ,MAAM,IAAI;AAAA,UAC5B,OAAO;AACL,oBAAQ,OAAO,IAAI,MAAM,MAAM,KAAK,SAAS,wBAAwB,CAAC;AAAA,UACxE;AAAA,QACF;AAAA,MACF,WAAW,iCAAiC,MAAM,IAAI,GAAG;AACvD,cAAM,UAAU,KAAK,kBAAkB,IAAI,MAAM,KAAK,SAAS;AAC/D,YAAI,SAAS;AACX,eAAK,kBAAkB,OAAO,MAAM,KAAK,SAAS;AAClD,cAAI,MAAM,KAAK,IAAI;AACjB,oBAAQ,QAAQ,MAAM,IAAI;AAAA,UAC5B,OAAO;AACL,oBAAQ,OAAO,IAAI,MAAM,MAAM,KAAK,SAAS,0BAA0B,CAAC;AAAA,UAC1E;AAAA,QACF;AAAA,MACF,WAAW,wBAAwB,MAAM,IAAI,GAAG;AAC9C,aAAK,cAAc,MAAM,IAAI;AAAA,MAC/B,WAAW,gBAAgB,MAAM,IAAI,GAAG;AACtC,aAAK,UAAU,MAAM,IAAI;AAAA,MAC3B,WAAW,2BAA2B,MAAM,IAAI,GAAG;AACjD,aAAK,YAAY,MAAM,KAAK,MAAM;AAAA,MACpC,WAAW,SAAS,MAAM,IAAI,KAAK,MAAM,KAAK,SAAS,SAAS;AAC9D,aAAK,aAAa;AAAA,MACpB,WAAW,SAAS,MAAM,IAAI,KAAK,MAAM,KAAK,SAAS,SAAS;AAC9D,aAAK,YAAY,IAAI,MAAM,OAAO,MAAM,KAAK,WAAW,oBAAoB,CAAC,CAAC;AAAA,MAChF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAa,OACX,SACA,UAA2C,CAAC,GACT;AACnC,UAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,UAAM,YAAY,QAAQ;AAC1B,QAAI,aAAa,QAAQ,cAAc,WAAW;AAChD,YAAM,QAAQ,aAAa,UAAU,SAAS;AAAA,IAChD;AACA,UAAM,uBACJ,QAAQ,qBAAqB,SACzB;AAAA,MACE,kBAAkB,QAAQ;AAAA,MAC1B,0BAA0B,QAAQ,4BAA4B,QAAQ;AAAA,MACtE,eACE,QAAQ,sBACP,QAAQ,4BAA4B,QAAQ;AAAA,IACjD,IACA,mBAAmB;AACzB,QAAI,QAAQ,yBAAyB,SAAS,sBAAsB,kBAAkB,OAAO;AAC3F,YAAM,IAAI;AAAA,QACR,6BAA6B,qBAAqB,gBAAgB,cAAc,qBAAqB,wBAAwB;AAAA,MAC/H;AAAA,IACF;AACA,UAAM,oBAAoB,OAAO,WAAW,sBAAsB;AAClE,UAAM,UAAU,OAAO,WAAW,YAAY;AAC9C,UAAM,eAAe,OAAO,qBAAqB,eAAe,CAAC,CAAC,QAAQ;AAC1E,UAAM,iBACJ,QAAQ,SAAS,kBAAkB,CAAC,qBAAqB,CAAC,WACtD,2EACA;AACN,UAAM,OACJ,QAAQ,SAAS,iBAAiB,CAAC,qBAAqB,CAAC,UAAU,gBAAgB;AACrF,QAAI,QAAQ,SAAS,SAAS,SAAS,OAAO;AAC5C,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,cACJ,SAAS,QACL,oCAAoC,QAAQ,uBAAuB,GAAG,IACtE;AACN,UAAM,gBACJ,SAAS,QACL,sCAAsC,QAAQ,yBAAyB,GAAG,IAC1E;AAIN,UAAM,YACJ,SAAS,QAAQ,4BAA4B,QAAQ,qBAAqB,GAAG,IAAI;AAInF,UAAM,sBAAsB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,uBAAuB,CAAC,CAAC;AACpF,UAAM,YACJ,SAAS,SAAS,sBAAsB,IACpC,4BAA4B,QAAQ,qBAAqB,IAAI,QAAQ,cAAc,EAAE,IACrF;AACN,UAAM,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,gBAAgB,CAAC,CAAC;AACtE,UAAM,mBAAgE;AAAA,MACpE,YAAY,QAAQ,cAAc,QAAQ;AAAA,MAC1C,WAAW,QAAQ;AAAA,MACnB;AAAA,MACA,qBAAqB,aAAa;AAAA,MAClC,qBAAqB,aAAa;AAAA,MAClC,uBAAuB,eAAe;AAAA,MACtC,uBAAuB,eAAe;AAAA,MACtC,mBAAmB,WAAW;AAAA,MAC9B,mBAAmB,WAAW;AAAA,MAC9B,mBAAmB,WAAW;AAAA,MAC9B,mBAAmB,WAAW;AAAA,MAC9B,YAAY,WAAW;AAAA,MACvB,qBAAqB,YAAY,sBAAsB;AAAA,MACvD,YAAY,QAAQ;AAAA,MACpB,qBAAqB,QAAQ;AAAA,MAC7B,iBAAiB,QAAQ;AAAA,IAC3B;AACA,UAAM,UACJ,QAAQ,gBACP,CAAC,KAAuB,MAAc,gBACrC,IAAI,iBAAiB,KAAK,MAAM,WAAW;AAC/C,UAAM,OAAO,QAAQ,SAAS,eAAe;AAAA,MAC3C,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,oBAAoB,CAAC,YAAY;AAAA,MACjC;AAAA,IACF,CAAC;AACD,WAAO,IAAI;AAAA,MACT;AAAA,MACA;AAAA,QACE;AAAA,QACA,eAAe;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA,kBAAkB,sBAAsB;AAAA,QACxC,0BAA0B,sBAAsB;AAAA,QAChD,eAAe,sBAAsB;AAAA,QACrC;AAAA,QACA,cAAc,cAAc,UAAa,CAAC,QAAQ;AAAA,MACpD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,KAAK,aAAa,IAAa;AAC7B,WAAO,KAAK,YAAY,EAAE,6BAA6C,WAAW,CAAC;AAAA,EACrF;AAAA,EAEA,KAAK,aAAa,IAAa;AAC7B,WAAO,KAAK,YAAY,EAAE,6BAA6C,WAAW,CAAC;AAAA,EACrF;AAAA,EAEA,WAAW,gBAAwB,aAAa,IAAa;AAC3D,WAAO,KAAK,YAAY;AAAA,MACtB;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAEA,QAAQ,KAAa,aAAa,IAAa;AAC7C,WAAO,KAAK,YAAY;AAAA,MACtB;AAAA,MACA;AAAA,MACA,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA,EAEA,YAAY,SAA6C;AACvD,QAAI,KAAK,WAAW;AAClB,aAAO;AAAA,IACT;AACA,QAAI,KAAK,aAAa;AACpB,aAAO,kCAAkC,KAAK,aAAa,OAAO;AAAA,IACpE;AACA,SAAK,KAAK,KAAK,YAAY,OAAO;AAClC,WAAO;AAAA,EACT;AAAA,EAEA,uBAAqD;AACnD,WAAO,KAAK,mBAAmB,QAAQ,EAAE,KAAK,CAAC,aAAa;AAC1D,UAAI,CAAC,SAAS,QAAQ;AACpB,cAAM,IAAI,MAAM,4CAA4C;AAAA,MAC9D;AACA,aAAO,SAAS;AAAA,IAClB,CAAC;AAAA,EACH;AAAA,EAEA,uBAAgD;AAC9C,WAAO,KAAK,mBAAmB,MAAM,EAAE;AAAA,MAAK,CAAC,cAC1C,SAAS,YAAY,CAAC,GAAG;AAAA,QAAI,CAAC,YAC7B,mBAAmB,eAAe,UAAU,IAAI,aAAa,OAAO;AAAA,MACtE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,sBAAqC;AACnC,WAAO,KAAK,mBAAmB,OAAO,EAAE,KAAK,MAAM,MAAS;AAAA,EAC9D;AAAA,EAEA,wBAAuD;AACrD,WAAO,KAAK,qBAAqB,EAAE,KAAK,CAAC,aAAa;AACpD,UAAI,CAAC,SAAS,OAAO;AACnB,cAAM,IAAI,MAAM,4CAA4C;AAAA,MAC9D;AACA,aAAO,SAAS;AAAA,IAClB,CAAC;AAAA,EACH;AAAA,EAEA,gBAA+C;AAC7C,QAAI,CAAC,KAAK,eAAe;AACvB,aAAO,CAAC;AAAA,IACV;AACA,UAAM,OAAO,oCAAoC,KAAK,eAAe,KAAK,kBAAkB;AAC5F,SAAK,qBAAqB,KAAK;AAC/B,eAAW,aAAa,KAAK,WAAW;AACtC,WAAK,cAAc,SAAS;AAAA,IAC9B;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,aAA2C;AACzC,QAAI,CAAC,KAAK,WAAW;AACnB,aAAO,CAAC;AAAA,IACV;AACA,UAAM,OAAO,0BAA0B,KAAK,WAAW,KAAK,cAAc;AAC1E,SAAK,iBAAiB,KAAK;AAC3B,eAAW,SAAS,KAAK,QAAQ;AAC/B,WAAK,UAAU,KAAK;AAAA,IACtB;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,YAA0C;AACxC,QAAI,CAAC,KAAK,WAAW;AACnB,aAAO,CAAC;AAAA,IACV;AACA,UAAM,OAAO,0BAA0B,KAAK,WAAW,KAAK,cAAc;AAC1E,SAAK,iBAAiB,KAAK;AAC3B,eAAW,SAAS,KAAK,QAAQ;AAC/B,WAAK,UAAU,KAAK;AAAA,IACtB;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,YAAY,UAAwE;AAClF,SAAK,mBAAmB,IAAI,QAAQ;AACpC,WAAO,MAAM;AACX,WAAK,mBAAmB,OAAO,QAAQ;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,QAAQ,UAAmE;AACzE,SAAK,eAAe,IAAI,QAAQ;AAChC,WAAO,MAAM;AACX,WAAK,eAAe,OAAO,QAAQ;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,QAAQ,UAAmE;AACzE,SAAK,eAAe,IAAI,QAAQ;AAChC,WAAO,MAAM;AACX,WAAK,eAAe,OAAO,QAAQ;AAAA,IACrC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAU,UAA0E;AAClF,SAAK,iBAAiB,IAAI,QAAQ;AAClC,WAAO,MAAM;AACX,WAAK,iBAAiB,OAAO,QAAQ;AAAA,IACvC;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,WAAW;AAClB;AAAA,IACF;AACA,SAAK,YAAY;AACjB,SAAK,KAAK,KAAK,YAAY,EAAE,6BAA6C,YAAY,GAAG,CAAC;AAC1F,SAAK,KAAK,WAAW;AACrB,eAAW,WAAW,KAAK,gBAAgB,OAAO,GAAG;AACnD,cAAQ,OAAO,IAAI,MAAM,oCAAoC,CAAC;AAAA,IAChE;AACA,SAAK,gBAAgB,MAAM;AAC3B,eAAW,WAAW,KAAK,kBAAkB,OAAO,GAAG;AACrD,cAAQ,OAAO,IAAI,MAAM,oCAAoC,CAAC;AAAA,IAChE;AACA,SAAK,kBAAkB,MAAM;AAC7B,SAAK,mBAAmB,MAAM;AAC9B,SAAK,eAAe,MAAM;AAC1B,SAAK,eAAe,MAAM;AAC1B,SAAK,iBAAiB,MAAM;AAAA,EAC9B;AAAA,EAEQ,cAAc,WAA8C;AAClE,eAAW,YAAY,KAAK,oBAAoB;AAC9C,eAAS,SAAS;AAAA,IACpB;AAAA,EACF;AAAA,EAEQ,UAAU,OAAyC;AACzD,eAAW,YAAY,KAAK,gBAAgB;AAC1C,eAAS,KAAK;AAAA,IAChB;AAAA,EACF;AAAA,EAEQ,YAAY,QAAgD;AAClE,eAAW,YAAY,KAAK,kBAAkB;AAC5C,eAAS,MAAM;AAAA,IACjB;AAAA,EACF;AAAA,EAEQ,UAAU,OAAyC;AACzD,eAAW,YAAY,KAAK,gBAAgB;AAC1C,eAAS,KAAK;AAAA,IAChB;AAAA,EACF;AAAA,EAEQ,mBACN,IAC6C;AAC7C,QAAI,KAAK,WAAW;AAClB,aAAO,QAAQ,OAAO,IAAI,MAAM,oCAAoC,CAAC;AAAA,IACvE;AACA,UAAM,YAAY,KAAK;AACvB,UAAM,UAAU,IAAI,QAA4C,CAAC,SAAS,WAAW;AACnF,WAAK,gBAAgB,IAAI,WAAW,EAAE,SAAS,OAAO,CAAC;AAAA,IACzD,CAAC;AACD,SAAK,KAAK,KAAK,YAAY,EAAE,MAAM,kBAAkB,WAAW,GAAG,CAAC;AACpE,WAAO;AAAA,EACT;AAAA,EAEQ,uBAAsE;AAC5E,QAAI,KAAK,WAAW;AAClB,aAAO,QAAQ,OAAO,IAAI,MAAM,oCAAoC,CAAC;AAAA,IACvE;AACA,UAAM,YAAY,KAAK;AACvB,UAAM,UAAU,IAAI,QAA8C,CAAC,SAAS,WAAW;AACrF,WAAK,kBAAkB,IAAI,WAAW,EAAE,SAAS,OAAO,CAAC;AAAA,IAC3D,CAAC;AACD,SAAK,KAAK,KAAK,YAAY,EAAE,MAAM,oBAAoB,WAAW,IAAI,QAAQ,CAAC;AAC/E,WAAO;AAAA,EACT;AACF;;;ACxaO,SAAS,SACd,KACA,QACA,OACA,OACS;AACT,QAAM,UAAU,IAAI,eAAe,QAAQ,KAAK;AAIhD,MAAI,cAAc,aAAa,SAAS,KAAK;AAC7C,SAAO,IAAI,aAAa,YAAY;AAAA,IAClC;AAAA,IACA,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ,CAAC;AACH;AAEO,SAAS,YACd,KACA,QACA,MACA,MACS;AACT,QAAM,YAAY,IAAI,gBAAgB,MAAM;AAC5C,MAAI,cAAc,YAAY,WAAW,MAAM,IAAI;AACnD,SAAO,IAAI,aAAa,YAAY;AAAA,IAClC;AAAA,IACA,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,SAAS,OAAO,IAAM,MAAM,OAAO,IAAM;AAAA,EAC3C,CAAC;AACH;AAaO,SAAS,kBACd,KACA,QACA,MACQ;AACR,QAAM,YAAY,SAAS,QAAQ,yBAAyB;AAC5D,MAAI,WAAW,UAAU;AACvB,WAAO,wBAAwB,SAAS;AAAA,EAC1C;AACA,SAAO,sBAAsB,IAAI,gBAAgB,MAAM,GAAG,SAAS;AACrE;AAQO,SAAS,qBAAqB,KAA6B,OAAuB;AACvF,SAAO,qBAAqB,IAAI,UAAU,KAAK,GAAG,2BAA2B;AAC/E;AAaO,SAAS,+BACd,KACA,QACA,aACA,WACQ;AACR,QAAM,YAAY,IAAI,gBAAgB,MAAM;AAC5C,SAAO,IAAI,cAAc;AAAA,IACvB,IAAI,aAAa,SAAS;AAAA,IAC1B;AAAA,IACA;AAAA,EACF;AACF;AAUO,SAAS,gCACd,KACA,aACA,WACQ;AACR,SAAO,IAAI,cAAc,gCAAgC,aAAa,SAAS;AACjF;AAYO,SAAS,6BACd,KACA,OACA,aACA,WACQ;AACR,MAAI,UAAU,KAAK;AACnB,SAAO,IAAI,cAAc,6BAA6B,OAAO,aAAa,SAAS;AACrF;AAQO,SAAS,oBAAoB,KAAqC;AACvE,SAAO,IAAI,cAAc,oBAAoB;AAC/C;AAEO,SAAS,eAAe,KAAoD;AACjF,QAAM,aAAoC,CAAC;AAC3C,WAAS,QAAQ,GAAG,QAAQ,IAAI,cAAc,eAAe,GAAG,SAAS;AACvE,eAAW,KAAK,IAAI,cAAc,qBAAqB,KAAK,CAAC;AAAA,EAC/D;AACA,SAAO;AACT;;;ACzJA,SAAS,WAAW,KAAyB,QAAiC;AAC5E,SAAO,IAAI,aAAa,IAAI,gBAAgB,MAAM,CAAC;AACrD;AAEO,SAAS,kBACd,KACA,SACA,WACA,gBACM;AACN,MAAI,cAAc,kBAAkB,SAAS,SAAS;AACtD,iBAAe,IAAI,SAAS,SAAS;AACvC;AAEO,SAAS,oBACd,KACA,QACA,WACA,MACM;AACN,QAAM,UAAU,WAAW,KAAK,MAAM;AACtC,QAAM,WAAW,OAAO,SAAS,WAAW,OAAO,KAAK,UAAU,IAAI;AACtE,MAAI,cAAc,wBAAwB,SAAS,WAAW,QAAQ;AACtE,MAAI,SAAS,EAAE,MAAM,wBAAwB,SAAS,WAAW,SAAS,CAAC;AAC7E;AAEO,SAAS,4BACd,KACA,QACA,aACA,UACA,eACM;AACN,QAAM,UAAU,WAAW,KAAK,MAAM;AACtC,MAAI,cAAc,4BAA4B,SAAS,aAAa,UAAU,aAAa;AAC3F,MAAI,SAAS;AAAA,IACX,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEO,SAAS,+BACd,KACA,QACA,aACA,WACA,OACM;AACN,QAAM,UAAU,WAAW,KAAK,MAAM;AACtC,MAAI,cAAc,+BAA+B,SAAS,aAAa,WAAW,KAAK;AACvF,MAAI,SAAS,EAAE,MAAM,mCAAmC,SAAS,aAAa,WAAW,MAAM,CAAC;AAClG;AAEO,SAAS,iBACd,KACA,QACA,KACM;AACN,QAAM,UAAU,WAAW,KAAK,MAAM;AACtC,MAAI,cAAc,iBAAiB,SAAS,GAAG;AAC/C,MAAI,SAAS,EAAE,MAAM,qBAAqB,SAAS,IAAI,CAAC;AAC1D;AAEO,SAAS,oBACd,KACA,QACA,QACM;AACN,QAAM,UAAU,WAAW,KAAK,MAAM;AACtC,QAAM,OAAO,WAAW,MAAM;AAC9B,MAAI,cAAc,oBAAoB,SAAS,IAAI;AACnD,MAAI,SAAS,EAAE,MAAM,wBAAwB,SAAS,QAAQ,KAAK,CAAC;AACtE;AAEO,SAAS,qBACd,KACA,QACA,SACM;AACN,QAAM,UAAU,WAAW,KAAK,MAAM;AACtC,QAAM,OAAO,YAAY,OAAO;AAChC,MAAI,cAAc,qBAAqB,SAAS,IAAI;AACpD,MAAI,SAAS,EAAE,MAAM,yBAAyB,SAAS,SAAS,KAAK,CAAC;AACxE;AAEO,SAAS,qBACd,KACA,QACA,SACA,UACM;AACN,QAAM,UAAU,WAAW,KAAK,MAAM;AACtC,MAAI,cAAc,qBAAqB,SAAS,SAAS,QAAQ;AACjE,MAAI,SAAS,EAAE,MAAM,yBAAyB,SAAS,SAAS,SAAS,CAAC;AAC5E;AAEO,SAAS,iCACd,KACA,QACA,cACM;AACN,QAAM,UAAU,WAAW,KAAK,MAAM;AACtC,MAAI,cAAc,iCAAiC,SAAS,YAAY;AACxE,MAAI,SAAS,EAAE,MAAM,qCAAqC,SAAS,aAAa,CAAC;AACnF;AAEO,SAAS,qBACd,KACA,WACA,MACM;AACN,QAAM,WAAW,OAAO,SAAS,WAAW,OAAO,KAAK,UAAU,IAAI;AACtE,MAAI,cAAc,yBAAyB,WAAW,QAAQ;AAC9D,MAAI,SAAS,EAAE,MAAM,yBAAyB,WAAW,SAAS,CAAC;AACrE;AAEO,SAAS,6BACd,KACA,aACA,UACA,eACM;AACN,MAAI,cAAc,6BAA6B,aAAa,UAAU,aAAa;AACnF,MAAI,SAAS,EAAE,MAAM,iCAAiC,aAAa,UAAU,cAAc,CAAC;AAC9F;AAEO,SAAS,gCACd,KACA,aACA,WACA,OACM;AACN,MAAI,cAAc,gCAAgC,aAAa,WAAW,KAAK;AAC/E,MAAI,SAAS,EAAE,MAAM,oCAAoC,aAAa,WAAW,MAAM,CAAC;AAC1F;AAEO,SAAS,6BACd,KACA,OACA,aACA,WACA,OACM;AACN,MAAI,cAAc,6BAA6B,OAAO,aAAa,WAAW,KAAK;AACnF,MAAI,SAAS,EAAE,MAAM,iCAAiC,OAAO,aAAa,WAAW,MAAM,CAAC;AAC9F;AAEO,SAAS,eACd,KACA,SACA,OACA,SACA,MACA,UACA,aACM;AACN,QAAM,gBAAgB,IAAI,gBAAgB,OAAO;AACjD,MAAI,cAAc,eAAe,eAAe,OAAO,SAAS,MAAM,UAAU,WAAW;AAC3F,MAAI,SAAS;AAAA,IACX,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEO,SAAS,gBACd,KACA,SACA,OACA,SACA,MACA,UACA,aACM;AACN,QAAM,gBAAgB,IAAI,gBAAgB,OAAO;AACjD,MAAI,cAAc,gBAAgB,eAAe,OAAO,SAAS,MAAM,UAAU,WAAW;AAC5F,MAAI,SAAS;AAAA,IACX,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEO,SAAS,WACd,KACA,SACA,OACA,SACA,YACA,OACA,aACM;AACN,QAAM,gBAAgB,IAAI,gBAAgB,OAAO;AACjD,MAAI,cAAc,WAAW,eAAe,OAAO,SAAS,YAAY,OAAO,WAAW;AAC1F,MAAI,SAAS;AAAA,IACX,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEO,SAAS,qBACd,KACA,SACA,QACM;AACN,QAAM,gBAAgB,IAAI,gBAAgB,OAAO;AACjD,MAAI,cAAc,qBAAqB,QAAQ,aAAa;AAC5D,MAAI,mBAAmB,EAAE,MAAM,yBAAyB,eAAe,OAAO,CAAC;AACjF;AAEO,SAAS,mBACd,KACA,SACA,OACM;AACN,QAAM,gBAAgB,IAAI,gBAAgB,OAAO;AACjD,MAAI,cAAc,mBAAmB,OAAO,aAAa;AACzD,MAAI,mBAAmB,EAAE,MAAM,uBAAuB,eAAe,MAAM,CAAC;AAC9E;AAEO,SAAS,cAAc,KAAyB,MAAwB;AAC7E,MAAI,cAAc,cAAc,IAAI;AACpC,MAAI,mBAAmB,EAAE,MAAM,qBAAqB,KAAK,CAAC;AAC5D;AAEO,SAAS,iBACd,KACA,SACA,QACM;AACN,QAAM,gBAAgB,IAAI,gBAAgB,OAAO;AACjD,MAAI,cAAc,iBAAiB,QAAQ,aAAa;AACxD,MAAI,mBAAmB,EAAE,MAAM,qBAAqB,eAAe,OAAO,CAAC;AAC7E;AAEO,SAAS,2BACd,KACA,SACA,UACM;AACN,QAAM,gBAAgB,IAAI,gBAAgB,OAAO;AACjD,MAAI,cAAc,2BAA2B,eAAe,QAAQ;AACpE,MAAI,SAAS,EAAE,MAAM,+BAA+B,eAAe,SAAS,CAAC;AAC/E;AAEO,SAAS,4BAA4B,KAAyB,SAAwB;AAC3F,MAAI,cAAc,4BAA4B,OAAO;AACrD,MAAI,SAAS,EAAE,MAAM,yBAAyB,QAAQ,CAAC;AACzD;AAEO,SAAS,UACd,KACA,SACA,YACM;AACN,QAAM,gBAAgB,IAAI,gBAAgB,OAAO;AACjD,MAAI,cAAc,UAAU,eAAe,UAAU;AACrD,MAAI,mBAAmB,EAAE,MAAM,cAAc,eAAe,WAAW,CAAC;AAC1E;AAEO,SAAS,YAAY,KAAyB,SAAgC;AACnF,QAAM,gBAAgB,IAAI,gBAAgB,OAAO;AACjD,MAAI,cAAc,YAAY,aAAa;AAC3C,MAAI,mBAAmB,EAAE,MAAM,mBAAmB,cAAc,CAAC;AACnE;AAEO,SAAS,cACd,KACA,SACA,MACA,aACM;AACN,QAAM,gBAAgB,IAAI,gBAAgB,OAAO;AACjD,MAAI,cAAc,cAAc,eAAe,MAAM,WAAW;AAChE,MAAI,SAAS,EAAE,MAAM,iBAAiB,eAAe,MAAM,YAAY,CAAC;AAC1E;;;AC7QO,SAAS,cAAc,KAA+B;AAC3D,MAAI;AAAA,IACF;AAAA,MACE,IAAI,YAAY;AAAA,MAChB,IAAI,iBAAiB;AAAA,MACrB,IAAI,iBAAiB;AAAA,MACrB,IAAI,yBAAyB;AAAA,IAC/B;AAAA,EACF;AACF;AAEO,SAAS,SAAS,KAAyB,KAAmB;AACnE,MAAI,YAAY,GAAG;AACnB,MAAI,iBAAiB,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,CAAC;AAC3C,MAAI,cAAc,SAAS,GAAG;AAC9B,gBAAc,GAAG;AACjB,MAAI,aAAa,YAAY;AAAA,IAC3B;AAAA,IACA,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ,CAAC;AACH;AAEO,SAAS,iBACd,KACA,UACM;AACN,QAAM,SAAS,SAAS,IAAI,CAAC,aAAa,EAAE,GAAG,QAAQ,EAAE;AACzD,MAAI,iBAAiB,MAAM;AAC3B,MAAI,YAAY,OAAO,CAAC,GAAG,OAAO,IAAI,YAAY,CAAC;AACnD,MAAI,cAAc,iBAAiB,MAAM;AACzC,gBAAc,GAAG;AACnB;AAEO,SAAS,iBACd,KACA,WACA,aACM;AACN,MAAI,iBAAiB,EAAE,WAAW,YAAY,CAAC;AAC/C,MAAI,yBAAyB,CAAC,EAAE,UAAU,GAAG,WAAW,YAAY,CAAC,CAAC;AACtE,MAAI,cAAc,iBAAiB,WAAW,WAAW;AACzD,gBAAc,GAAG;AACnB;AAEO,SAAS,yBACd,KACA,UACM;AACN,QAAM,SAAS,SAAS,IAAI,CAAC,aAAa,EAAE,GAAG,QAAQ,EAAE;AACzD,MAAI,yBAAyB,MAAM;AACnC,QAAM,QAAQ,OAAO,CAAC;AACtB,MAAI,OAAO;AACT,QAAI,iBAAiB,EAAE,WAAW,MAAM,WAAW,aAAa,MAAM,YAAY,CAAC;AAAA,EACrF;AACA,MAAI,cAAc,yBAAyB,MAAM;AACjD,gBAAc,GAAG;AACnB;AAEO,SAAS,QACd,KACA,UACA,QACA,UAAU,MACD;AACT,MAAI,cAAc,QAAQ,UAAU,QAAQ,OAAO;AAUnD,SAAO,IAAI,aAAa,YAAY;AAAA,IAClC;AAAA,IACA,UAAU,UAAU,IAAI;AAAA,IACxB,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,QAAQ,KAAK,MAAM,SAAS,GAAS;AAAA,EACvC,CAAC;AACH;AAEO,SAAS,iBACd,KACA,aACA,MACQ;AACR,SAAO,IAAI,cAAc,iBAAiB,aAAa,IAAI;AAC7D;AAEA,eAAsB,kBAAkB,KAAwD;AAC9F,QAAM,QAAQ,MAAM,IAAI,aAAa,sBAAsB;AAC3D,MAAI,wBAAwB,KAAK;AACjC,SAAO;AACT;AAEO,SAAS,qBAAqB,KAA2D;AAC9F,SAAO,IAAI,wBAAwB;AACrC;;;AClFO,IAAM,eAAN,MAAM,cAAa;AAAA,EAuChB,YACN,SACA,cACA,eACA,YACA,kBACA,qBACA;AApCF,SAAiB,kBAAkB,oBAAI,IAAqC;AAC5E,SAAiB,QAAQ,oBAAI,IAAwB;AACrD,SAAiB,YAAY,oBAAI,IAAoC;AACrE,SAAiB,UAAU,oBAAI,IAA0B;AACzD,SAAiB,eAAyB,CAAC;AAC3C,SAAiB,aAAa,oBAAI,IAA+B;AACjE,SAAiB,iBAAiB,oBAAI,IAAoB;AAC1D,SAAiB,iBAAiB,oBAAI,IAGpC;AACF,SAAiB,QAAqB,CAAC;AACvC,SAAiB,iBAAiB,oBAAI,IAAoB;AAC1D,SAAiB,eAAe,oBAAI,IAAoB;AAGxD,SAAQ,WAAW;AACnB,SAAQ,gBAAgB,EAAE,WAAW,GAAG,aAAa,EAAE;AACvD,SAAQ,gBAAsC,CAAC,EAAE,UAAU,GAAG,KAAK,IAAI,CAAC;AACxE,SAAQ,wBAAsD;AAAA,MAC5D,EAAE,UAAU,GAAG,WAAW,GAAG,aAAa,EAAE;AAAA,IAC9C;AAEA,SAAQ,aAAa;AACrB,SAAQ,eAAe;AACvB,SAAQ,mBAAmB;AAC3B,SAAiB,wBAA6D,CAAC;AAC/E,SAAQ,YAAY;AAUlB,SAAK,UAAU;AACf,SAAK,eAAe;AACpB,SAAK,gBAAgB;AACrB,SAAK,OAAO,aAAa;AACzB,SAAK,eAAe,aAAa;AACjC,SAAK,aAAa;AAClB,SAAK,mBAAmB;AACxB,SAAK,sBAAsB;AAC3B,SAAK,YAAY,qBAAqB;AAAA,MACpC,YAAY,KAAK;AAAA,MACjB,cAAc,KAAK;AAAA,MACnB,eAAe,KAAK;AAAA,MACpB,qBAAqB,CAAC,YAAY;AAChC,aAAK,mBAAmB;AAAA,MAC1B;AAAA,MACA,4BAA4B,MAAM,KAAK,2BAA2B;AAAA,MAClE,UAAU,CAAC,QAAQ,KAAK,SAAS,GAAG;AAAA,MACpC,kBAAkB,CAAC,aAAa,KAAK,iBAAiB,QAAQ;AAAA,MAC9D,SAAS,CAAC,UAAU,QAAQ,YAAY,KAAK,QAAQ,UAAU,QAAQ,OAAO;AAAA,IAChF,CAAC;AAAA,EACH;AAAA,EAEA,aAAa,OACX,SACA,UAA+B,CAAC,GACT;AACvB,UAAM,aAAa,QAAQ,cAAc,QAAQ;AACjD,UAAM,YAAY,QAAQ,oBAAoB,QAAQ,aAAa;AACnE,UAAM,eAAe,KAAK;AAAA,MACxB;AAAA,MACA,KAAK,MAAM,QAAQ,uBAAuB,QAAQ,gBAAgB,CAAC;AAAA,IACrE;AACA,UAAM,eAAe,MAAM,yBAAyB,OAAO,SAAS,OAAO;AAC3E,UAAM,gBAAgB,QAAQ,iBAAiB,IAAI,eAAe,YAAY,SAAS;AACvF,WAAO,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,UAAyB;AAC7B,QAAI,KAAK,WAAW;AAClB;AAAA,IACF;AACA,UAAM,KAAK,QAAQ,UAAU;AAAA,EAC/B;AAAA,EAEA,MAAM,SAAwB;AAC5B,QAAI,KAAK,WAAW;AAClB;AAAA,IACF;AACA,UAAM,KAAK,QAAQ,SAAS;AAAA,EAC9B;AAAA,EAEA,SAAS,KAAmB;AAC1B,IAAM,SAAS,KAAK,cAAc,GAAG;AAAA,EACvC;AAAA,EAEA,iBAAiB,UAA+C;AAC9D,IAAM,iBAAiB,KAAK,cAAc,QAAQ;AAAA,EACpD;AAAA,EAEA,iBAAiB,WAAmB,aAA2B;AAC7D,IAAM,iBAAiB,KAAK,cAAc,WAAW,WAAW;AAAA,EAClE;AAAA,EAEA,yBAAyB,UAAuD;AAC9E,IAAM,yBAAyB,KAAK,cAAc,QAAQ;AAAA,EAC5D;AAAA,EAEA,QAAQ,UAAkB,QAAgB,UAAU,MAAe;AACjE,WAAa,QAAQ,KAAK,cAAc,UAAU,QAAQ,OAAO;AAAA,EACnE;AAAA,EAEA,iBAAiB,aAAqB,MAAsB;AAC1D,WAAa,iBAAiB,KAAK,cAAc,aAAa,IAAI;AAAA,EACpE;AAAA,EAEA,oBAAmD;AACjD,WAAa,kBAAkB,KAAK,YAAY;AAAA,EAClD;AAAA,EAEA,uBAAyD;AACvD,WAAa,qBAAqB,KAAK,YAAY;AAAA,EACrD;AAAA,EAEA,SAAS,QAAgB,OAAwB,OAAwB;AACvE,WAAiB,SAAS,KAAK,kBAAkB,QAAQ,OAAO,KAAK;AAAA,EACvE;AAAA,EAEA,cACE,QACA,OACA,KACA,OACA,QAA2C,UACrC;AACN,IAAW,cAAc,KAAK,mBAAmB,QAAQ,OAAO,KAAK,OAAO,KAAK;AAAA,EACnF;AAAA,EAEA,mBACE,QACA,KACA,OACA,QAA2C,UACrC;AACN,IAAW,mBAAmB,KAAK,mBAAmB,QAAQ,KAAK,OAAO,KAAK;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,kBAAkB,SAAiB,QAAoD;AACrF,IAAW,kBAAkB,KAAK,mBAAmB,SAAS,MAAM;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,kBAAkB,QAAyB,MAAiC;AAC1E,WAAiB,kBAAkB,KAAK,kBAAkB,QAAQ,IAAI;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,qBAAqB,OAAuB;AAC1C,WAAiB,qBAAqB,KAAK,kBAAkB,KAAK;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,+BACE,QACA,aACA,WACQ;AACR,WAAiB;AAAA,MACf,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,gCAAgC,aAAqB,WAA2B;AAC9E,WAAiB,gCAAgC,KAAK,kBAAkB,aAAa,SAAS;AAAA,EAChG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,6BAA6B,OAAe,aAAqB,WAA2B;AAC1F,WAAiB;AAAA,MACf,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,sBAA8B;AAC5B,WAAiB,oBAAoB,KAAK,gBAAgB;AAAA,EAC5D;AAAA,EAEA,iBAAwC;AACtC,WAAiB,eAAe,KAAK,gBAAgB;AAAA,EACvD;AAAA,EAEA,YAAY,QAAyB,MAAe,MAAwB;AAC1E,WAAiB,YAAY,KAAK,kBAAkB,QAAQ,MAAM,IAAI;AAAA,EACxE;AAAA,EAEA,aAAa,QAAyB,IAAqB;AACzD,WAAO,KAAK,kBAAkB,KAAK,aAAa,QAAQ,2BAA2B,GAAG,EAAE;AAAA,EAC1F;AAAA,EAEA,YAAY,QAAyB,KAAsB;AACzD,WAAO,KAAK,kBAAkB,KAAK,aAAa,QAAQ,sBAAsB,GAAG,GAAG;AAAA,EACtF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,cAAc,OAAsD;AAClE,IAAM,cAAc,KAAK,cAAc,KAAK;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkB,QAAyB,OAAqB;AAC9D,IAAM,kBAAkB,KAAK,cAAc,QAAQ,KAAK;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBACE,QACA,aACA,cACM;AACN,IAAM,iBAAiB,KAAK,cAAc,QAAQ,aAAa,YAAY;AAAA,EAC7E;AAAA,EAEA,SAAS,QAAyB,OAAgC;AAChE,IAAM,SAAS,KAAK,cAAc,QAAQ,KAAK;AAAA,EACjD;AAAA,EAEA,cAAc,OAA0B;AACtC,IAAM,cAAc,KAAK,cAAc,KAAK;AAAA,EAC9C;AAAA,EAEA,WAAW,OAAe,IAAqB;AAC7C,WAAa,WAAW,KAAK,cAAc,OAAO,EAAE;AAAA,EACtD;AAAA,EAEA,kBAAkB,QAAyB,WAAyB;AAClE,UAAM,YAAY,KAAK,gBAAgB,MAAM;AAC7C,UAAM,UAAU,KAAK,aAAa,SAAS;AAC3C,IAAO,kBAAkB,KAAK,cAAc,SAAS,WAAW,KAAK,cAAc;AACnF,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,oBAAoB,QAAyB,WAAmB,MAA6B;AAC3F,IAAO,oBAAoB,KAAK,cAAc,QAAQ,WAAW,IAAI;AAAA,EACvE;AAAA,EAEA,4BACE,QACA,aACA,UACA,gBAAgB,OACV;AACN,IAAO;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,+BACE,QACA,aACA,WACA,OACM;AACN,IAAO,+BAA+B,KAAK,cAAc,QAAQ,aAAa,WAAW,KAAK;AAAA,EAChG;AAAA,EAEA,iBAAiB,QAAyB,KAAmB;AAC3D,IAAO,iBAAiB,KAAK,cAAc,QAAQ,GAAG;AAAA,EACxD;AAAA,EAEA,oBAAoB,QAAyB,QAA+B;AAC1E,IAAO,oBAAoB,KAAK,cAAc,QAAQ,MAAM;AAAA,EAC9D;AAAA,EAEA,qBAAqB,QAAyB,SAAiC;AAC7E,IAAO,qBAAqB,KAAK,cAAc,QAAQ,OAAO;AAAA,EAChE;AAAA,EAEA,qBAAqB,QAAyB,SAAiB,UAAwB;AACrF,IAAO,qBAAqB,KAAK,cAAc,QAAQ,SAAS,QAAQ;AAAA,EAC1E;AAAA,EAEA,iCAAiC,QAAyB,cAA4B;AACpF,IAAO,iCAAiC,KAAK,cAAc,QAAQ,YAAY;AAAA,EACjF;AAAA,EAEA,WAAW,QAAyB,WAAmB,MAA6B;AAClF,QAAI,WAAW,UAAU;AACvB,WAAK,qBAAqB,WAAW,IAAI;AACzC;AAAA,IACF;AACA,SAAK,oBAAoB,QAAQ,WAAW,IAAI;AAAA,EAClD;AAAA,EAEA,uBACE,QACA,aACA,UACA,gBAAgB,OACV;AACN,QAAI,WAAW,UAAU;AACvB,WAAK,6BAA6B,aAAa,UAAU,aAAa;AACtE;AAAA,IACF;AACA,SAAK,4BAA4B,QAAQ,aAAa,UAAU,aAAa;AAAA,EAC/E;AAAA,EAEA,gBAAgB,QAAyB,WAAyB;AAChE,QAAI,WAAW,UAAU;AACvB,WAAK,mBAAmB,SAAS;AACjC;AAAA,IACF;AACA,SAAK,kBAAkB,QAAQ,SAAS;AAAA,EAC1C;AAAA,EAEA,gBAAgB,OAAe,WAAyB;AACtD,IAAM,gBAAgB,KAAK,cAAc,OAAO,SAAS;AAAA,EAC3D;AAAA,EAEA,mBAAmB,WAAyB;AAC1C,SAAK,cAAc,mBAAmB,SAAS;AAC/C,SAAK,kBAAkB;AACvB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,qBAAqB,WAAmB,MAA6B;AACnE,IAAO,qBAAqB,KAAK,cAAc,WAAW,IAAI;AAAA,EAChE;AAAA,EAEA,6BACE,aACA,UACA,gBAAgB,OACV;AACN,IAAO,6BAA6B,KAAK,cAAc,aAAa,UAAU,aAAa;AAAA,EAC7F;AAAA,EAEA,gCAAgC,aAAqB,WAAmB,OAAqB;AAC3F,IAAO,gCAAgC,KAAK,cAAc,aAAa,WAAW,KAAK;AAAA,EACzF;AAAA,EAEA,6BACE,OACA,aACA,WACA,OACM;AACN,SAAK,UAAU,KAAK;AACpB,IAAO,6BAA6B,KAAK,cAAc,OAAO,aAAa,WAAW,KAAK;AAAA,EAC7F;AAAA,EAEA,0BACE,QACA,aACA,WACA,OACM;AACN,QAAI,WAAW,UAAU;AACvB,WAAK,gCAAgC,aAAa,WAAW,KAAK;AAClE;AAAA,IACF;AACA,SAAK,+BAA+B,QAAQ,aAAa,WAAW,KAAK;AAAA,EAC3E;AAAA,EAEA,eAAe,WAAyB;AACtC,SAAK,mBAAmB,SAAS;AAAA,EACnC;AAAA,EAEA,QACE,SACA,QACA,UACA,OAA2D,CAAC,GACpD;AACR,WAAa,QAAQ,KAAK,aAAa,SAAS,QAAQ,UAAU,IAAI;AAAA,EACxE;AAAA,EAEA,WAAW,QAAsB;AAC/B,IAAM,WAAW,KAAK,aAAa,MAAM;AAAA,EAC3C;AAAA,EAEA,aAAa,WAAoD;AAC/D,IAAM,aAAa,KAAK,aAAa,SAAS;AAAA,EAChD;AAAA,EAEA,qBACE,SACA,SAA+D,CAAC,GAC1D;AACN,IAAO,qBAAqB,KAAK,cAAc,SAAS,MAAM;AAAA,EAChE;AAAA,EAEA,mBAAmB,SAA0B,QAA0C,CAAC,GAAS;AAC/F,IAAO,mBAAmB,KAAK,cAAc,SAAS,KAAK;AAAA,EAC7D;AAAA,EAEA,cAAc,MAAwB;AACpC,IAAO,cAAc,KAAK,cAAc,IAAI;AAAA,EAC9C;AAAA,EAEA,iBACE,SACA,SAAwE,CAAC,GACnE;AACN,IAAO,iBAAiB,KAAK,cAAc,SAAS,MAAM;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,2BAA2B,SAA0B,UAAyB;AAC5E,IAAO,2BAA2B,KAAK,cAAc,SAAS,QAAQ;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,4BAA4B,SAAwB;AAClD,IAAO,4BAA4B,KAAK,cAAc,OAAO;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,UAAU,SAA0B,YAA0B;AAC5D,IAAO,UAAU,KAAK,cAAc,SAAS,UAAU;AAAA,EACzD;AAAA;AAAA,EAGA,YAAY,SAAgC;AAC1C,IAAO,YAAY,KAAK,cAAc,OAAO;AAAA,EAC/C;AAAA,EAEA,eACE,SACA,OACA,SACA,MACA,UACA,cAAc,IACR;AACN,IAAO,eAAe,KAAK,cAAc,SAAS,OAAO,SAAS,MAAM,UAAU,WAAW;AAAA,EAC/F;AAAA,EAEA,gBACE,SACA,OACA,SACA,MACA,WAAW,GACX,cAAc,IACR;AACN,IAAO,gBAAgB,KAAK,cAAc,SAAS,OAAO,SAAS,MAAM,UAAU,WAAW;AAAA,EAChG;AAAA,EAEA,WACE,SACA,OACA,SACA,YACA,OACA,cAAc,IACR;AACN,IAAO,WAAW,KAAK,cAAc,SAAS,OAAO,SAAS,YAAY,OAAO,WAAW;AAAA,EAC9F;AAAA,EAEA,cAAc,SAA0B,MAAkB,cAAc,IAAU;AAChF,IAAO,cAAc,KAAK,cAAc,SAAS,MAAM,WAAW;AAAA,EACpE;AAAA,EAEA,cAAc,cAAc,IAAU;AACpC,SAAK,cAAc,cAAc,WAAW;AAC5C,SAAK,SAAS,EAAE,MAAM,iBAAiB,YAAY,CAAC;AAAA,EACtD;AAAA,EAEA,iBAAiB,SAA+B;AAC9C,IAAQ,iBAAiB,KAAK,gBAAgB,OAAO;AAAA,EACvD;AAAA,EAEA,UAAU,SAA0B,SAA2B;AAC7D,WAAe,UAAU,KAAK,gBAAgB,SAAS,OAAO;AAAA,EAChE;AAAA,EAEA,MAAM,OAAe,QAAyB;AAC5C,WAAe,MAAM,KAAK,gBAAgB,OAAO,MAAM;AAAA,EACzD;AAAA,EAEA,gBAA8C;AAC5C,WAAe,cAAc,KAAK,cAAc;AAAA,EAClD;AAAA,EAEA,gBAAyC;AACvC,WAAe,cAAc,KAAK,cAAc;AAAA,EAClD;AAAA,EAEA,MAAM,eAA8B;AAClC,WAAe,aAAa,KAAK,cAAc;AAAA,EACjD;AAAA,EAEA,aAAa,MAAmC;AAC9C,SAAK,cAAc,aAAa,IAAI;AAIpC,SAAK,SAAS,EAAE,MAAM,iBAAiB,QAAQ,KAAK,CAAC;AACrD,SAAK,aAAa,YAAY;AAAA,MAC5B;AAAA,MACA,YAAY;AAAA,MACZ,QAAQ,KAAK,UAAU,IAAI;AAAA,IAC7B,CAAC;AAAA,EACH;AAAA,EAEA,UAAU,KAAa,OAAO,IAAY;AACxC,WAAe,UAAU,KAAK,eAAe,KAAK,IAAI;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,SAAqF;AAC9F,WAAe,WAAW,KAAK,eAAe,OAAO;AAAA,EACvD;AAAA,EAEA,cAAsB;AACpB,WAAe,YAAY,KAAK,aAAa;AAAA,EAC/C;AAAA,EAEA,cAAc,OAA6B;AACzC,WAAe,cAAc,KAAK,eAAe,KAAK;AAAA,EACxD;AAAA,EAEA,OAAO,UAAgC;AACrC,WAAe,OAAO,KAAK,eAAe,QAAQ;AAAA,EACpD;AAAA,EAEA,WAAW,UAA2B;AACpC,WAAe,WAAW,KAAK,eAAe,QAAQ;AAAA,EACxD;AAAA,EAEA,mBAAmB,eAAuB,aAA8B;AACtE,WAAe,mBAAmB,KAAK,eAAe,eAAe,WAAW;AAAA,EAClF;AAAA,EAEA,MAAM,cAAc,aAA8C;AAChE,UAAM,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM,WAAW,CAAC;AAClD,UAAM,SAAyB,CAAC;AAChC,aAAS,KAAK,GAAG,KAAK,KAAK,qBAAqB,MAAM;AACpD,aAAO,KAAK,IAAI,aAAa,MAAM,CAAC;AAAA,IACtC;AACA,WAAO,KAAK,cAAc,cAAc,QAAQ,KAAK,gBAAgB;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAU,UAA0E;AAClF,WAAO,KAAK,aAAa,UAAU,QAAQ;AAAA,EAC7C;AAAA,EAEA,QAAQ,UAAmE;AACzE,WAAO,KAAK,aAAa,QAAQ,QAAQ;AAAA,EAC3C;AAAA,EAEA,QAAQ,UAAmE;AACzE,WAAO,KAAK,aAAa,QAAQ,QAAQ;AAAA,EAC3C;AAAA,EAEA,YAAY,UAAwE;AAClF,WAAO,KAAK,aAAa,YAAY,QAAQ;AAAA,EAC/C;AAAA,EAEA,gBAA+C;AAC7C,WAAO,KAAK,aAAa,cAAc;AAAA,EACzC;AAAA,EAEA,aAA2C;AACzC,WAAO,KAAK,aAAa,WAAW;AAAA,EACtC;AAAA,EAEA,YAA0C;AACxC,WAAO,KAAK,aAAa,UAAU;AAAA,EACrC;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,WAAW;AAClB;AAAA,IACF;AACA,SAAK,YAAY;AACjB,SAAK,UAAU,KAAK;AACpB,SAAK,aAAa,cAAc;AAChC,SAAK,aAAa,QAAQ;AAC1B,SAAK,cAAc,QAAQ;AAAA,EAC7B;AAAA,EAEQ,aAAgC;AACtC,WAAa,WAAW,KAAK,YAAY;AAAA,EAC3C;AAAA,EAEQ,YAAkB;AACxB,IAAM,UAAU,KAAK,YAAY;AAAA,EACnC;AAAA,EAEQ,mBAAmB,SAAkD;AAC3E,QAAI,KAAK,WAAW;AAClB;AAAA,IACF;AACA,QAAI,KAAK,kBAAkB;AACzB,WAAK,sBAAsB,KAAK,OAAO;AACvC;AAAA,IACF;AACA,SAAK,SAAS,OAAO;AAAA,EACvB;AAAA,EAEQ,6BAAmC;AACzC,QAAI,KAAK,aAAa,KAAK,sBAAsB,WAAW,GAAG;AAC7D;AAAA,IACF;AACA,UAAM,UAAU,KAAK,sBAAsB,OAAO,CAAC;AACnD,eAAW,WAAW,SAAS;AAC7B,WAAK,SAAS,OAAO;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,SAAS,SAAkC,UAAiC;AAClF,QAAI,KAAK,WAAW;AAClB;AAAA,IACF;AACA,QAAI,YAAY,SAAS,SAAS,GAAG;AACnC,WAAK,aAAa,KAAK,KAAK,YAAY,SAAS,QAAQ;AAAA,IAC3D,OAAO;AACL,WAAK,aAAa,KAAK,KAAK,YAAY,OAAO;AAAA,IACjD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAY,eAAmC;AAC7C,WAAO;AAAA,MACL,eAAe,KAAK;AAAA,MACpB,cAAc,KAAK;AAAA,MACnB,YAAY,KAAK;AAAA,MACjB,gBAAgB,KAAK;AAAA,MACrB,gBAAgB,KAAK;AAAA,MACrB,OAAO,KAAK;AAAA,MACZ,gBAAgB,KAAK;AAAA,MACrB,cAAc,KAAK;AAAA,MACnB,UAAU,CAAC,YAAY,KAAK,SAAS,OAAO;AAAA,MAC5C,iBAAiB,CAAC,WAAW,KAAK,gBAAgB,MAAM;AAAA,MACxD,WAAW,CAAC,UAAU,KAAK,UAAU,KAAK;AAAA,MAC1C,YAAY,MAAM,KAAK,WAAW;AAAA,MAClC,WAAW,MAAM,KAAK,UAAU;AAAA,MAChC,mBAAmB,CAAC,SAAS,UAAU,KAAK,kBAAkB,SAAS,KAAK;AAAA,MAC5E,oBAAoB,MAAM,KAAK;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,eAAmC;AAC7C,WAAO;AAAA,MACL,eAAe,KAAK;AAAA,MACpB,cAAc,KAAK;AAAA,MACnB,UAAU,CAAC,YAAY,KAAK,SAAS,OAAO;AAAA,MAC5C,oBAAoB,CAAC,YAAY,KAAK,mBAAmB,OAAO;AAAA,MAChE,iBAAiB,CAAC,WAAW,KAAK,gBAAgB,MAAM;AAAA,MACxD,iBAAiB,CAAC,WAAW,KAAK,gBAAgB,MAAM;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,oBAA6C;AACvD,WAAO;AAAA,MACL,eAAe,KAAK;AAAA,MACpB,iBAAiB,KAAK;AAAA,MACtB,UAAU,CAAC,YAAY,KAAK,SAAS,OAAO;AAAA,MAC5C,gBAAgB,CAAC,QAAQ,UAAU,KAAK,eAAe,QAAQ,KAAK;AAAA,IACtE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,iBAAuC;AACjD,WAAO;AAAA,MACL,eAAe,KAAK;AAAA,MACpB,cAAc,KAAK;AAAA,MACnB,qBAAqB,KAAK;AAAA,MAC1B,UAAU,CAAC,YAAY,KAAK,SAAS,OAAO;AAAA,MAC5C,kBAAkB,MAAM,KAAK;AAAA,MAC7B,kBAAkB,CAAC,WAAW;AAC5B,aAAK,gBAAgB;AAAA,MACvB;AAAA,MACA,iBAAiB,CAAC,WAAW,KAAK,gBAAgB,MAAM;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAY,mBAA2C;AACrD,WAAO;AAAA,MACL,eAAe,KAAK;AAAA,MACpB,cAAc,KAAK;AAAA,MACnB,cAAc,KAAK;AAAA,MACnB,gBAAgB,CAAC,QAAQ,UAAU,KAAK,eAAe,QAAQ,KAAK;AAAA,MACpE,iBAAiB,CAAC,WAAW,KAAK,gBAAgB,MAAM;AAAA,MACxD,WAAW,CAAC,UAAU,KAAK,UAAU,KAAK;AAAA,IAC5C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,eAAmC;AAC7C,WAAO;AAAA,MACL,eAAe,KAAK;AAAA,MACpB,cAAc,KAAK;AAAA,MACnB,UAAU,CAAC,YAAY,KAAK,SAAS,OAAO;AAAA,MAC5C,aAAa,MAAM,KAAK;AAAA,MACxB,aAAa,CAAC,QAAQ;AACpB,aAAK,WAAW;AAAA,MAClB;AAAA,MACA,kBAAkB,MAAM,KAAK;AAAA,MAC7B,kBAAkB,CAAC,cAAc;AAC/B,aAAK,gBAAgB;AAAA,MACvB;AAAA,MACA,kBAAkB,MAAM,KAAK;AAAA,MAC7B,kBAAkB,CAAC,aAAa;AAC9B,aAAK,gBAAgB;AAAA,MACvB;AAAA,MACA,0BAA0B,MAAM,KAAK;AAAA,MACrC,0BAA0B,CAAC,aAAa;AACtC,aAAK,wBAAwB;AAAA,MAC/B;AAAA,MACA,yBAAyB,CAAC,UAAU;AAClC,aAAK,uBAAuB;AAAA,MAC9B;AAAA,MACA,yBAAyB,MAAM,KAAK;AAAA,IACtC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,cAAiC;AAC3C,WAAO;AAAA,MACL,eAAe,KAAK;AAAA,MACpB,OAAO,KAAK;AAAA,MACZ,WAAW,KAAK;AAAA,MAChB,gBAAgB,MAAM,KAAK;AAAA,MAC3B,UAAU,CAAC,SAAS,aAAa,KAAK,SAAS,SAAS,QAAQ;AAAA,MAChE,iBAAiB,CAAC,WAAW,KAAK,gBAAgB,MAAM;AAAA,MACxD,iBAAiB,CAAC,WAAW,KAAK,gBAAgB,MAAM;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,gBAAqC;AAC/C,WAAO;AAAA,MACL,eAAe,KAAK;AAAA,MACpB,SAAS,KAAK;AAAA,MACd,iBAAiB,MAAM,KAAK;AAAA,MAC5B,iBAAiB,CAAC,UAAU;AAC1B,aAAK,eAAe;AAAA,MACtB;AAAA,MACA,UAAU,CAAC,YAAY,KAAK,SAAS,OAAO;AAAA,MAC5C,aAAa,CAAC,YAAY,KAAK,aAAa,YAAY,OAAO;AAAA,MAC/D,SAAS,CAAC,UAAU,QAAQ,YAAY,KAAK,QAAQ,UAAU,QAAQ,OAAO;AAAA,IAChF;AAAA,EACF;AAAA;AAAA;AAAA,EAIQ,aAAa,QAAyB,WAA2B;AACvE,QAAI,WAAW,UAAU;AACvB,aAAO,wBAAwB,SAAS;AAAA,IAC1C;AACA,WAAO,sBAAsB,KAAK,gBAAgB,MAAM,GAAG,SAAS;AAAA,EACtE;AAAA;AAAA;AAAA,EAIQ,kBAAkB,SAAiB,OAAwB;AACjE,SAAK,cAAc,aAAa,SAAS,KAAK;AAC9C,WAAO,KAAK,aAAa,YAAY;AAAA,MACnC;AAAA,MACA,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA,EAEQ,eAAe,QAAgB,OAAgC;AACrE,WAAO,eAAe,KAAK,eAAe,GAAG,QAAQ,KAAK;AAAA,EAC5D;AAAA,EAEQ,gBAAgB,QAAiC;AACvD,WAAO,gBAAgB,MAAM;AAAA,EAC/B;AAAA,EAEQ,gBAAgB,QAAiC;AACvD,UAAM,UAAU,KAAK,gBAAgB,MAAM;AAC3C,QAAI,CAAC,OAAO,UAAU,OAAO,KAAK,WAAW,GAAG;AAC9C,YAAM,IAAI,MAAM,oCAAoC,OAAO,MAAM,CAAC,EAAE;AAAA,IACtE;AACA,UAAM,WAAW,KAAK,aAAa,QAAQ,OAAO;AAClD,QAAI,YAAY,GAAG;AACjB,aAAO;AAAA,IACT;AACA,SAAK,aAAa,KAAK,OAAO;AAC9B,SAAK,UAAU;AACf,WAAO,KAAK,aAAa,SAAS;AAAA,EACpC;AAAA,EAEQ,UAAU,OAAuB;AACvC,UAAM,WAAW,KAAK,MAAM,KAAK;AACjC,QAAI,CAAC,OAAO,UAAU,QAAQ,KAAK,YAAY,GAAG;AAChD,YAAM,IAAI,MAAM,iCAAiC,OAAO,KAAK,CAAC,EAAE;AAAA,IAClE;AACA,UAAM,WAAW,KAAK,MAAM,UAAU,CAAC,QAAQ,IAAI,UAAU,QAAQ;AACrE,QAAI,YAAY,GAAG;AACjB,aAAO;AAAA,IACT;AACA,SAAK,MAAM,KAAK,EAAE,OAAO,SAAS,CAAC;AACnC,SAAK,UAAU;AACf,WAAO,KAAK,MAAM,SAAS;AAAA,EAC7B;AACF;;;AC3yBO,IAAM,2BAAoD;AAAA,EAC/D,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,cAAc;AAChB;AAEO,SAAS,uBAAuB,QAAwD;AAC7F,SAAO;AAAA,IACL,UAAU,OAAO,YAAY,yBAAyB;AAAA,IACtD,YAAY,OAAO,cAAc,yBAAyB;AAAA,IAC1D,cAAc,OAAO,gBAAgB,yBAAyB;AAAA,EAChE;AACF;;;AC5JO,IAAM,wCAAN,MAAM,sCAAqC;AAAA,EA6BhD,YACE,UAAuD,CAAC,GACxD,WACA;AA1BF,SAAQ,SAAS;AAOjB,SAAQ,iBAAiB,OAAO;AAGhC;AAAA;AAAA,SAAQ,kBAA2C,EAAE,GAAG,yBAAyB;AASjF,SAAiB,YAAY,oBAAI,IAAwB;AACzD,SAAiB,qBAAqB,oBAAI,IAAoB;AAC9D,SAAiB,oBAAoB,oBAAI,IAAwB;AAM/D,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,gBAAgB,CAAC,CAAC;AACrE,SAAK,YAAY;AACjB,SAAK,sBAAsB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,uBAAuB,IAAI,CAAC;AACtF,SAAK,cAAc,QAAQ,sBACvB,KAAK,4BAA4B,QAAQ,qBAAqB,QAAQ,mBAAmB,IACzF;AACJ,SAAK,gBAAgB,QAAQ,wBACzB,KAAK;AAAA,MACH,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV,IACA;AACJ,SAAK,YAAY,QAAQ,oBACrB,0BAA0B,QAAQ,mBAAmB,QAAQ,iBAAiB,IAC9E;AACJ,SAAK,YAAY,QAAQ,oBACrB;AAAA,MACE,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV,IACA;AACJ,SAAK,SAAS,IAAI,eAAe,KAAK,YAAY,KAAK,SAAS;AAGhE,SAAK,OAAO,gBAAgB,KAAK,cAAc,KAAK,SAAS;AAC7D,SAAK,iBAAiB,IAAI,MAAM,KAAK,YAAY;AACjD,aAAS,KAAK,GAAG,KAAK,KAAK,cAAc,MAAM;AAC7C,WAAK,eAAe,EAAE,IAAI,KAAK,OAAO,iBAAiB,IAAI,KAAK,SAAS;AAAA,IAC3E;AAIA,QAAI,KAAK,WAAW;AAClB,YAAM,WAAW,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,uBAAuB,KAAK,SAAS,CAAC;AACtF,WAAK,OAAO,wBAAwB,UAAU,KAAK,UAAU,KAAK;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,QAAQ,QAAsB,SAAiC;AAC7D,QAAI,KAAK,QAAQ;AACf,aAAO;AAAA,IACT;AACA,UAAM,SAAS,QAAQ,CAAC;AACxB,UAAM,cAAc,SAAS,CAAC;AAC9B,QAAI,CAAC,aAAa;AAChB,aAAO;AAAA,IACT;AACA,UAAM,SAAS,YAAY;AAC3B,QAAI,SAAS,KAAK,WAAW;AAC3B,iBAAW,WAAW,UAAU,CAAC,GAAG;AAClC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,WAAK,iBAAiB;AACtB,aAAO;AAAA,IACT;AAEA,SAAK,cAAc;AAMnB,QAAI,eAAe;AACnB,QAAI,eAAe,KAAK,WAAW;AACjC,UAAI,CAAC,sCAAqC,8BAA8B;AACtE,8CAAqC,+BAA+B;AAEpE,gBAAQ;AAAA,UACN,mDAAmD,YAAY,0CAC3B,KAAK,SAAS;AAAA,QACpD;AAAA,MACF;AACA,qBAAe,KAAK;AAAA,IACtB;AAMA,SAAK,KAAK,eAAe,CAAC,GAAG,cAAc,OAAO,GAAG;AACnD,WAAK,wBAAwB;AAAA,IAC/B;AAEA,UAAM,QAAQ,OAAO,CAAC;AAGtB,aAAS,KAAK,GAAG,KAAK,KAAK,cAAc,MAAM;AAC7C,YAAM,MAAM,KAAK,eAAe,EAAE;AAClC,YAAM,SAAS,QAAQ,EAAE;AACzB,UAAI,UAAU,OAAO,WAAW,cAAc;AAC5C,YAAI,IAAI,OAAO,SAAS,GAAG,YAAY,CAAC;AAAA,MAC1C,OAAO;AACL,YAAI,KAAK,GAAG,GAAG,YAAY;AAAA,MAC7B;AAAA,IACF;AAGA,SAAK,OAAO,gBAAgB,YAAY;AAExC,aAAS,KAAK,GAAG,KAAK,OAAO,QAAQ,MAAM;AACzC,YAAM,SAAS,OAAO,EAAE;AACxB,YAAM,SAAS,KAAK,eAAe,EAAE,KAAK,KAAK,eAAe,CAAC;AAC/D,UAAI,QAAQ;AACV,eAAO,IAAI,OAAO,SAAS,GAAG,KAAK,IAAI,OAAO,QAAQ,YAAY,CAAC,CAAC;AACpE,YAAI,OAAO,SAAS,cAAc;AAChC,iBAAO,KAAK,GAAG,YAAY;AAAA,QAC7B;AAAA,MACF,OAAO;AACL,eAAO,KAAK,CAAC;AAAA,MACf;AAAA,IACF;AACA,SAAK,iBAAiB;AACtB,SAAK,cAAc;AACnB,SAAK,aAAa;AAClB,SAAK,oBAAoB;AACzB,WAAO;AAAA,EACT;AAAA,EAEQ,0BAAgC;AACtC,aAAS,KAAK,GAAG,KAAK,KAAK,cAAc,MAAM;AAC7C,WAAK,eAAe,EAAE,IAAI,KAAK,OAAO,iBAAiB,IAAI,KAAK,SAAS;AAAA,IAC3E;AAAA,EACF;AAAA,EAEA,eAAe,SAA0C;AACvD,QAAI,CAAC,KAAK,QAAQ;AAChB,WAAK,aAAa,OAAO;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,SAAwC;AAClD,QAAI,KAAK,QAAQ;AACf;AAAA,IACF;AACA,YAAQ,QAAQ,MAAM;AAAA,MACpB,KAAK;AACH,aAAK,UAAU,MAAM;AACrB,mBAAW,QAAQ,QAAQ,OAAO;AAChC,cAAI,KAAK,OAAO,QAAW;AACzB,iBAAK,UAAU,IAAI,KAAK,IAAI,IAAI;AAAA,UAClC;AAAA,QACF;AACA,aAAK,OAAO,SAAS,QAAQ,KAAK;AAClC;AAAA,MACF,KAAK;AACH,mBAAW,UAAU,QAAQ,WAAW;AACtC,eAAK,UAAU,OAAO,MAAM;AAAA,QAC9B;AACA,mBAAW,QAAQ,QAAQ,SAAS;AAClC,cAAI,KAAK,OAAO,QAAW;AACzB,iBAAK,UAAU,IAAI,KAAK,IAAI,IAAI;AAAA,UAClC;AAAA,QACF;AACA,aAAK,OAAO,SAAS,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC,CAAC;AACxD;AAAA,MACF,KAAK,wBAAwB;AAC3B,cAAM,WAAW,KAAK,OAAO;AAAA,UAC3B,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,QACV;AACA,aAAK,mBAAmB,IAAI,QAAQ,QAAQ,SAAS,EAAE;AACvD,aAAK,kBAAkB,IAAI,QAAQ,QAAQ,QAAQ,IAAI;AACvD;AAAA,MACF;AAAA,MACA,KAAK,gBAAgB;AACnB,cAAM,aAAa,KAAK,mBAAmB,IAAI,QAAQ,MAAM;AAC7D,YAAI,eAAe,QAAW;AAC5B,eAAK,OAAO,eAAe,YAAY,QAAQ,WAAW,QAAQ,QAAQ;AAAA,QAC5E;AACA;AAAA,MACF;AAAA,MACA,KAAK,sBAAsB;AACzB,cAAM,aAAa,KAAK,mBAAmB,IAAI,QAAQ,MAAM;AAC7D,cAAM,OAAO,KAAK,kBAAkB,IAAI,QAAQ,MAAM;AACtD,YAAI,eAAe,UAAa,MAAM;AACpC,eAAK,UAAU,IAAI,QAAQ,QAAQ,EAAE,GAAG,MAAM,cAAc,WAAW,CAAC;AACxE,eAAK,kBAAkB,OAAO,QAAQ,MAAM;AAC5C,eAAK,OAAO,SAAS,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC,CAAC;AAAA,QAC1D;AACA;AAAA,MACF;AAAA,MACA,KAAK;AACH,aAAK,OAAO,aAAa,QAAQ,KAAK;AACtC;AAAA,MACF,KAAK;AACH,aAAK,OAAO,WAAW,QAAQ,OAAO;AACtC;AAAA,MACF,KAAK;AACH,aAAK,kBAAkB,uBAAuB,QAAQ,MAAM;AAC5D,aAAK,OAAO,aAAa,QAAQ,MAAM;AACvC;AAAA,MACF,KAAK;AACH,aAAK,OAAO,kBAAkB,QAAQ,SAAS,QAAQ,MAAM;AAC7D;AAAA,MACF,KAAK;AACH,YAAI,QAAQ,eAAe;AACzB,eAAK,OAAO,iBAAiB,QAAQ,aAAa;AAAA,QACpD,OAAO;AACL,eAAK,OAAO,SAAS,QAAQ,GAAG;AAAA,QAClC;AACA,YAAI,QAAQ,uBAAuB;AACjC,eAAK,OAAO,yBAAyB,QAAQ,qBAAqB;AAAA,QACpE,OAAO;AACL,eAAK,OAAO;AAAA,YACV,QAAQ,cAAc;AAAA,YACtB,QAAQ,cAAc;AAAA,UACxB;AAAA,QACF;AACA;AAAA,MACF,KAAK;AACH,YAAI,QAAQ,OAAO;AACjB,eAAK,OAAO,cAAc,QAAQ,KAAK;AAAA,QACzC;AACA,aAAK,OAAO,cAAc,QAAQ,KAAK;AACvC,mBAAW,SAAS,QAAQ,eAAe,CAAC,GAAG;AAC7C,eAAK,OAAO,kBAAkB,MAAM,SAAS,MAAM,SAAS;AAAA,QAC9D;AACA,mBAAW,SAAS,QAAQ,aAAa,CAAC,GAAG;AAC3C,eAAK,OAAO,gBAAgB,MAAM,OAAO,MAAM,SAAS;AAAA,QAC1D;AACA,YAAI,QAAQ,iBAAiB;AAC3B,eAAK,OAAO,mBAAmB,QAAQ,eAAe;AAAA,QACxD;AACA,mBAAW,WAAW,QAAQ,kBAAkB,CAAC,GAAG;AAClD,eAAK,OAAO,iBAAiB,QAAQ,SAAS,QAAQ,aAAa,QAAQ,aAAa;AAAA,QAC1F;AACA;AAAA,MACF,KAAK;AACH,aAAK,OAAO,iBAAiB,QAAQ,UAAU,QAAQ,YAAY;AACnE,aAAK,OAAO,iBAAiB,QAAQ,MAAM;AAC3C,aAAK,OAAO,uBAAuB,QAAQ,mBAAmB;AAC9D,aAAK,OAAO,gBAAgB,QAAQ,aAAa,SAAS,QAAQ,aAAa,IAAI;AACnF;AAAA,MACF,KAAK;AACH,aAAK,OAAO,wBAAwB,QAAQ,SAAS,QAAQ,WAAW,QAAQ,QAAQ;AACxF;AAAA,MACF,KAAK;AACH,aAAK,OAAO,yBAAyB,QAAQ,WAAW,QAAQ,QAAQ;AACxE;AAAA,MACF,KAAK;AACH,aAAK,OAAO;AAAA,UACV,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,QACV;AACA;AAAA,MACF,KAAK;AACH,aAAK,OAAO;AAAA,UACV,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,QACV;AACA;AAAA,MACF,KAAK;AACH,aAAK,OAAO;AAAA,UACV,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,QACV;AACA;AAAA,MACF,KAAK;AACH,aAAK,OAAO;AAAA,UACV,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,QACV;AACA;AAAA,MACF,KAAK;AACH,aAAK,OAAO;AAAA,UACV,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,QACV;AACA;AAAA,MACF,KAAK;AACH,aAAK,OAAO,iBAAiB,QAAQ,SAAS,QAAQ,GAAG;AACzD;AAAA,MACF,KAAK;AACH,aAAK,OAAO,oBAAoB,QAAQ,SAAS,QAAQ,MAAM;AAC/D;AAAA,MACF,KAAK;AACH,aAAK,OAAO,qBAAqB,QAAQ,SAAS,QAAQ,OAAO;AACjE;AAAA,MACF,KAAK;AACH,aAAK,OAAO,qBAAqB,QAAQ,SAAS,QAAQ,SAAS,QAAQ,QAAQ;AACnF;AAAA,MACF,KAAK;AACH,aAAK,OAAO,iCAAiC,QAAQ,SAAS,QAAQ,YAAY;AAClF;AAAA,MACF,KAAK;AACH,aAAK,OAAO,qBAAqB,QAAQ,QAAQ,QAAQ,aAAa;AACtE;AAAA,MACF,KAAK;AACH,aAAK,OAAO,mBAAmB,QAAQ,OAAO,QAAQ,aAAa;AACnE;AAAA,MACF,KAAK;AACH,aAAK,OAAO,cAAc,QAAQ,IAAI;AACtC;AAAA,MACF,KAAK;AACH,aAAK,OAAO,iBAAiB,QAAQ,QAAQ,QAAQ,aAAa;AAClE;AAAA,MACF,KAAK;AACH,aAAK,OAAO,UAAU,QAAQ,eAAe,QAAQ,cAAc,EAAE;AACrE;AAAA,MACF,KAAK;AACH,aAAK,OAAO,YAAY,QAAQ,aAAa;AAC7C;AAAA,MACF,KAAK;AACH,aAAK,OAAO;AAAA,UACV,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,QACV;AACA;AAAA,MACF,KAAK;AACH,aAAK,OAAO;AAAA,UACV,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,QACV;AACA;AAAA,MACF,KAAK;AACH,aAAK,OAAO;AAAA,UACV,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,QACV;AACA;AAAA,MACF,KAAK;AACH,aAAK,OAAO,cAAc,QAAQ,eAAe,QAAQ,MAAM,QAAQ,WAAW;AAClF;AAAA,MACF,KAAK;AACH,aAAK,OAAO,cAAc,QAAQ,WAAW;AAC7C;AAAA,MACF,KAAK;AACH,aAAK,OAAO,2BAA2B,QAAQ,eAAe,QAAQ,QAAQ;AAC9E;AAAA,MACF,KAAK;AACH,aAAK,OAAO,4BAA4B,QAAQ,OAAO;AACvD;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,sBAAsB,SAAkD;AACtE,QAAI,KAAK,QAAQ;AACf;AAAA,IACF;AACA,QAAI;AACF,UAAI,QAAQ,OAAO,UAAU;AAC3B,cAAM,SAAS,KAAK,OAAO,cAAc;AACzC,aAAK,WAAW,cAAc;AAAA,UAC5B,MAAM;AAAA,UACN,WAAW,QAAQ;AAAA,UACnB,IAAI;AAAA,UACJ,QAAQ;AAAA,YACN,gBAAgB,OAAO;AAAA,YACvB,eAAe,OAAO;AAAA,YACtB,OAAO,OAAO;AAAA,YACd,cAAc,OAAO;AAAA,YACrB,QAAQ,OAAO;AAAA,YACf,qBAAqB,OAAO;AAAA,UAC9B;AAAA,QACF,CAA8C;AAC9C;AAAA,MACF;AACA,UAAI,QAAQ,OAAO,QAAQ;AACzB,cAAM,WAAW,KAAK,OAAO,cAAc;AAC3C,cAAM,WAAuB,CAAC;AAC9B,iBAAS,KAAK,GAAG,KAAK,SAAS,QAAQ,MAAM;AAC3C,gBAAM,SAAS,SAAS,EAAE;AAC1B,gBAAM,OAAiB,CAAC;AACxB,mBAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,iBAAK,KAAK,OAAO,OAAO,CAAC,CAAC,CAAC;AAAA,UAC7B;AACA,mBAAS,KAAK,IAAI;AAAA,QACpB;AACA,aAAK,WAAW,cAAc;AAAA,UAC5B,MAAM;AAAA,UACN,WAAW,QAAQ;AAAA,UACnB,IAAI;AAAA,UACJ;AAAA,QACF,CAA8C;AAC9C;AAAA,MACF;AACA,WAAK,OAAO,aAAa;AACzB,WAAK,WAAW,cAAc;AAAA,QAC5B,MAAM;AAAA,QACN,WAAW,QAAQ;AAAA,QACnB,IAAI;AAAA,MACN,CAA8C;AAAA,IAChD,SAAS,OAAO;AACd,WAAK,WAAW,cAAc;AAAA,QAC5B,MAAM;AAAA,QACN,WAAW,QAAQ;AAAA,QACnB,IAAI;AAAA,QACJ,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC9D,CAA8C;AAAA,IAChD;AAAA,EACF;AAAA,EAEA,wBAAwB,SAAoD;AAC1E,QAAI,KAAK,QAAQ;AACf;AAAA,IACF;AACA,QAAI;AACF,WAAK,WAAW,cAAc;AAAA,QAC5B,MAAM;AAAA,QACN,WAAW,QAAQ;AAAA,QACnB,IAAI;AAAA,QACJ,OAAO,KAAK,OAAO,kBAAkB;AAAA,MACvC,CAAgD;AAAA,IAClD,SAAS,OAAO;AACd,WAAK,WAAW,cAAc;AAAA,QAC5B,MAAM;AAAA,QACN,WAAW,QAAQ;AAAA,QACnB,IAAI;AAAA,QACJ,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC9D,CAAgD;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,QAAI,CAAC,KAAK,QAAQ;AAChB,WAAK,OAAO,QAAQ;AACpB,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AAAA,EAEQ,gBAAsB;AAC5B,QAAI,CAAC,KAAK,aAAa;AACrB;AAAA,IACF;AACA,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,YAAM,UAAU,iCAAiC,KAAK,WAAW;AACjE,UAAI,CAAC,SAAS;AACZ;AAAA,MACF;AACA,WAAK,aAAa,OAAO;AAAA,IAC3B;AAAA,EACF;AAAA,EAEQ,aAAa,SAA0C;AAC7D,UAAM,aAAa,OAAO,QAAQ,cAAc,EAAE;AAClD,YAAQ,QAAQ,MAAM;AAAA,MACpB;AAGE,aAAK,OAAO;AAAA,UACV,KAAK,MAAM,OAAO,QAAQ,YAAY,CAAC,CAAC;AAAA,UACxC,OAAO,QAAQ,YAAY,CAAC;AAAA,UAC5B;AAAA,QACF;AACA;AAAA,MACF;AACE,aAAK,OAAO;AAAA,UACV,KAAK,MAAM,OAAO,QAAQ,YAAY,CAAC,CAAC;AAAA,UACxC,OAAO,QAAQ,YAAY,CAAC;AAAA,UAC5B;AAAA,QACF;AACA;AAAA,MACF;AACE,aAAK,OAAO,KAAK,UAAU;AAC3B;AAAA,MACF;AACE,aAAK,OAAO,KAAK,UAAU;AAC3B;AAAA,MACF;AACE,aAAK,OAAO,WAAW,OAAO,QAAQ,UAAU,CAAC,GAAG,UAAU;AAC9D;AAAA,MACF;AACE,aAAK,OAAO,QAAQ,OAAO,QAAQ,YAAY,CAAC,GAAG,UAAU;AAC7D;AAAA,MACF;AACE,aAAK,OAAO,SAAS,OAAO,QAAQ,YAAY,GAAG,CAAC;AACpD;AAAA,MACF;AACE,aAAK,OAAO;AAAA,UACV,OAAO,QAAQ,YAAY,CAAC;AAAA,UAC5B,OAAO,QAAQ,UAAU,CAAC,IAAI;AAAA,UAC9B,QAAQ,aAAa;AAAA,QACvB;AACA;AAAA,MACF;AACE,aAAK,OAAO,WAAW,QAAQ,QAAQ,MAAM,CAAC;AAC9C;AAAA,MACF;AAGE,aAAK,OAAO;AAAA,UACV,OAAO,QAAQ,UAAU,CAAC;AAAA,UAC1B,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,QAAQ,YAAY,CAAC,CAAC,CAAC;AAAA,UACrD;AAAA,QACF;AACA;AAAA,MACF;AAKE,aAAK,OAAO,aAAa;AAAA,UACvB,SAAS,QAAQ,QAAQ,MAAM;AAAA,UAC/B,UAAU,KAAK,gBAAgB;AAAA,UAC/B,YAAY,KAAK,gBAAgB;AAAA,UACjC,cAAc,KAAK,gBAAgB;AAAA,QACrC,CAAC;AACD;AAAA,MACF;AAGE,aAAK,OAAO,WAAW,KAAK,MAAM,OAAO,QAAQ,YAAY,CAAC,CAAC,GAAG,UAAU;AAC5E;AAAA,MACF;AACE,aAAK,OAAO;AAAA,UACV,KAAK,MAAM,OAAO,QAAQ,YAAY,CAAC,CAAC;AAAA,UACxC,SAAS,OAAO,QAAQ,UAAU,CAAC,IAAI,OAAS,CAAC;AAAA,UACjD,SAAS,OAAO,QAAQ,UAAU,CAAC,IAAI,OAAS,CAAC;AAAA,UACjD;AAAA,QACF;AACA;AAAA,MACF;AACE,aAAK,uBAAuB;AAAA,UAC1B;AAAA,UACA;AAAA,UACA,aAAa;AAAA,UACb,gBAAgB;AAAA,UAChB,uBAAuB;AAAA,UACvB,uBAAuB;AAAA,UACvB,OAAO,OAAO,QAAQ,IAAI;AAAA,QAC5B,CAAC;AACD;AAAA,IACJ;AAAA,EACF;AAAA,EAEQ,mBAAyB;AAC/B,eAAW,QAAQ,KAAK,OAAO,eAAe,EAAE,GAAG;AACjD,WAAK,uBAAuB,oBAAoB,IAAI,CAAC;AAAA,IACvD;AAAA,EACF;AAAA,EAEQ,uBAAuB,QAA2C;AACxE,QAAI,KAAK,eAAe;AACtB,2CAAqC,KAAK,eAAe,MAAM;AAC/D;AAAA,IACF;AACA,SAAK,WAAW,cAAc,MAAM;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaQ,gBAAsB;AAC5B,QAAI,KAAK,uBAAuB,KAAM,CAAC,KAAK,aAAa,CAAC,KAAK,WAAY;AACzE;AAAA,IACF;AACA,eAAW,QAAQ,KAAK,OAAO,oBAAoB,EAAE,GAAG;AACtD,YAAM,QAAQ,gBAAgB,IAAI;AAClC,UACE,MAAM,UAAU,KAAK,kBACrB,MAAM,QAAQ,KAAK,iBAAiB,KAAK,qBACzC;AACA;AAAA,MACF;AACA,UAAI,MAAM,UAAU,KAAK,gBAAgB;AACvC,aAAK,iBAAiB,MAAM;AAAA,MAC9B;AAKA,UAAI,KAAK,WAAW;AAClB,aAAK,eAAe,KAAK;AAAA,MAC3B,OAAO;AACL,aAAK,WAAW,UAAU,KAAK;AAC/B,aAAK,WAAW,cAAc,KAAK;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,eAAe,OAAyC;AAC9D,UAAM,OAAO,KAAK;AAClB,QAAI,CAAC,MAAM;AACT;AAAA,IACF;AACA,UAAM,aAAa,QAAQ,KAAK,KAAK,QAAQ,CAAC;AAC9C,UAAM,SAAU,aAAa,KAAK,WAAY;AAC9C,SAAK,QAAQ,MAAM,IAAI,cAAc,MAAM,KAAK;AAChD,SAAK,QAAQ,SAAS,CAAC,IAAI,cAAc,MAAM,KAAK;AACpD,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,EAAE,IAAI,MAAM;AAClC,SAAK,QAAQ,SAAS,EAAE,IAAI,MAAM;AAClC,SAAK,QAAQ,SAAS,EAAE,IAAI,MAAM;AAClC,SAAK,QAAQ,SAAS,EAAE,IAAI,MAAM;AAClC,YAAQ,MAAM,KAAK,QAAQ,GAAG,aAAa,CAAC;AAAA,EAM9C;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAqB;AAC3B,UAAM,OAAO,KAAK;AAClB,QAAI,CAAC,MAAM;AACT;AAAA,IACF;AACA,eAAW,QAAQ,KAAK,OAAO,oBAAoB,EAAE,GAAG;AACtD,WAAK,eAAe,MAAM,IAAI;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,sBAA4B;AAClC,QAAI,CAAC,KAAK,WAAW,aAAa;AAChC;AAAA,IACF;AACA,UAAM,SAAS,KAAK,OAAO,kBAAkB,GAAG;AAChD,QAAI,OAAO,WAAW,GAAG;AACvB;AAAA,IACF;AACA,SAAK,UAAU,YAAY,EAAE,MAAM,gBAAgB,OAAO,CAAC;AAAA,EAC7D;AAAA,EAEQ,eAAe,MAA6B,QAAoC;AACtF,UAAM,aAAa,QAAQ,KAAK,KAAK,QAAQ,CAAC;AAC9C,UAAM,OAAQ,aAAa,KAAK,WAAY,KAAK;AACjD,SAAK,QAAQ,IAAI,IAAI,cAAc,OAAO,WAAW;AACrD,SAAK,QAAQ,OAAO,CAAC,IAAI,cAAc,OAAO,WAAW;AACzD,SAAK,QAAQ,OAAO,CAAC,IAAI,OAAO;AAChC,UAAM,YAAY,KAAK,IAAI,KAAK,OAAO,OAAO,MAAM,MAAM;AAC1D,SAAK,QAAQ,OAAO,CAAC,IAAI;AACzB,UAAM,aAAa,KAAK,IAAI,KAAK,WAAW,OAAO,OAAO,MAAM;AAChE,SAAK,QAAQ,OAAO,CAAC,IAAI;AACzB,UAAM,YAAY,OAAO;AACzB,aAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AAClC,WAAK,QAAQ,YAAY,CAAC,IAAI,OAAO,MAAM,CAAC;AAAA,IAC9C;AACA,UAAM,aAAa,YAAY,KAAK;AACpC,aAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,YAAM,QAAQ,OAAO,OAAO,CAAC;AAC7B,WAAK,QAAQ,aAAa,IAAI,CAAC,IAAI,MAAM;AACzC,WAAK,QAAQ,aAAa,IAAI,IAAI,CAAC,IAAI,MAAM;AAAA,IAC/C;AACA,YAAQ,MAAM,KAAK,QAAQ,GAAG,aAAa,CAAC;AAAA,EAI9C;AAAA,EAEQ,4BACN,cACA,kBAC+B;AAC/B,UAAM,OAAO;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO,EAAE,cAAc,QAAQ,KAAK,QAAQ,MAAM,KAAK,MAAM,UAAU,KAAK,SAAS;AAAA,EACvF;AAAA,EAEQ,8BACN,cACA,kBACiC;AACjC,UAAM,OAAO;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO,EAAE,cAAc,QAAQ,KAAK,QAAQ,MAAM,KAAK,MAAM,UAAU,KAAK,SAAS;AAAA,EACvF;AACF;AAzuBa,sCACI,+BAA+B;AADzC,IAAM,uCAAN;;;AClCA,SAAS,6CACd,OAAO,oCACD;AACN,QAAM,QAAQ;AAId,MAAI,CAAC,MAAM,yBAAyB,CAAC,MAAM,mBAAmB;AAC5D,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AACA,QAAM,OAAO,MAAM;AAAA,EACnB,MAAM,uDAAuD,KAAK;AAAA,IAKhE,YAAY,SAA8E;AACxF,YAAM;AAJR,WAAiB,kBAA6B,CAAC;AAK7C,YAAM,OAAO,KAAK;AAClB,YAAM,mBAAmB,SAAS,oBAAoB,CAAC;AACvD,WAAK,KAAK,iBAAiB,kBAAkB,IAAI;AACjD,YAAM,YAAY,CAAC,UAA6B;AAC9C,YAAI,CAAC,KAAK,QAAQ;AAChB,cAAI,KAAK,gBAAgB,SAAS,MAAM;AACtC,iBAAK,gBAAgB,KAAK,MAAM,IAAI;AAAA,UACtC;AACA;AAAA,QACF;AACA,YAAI,sBAAsB,MAAM,IAAI,GAAG;AACrC,eAAK,OAAO,eAAe,MAAM,IAAI;AAAA,QACvC,WAAW,oBAAoB,MAAM,IAAI,GAAG;AAC1C,eAAK,OAAO,YAAY,MAAM,IAAI;AAAA,QACpC,WAAW,8BAA8B,MAAM,IAAI,GAAG;AACpD,eAAK,OAAO,sBAAsB,MAAM,IAAI;AAAA,QAC9C,WAAW,gCAAgC,MAAM,IAAI,GAAG;AACtD,eAAK,OAAO,wBAAwB,MAAM,IAAI;AAAA,QAChD;AAAA,MACF;AACA,UAAI,MAAM,kBAAkB;AAC1B,aAAK,iBAAiB,WAAW,SAAS;AAC1C,aAAK,QAAQ;AAAA,MACf,WAAW,MAAM;AACf,aAAK,YAAY;AAAA,MACnB;AAAA,IACF;AAAA,IAEA,QAAQ,QAAsB,SAAiC;AAC7D,UAAI,KAAK,QAAQ;AACf,eAAO,KAAK,OAAO,QAAQ,QAAQ,OAAO;AAAA,MAC5C;AACA,YAAM,SAAS,QAAQ,CAAC;AACxB,iBAAW,WAAW,UAAU,CAAC,GAAG;AAClC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,aAAO;AAAA,IACT;AAAA,IAEQ,wBAA8B;AACpC,YAAM,WAAW,KAAK,gBAAgB,OAAO,CAAC;AAC9C,iBAAW,QAAQ,UAAU;AAC3B,YAAI,sBAAsB,IAAI,GAAG;AAC/B,eAAK,QAAQ,eAAe,IAAI;AAAA,QAClC,WAAW,oBAAoB,IAAI,GAAG;AACpC,eAAK,QAAQ,YAAY,IAAI;AAAA,QAC/B,WAAW,8BAA8B,IAAI,GAAG;AAC9C,eAAK,QAAQ,sBAAsB,IAAI;AAAA,QACzC,WAAW,gCAAgC,IAAI,GAAG;AAChD,eAAK,QAAQ,wBAAwB,IAAI;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAAA,IAEA,MAAc,iBACZ,SACA,MACe;AACf,UAAI;AACF,cAAMC,eACJ,WACA;AACF,YAAIA,cAAa;AACf,gBAAMA;AAAA,QACR;AACA,YAAI,CAAC,cAAc,GAAG;AAKpB,gBAAM,gBACJ,WAGA;AACF,cAAI,CAAC,eAAe;AAClB,kBAAM,IAAI,MAAM,mDAAmD;AAAA,UACrE;AACA,gBAAM,KAAiB;AAAA,YACrB,YAAY,CAAC,SAAS;AAAA,YACtB,YAAY,QAAQ;AAAA,YACpB;AAAA,UACF,CAAC;AAAA,QACH;AACA,aAAK,SAAS,IAAI,qCAAqC,SAAS;AAAA,UAC9D,aAAa,CAAC,YAAY,MAAM,cAAc,OAAO;AAAA,UACrD,SAAS,CAAC,UAAU,MAAM,cAAc,KAAK;AAAA,QAC/C,CAAC;AACD,mBAAW,WAAW,QAAQ,uBAAuB,CAAC,GAAG;AACvD,eAAK,OAAO,YAAY,OAAO;AAAA,QACjC;AACA,mBAAW,WAAW,QAAQ,mBAAmB,CAAC,GAAG;AACnD,eAAK,OAAO,eAAe,OAAO;AAAA,QACpC;AACA,aAAK,sBAAsB;AAC3B,cAAM,cAAc,EAAE,MAAM,SAAS,eAAe,SAAS,CAAC;AAAA,MAChE,SAAS,OAAO;AACd,cAAM,cAAc;AAAA,UAClB,MAAM;AAAA,UACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAChE,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACA,QAAM,kBAAkB,MAAM,8CAA8C;AAC9E;;;ACvGO,IAAM,yBAAN,MAA6B;AAAA,EAgBlC,YAAY,SAAwC,WAA8B;AAXlF,SAAQ,SAAS;AACjB,SAAQ,kBAAkB;AAC1B,SAAQ,iBAAiB;AAGzB,SAAQ,oBAAoB;AAO1B,QAAI,CAAC,QAAQ,WAAW;AACtB,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC1C;AACA,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,sBAAsB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,uBAAuB,IAAI,CAAC;AACtF,SAAK,yBAAyB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,0BAA0B,CAAC,CAAC;AACzF,SAAK,YAAY;AACjB,SAAK,sBAAsB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,uBAAuB,IAAI,CAAC;AACtF,SAAK,YAAY,QAAQ,oBACrB,0BAA0B,QAAQ,mBAAmB,QAAQ,iBAAiB,IAC9E;AACJ,SAAK,eAAe,QAAQ,uBACxB;AAAA,MACE,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV,IACA;AACJ,UAAM,oBAAoB,KAAK,cAAc,SAAS,KAAK,IAAI,GAAG,QAAQ,iBAAiB,EAAE;AAC7F,SAAK,gBAAgB,IAAI,aAAa,iBAAiB;AACvD,SAAK,QAAQ,MAAM,cAAc,QAAQ,WAAW,KAAK,YAAY,KAAK,SAAS;AACnF,SAAK,MAAM,QAAQ;AACnB,UAAM,kBAAkB,KAAK,MAAM,WAAW;AAC9C,UAAM,aAAa,QAAQ,cAAc;AACzC,QAAI,eAAe,iBAAiB;AAClC,YAAM,IAAI,MAAM,8CAA8C;AAAA,IAChE;AACA,SAAK,WAAW,KAAK,MAAM,qBAAqB;AAAA,EAClD;AAAA,EAEA,QAAQ,QAAsB,SAAiC;AAC7D,QAAI,KAAK,QAAQ;AACf,aAAO;AAAA,IACT;AACA,UAAM,SAAS,QAAQ,CAAC;AACxB,UAAM,UAAU,SAAS,CAAC;AAC1B,UAAM,WAAW,SAAS,CAAC;AAC3B,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,IACT;AACA,UAAM,SAAS,QAAQ;AAOvB,UAAM,SAAS,KAAK,IAAI,QAAQ,KAAK,SAAS;AAE9C,aAAS,QAAQ,GAAG,QAAQ,KAAK,SAAS,WAAW,QAAQ,SAAS;AACpE,YAAM,QAAQ,OAAO,KAAK;AAC1B,YAAM,OAAO,QAAQ,CAAC;AACtB,YAAM,QAAQ,QAAQ,CAAC;AACvB,YAAM,aAAa,KAAK,SAAS,WAAW,KAAK;AACjD,YAAM,cAAc,KAAK,SAAS,YAAY,KAAK;AACnD,UAAI,QAAQ,KAAK,UAAU,QAAQ;AACjC,mBAAW,IAAI,KAAK,SAAS,GAAG,MAAM,CAAC;AACvC,YAAI,SAAS,MAAM,UAAU,QAAQ;AACnC,sBAAY,IAAI,MAAM,SAAS,GAAG,MAAM,CAAC;AAAA,QAC3C,OAAO;AACL,sBAAY,IAAI,KAAK,SAAS,GAAG,MAAM,CAAC;AAAA,QAC1C;AAAA,MACF,OAAO;AACL,mBAAW,KAAK,CAAC;AACjB,oBAAY,KAAK,CAAC;AAAA,MACpB;AAAA,IACF;AAEA,SAAK,SAAS,QAAQ,MAAM;AAC5B,QAAI,WAAW,QAAQ;AACrB,cAAQ,IAAI,KAAK,SAAS,QAAQ,SAAS,GAAG,MAAM,CAAC;AACrD,UAAI,UAAU;AACZ,iBAAS,IAAI,KAAK,SAAS,SAAS,SAAS,GAAG,MAAM,CAAC;AAAA,MACzD;AAAA,IACF,OAAO;AAEL,cAAQ,KAAK,CAAC;AACd,cAAQ,IAAI,KAAK,SAAS,QAAQ,SAAS,GAAG,MAAM,CAAC;AACrD,UAAI,UAAU;AACZ,iBAAS,KAAK,CAAC;AACf,iBAAS,IAAI,KAAK,SAAS,SAAS,SAAS,GAAG,MAAM,CAAC;AAAA,MACzD;AAAA,IACF;AACA,SAAK,mBAAmB;AACxB,SAAK;AAAA,MACH,KAAK,SAAS,QAAQ,SAAS,GAAG,MAAM;AAAA,MACxC,KAAK,SAAS,SAAS,SAAS,GAAG,MAAM;AAAA,IAC3C;AACA,SAAK;AAAA,MACH,KAAK,SAAS,QAAQ,SAAS,GAAG,MAAM;AAAA,MACxC,KAAK,SAAS,SAAS,SAAS,GAAG,MAAM;AAAA,IAC3C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,eAAe,SAAqC;AAClD,QAAI,KAAK,QAAQ;AACf;AAAA,IACF;AACA,QAAI,QAAQ,SAAS,WAAW;AAC9B,WAAK,QAAQ;AACb;AAAA,IACF;AACA,QAAI,QAAQ,SAAS,oBAAoB;AACvC,WAAK,sBAAsB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,MAAM,CAAC;AACjE;AAAA,IACF;AACA,QAAI,QAAQ,SAAS,4BAA4B;AAC/C,WAAK,MAAM;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ,aAAa,KAAK;AAAA,QAC1B,QAAQ;AAAA,QACR,QAAQ,SAAS;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,QAAI,CAAC,KAAK,QAAQ;AAChB,WAAK,MAAM,OAAO;AAClB,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AAAA,EAEQ,aAAa,MAAoB,OAA2B;AAClE,QAAI,CAAC,KAAK,aAAa,KAAK,uBAAuB,GAAG;AACpD;AAAA,IACF;AACA,QAAI,KAAK,kBAAkB,KAAK,iBAAiB,KAAK,qBAAqB;AACzE;AAAA,IACF;AACA,SAAK,iBAAiB,KAAK;AAE3B,QAAI,QAAQ;AACZ,QAAI,QAAQ;AACZ,QAAI,OAAO;AACX,QAAI,OAAO;AACX,QAAI,QAAQ;AACZ,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAM,IAAI,KAAK,CAAC,KAAK;AACrB,YAAM,IAAI,MAAM,CAAC,KAAK;AACtB,YAAM,OAAO,KAAK,IAAI,CAAC;AACvB,YAAM,OAAO,KAAK,IAAI,CAAC;AACvB,UAAI,OAAO,OAAO;AAChB,gBAAQ;AAAA,MACV;AACA,UAAI,OAAO,OAAO;AAChB,gBAAQ;AAAA,MACV;AACA,cAAQ,IAAI;AACZ,cAAQ,IAAI;AACZ,eAAS,IAAI;AAAA,IACf;AACA,UAAM,OAAO,KAAK,KAAK,OAAO,KAAK,IAAI,GAAG,KAAK,MAAM,CAAC;AACtD,UAAM,OAAO,KAAK,KAAK,OAAO,KAAK,IAAI,GAAG,MAAM,MAAM,CAAC;AACvD,UAAM,cAAc,KAAK,KAAK,OAAO,IAAI;AACzC,UAAM,QAAoC;AAAA,MACxC,MAAM;AAAA,MACN,UAAU;AAAA,MACV,OAAO,KAAK;AAAA,MACZ,SAAS,KAAK,KAAK;AAAA,MACnB,SAAS,KAAK,KAAK;AAAA,MACnB,QAAQ,KAAK,IAAI;AAAA,MACjB,QAAQ,KAAK,IAAI;AAAA,MACjB,aAAa,cAAc,IAAI,QAAQ,cAAc;AAAA,MACrD,aAAa,KAAK,KAAK;AAAA,MACvB,aAAa,KAAK,KAAK;AAAA,MACvB,eAAe,OAAO;AAAA,MACtB,eAAe,OAAO;AAAA,MACtB,gBAAgB,OAAO;AAAA,MACvB,iBAAiB,OAAO;AAAA,IAC1B;AACA,SAAK,UAAU,UAAU,KAAK;AAC9B,QAAI,KAAK,WAAW;AAClB,WAAK,eAAe,KAAK;AAAA,IAC3B,OAAO;AACL,WAAK,UAAU,cAAc,KAAK;AAAA,IACpC;AAAA,EACF;AAAA,EAEQ,eAAe,OAAyC;AAC9D,UAAM,OAAO,KAAK;AAClB,QAAI,CAAC,MAAM;AACT;AAAA,IACF;AACA,UAAM,aAAa,QAAQ,KAAK,KAAK,QAAQ,CAAC;AAC9C,UAAM,SAAU,aAAa,KAAK,WAAY;AAC9C,SAAK,QAAQ,MAAM,IAAI,cAAc,MAAM,KAAK;AAChD,SAAK,QAAQ,SAAS,CAAC,IAAI,cAAc,MAAM,KAAK;AACpD,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,SAAS,EAAE,IAAI,MAAM;AAClC,SAAK,QAAQ,SAAS,EAAE,IAAI,MAAM;AAClC,SAAK,QAAQ,SAAS,EAAE,IAAI,MAAM;AAClC,SAAK,QAAQ,SAAS,EAAE,IAAI,MAAM;AAClC,YAAQ,MAAM,KAAK,QAAQ,GAAG,aAAa,CAAC;AAAA,EAM9C;AAAA,EAEQ,gBAAgB,MAAoB,OAA2B;AACrE,QAAI,KAAK,0BAA0B,GAAG;AACpC;AAAA,IACF;AACA,QAAI,KAAK,kBAAkB,KAAK,oBAAoB,KAAK,wBAAwB;AAC/E;AAAA,IACF;AACA,SAAK,oBAAoB,KAAK;AAC9B,SAAK,gBAAgB,MAAM,KAAK;AAChC,QAAI,KAAK,cAAc;AACrB,WAAK,kBAAkB,KAAK,iBAAiB,KAAK,aAAa;AAC/D;AAAA,IACF;AACA,UAAM,WAA0C;AAAA,MAC9C,MAAM;AAAA,MACN,OAAO,KAAK;AAAA,MACZ,OAAO,IAAI,aAAa,KAAK,aAAa;AAAA,IAC5C;AACA,SAAK,WAAW,aAAa,QAAQ;AACrC,SAAK,WAAW,cAAc,QAAQ;AAAA,EACxC;AAAA,EAEQ,gBAAgB,MAAoB,OAA2B;AAQrE,UAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,QAAQ,MAAM,MAAM,CAAC;AACzD,UAAM,UAAU,KAAK,MAAM,IAAI,CAAC;AAChC,aAAS,OAAO,GAAG,OAAO,KAAK,cAAc,QAAQ,QAAQ;AAC3D,UAAI,QAAQ,SAAS;AACnB,aAAK,cAAc,IAAI,IAAI,cAAc,CAAC;AAC1C;AAAA,MACF;AACA,YAAM,MAAM,OAAO;AACnB,UAAI,OAAO;AACX,UAAI,OAAO;AACX,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,cAAM,SAAS,QAAQ,KAAK,CAAC,KAAK,MAAM,MAAM,CAAC,KAAK;AACpD,cAAM,QAAS,KAAK,KAAK,KAAK,MAAM,IAAK;AACzC,gBAAQ,SAAS,KAAK,IAAI,KAAK;AAC/B,gBAAQ,SAAS,KAAK,IAAI,KAAK;AAAA,MACjC;AACA,WAAK,cAAc,IAAI,IAAI,cAAe,IAAI,KAAK,MAAM,MAAM,IAAI,IAAK,CAAC;AAAA,IAC3E;AAAA,EACF;AAAA,EAEQ,kBAAkB,OAAe,OAA2B;AAClE,UAAM,OAAO,KAAK;AAClB,QAAI,CAAC,MAAM;AACT;AAAA,IACF;AACA,UAAM,aAAa,QAAQ,KAAK,KAAK,QAAQ,CAAC;AAC9C,UAAM,SAAU,aAAa,KAAK,WAAY,KAAK;AACnD,SAAK,QAAQ,MAAM,IAAI,cAAc,KAAK;AAC1C,SAAK,QAAQ,SAAS,CAAC,IAAI,cAAc,KAAK;AAC9C,SAAK,QAAQ,SAAS,CAAC,IAAI,MAAM;AACjC,SAAK,QAAQ,IAAI,MAAM,SAAS,GAAG,KAAK,KAAK,GAAG,SAAS,CAAC;AAC1D,YAAQ,MAAM,KAAK,QAAQ,GAAG,aAAa,CAAC;AAAA,EAK9C;AACF;AAEO,SAAS,+BAA+B,OAAO,4BAAkC;AACtF,QAAM,QAAQ;AAId,MAAI,CAAC,MAAM,yBAAyB,CAAC,MAAM,mBAAmB;AAC5D,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AACA,QAAM,OAAO,MAAM;AAAA,EACnB,MAAM,yCAAyC,KAAK;AAAA,IAIlD,YAAY,SAAgE;AAC1E,YAAM;AACN,YAAM,OAAO,KAAK;AAClB,WAAK,SAAS,IAAI,uBAAuB,SAAS,oBAAoB,EAAE,WAAW,GAAG,GAAG;AAAA,QACvF,aAAa,CAAC,YAAY,MAAM,cAAc,OAAO;AAAA,MACvD,CAAC;AACD,YAAM,YAAY,CAAC,UAA6B;AAC9C,YAAI,iBAAiB,MAAM,IAAI,GAAG;AAChC,eAAK,OAAO,eAAe,MAAM,IAAI;AAAA,QACvC;AAAA,MACF;AACA,UAAI,MAAM,kBAAkB;AAC1B,aAAK,iBAAiB,WAAW,SAAS;AAC1C,aAAK,QAAQ;AAAA,MACf,WAAW,MAAM;AACf,aAAK,YAAY;AAAA,MACnB;AAAA,IACF;AAAA,IAEA,QAAQ,QAAsB,SAAiC;AAC7D,aAAO,KAAK,OAAO,QAAQ,QAAQ,OAAO;AAAA,IAC5C;AAAA,EACF;AACA,QAAM,kBAAkB,MAAM,gCAAgC;AAChE;;;ACtWO,IAAM,8CAAN,MAAM,4CAA2C;AAAA,EAmBtD,YAAY,UAA6D,CAAC,GAAG;AAF7E,SAAQ,YAAY;AAGlB,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,gBAAgB,CAAC,CAAC;AACrE,SAAK,UAAU,IAAI,qBAAqB,QAAQ,UAAU,iBAAiB;AAC3E,SAAK,QAAQ,QAAQ,KAAK,YAAY,KAAK,WAAW,KAAK,YAAY;AAIvE,SAAK,YAAY,KAAK,QAAQ,mBAAmB,KAAK,SAAS;AAC/D,SAAK,aAAa,KAAK,QAAQ,oBAAoB,KAAK,SAAS;AACjE,SAAK,iBAAiB,CAAC;AACvB,QAAI,KAAK,eAAe,GAAG;AACzB,eAAS,KAAK,GAAG,KAAK,KAAK,cAAc,MAAM;AAC7C,aAAK,eAAe,KAAK,KAAK,QAAQ,uBAAuB,IAAI,KAAK,SAAS,CAAC;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,eAAe,SAAkD;AAC/D,QAAI,KAAK,WAAW;AAClB;AAAA,IACF;AACA,QAAI,QAAQ,SAAS,aAAa;AAIhC,WAAK,QAAQ,UAAU,QAAQ,MAAM;AAAA,IACvC,WAAW,QAAQ,SAAS,SAAS;AACnC,WAAK,QAAQ,MAAM;AAAA,IACrB,WAAW,QAAQ,SAAS,WAAW;AACrC,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA,EAEA,QAAQ,QAAsB,SAAiC;AAC7D,UAAM,SAAS,QAAQ,CAAC;AACxB,QAAI,KAAK,aAAa,CAAC,UAAU,OAAO,WAAW,GAAG;AACpD,aAAO,CAAC,KAAK;AAAA,IACf;AAMA,QAAI,KAAK,UAAU,eAAe,GAAG;AACnC,WAAK,iBAAiB;AAAA,IACxB;AAEA,UAAM,QAAQ,OAAO,CAAC;AACtB,UAAM,kBAAkB,OAAO,CAAC,GAAG,UAAU;AAC7C,UAAM,oBAAoB,KAAK,IAAI,KAAK,cAAc,OAAO,MAAM;AACnE,QAAI,oBAAoB,KAAK,sBAAsB,GAAG;AACpD,aAAO;AAAA,IACT;AAEA,QAAI,sBAAsB,GAAG;AAG3B,YAAMC,UAAS,KAAK,mBAAmB,eAAe;AACtD,YAAM,SAAS,QAAQ,CAAC;AACxB,UAAI,QAAQ;AACV,aAAK,UAAU,IAAI,OAAO,SAAS,GAAGA,OAAM,CAAC;AAAA,MAC/C,OAAO;AACL,aAAK,UAAU,KAAK,GAAG,GAAGA,OAAM;AAAA,MAClC;AACA,WAAK,QAAQ;AAAA,QACX,KAAK,UAAU,SAAS,GAAGA,OAAM;AAAA,QACjC,KAAK,WAAW,SAAS,GAAGA,OAAM;AAAA,MACpC;AACA,aAAO,CAAC,EAAE,IAAI,KAAK,WAAW,SAAS,GAAGA,OAAM,CAAC;AACjD,aAAO;AAAA,IACT;AAEA,UAAM,SAAS,KAAK,0BAA0B,iBAAiB,iBAAiB;AAChF,UAAM,WAAW;AAIjB,aAAS,KAAK,GAAG,KAAK,UAAU,MAAM;AACpC,YAAM,MAAM,QAAQ,EAAE;AACtB,YAAM,MAAM,KAAK,eAAe,EAAE;AAClC,UAAI,CAAC,KAAK;AACR;AAAA,MACF;AACA,UAAI,KAAK;AACP,YAAI,IAAI,IAAI,SAAS,GAAG,MAAM,CAAC;AAAA,MACjC,OAAO;AACL,YAAI,KAAK,GAAG,GAAG,MAAM;AAAA,MACvB;AAAA,IACF;AACA,SAAK,QAAQ,sBAAsB,MAAM;AACzC,aAAS,KAAK,GAAG,KAAK,UAAU,MAAM;AACpC,YAAM,MAAM,KAAK,eAAe,EAAE;AAClC,UAAI,KAAK;AACP,eAAO,EAAE,EAAE,IAAI,IAAI,SAAS,GAAG,MAAM,CAAC;AAAA,MACxC;AAAA,IAEF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,WAAW;AAClB;AAAA,IACF;AACA,SAAK,YAAY;AACjB,SAAK,QAAQ,OAAO;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAyB;AAC/B,SAAK,YAAY,KAAK,QAAQ,mBAAmB,KAAK,SAAS;AAC/D,SAAK,aAAa,KAAK,QAAQ,oBAAoB,KAAK,SAAS;AACjE,QAAI,KAAK,eAAe,GAAG;AACzB,eAAS,KAAK,GAAG,KAAK,KAAK,cAAc,MAAM;AAC7C,aAAK,eAAe,EAAE,IAAI,KAAK,QAAQ,uBAAuB,IAAI,KAAK,SAAS;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,mBAAmB,QAAwB;AACjD,UAAM,WAAW,KAAK,UAAU;AAChC,QAAI,UAAU,UAAU;AACtB,aAAO;AAAA,IACT;AACA,QAAI,CAAC,4CAA2C,oBAAoB;AAClE,kDAA2C,qBAAqB;AAEhE,cAAQ;AAAA,QACN,yDAAyD,MAAM,+CAC3B,QAAQ;AAAA,MAE9C;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,0BAA0B,QAAgB,UAA0B;AAC1E,UAAM,WAAW,KAAK,eAAe,CAAC,GAAG,UAAU;AACnD,QAAI,UAAU,UAAU;AACtB,aAAO;AAAA,IACT;AACA,QAAI,CAAC,4CAA2C,2BAA2B;AACzE,kDAA2C,4BAA4B;AAEvE,cAAQ;AAAA,QACN,yDAAyD,MAAM,IAAI,QAAQ,iDACzB,QAAQ;AAAA,MAE5D;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAnMa,4CACI,qBAAqB;AADzB,4CAEI,4BAA4B;AAFtC,IAAM,6CAAN;AAqMA,SAAS,mDACd,OAAO,2CACD;AACN,QAAM,QAAQ;AAId,MAAI,CAAC,MAAM,yBAAyB,CAAC,MAAM,mBAAmB;AAC5D,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AACA,QAAM,OAAO,MAAM;AAAA,EACnB,MAAM,6DAA6D,KAAK;AAAA,IAItE,YAAY,SAET;AACD,YAAM;AACN,YAAM,OAAO,KAAK;AAClB,WAAK,SAAS,IAAI,2CAA2C,SAAS,oBAAoB,CAAC,CAAC;AAC5F,YAAM,YAAY,CAAC,UAA6B;AAC9C,YAAI,8BAA8B,MAAM,IAAI,GAAG;AAC7C,eAAK,OAAO,eAAe,MAAM,IAAI;AAAA,QACvC;AAAA,MACF;AACA,UAAI,MAAM,kBAAkB;AAC1B,aAAK,iBAAiB,WAAW,SAAS;AAC1C,aAAK,QAAQ;AAAA,MACf,WAAW,MAAM;AACf,aAAK,YAAY;AAAA,MACnB;AAAA,IACF;AAAA,IAEA,QAAQ,QAAsB,SAAiC;AAC7D,aAAO,KAAK,OAAO,QAAQ,QAAQ,OAAO;AAAA,IAC5C;AAAA,EACF;AACA,QAAM,kBAAkB,MAAM,oDAAoD;AACpF;","names":["module","module","module","module","marker","SonareEngineCommandType","SonareEngineTelemetryType","SonareEngineTelemetryError","marker","initPromise","frames"]}