@viji-dev/core 0.5.3 → 0.5.4

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.
@@ -1897,7 +1897,7 @@ class EssentiaOnsetDetection {
1897
1897
  this.initPromise = (async () => {
1898
1898
  try {
1899
1899
  const essentiaModule = await import("./essentia.js-core.es-DnrJE0uR.js");
1900
- const wasmModule = await import("./essentia-wasm.web-CPrFAj59.js").then((n) => n.e);
1900
+ const wasmModule = await import("./essentia-wasm.web-aU6UPupF.js").then((n) => n.e);
1901
1901
  const EssentiaClass = essentiaModule.Essentia || essentiaModule.default?.Essentia || essentiaModule.default;
1902
1902
  let WASMModule = wasmModule.default || wasmModule.EssentiaWASM || wasmModule.default?.EssentiaWASM;
1903
1903
  if (!WASMModule) {
@@ -6179,9 +6179,22 @@ class OnsetTapManager {
6179
6179
  modeChangeListeners = /* @__PURE__ */ new Set();
6180
6180
  sessionEndListeners = /* @__PURE__ */ new Set();
6181
6181
  muteChangeListeners = /* @__PURE__ */ new Set();
6182
- tap(instrument) {
6182
+ /**
6183
+ * Record a tap on `instrument`. Drives the visual envelope, advances
6184
+ * `lastTapTime`, and (by default) feeds the pattern-recognition pipeline.
6185
+ *
6186
+ * `options.skipRecognition: true` retains the visual side and session-timer
6187
+ * scheduling but bypasses the recognition pipeline (no `tapIOIs` push,
6188
+ * no `tryRecognizePattern`, no `applyPattern`, no `handlePatternTap`).
6189
+ * Mode stays whatever it was. Useful for host-side relay of forwarded
6190
+ * controller-tap messages where another instance is doing the
6191
+ * authoritative recognition. The `MIN_TAP_INTERVAL_MS` debounce still
6192
+ * applies (visual rate-limit).
6193
+ */
6194
+ tap(instrument, options) {
6183
6195
  const s = this.state[instrument];
6184
6196
  const now = performance.now();
6197
+ const skipRecognition = options?.skipRecognition === true;
6185
6198
  if (s.muted) {
6186
6199
  s.muted = false;
6187
6200
  s.mutedAt = 0;
@@ -6191,18 +6204,21 @@ class OnsetTapManager {
6191
6204
  if (s.lastTapTime > 0) {
6192
6205
  ioi = now - s.lastTapTime;
6193
6206
  if (ioi < MIN_TAP_INTERVAL_MS) return;
6194
- if (ioi > MAX_TAP_INTERVAL_MS) {
6195
- s.tapIOIs = [];
6196
- ioi = -1;
6197
- } else {
6198
- s.tapIOIs.push(ioi);
6199
- if (s.tapIOIs.length > MAX_TAP_HISTORY) s.tapIOIs.shift();
6207
+ if (!skipRecognition) {
6208
+ if (ioi > MAX_TAP_INTERVAL_MS) {
6209
+ s.tapIOIs = [];
6210
+ ioi = -1;
6211
+ } else {
6212
+ s.tapIOIs.push(ioi);
6213
+ if (s.tapIOIs.length > MAX_TAP_HISTORY) s.tapIOIs.shift();
6214
+ }
6200
6215
  }
6201
6216
  }
6202
6217
  s.lastTapTime = now;
6203
6218
  s.pendingTapEvents.push(now);
6204
6219
  s.sessionActive = true;
6205
6220
  this.scheduleSessionTimers(instrument);
6221
+ if (skipRecognition) return;
6206
6222
  if (s.mode === "auto") {
6207
6223
  this.setMode(instrument, "tapping");
6208
6224
  if (ioi > 0) {
@@ -6302,16 +6318,27 @@ class OnsetTapManager {
6302
6318
  /**
6303
6319
  * Serialize per-instrument onset state for cross-instance transfer.
6304
6320
  * Wall-clock fields are in this instance's `performance.now()` clock space.
6321
+ *
6322
+ * `options.instruments` scopes the output to the listed instruments only;
6323
+ * omitted instruments are absent from the payload (the receiver's
6324
+ * `applyInstrumentPayload` skips missing keys, leaving the receiver's
6325
+ * existing state for those instruments untouched). Default = all three —
6326
+ * the full-state-transfer used for same-process scene-switch.
6327
+ *
6328
+ * Cross-device commits should typically scope to the just-completed
6329
+ * instrument so an unrelated instrument's state on the receiver isn't
6330
+ * inadvertently overwritten.
6305
6331
  */
6306
- exportSessionState() {
6332
+ exportSessionState(options) {
6333
+ const list = options?.instruments ?? INSTRUMENTS;
6334
+ const instruments = {};
6335
+ for (const inst of list) {
6336
+ instruments[inst] = this.serializeInstrument(inst);
6337
+ }
6307
6338
  return {
6308
6339
  version: STATE_SCHEMA_VERSION,
6309
6340
  senderTime: performance.now(),
6310
- instruments: {
6311
- kick: this.serializeInstrument("kick"),
6312
- snare: this.serializeInstrument("snare"),
6313
- hat: this.serializeInstrument("hat")
6314
- }
6341
+ instruments
6315
6342
  };
6316
6343
  }
6317
6344
  /**
@@ -8497,10 +8524,13 @@ class AudioSystem {
8497
8524
  // Public API Methods for Audio Analysis Configuration
8498
8525
  // ═══════════════════════════════════════════════════════════
8499
8526
  /**
8500
- * Record a tap for the specified instrument onset
8527
+ * Record a tap for the specified instrument onset.
8528
+ * `options.skipRecognition` retains visual envelope + session timing but
8529
+ * bypasses the recognition pipeline — used by host-side relay of forwarded
8530
+ * tap messages where another core is doing the authoritative recognition.
8501
8531
  */
8502
- tapOnset(instrument) {
8503
- this.onsetTapManager.tap(instrument);
8532
+ tapOnset(instrument, options) {
8533
+ this.onsetTapManager.tap(instrument, options);
8504
8534
  }
8505
8535
  /**
8506
8536
  * Clear tap pattern for an instrument, restoring auto-detection
@@ -8550,8 +8580,8 @@ class AudioSystem {
8550
8580
  // audio block is for same-process scene-switch transfer (sender's audio
8551
8581
  // analysis state would corrupt receiver's tracking on a different source).
8552
8582
  // ─────────────────────────────────────────────────────────────────────────
8553
- exportOnsetSessionState() {
8554
- return this.onsetTapManager.exportSessionState();
8583
+ exportOnsetSessionState(options) {
8584
+ return this.onsetTapManager.exportSessionState(options);
8555
8585
  }
8556
8586
  importOnsetSessionState(state, clockOffset) {
8557
8587
  this.onsetTapManager.importSessionState(state, clockOffset);
@@ -11108,10 +11138,21 @@ class VijiCore {
11108
11138
  * Tap an onset for a specific instrument.
11109
11139
  * First tap switches the instrument from auto to tapping mode.
11110
11140
  * If a repeating pattern is recognized, it continues after tapping stops.
11141
+ *
11142
+ * `options.skipRecognition: true` keeps the visual envelope and session
11143
+ * timing but bypasses pattern recognition entirely (no IOI accumulation,
11144
+ * no mode transition, no `applyPattern`, no `handlePatternTap`). Use
11145
+ * this when relaying tap messages from another instance that owns the
11146
+ * authoritative recognition (e.g. host receiving forwarded controller
11147
+ * taps over WebRTC). The receiving core's mode is then driven only by
11148
+ * `importSessionState` from the authoritative sender.
11149
+ *
11150
+ * The `MIN_TAP_INTERVAL_MS` debounce still applies regardless of the
11151
+ * `skipRecognition` flag.
11111
11152
  */
11112
- tap: (instrument) => {
11153
+ tap: (instrument, options) => {
11113
11154
  this.validateReady();
11114
- this.audioSystem?.tapOnset(instrument);
11155
+ this.audioSystem?.tapOnset(instrument, options);
11115
11156
  },
11116
11157
  /**
11117
11158
  * Clear the tap pattern for an instrument, restoring auto-detection
@@ -11214,10 +11255,22 @@ class VijiCore {
11214
11255
  * Cross-device-safe (no audio analysis state included). Pair with
11215
11256
  * `importSessionState` on a receiver. Wall-clock fields are in this
11216
11257
  * instance's `performance.now()` clock space.
11258
+ *
11259
+ * `options.instruments` scopes the snapshot to the listed instruments
11260
+ * only; omitted instruments are absent from the payload. The receiver
11261
+ * leaves its existing state for those instruments untouched (the
11262
+ * receiver's `applyInstrumentPayload` skips missing keys). Default =
11263
+ * all three.
11264
+ *
11265
+ * Cross-device commits should typically scope to the just-completed
11266
+ * instrument (e.g. `exportSessionState({ instruments: [ev.instrument] })`
11267
+ * inside an `onSessionEnd` handler) so the receiver's unrelated
11268
+ * instrument state isn't inadvertently overwritten by the sender's
11269
+ * default values.
11217
11270
  */
11218
- exportSessionState: () => {
11271
+ exportSessionState: (options) => {
11219
11272
  this.validateReady();
11220
- return this.audioSystem?.exportOnsetSessionState() ?? {
11273
+ return this.audioSystem?.exportOnsetSessionState(options) ?? {
11221
11274
  version: 1,
11222
11275
  senderTime: performance.now(),
11223
11276
  instruments: {}
@@ -11649,7 +11702,7 @@ function validateCoreStatePayload(state) {
11649
11702
  }
11650
11703
  return null;
11651
11704
  }
11652
- const VERSION = "0.5.3";
11705
+ const VERSION = "0.5.4";
11653
11706
  export {
11654
11707
  AudioSystem as A,
11655
11708
  VERSION as V,
@@ -11657,4 +11710,4 @@ export {
11657
11710
  VijiCoreError as b,
11658
11711
  getDefaultExportFromCjs as g
11659
11712
  };
11660
- //# sourceMappingURL=index-Bhq4eJe_.js.map
11713
+ //# sourceMappingURL=index-_PbbZgmh.js.map