@libraz/libsonare 1.3.2 → 1.3.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.
package/README.md CHANGED
@@ -623,6 +623,51 @@ function readMeters() {
623
623
  }
624
624
  ```
625
625
 
626
+ #### RealtimeEngine AudioWorklet facade
627
+
628
+ For browser DAW-style playback, `SonareEngine` keeps a main-thread
629
+ `RealtimeEngine` mirror for offline renders and synchronizes the live worklet
630
+ engine through control messages. The default runtime target is the embind engine;
631
+ the `sonare-rt` runtime remains a transport-focused fallback.
632
+
633
+ ```typescript
634
+ import { init } from '@libraz/libsonare';
635
+ import { init as initWorklet, SonareEngine } from '@libraz/libsonare/worklet';
636
+
637
+ await init();
638
+ await audioContext.audioWorklet.addModule('/worklet.js');
639
+ await initWorklet();
640
+
641
+ const engine = await SonareEngine.create(audioContext, { mode: 'sab' });
642
+ engine.setTrackLanes([{ trackId: 1 }]);
643
+ engine.setTrackStripJson(1, trackSceneJson);
644
+ engine.addClip(1, [clipL, clipR], 0);
645
+ engine.setTempoSegments([{ startPpq: 0, bpm: 120 }]);
646
+ engine.setTimeSignatureSegments([{ startPpq: 0, numerator: 4, denominator: 4 }]);
647
+ engine.transport.play();
648
+ ```
649
+
650
+ | Need | Facade/API |
651
+ |---|---|
652
+ | Track routing, fader, pan, solo/mute | `setTrackLanes`, `setStripGain`, `setStripPan`, `setSoloMute` |
653
+ | Track/master inserts and EQ | `setTrackStripJson`, `setMasterStripJson`, `setTrackStripEqBand`, `setMasterStripEqBand`, insert bypass methods |
654
+ | Sends and buses | `setSends`, `setBusGain`, `setBusStripJson` |
655
+ | MIDI clips and live MIDI | `setMidiClips`, `pushMidiNoteOn`, `pushMidiNoteOff`, `pushMidiCc`, `pushMidiPanic` |
656
+ | Instruments | `setBuiltinInstrument`, `setSynthInstrument`, `loadSoundFont`, `setSf2Instrument` |
657
+ | Recording and monitoring | `configureCapture` (incl. the `inputMonitor` option), `armRecord`, `punch`, `capturedAudio`, `captureStatus` |
658
+ | Transport, tempo, markers | `getTransportState`, `cachedTransportState`, `setTempoSegments`, `setTimeSignatureSegments`, marker methods, `setLoopFromMarkers` |
659
+ | Clip updates | `addClip`, `removeClip`; the facade sends clip deltas while the processor keeps full-sync compatibility |
660
+ | Meters | `onMeter` messages or the meter SharedArrayBuffer ring; records include master, lane, bus, and input target ids |
661
+
662
+ Studio integration notes:
663
+
664
+ - If a host worklet entry filters message names before forwarding, add every
665
+ `sync*`, `captureRequest`, and `transportRequest` message used above to that
666
+ allowlist; otherwise the host may silently drop the new control messages.
667
+ - If a host vendors built worklet bundles, regenerate and reimport
668
+ `worklet.js`, `worklet.d.ts`, `sonare.js`, `sonare.wasm`,
669
+ `sonare-rt.js`, `sonare-rt-module.js`, and `sonare-rt.wasm` together.
670
+
626
671
  ### Progress callback
627
672
 
628
673
  `masteringChainWithProgress` (and its stereo variant) is `masteringChain` with
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { A as AcousticOptions, a as AcousticResult, b as AnalysisResult, c as AnalyzeBpmOptions, d as AnalyzeDynamicsOptions, e as AnalyzeRhythmOptions, f as AnalyzeSectionsOptions, g as AnalyzeTimbreOptions, h as AnalyzerStats, i as Audio, j as AutomationCurve, B as BarChord, k as Beat, l as BindMicrophoneInputOptions, m as BindWebMidiOptions, n as BpmAnalysisResult, o as BpmCandidate, p as BrowserAudioDecodeOptions, q as BuiltinSynthBinding, r as BuiltinSynthConfig, s as BuiltinSynthWaveform, C as Chord, t as ChordAnalysisResult, u as ChordChange, v as ChordDetectionOptions, w as ChordQuality, x as ChromaResult, y as ClippingRegion, z as ClippingReport, D as CompressorDetector, E as CompressorOptions, F as CqtResult, G as DeclickOptions, H as DeclipOptions, I as DecomposeResult, J as DecrackleMode, K as DecrackleOptions, L as DehumOptions, M as DenoiseClassicalMode, N as DenoiseClassicalNoiseEstimator, O as DenoiseClassicalOptions, P as DereverbClassicalOptions, Q as DynamicRangeReport, R as Dynamics, S as DynamicsAnalysisResult, T as DynamicsResult, U as EXPECTED_ENGINE_ABI_VERSION, V as EXPECTED_PROJECT_ABI_VERSION, W as EngineAutomationPoint, X as EngineBounceOptions, Y as EngineBounceResult, Z as EngineCapabilities, _ as EngineCaptureStatus, $ as EngineClip, a0 as EngineFreezeOptions, a1 as EngineFreezeResult, a2 as EngineGraphSpec, a3 as EngineMarker, a4 as EngineMeterTelemetry, a5 as EngineMetronomeConfig, a6 as EngineParameterInfo, a7 as EngineTelemetry, a8 as EngineTransportState, a9 as EqBand, aa as EqBandPhase, ab as EqBandType, ac as EqCoeffMode, ad as EqMatchOptions, ae as EqSpectrumSnapshot, af as EqStereoPlacement, ag as ErrorCode, ah as FrameBuffer, ai as GateOptions, aj as GoniometerPoint, ak as HpssResult, al as HpssWithResidualResult, am as Key, an as KeyCandidate, ao as KeyDetectionOptions, ap as KeyProfile, aq as KeyProfileName, ar as LufsResult, as as MasteringChainConfig, at as MasteringChainResult, au as MasteringOptions, av as MasteringPreset, aw as MasteringProcessorParams, ax as MasteringResult, ay as MasteringStereoChainResult, az as MasteringStereoResult, aA as Matrix2dResult, aB as MelPowerResult, aC as MelSpectrogramResult, aD as MelodyOptions, aE as MelodyPoint, aF as MelodyResult, aG as MeterTap, aH as MeteringDetectClippingOptions, aI as MeteringDynamicRangeOptions, aJ as MfccResult, aK as MicrophoneInputBinding, aL as MidiCcBindOptions, aM as MidiCcLearnOptions, aN as MixMeterSnapshot, aO as MixOptions, aP as MixResult, aQ as Mixer, aR as MixerProcessResult, aS as MixerRealtimeBuffer, aT as Mode, aU as NoteStretchOptions, aV as OpfsClipPageProviderBinding, aW as OpfsClipPageProviderOptions, aX as PairAnalysis, aY as PairProcessor, aZ as PanLaw, a_ as PanMode, a$ as PatternScore, b0 as PhaseScopeReport, b1 as Pitch, b1 as PitchClass, b2 as PitchResult, b3 as ProgressiveEstimate, b4 as Project, b5 as ProjectAssistSidecar, b6 as ProjectAutomationCurve, b7 as ProjectAutomationLaneDesc, b8 as ProjectAutomationPoint, b9 as ProjectBounceOptions, ba as ProjectChordSymbol, bb as ProjectClipCompSegment, bc as ProjectClipDesc, bd as ProjectClipFade, be as ProjectClipTake, bf as ProjectCompileResult, bg as ProjectFadeCurve, bh as ProjectKeySegment, bi as ProjectLoopMode, bj as ProjectLoopRecordingDesc, bk as ProjectLoopRecordingResult, bl as ProjectMidiClipResult, bm as ProjectMidiEvent, bn as ProjectNotePairValidation, bo as ProjectTrackDesc, bp as ProjectTrackKind, bq as ProjectWarpAnchor, br as ProjectWarpMapDesc, bs as RealtimeEngine, bt as RealtimeVoiceChanger, bu as RealtimeVoiceChangerConfigInput, bv as RealtimeVoiceChangerInterleavedBuffer, bw as RealtimeVoiceChangerMonoBuffer, bx as RealtimeVoiceChangerPlanarBuffer, by as RealtimeVoiceChangerPodConfig, bz as RhythmAnalysisResult, bA as RhythmFeatures, bB as RirResult, bC as RirSynthOptions, bD as RoomEstimateOptions, bE as RoomEstimateResult, bF as RoomGeometryOptions, bG as RoomMorphOptions, bH as SYNTH_BODY_TYPES, bI as SYNTH_ENGINE_MODES, bJ as SYNTH_FILTER_MODELS, bK as SYNTH_FILTER_OUTPUTS, bL as SYNTH_MOD_DESTINATIONS, bM as SYNTH_MOD_SOURCES, bN as SYNTH_OSC_WAVEFORMS, bO as Section, bP as SectionType, bQ as SendTiming, bR as Sf2InstrumentConfig, bS as Sf2ProgramStatus, bT as SoloProcessor, bU as SonareError, bV as SourceBackend, bW as SpectrumOptions, bX as SpectrumReport, bY as StereoAnalysis, bZ as StftPowerResult, b_ as StftResult, b$ as StreamAnalyzer, c0 as StreamConfig, c1 as StreamConfigDefaults, c2 as StreamFramesI16, c3 as StreamFramesU8, c4 as StreamQuantizeConfig, c5 as StreamingEqualizer, c6 as StreamingEqualizerConfig, c7 as StreamingMasteringChain, c8 as StreamingMasteringChainConfig, c9 as StreamingPlatform, ca as StreamingRetune, cb as StreamingRetuneConfig, cc as SynthBodyType, cd as SynthEngineMode, ce as SynthEnumTables, cf as SynthFilterModel, cg as SynthFilterOutput, ch as SynthModDestination, ci as SynthModRouting, cj as SynthModSource, ck as SynthOscWaveform, cl as SynthPatch, cm as TempogramMode, cn as Timbre, co as TimbreAnalysisResult, cp as TimbreFrame, cq as TimeSignature, cr as TransientShaperOptions, cs as TrimSilenceMode, ct as TrimSilenceOptions, cu as ValidateOptions, cv as VectorscopeReport, cw as VoiceChangeOptions, cx as VoiceChangeRealtimeOptions, cy as VoicePresetId, cz as WaveformPeakPyramidOptions, cA as WaveformPeaksOptions, cB as WaveformPeaksReport, cC as WebMidiBinding, cD as WebMidiCcBinding, cE as WebMidiInputInfo, cF as amplitudeToDb, cG as analyze, cH as analyzeBpm, cI as analyzeDynamics, cJ as analyzeImpulseResponse, cK as analyzeMelody, cL as analyzeRhythm, cM as analyzeSections, cN as analyzeTimbre, cO as analyzeWithProgress, cP as bassChroma, cQ as bindMicrophoneInput, cR as bindWebMidi, cS as chordFunctionalAnalysis, cT as chroma, cU as chromaCens, cV as cqt, cW as createOpfsClipPageProvider, cX as createOpfsClipPageWorker, cY as cyclicTempogram, cZ as dbToAmplitude, c_ as dbToPower, c$ as decompose, d0 as decomposeWithInit, d1 as deemphasis, d2 as detectAcoustic, d3 as detectBeats, d4 as detectBpm, d5 as detectChords, d6 as detectDownbeats, d7 as detectKey, d8 as detectKeyCandidates, d9 as detectOnsets, da as ebur128LoudnessRange, db as engineAbiVersion, dc as engineCapabilities, dd as estimateRoom, de as estimateTuning, df as fixFrames, dg as fixLength, dh as fourierTempogram, di as frameSignal, dj as framesToSamples, dk as framesToTime, dl as harmonic, dm as hasFfmpegSupport, dn as hpss, dp as hpssWithResidual, dq as hybridCqt, dr as hzToMel, ds as hzToMidi, dt as hzToNote, init, isInitialized, du as isSonareError, dv as isWebMidiAvailable, dw as lufs, dx as lufsInterleaved, dy as masterAudio, dz as masterAudioStereo, dA as masterAudioStereoWithProgress, dB as masterAudioWithProgress, dC as mastering, dD as masteringAssistantSuggest, dE as masteringAudioProfile, dF as masteringChain, dG as masteringChainStereo, dH as masteringChainStereoWithProgress, dI as masteringChainWithProgress, dJ as masteringDynamicsCompressor, dK as masteringDynamicsGate, dL as masteringDynamicsTransientShaper, dM as masteringInsertNames, dN as masteringInsertParamNames, dO as masteringPairAnalysisNames, dP as masteringPairAnalyze, dQ as masteringPairProcess, dR as masteringPairProcessorNames, dS as masteringPresetNames, dT as masteringProcess, dU as masteringProcessStereo, dV as masteringProcessorNames, dW as masteringRepairDeclick, dX as masteringRepairDeclip, dY as masteringRepairDecrackle, dZ as masteringRepairDehum, d_ as masteringRepairDenoiseClassical, d$ as masteringRepairDereverbClassical, e0 as masteringRepairTrimSilence, e1 as masteringStereoAnalysisNames, e2 as masteringStereoAnalyze, e3 as masteringStreamingPreview, e4 as melSpectrogram, e5 as melToAudio, e6 as melToHz, e7 as melToStft, e8 as meteringCrestFactorDb, e9 as meteringDcOffset, ea as meteringDetectClipping, eb as meteringDynamicRange, ec as meteringPeakDb, ed as meteringPhaseScope, ee as meteringPhaseScopeDecimated, ef as meteringRmsDb, eg as meteringSpectrum, eh as meteringSpectrumFrame, ei as meteringStereoCorrelation, ej as meteringStereoWidth, ek as meteringTruePeakDb, el as meteringVectorscope, em as meteringVectorscopeDecimated, en as mfcc, eo as mfccToAudio, ep as mfccToMel, eq as midiToHz, er as mixStereo, es as mixingScenePresetJson, et as mixingScenePresetNames, eu as momentaryLufs, ev as nnFilter, ew as nnlsChroma, ex as normalize, ey as noteStretch, ez as noteToHz, eA as onsetEnvelope, eB as onsetStrengthMulti, eC as opfsClipPageWorkerSource, eD as padCenter, eE as pcen, eF as peakPick, eG as percussive, eH as phaseVocoder, eI as pitchCorrectToMidi, eJ as pitchCorrectToMidiTimevarying, eK as pitchPyin, eL as pitchShift, eM as pitchTuning, eN as pitchYin, eO as plp, eP as polyFeatures, eQ as powerToDb, eR as preemphasis, eS as projectAbiVersion, eT as pseudoCqt, eU as realtimeVoiceChangerPresetConfig, eV as realtimeVoiceChangerPresetJson, eW as realtimeVoiceChangerPresetNames, eX as remix, eY as resample, eZ as rmsEnergy, e_ as roomMorph, e$ as samplesToFrames, f0 as scaleCorrectionSemitones, f1 as scalePitchClassEnabled, f2 as scaleQuantizeMidi, f3 as shortTermLufs, f4 as spectralBandwidth, f5 as spectralCentroid, f6 as spectralContrast, f7 as spectralFlatness, f8 as spectralRolloff, f9 as splitSilence, fa as stft, fb as stftDb, fc as streamAnalyzerConfigDefaults, fd as synthEnumTables, fe as synthPresetNames, ff as synthPresetPatch, fg as synthesizeRir, fh as tempogram, fi as tempogramRatio, fj as timeStretch, fk as timeToFrames, fl as tonnetz, fm as trim, fn as trimSilence, fo as validateRealtimeVoiceChangerPresetJson, fp as vectorNormalize, fq as version, fr as voiceChange, fs as voiceChangeRealtime, ft as voiceChangerAbiVersion, fu as voiceCharacterPresetId, fv as vqt, fw as waveformPeakPyramid, fx as waveformPeaks, fy as zeroCrossingRate, fz as zeroCrossings } from './worklet.js';
1
+ export { A as AcousticOptions, a as AcousticResult, b as AnalysisResult, c as AnalyzeBpmOptions, d as AnalyzeDynamicsOptions, e as AnalyzeRhythmOptions, f as AnalyzeSectionsOptions, g as AnalyzeTimbreOptions, h as AnalyzerStats, i as Audio, j as AutomationCurve, B as BarChord, k as Beat, l as BindMicrophoneInputOptions, m as BindWebMidiOptions, n as BpmAnalysisResult, o as BpmCandidate, p as BrowserAudioDecodeOptions, q as BuiltinSynthBinding, r as BuiltinSynthConfig, s as BuiltinSynthWaveform, C as Chord, t as ChordAnalysisResult, u as ChordChange, v as ChordDetectionOptions, w as ChordQuality, x as ChromaResult, y as ClippingRegion, z as ClippingReport, D as CompressorDetector, E as CompressorOptions, F as CqtResult, G as DeclickOptions, H as DeclipOptions, I as DecomposeResult, J as DecrackleMode, K as DecrackleOptions, L as DehumOptions, M as DenoiseClassicalMode, N as DenoiseClassicalNoiseEstimator, O as DenoiseClassicalOptions, P as DereverbClassicalOptions, Q as DynamicRangeReport, R as Dynamics, S as DynamicsAnalysisResult, T as DynamicsResult, U as EXPECTED_ENGINE_ABI_VERSION, V as EXPECTED_PROJECT_ABI_VERSION, W as EngineAutomationPoint, X as EngineBounceOptions, Y as EngineBounceResult, Z as EngineBus, _ as EngineCapabilities, $ as EngineCaptureStatus, a0 as EngineClip, a1 as EngineFreezeOptions, a2 as EngineFreezeResult, a3 as EngineGraphSpec, a4 as EngineMarker, a5 as EngineMeterTelemetry, a6 as EngineMetronomeConfig, a7 as EngineMidiClipSchedule, a8 as EngineMidiEvent, a9 as EngineParameterInfo, aa as EngineTelemetry, ab as EngineTempoSegment, ac as EngineTimeSignatureSegment, ad as EngineTrackLane, ae as EngineTrackSend, af as EngineTransportState, ag as EqBand, ah as EqBandPhase, ai as EqBandType, aj as EqCoeffMode, ak as EqMatchOptions, al as EqSpectrumSnapshot, am as EqStereoPlacement, an as ErrorCode, ao as FrameBuffer, ap as GateOptions, aq as GoniometerPoint, ar as HpssResult, as as HpssWithResidualResult, at as Key, au as KeyCandidate, av as KeyDetectionOptions, aw as KeyProfile, ax as KeyProfileName, ay as LufsResult, az as MasteringChainConfig, aA as MasteringChainResult, aB as MasteringOptions, aC as MasteringPreset, aD as MasteringProcessorParams, aE as MasteringResult, aF as MasteringStereoChainResult, aG as MasteringStereoResult, aH as Matrix2dResult, aI as MelPowerResult, aJ as MelSpectrogramResult, aK as MelodyOptions, aL as MelodyPoint, aM as MelodyResult, aN as MeterTap, aO as MeteringDetectClippingOptions, aP as MeteringDynamicRangeOptions, aQ as MfccResult, aR as MicrophoneInputBinding, aS as MidiCcBindOptions, aT as MidiCcLearnOptions, aU as MixMeterSnapshot, aV as MixOptions, aW as MixResult, aX as Mixer, aY as MixerProcessResult, aZ as MixerRealtimeBuffer, a_ as Mode, a$ as NoteStretchOptions, b0 as OpfsClipPageProviderBinding, b1 as OpfsClipPageProviderOptions, b2 as PairAnalysis, b3 as PairProcessor, b4 as PanLaw, b5 as PanMode, b6 as PatternScore, b7 as PhaseScopeReport, b8 as Pitch, b8 as PitchClass, b9 as PitchResult, ba as ProgressiveEstimate, bb as Project, bc as ProjectAssistSidecar, bd as ProjectAutomationCurve, be as ProjectAutomationLaneDesc, bf as ProjectAutomationPoint, bg as ProjectBounceOptions, bh as ProjectChordSymbol, bi as ProjectClipCompSegment, bj as ProjectClipDesc, bk as ProjectClipFade, bl as ProjectClipTake, bm as ProjectCompileResult, bn as ProjectFadeCurve, bo as ProjectKeySegment, bp as ProjectLoopMode, bq as ProjectLoopRecordingDesc, br as ProjectLoopRecordingResult, bs as ProjectMidiClipResult, bt as ProjectMidiEvent, bu as ProjectNotePairValidation, bv as ProjectTrackDesc, bw as ProjectTrackKind, bx as ProjectWarpAnchor, by as ProjectWarpMapDesc, bz as RealtimeEngine, bA as RealtimeVoiceChanger, bB as RealtimeVoiceChangerConfigInput, bC as RealtimeVoiceChangerInterleavedBuffer, bD as RealtimeVoiceChangerMonoBuffer, bE as RealtimeVoiceChangerPlanarBuffer, bF as RealtimeVoiceChangerPodConfig, bG as RhythmAnalysisResult, bH as RhythmFeatures, bI as RirResult, bJ as RirSynthOptions, bK as RoomEstimateOptions, bL as RoomEstimateResult, bM as RoomGeometryOptions, bN as RoomMorphOptions, bO as SYNTH_BODY_TYPES, bP as SYNTH_ENGINE_MODES, bQ as SYNTH_FILTER_MODELS, bR as SYNTH_FILTER_OUTPUTS, bS as SYNTH_MOD_DESTINATIONS, bT as SYNTH_MOD_SOURCES, bU as SYNTH_OSC_WAVEFORMS, bV as Section, bW as SectionType, bX as SendTiming, bY as Sf2InstrumentConfig, bZ as Sf2ProgramStatus, b_ as SoloProcessor, b$ as SonareError, c0 as SourceBackend, c1 as SpectrumOptions, c2 as SpectrumReport, c3 as StereoAnalysis, c4 as StftPowerResult, c5 as StftResult, c6 as StreamAnalyzer, c7 as StreamConfig, c8 as StreamConfigDefaults, c9 as StreamFramesI16, ca as StreamFramesU8, cb as StreamQuantizeConfig, cc as StreamingEqualizer, cd as StreamingEqualizerConfig, ce as StreamingMasteringChain, cf as StreamingMasteringChainConfig, cg as StreamingPlatform, ch as StreamingRetune, ci as StreamingRetuneConfig, cj as SynthBodyType, ck as SynthEngineMode, cl as SynthEnumTables, cm as SynthFilterModel, cn as SynthFilterOutput, co as SynthModDestination, cp as SynthModRouting, cq as SynthModSource, cr as SynthOscWaveform, cs as SynthPatch, ct as TempogramMode, cu as Timbre, cv as TimbreAnalysisResult, cw as TimbreFrame, cx as TimeSignature, cy as TransientShaperOptions, cz as TrimSilenceMode, cA as TrimSilenceOptions, cB as ValidateOptions, cC as VectorscopeReport, cD as VoiceChangeOptions, cE as VoiceChangeRealtimeOptions, cF as VoicePresetId, cG as WaveformPeakPyramidOptions, cH as WaveformPeaksOptions, cI as WaveformPeaksReport, cJ as WebMidiBinding, cK as WebMidiCcBinding, cL as WebMidiInputInfo, cM as amplitudeToDb, cN as analyze, cO as analyzeBpm, cP as analyzeDynamics, cQ as analyzeImpulseResponse, cR as analyzeMelody, cS as analyzeRhythm, cT as analyzeSections, cU as analyzeTimbre, cV as analyzeWithProgress, cW as bassChroma, cX as bindMicrophoneInput, cY as bindWebMidi, cZ as chordFunctionalAnalysis, c_ as chroma, c$ as chromaCens, d0 as cqt, d1 as createOpfsClipPageProvider, d2 as createOpfsClipPageWorker, d3 as cyclicTempogram, d4 as dbToAmplitude, d5 as dbToPower, d6 as decompose, d7 as decomposeWithInit, d8 as deemphasis, d9 as detectAcoustic, da as detectBeats, db as detectBpm, dc as detectChords, dd as detectDownbeats, de as detectKey, df as detectKeyCandidates, dg as detectOnsets, dh as ebur128LoudnessRange, di as engineAbiVersion, dj as engineCapabilities, dk as estimateRoom, dl as estimateTuning, dm as fixFrames, dn as fixLength, dp as fourierTempogram, dq as frameSignal, dr as framesToSamples, ds as framesToTime, dt as harmonic, du as hasFfmpegSupport, dv as hpss, dw as hpssWithResidual, dx as hybridCqt, dy as hzToMel, dz as hzToMidi, dA as hzToNote, init, isInitialized, dB as isSonareError, dC as isWebMidiAvailable, dD as lufs, dE as lufsInterleaved, dF as masterAudio, dG as masterAudioStereo, dH as masterAudioStereoWithProgress, dI as masterAudioWithProgress, dJ as mastering, dK as masteringAssistantSuggest, dL as masteringAudioProfile, dM as masteringChain, dN as masteringChainStereo, dO as masteringChainStereoWithProgress, dP as masteringChainWithProgress, dQ as masteringDynamicsCompressor, dR as masteringDynamicsGate, dS as masteringDynamicsTransientShaper, dT as masteringInsertNames, dU as masteringInsertParamNames, dV as masteringPairAnalysisNames, dW as masteringPairAnalyze, dX as masteringPairProcess, dY as masteringPairProcessorNames, dZ as masteringPresetNames, d_ as masteringProcess, d$ as masteringProcessStereo, e0 as masteringProcessorNames, e1 as masteringRepairDeclick, e2 as masteringRepairDeclip, e3 as masteringRepairDecrackle, e4 as masteringRepairDehum, e5 as masteringRepairDenoiseClassical, e6 as masteringRepairDereverbClassical, e7 as masteringRepairTrimSilence, e8 as masteringStereoAnalysisNames, e9 as masteringStereoAnalyze, ea as masteringStreamingPreview, eb as melSpectrogram, ec as melToAudio, ed as melToHz, ee as melToStft, ef as meteringCrestFactorDb, eg as meteringDcOffset, eh as meteringDetectClipping, ei as meteringDynamicRange, ej as meteringPeakDb, ek as meteringPhaseScope, el as meteringPhaseScopeDecimated, em as meteringRmsDb, en as meteringSpectrum, eo as meteringSpectrumFrame, ep as meteringStereoCorrelation, eq as meteringStereoWidth, er as meteringTruePeakDb, es as meteringVectorscope, et as meteringVectorscopeDecimated, eu as mfcc, ev as mfccToAudio, ew as mfccToMel, ex as midiToHz, ey as mixStereo, ez as mixingScenePresetJson, eA as mixingScenePresetNames, eB as momentaryLufs, eC as nnFilter, eD as nnlsChroma, eE as normalize, eF as noteStretch, eG as noteToHz, eH as onsetEnvelope, eI as onsetStrengthMulti, eJ as opfsClipPageWorkerSource, eK as padCenter, eL as pcen, eM as peakPick, eN as percussive, eO as phaseVocoder, eP as pitchCorrectToMidi, eQ as pitchCorrectToMidiTimevarying, eR as pitchPyin, eS as pitchShift, eT as pitchTuning, eU as pitchYin, eV as plp, eW as polyFeatures, eX as powerToDb, eY as preemphasis, eZ as projectAbiVersion, e_ as pseudoCqt, e$ as realtimeVoiceChangerPresetConfig, f0 as realtimeVoiceChangerPresetJson, f1 as realtimeVoiceChangerPresetNames, f2 as remix, f3 as resample, f4 as rmsEnergy, f5 as roomMorph, f6 as samplesToFrames, f7 as scaleCorrectionSemitones, f8 as scalePitchClassEnabled, f9 as scaleQuantizeMidi, fa as shortTermLufs, fb as spectralBandwidth, fc as spectralCentroid, fd as spectralContrast, fe as spectralFlatness, ff as spectralRolloff, fg as splitSilence, fh as stft, fi as stftDb, fj as streamAnalyzerConfigDefaults, fk as synthEnumTables, fl as synthPresetNames, fm as synthPresetPatch, fn as synthesizeRir, fo as tempogram, fp as tempogramRatio, fq as timeStretch, fr as timeToFrames, fs as tonnetz, ft as trim, fu as trimSilence, fv as validateRealtimeVoiceChangerPresetJson, fw as vectorNormalize, fx as version, fy as voiceChange, fz as voiceChangeRealtime, fA as voiceChangerAbiVersion, fB as voiceCharacterPresetId, fC as vqt, fD as waveformPeakPyramid, fE as waveformPeaks, fF as zeroCrossingRate, fG as zeroCrossings } from './worklet.js';
2
2
  export { ProgressCallback } from './sonare.js';
package/dist/index.js CHANGED
@@ -54,6 +54,7 @@ function makeSonareError(raw, thrown) {
54
54
  }
55
55
  function wrapModuleErrors(raw) {
56
56
  const cache = /* @__PURE__ */ new Map();
57
+ const objectCache = /* @__PURE__ */ new WeakMap();
57
58
  const convert = (error) => {
58
59
  const ptr = nativeExceptionPtr(error);
59
60
  if (ptr !== null) {
@@ -61,6 +62,83 @@ function wrapModuleErrors(raw) {
61
62
  }
62
63
  throw error;
63
64
  };
65
+ const wrapNativeObject = (value) => {
66
+ if (value === null || typeof value !== "object") {
67
+ return value;
68
+ }
69
+ if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer || value instanceof Promise) {
70
+ return value;
71
+ }
72
+ const objectValue = value;
73
+ const cached = objectCache.get(objectValue);
74
+ if (cached) {
75
+ return cached;
76
+ }
77
+ const methodCache = /* @__PURE__ */ new Map();
78
+ const wrapped = new Proxy(objectValue, {
79
+ get(target, prop, receiver) {
80
+ const member = Reflect.get(target, prop, receiver);
81
+ if (typeof member !== "function") {
82
+ return member;
83
+ }
84
+ const cachedMethod = methodCache.get(prop);
85
+ if (cachedMethod) {
86
+ return cachedMethod;
87
+ }
88
+ const method = member;
89
+ const wrappedMethod = (...args) => {
90
+ try {
91
+ return wrapNativeObject(Reflect.apply(method, target, args));
92
+ } catch (error) {
93
+ return convert(error);
94
+ }
95
+ };
96
+ methodCache.set(prop, wrappedMethod);
97
+ return wrappedMethod;
98
+ }
99
+ });
100
+ objectCache.set(objectValue, wrapped);
101
+ return wrapped;
102
+ };
103
+ const wrapFunction = (value) => {
104
+ const fnCache = /* @__PURE__ */ new Map();
105
+ return new Proxy(value, {
106
+ get(target, prop, receiver) {
107
+ const member = Reflect.get(target, prop, receiver);
108
+ if (typeof member !== "function") {
109
+ return member;
110
+ }
111
+ const cachedMember = fnCache.get(prop);
112
+ if (cachedMember) {
113
+ return cachedMember;
114
+ }
115
+ const fn = member;
116
+ const wrappedMember = (...args) => {
117
+ try {
118
+ return wrapNativeObject(Reflect.apply(fn, target, args));
119
+ } catch (error) {
120
+ return convert(error);
121
+ }
122
+ };
123
+ fnCache.set(prop, wrappedMember);
124
+ return wrappedMember;
125
+ },
126
+ apply(t, thisArg, args) {
127
+ try {
128
+ return wrapNativeObject(Reflect.apply(t, thisArg, args));
129
+ } catch (error) {
130
+ return convert(error);
131
+ }
132
+ },
133
+ construct(t, args, newTarget) {
134
+ try {
135
+ return wrapNativeObject(Reflect.construct(t, args, newTarget));
136
+ } catch (error) {
137
+ return convert(error);
138
+ }
139
+ }
140
+ });
141
+ };
64
142
  return new Proxy(raw, {
65
143
  get(target, prop, receiver) {
66
144
  const value = Reflect.get(target, prop, receiver);
@@ -71,23 +149,7 @@ function wrapModuleErrors(raw) {
71
149
  if (cached) {
72
150
  return cached;
73
151
  }
74
- const fn = value;
75
- const wrapped = new Proxy(fn, {
76
- apply(t, thisArg, args) {
77
- try {
78
- return Reflect.apply(t, thisArg, args);
79
- } catch (error) {
80
- return convert(error);
81
- }
82
- },
83
- construct(t, args, newTarget) {
84
- try {
85
- return Reflect.construct(t, args, newTarget);
86
- } catch (error) {
87
- return convert(error);
88
- }
89
- }
90
- });
152
+ const wrapped = wrapFunction(value);
91
153
  cache.set(prop, wrapped);
92
154
  return wrapped;
93
155
  }
@@ -2609,10 +2671,25 @@ function waveformPeakPyramid(samples, channels, options = {}) {
2609
2671
 
2610
2672
  // src/opfs_clip_pages.ts
2611
2673
  var opfsClipPageWorkerSource = `
2674
+ const sonareClipPageReadQueues = new Map();
2675
+
2676
+ function sonareEnqueueClipPageRead(key, task) {
2677
+ const previous = sonareClipPageReadQueues.get(key) || Promise.resolve();
2678
+ const next = previous.catch(() => undefined).then(task);
2679
+ const queued = next.finally(() => {
2680
+ if (sonareClipPageReadQueues.get(key) === queued) {
2681
+ sonareClipPageReadQueues.delete(key);
2682
+ }
2683
+ });
2684
+ sonareClipPageReadQueues.set(key, queued);
2685
+ return next;
2686
+ }
2687
+
2612
2688
  self.onmessage = async (event) => {
2613
2689
  const message = event.data;
2614
2690
  if (!message || message.type !== 'sonare:read-clip-page') return;
2615
2691
  const { requestId, path, pageIndex, numChannels, numSamples, pageFrames, dataOffsetBytes = 0 } = message;
2692
+ await sonareEnqueueClipPageRead(String(path), async () => {
2616
2693
  try {
2617
2694
  if (pageIndex < 0) {
2618
2695
  self.postMessage({ type: 'sonare:clip-page', requestId, pageIndex, ok: false });
@@ -2675,6 +2752,7 @@ self.onmessage = async (event) => {
2675
2752
  error: error instanceof Error ? error.message : String(error),
2676
2753
  });
2677
2754
  }
2755
+ });
2678
2756
  };
2679
2757
  `;
2680
2758
  function createOpfsClipPageWorker() {
@@ -2694,6 +2772,7 @@ function createOpfsClipPageProvider(engine, options) {
2694
2772
  const ownsWorker = options.worker === void 0 || options.terminateWorkerOnClose === true;
2695
2773
  let nextRequestId = 1;
2696
2774
  let closed = false;
2775
+ let readQueue = Promise.resolve();
2697
2776
  const pending = /* @__PURE__ */ new Map();
2698
2777
  const onMessage = (event) => {
2699
2778
  const response = event.data;
@@ -2733,15 +2812,29 @@ function createOpfsClipPageProvider(engine, options) {
2733
2812
  const promise = new Promise((resolve, reject) => {
2734
2813
  pending.set(requestId, { resolve, reject });
2735
2814
  });
2736
- worker.postMessage({
2737
- type: "sonare:read-clip-page",
2738
- requestId,
2739
- path: options.path,
2740
- pageIndex,
2741
- numChannels: options.numChannels,
2742
- numSamples: options.numSamples,
2743
- pageFrames: options.pageFrames,
2744
- dataOffsetBytes: options.dataOffsetBytes ?? 0
2815
+ readQueue = readQueue.catch(() => void 0).then(() => {
2816
+ if (closed) {
2817
+ const entry = pending.get(requestId);
2818
+ pending.delete(requestId);
2819
+ entry?.reject(new Error("OpfsClipPageProvider is closed"));
2820
+ return;
2821
+ }
2822
+ worker.postMessage({
2823
+ type: "sonare:read-clip-page",
2824
+ requestId,
2825
+ path: options.path,
2826
+ pageIndex,
2827
+ numChannels: options.numChannels,
2828
+ numSamples: options.numSamples,
2829
+ pageFrames: options.pageFrames,
2830
+ dataOffsetBytes: options.dataOffsetBytes ?? 0
2831
+ });
2832
+ return promise.then(
2833
+ () => void 0,
2834
+ () => void 0
2835
+ );
2836
+ });
2837
+ readQueue.catch(() => {
2745
2838
  });
2746
2839
  return promise;
2747
2840
  };
@@ -3492,9 +3585,6 @@ function engineCapabilities() {
3492
3585
  };
3493
3586
  }
3494
3587
  var RealtimeEngine = class {
3495
- nativeExt() {
3496
- return this.native;
3497
- }
3498
3588
  constructor(sampleRate = 48e3, maxBlockSize = 128, commandCapacity = 1024, telemetryCapacity = 1024) {
3499
3589
  const module2 = getSonareModule();
3500
3590
  const capabilities = engineCapabilities();
@@ -3521,8 +3611,14 @@ var RealtimeEngine = class {
3521
3611
  setParameterSmoothed(paramId, value, renderFrame = -1) {
3522
3612
  this.native.setParameterSmoothed(paramId, value, renderFrame);
3523
3613
  }
3614
+ setSoloMute(laneIndex, solo, mute, renderFrame = -1) {
3615
+ this.native.setSoloMute(laneIndex, solo, mute, renderFrame);
3616
+ }
3617
+ setMidiClips(clips) {
3618
+ this.native.setMidiClips(clips);
3619
+ }
3524
3620
  setBuiltinInstrument(config = {}, destinationId = config.destinationId ?? 0) {
3525
- this.nativeExt().setBuiltinInstrument(destinationId, config);
3621
+ this.native.setBuiltinInstrument(destinationId, config);
3526
3622
  }
3527
3623
  /**
3528
3624
  * Bind the patch-driven NativeSynth to a realtime MIDI destination. `patch`
@@ -3534,7 +3630,7 @@ var RealtimeEngine = class {
3534
3630
  * binding convenience, not part of the NativeSynth patch itself.
3535
3631
  */
3536
3632
  setSynthInstrument(patch = {}, destinationId = (typeof patch === "object" ? patch.destinationId : void 0) ?? 0) {
3537
- this.nativeExt().setSynthInstrument(destinationId, patch);
3633
+ this.native.setSynthInstrument(destinationId, patch);
3538
3634
  }
3539
3635
  /**
3540
3636
  * Load (parse) SoundFont 2 bytes into the engine so SF2 instruments can be
@@ -3543,7 +3639,7 @@ var RealtimeEngine = class {
3543
3639
  * not referenced afterwards. Replaces any previously loaded SoundFont.
3544
3640
  */
3545
3641
  loadSoundFont(data) {
3546
- this.nativeExt().loadSoundFont(data);
3642
+ this.native.loadSoundFont(data);
3547
3643
  }
3548
3644
  /**
3549
3645
  * Bind a GS-compatible SoundFont player to a realtime MIDI destination, fed
@@ -3555,13 +3651,13 @@ var RealtimeEngine = class {
3555
3651
  * synthesizer GM fallback bank (the data-free floor).
3556
3652
  */
3557
3653
  setSf2Instrument(config = {}, destinationId = config.destinationId ?? 0) {
3558
- this.nativeExt().setSf2Instrument(destinationId, config);
3654
+ this.native.setSf2Instrument(destinationId, config);
3559
3655
  }
3560
3656
  clearMidiInstrument(destinationId = 0) {
3561
- this.nativeExt().clearMidiInstrument(destinationId);
3657
+ this.native.clearMidiInstrument(destinationId);
3562
3658
  }
3563
3659
  midiInstrumentCount() {
3564
- return this.nativeExt().midiInstrumentCount();
3660
+ return this.native.midiInstrumentCount();
3565
3661
  }
3566
3662
  /**
3567
3663
  * Bind a live MIDI CC to an engine automation parameter. The MIDI event still
@@ -3569,7 +3665,7 @@ var RealtimeEngine = class {
3569
3665
  * mapped into [minValue, maxValue] for `paramId`.
3570
3666
  */
3571
3667
  bindMidiCc(channel, controller, paramId, options = {}) {
3572
- this.nativeExt().bindMidiCc(
3668
+ this.native.bindMidiCc(
3573
3669
  channel,
3574
3670
  controller,
3575
3671
  paramId,
@@ -3578,42 +3674,42 @@ var RealtimeEngine = class {
3578
3674
  );
3579
3675
  }
3580
3676
  clearMidiCcBindings() {
3581
- this.nativeExt().clearMidiCcBindings();
3677
+ this.native.clearMidiCcBindings();
3582
3678
  }
3583
3679
  midiCcBindingCount() {
3584
- return this.nativeExt().midiCcBindingCount();
3680
+ return this.native.midiCcBindingCount();
3585
3681
  }
3586
3682
  /** Install/replace a live non-destructive MIDI-FX insert for one destination. */
3587
3683
  setMidiFx(destinationId, configJson) {
3588
- this.nativeExt().setMidiFx(destinationId, configJson);
3684
+ this.native.setMidiFx(destinationId, configJson);
3589
3685
  }
3590
3686
  clearMidiFx(destinationId = 0) {
3591
- this.nativeExt().clearMidiFx(destinationId);
3687
+ this.native.clearMidiFx(destinationId);
3592
3688
  }
3593
3689
  /** Enable the engine-owned live MIDI input source for a destination. */
3594
3690
  setMidiInputSource(destinationId = 0) {
3595
- this.nativeExt().setMidiInputSource(destinationId);
3691
+ this.native.setMidiInputSource(destinationId);
3596
3692
  }
3597
3693
  clearMidiInputSource() {
3598
- this.nativeExt().clearMidiInputSource();
3694
+ this.native.clearMidiInputSource();
3599
3695
  }
3600
3696
  midiInputPendingCount() {
3601
- return this.nativeExt().midiInputPendingCount();
3697
+ return this.native.midiInputPendingCount();
3602
3698
  }
3603
3699
  pushMidiInputNoteOn(group, channel, note, velocity, portTimeSamples = 0) {
3604
- this.nativeExt().pushMidiInputNoteOn(group, channel, note, velocity, portTimeSamples);
3700
+ this.native.pushMidiInputNoteOn(group, channel, note, velocity, portTimeSamples);
3605
3701
  }
3606
3702
  pushMidiInputNoteOff(group, channel, note, velocity = 0, portTimeSamples = 0) {
3607
- this.nativeExt().pushMidiInputNoteOff(group, channel, note, velocity, portTimeSamples);
3703
+ this.native.pushMidiInputNoteOff(group, channel, note, velocity, portTimeSamples);
3608
3704
  }
3609
3705
  pushMidiInputCc(group, channel, controller, value, portTimeSamples = 0) {
3610
- this.nativeExt().pushMidiInputCc(group, channel, controller, value, portTimeSamples);
3706
+ this.native.pushMidiInputCc(group, channel, controller, value, portTimeSamples);
3611
3707
  }
3612
3708
  pushMidiNoteOn(destinationId, group, channel, note, velocity, renderFrame = -1) {
3613
- this.nativeExt().pushMidiNoteOn(destinationId, group, channel, note, velocity, renderFrame);
3709
+ this.native.pushMidiNoteOn(destinationId, group, channel, note, velocity, renderFrame);
3614
3710
  }
3615
3711
  pushMidiNoteOff(destinationId, group, channel, note, velocity = 0, renderFrame = -1) {
3616
- this.nativeExt().pushMidiNoteOff(destinationId, group, channel, note, velocity, renderFrame);
3712
+ this.native.pushMidiNoteOff(destinationId, group, channel, note, velocity, renderFrame);
3617
3713
  }
3618
3714
  /**
3619
3715
  * Queue an immediate (live) MIDI control change to a MIDI destination
@@ -3622,21 +3718,21 @@ var RealtimeEngine = class {
3622
3718
  * immediate. Mirrors the Node/Python/C-ABI `pushMidiCc`.
3623
3719
  */
3624
3720
  pushMidiCc(destinationId, group, channel, controller, value, renderFrame = -1) {
3625
- this.nativeExt().pushMidiCc(destinationId, group, channel, controller, value, renderFrame);
3721
+ this.native.pushMidiCc(destinationId, group, channel, controller, value, renderFrame);
3626
3722
  }
3627
3723
  /**
3628
3724
  * Queue a MIDI panic (all-notes-off) releasing every sounding note at
3629
3725
  * `renderFrame` (-1 = immediate). Mirrors the C-ABI `pushMidiPanic`.
3630
3726
  */
3631
3727
  pushMidiPanic(renderFrame = -1) {
3632
- this.nativeExt().pushMidiPanic(renderFrame);
3728
+ this.native.pushMidiPanic(renderFrame);
3633
3729
  }
3634
3730
  /**
3635
3731
  * Remove all registered parameters (and their automation lanes). Control-thread
3636
3732
  * only; not realtime-safe. Mirrors the C-ABI `clearParameters`.
3637
3733
  */
3638
3734
  clearParameters() {
3639
- this.nativeExt().clearParameters();
3735
+ this.native.clearParameters();
3640
3736
  }
3641
3737
  /** Read back the current transport state snapshot. */
3642
3738
  getTransportState() {
@@ -3657,9 +3753,18 @@ var RealtimeEngine = class {
3657
3753
  setTempo(bpm) {
3658
3754
  this.native.setTempo(bpm);
3659
3755
  }
3756
+ setTempoSegments(segments) {
3757
+ this.native.setTempoSegments([...segments]);
3758
+ }
3660
3759
  setTimeSignature(numerator, denominator) {
3661
3760
  this.native.setTimeSignature(numerator, denominator);
3662
3761
  }
3762
+ setTimeSignatureSegments(segments) {
3763
+ this.native.setTimeSignatureSegments([...segments]);
3764
+ }
3765
+ sampleAtPpq(ppq) {
3766
+ return Number(this.native.sampleAtPpq(ppq));
3767
+ }
3663
3768
  setLoop(startPpq, endPpq, enabled = true) {
3664
3769
  this.native.setLoop(startPpq, endPpq, enabled);
3665
3770
  }
@@ -3728,21 +3833,81 @@ var RealtimeEngine = class {
3728
3833
  clipCount() {
3729
3834
  return this.native.clipCount();
3730
3835
  }
3836
+ setTrackLanes(lanes) {
3837
+ this.native.setTrackLanes(
3838
+ lanes.map((lane) => typeof lane === "number" ? { trackId: lane } : lane)
3839
+ );
3840
+ }
3841
+ setTrackBuses(buses) {
3842
+ this.native.setTrackBuses(buses);
3843
+ }
3844
+ setBusStripJson(busId, sceneJson) {
3845
+ try {
3846
+ JSON.parse(sceneJson);
3847
+ } catch (error) {
3848
+ const message = error instanceof Error ? error.message : "invalid bus strip JSON";
3849
+ throw new SonareError(2 /* InvalidFormat */, "InvalidFormat", message);
3850
+ }
3851
+ this.native.setBusStripJson(busId, sceneJson);
3852
+ }
3853
+ setTrackStripJson(trackId, sceneJson) {
3854
+ try {
3855
+ JSON.parse(sceneJson);
3856
+ } catch (error) {
3857
+ const message = error instanceof Error ? error.message : "invalid track strip JSON";
3858
+ throw new SonareError(2 /* InvalidFormat */, "InvalidFormat", message);
3859
+ }
3860
+ this.native.setTrackStripJson(trackId, sceneJson);
3861
+ }
3862
+ setTrackStripEqBand(trackId, bandIndex, band) {
3863
+ this.native.setTrackStripEqBandJson(
3864
+ trackId,
3865
+ bandIndex,
3866
+ typeof band === "string" ? band : JSON.stringify(band)
3867
+ );
3868
+ }
3869
+ setTrackStripEqBandJson(trackId, bandIndex, bandJson) {
3870
+ this.native.setTrackStripEqBandJson(trackId, bandIndex, bandJson);
3871
+ }
3872
+ setTrackStripInsertBypassed(trackId, insertIndex, bypassed, resetOnBypass = false) {
3873
+ this.native.setTrackStripInsertBypassed(trackId, insertIndex, bypassed, resetOnBypass);
3874
+ }
3875
+ setMasterStripJson(sceneJson) {
3876
+ try {
3877
+ JSON.parse(sceneJson);
3878
+ } catch (error) {
3879
+ const message = error instanceof Error ? error.message : "invalid master strip JSON";
3880
+ throw new SonareError(2 /* InvalidFormat */, "InvalidFormat", message);
3881
+ }
3882
+ this.native.setMasterStripJson(sceneJson);
3883
+ }
3884
+ setMasterStripEqBand(bandIndex, band) {
3885
+ this.native.setMasterStripEqBandJson(
3886
+ bandIndex,
3887
+ typeof band === "string" ? band : JSON.stringify(band)
3888
+ );
3889
+ }
3890
+ setMasterStripEqBandJson(bandIndex, bandJson) {
3891
+ this.native.setMasterStripEqBandJson(bandIndex, bandJson);
3892
+ }
3893
+ setMasterStripInsertBypassed(insertIndex, bypassed, resetOnBypass = false) {
3894
+ this.native.setMasterStripInsertBypassed(insertIndex, bypassed, resetOnBypass);
3895
+ }
3731
3896
  createClipPageProvider(numChannels, numSamples, pageFrames) {
3732
- const id = this.nativeExt().createClipPageProvider(numChannels, numSamples, pageFrames);
3897
+ const id = this.native.createClipPageProvider(numChannels, numSamples, pageFrames);
3733
3898
  return new ClipPageProvider(this, id);
3734
3899
  }
3735
3900
  supplyClipPage(providerId, pageIndex, channels) {
3736
- this.nativeExt().supplyClipPage(providerId, pageIndex, channels);
3901
+ this.native.supplyClipPage(providerId, pageIndex, channels);
3737
3902
  }
3738
3903
  clearClipPage(providerId, pageIndex) {
3739
- this.nativeExt().clearClipPage(providerId, pageIndex);
3904
+ this.native.clearClipPage(providerId, pageIndex);
3740
3905
  }
3741
3906
  destroyClipPageProvider(providerId) {
3742
- this.nativeExt().destroyClipPageProvider(providerId);
3907
+ this.native.destroyClipPageProvider(providerId);
3743
3908
  }
3744
3909
  popClipPageRequest() {
3745
- return this.nativeExt().popClipPageRequest();
3910
+ return this.native.popClipPageRequest();
3746
3911
  }
3747
3912
  setCaptureBuffer(numChannels, capacityFrames) {
3748
3913
  this.native.setCaptureBuffer(numChannels, capacityFrames);
@@ -4105,7 +4270,6 @@ async function bindWebMidi(engine, options = {}) {
4105
4270
  engine.setMidiInputSource(destinationId);
4106
4271
  const bound = /* @__PURE__ */ new Map();
4107
4272
  let closed = false;
4108
- let runningStatus = 0;
4109
4273
  const shouldBind = (input) => input.state !== "disconnected" && (selectedIds.size === 0 || selectedIds.has(input.id));
4110
4274
  const snapshotInputs = () => Array.from(iterInputs(access), ([id, input]) => ({
4111
4275
  id,
@@ -4118,22 +4282,26 @@ async function bindWebMidi(engine, options = {}) {
4118
4282
  if (bound.has(input.id) || !shouldBind(input)) {
4119
4283
  return;
4120
4284
  }
4121
- const listener = (event) => {
4122
- const status = dispatchMidiMessage(
4123
- engine,
4124
- event,
4125
- group,
4126
- runningStatus,
4127
- options.timestampToSamples
4128
- );
4129
- runningStatus = status;
4285
+ const entry = {
4286
+ input,
4287
+ listener: (event) => {
4288
+ entry.runningStatus = dispatchMidiMessage(
4289
+ engine,
4290
+ event,
4291
+ group,
4292
+ entry.runningStatus,
4293
+ options.timestampToSamples
4294
+ );
4295
+ },
4296
+ runningStatus: 0
4130
4297
  };
4298
+ const listener = entry.listener;
4131
4299
  if (input.addEventListener) {
4132
4300
  input.addEventListener("midimessage", listener);
4133
4301
  } else {
4134
4302
  input.onmidimessage = listener;
4135
4303
  }
4136
- bound.set(input.id, { input, listener });
4304
+ bound.set(input.id, entry);
4137
4305
  };
4138
4306
  const unbindInput = (input) => {
4139
4307
  const entry = bound.get(input.id);
@@ -4318,7 +4486,7 @@ async function init(options) {
4318
4486
  }
4319
4487
  initPromise = (async () => {
4320
4488
  try {
4321
- const createModule = (await import("./sonare.js")).default;
4489
+ const createModule = options?.moduleFactory ?? (await import("./sonare.js")).default;
4322
4490
  module = await createModule(options);
4323
4491
  setSonareModule(module);
4324
4492
  } catch (error) {