@viji-dev/core 0.2.19 → 0.3.0
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 +153 -32
- package/dist/artist-dts-p5.js +1 -1
- package/dist/artist-dts.js +1 -1
- package/dist/artist-global.d.ts +115 -14
- package/dist/artist-js-ambient.d.ts +43 -1
- package/dist/artist-jsdoc.d.ts +43 -1
- package/dist/assets/{viji.worker-C8mrsLDG.js → viji.worker-b3XR7zKX.js} +546 -55
- package/dist/assets/viji.worker-b3XR7zKX.js.map +1 -0
- package/dist/assets/wasm/essentia-wasm.web.wasm +0 -0
- package/dist/essentia-wasm.web-CO8uMw0d.js +5696 -0
- package/dist/essentia-wasm.web-CO8uMw0d.js.map +1 -0
- package/dist/essentia.js-core.es-DnrJE0uR.js +3174 -0
- package/dist/essentia.js-core.es-DnrJE0uR.js.map +1 -0
- package/dist/index-BdLMCFEN.js +16180 -0
- package/dist/index-BdLMCFEN.js.map +1 -0
- package/dist/index.d.ts +1129 -37
- package/dist/index.js +5 -2613
- package/dist/index.js.map +1 -1
- package/dist/shader-uniforms.js +125 -0
- package/package.json +5 -2
- package/dist/assets/viji.worker-C8mrsLDG.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,27 +1,643 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
/* Excluded from this release type: AnalysisConfiguration */
|
|
2
|
+
|
|
3
|
+
declare interface AudioAnalysisState {
|
|
4
|
+
isConnected: boolean;
|
|
5
|
+
currentBPM: number;
|
|
6
|
+
confidence: number;
|
|
7
|
+
mode: 'auto' | 'manual';
|
|
8
|
+
tapCount: number;
|
|
9
|
+
isLocked: boolean;
|
|
10
|
+
sensitivity: number;
|
|
7
11
|
}
|
|
8
12
|
|
|
9
13
|
export declare interface AudioAPI {
|
|
10
14
|
isConnected: boolean;
|
|
11
15
|
volume: {
|
|
12
|
-
|
|
16
|
+
current: number;
|
|
13
17
|
peak: number;
|
|
18
|
+
smoothed: number;
|
|
19
|
+
};
|
|
20
|
+
bands: {
|
|
21
|
+
low: number;
|
|
22
|
+
lowMid: number;
|
|
23
|
+
mid: number;
|
|
24
|
+
highMid: number;
|
|
25
|
+
high: number;
|
|
26
|
+
lowSmoothed: number;
|
|
27
|
+
lowMidSmoothed: number;
|
|
28
|
+
midSmoothed: number;
|
|
29
|
+
highMidSmoothed: number;
|
|
30
|
+
highSmoothed: number;
|
|
14
31
|
};
|
|
15
|
-
beat
|
|
16
|
-
|
|
32
|
+
beat: {
|
|
33
|
+
kick: number;
|
|
34
|
+
snare: number;
|
|
35
|
+
hat: number;
|
|
36
|
+
any: number;
|
|
37
|
+
kickSmoothed: number;
|
|
38
|
+
snareSmoothed: number;
|
|
39
|
+
anySmoothed: number;
|
|
40
|
+
triggers: {
|
|
41
|
+
any: boolean;
|
|
42
|
+
kick: boolean;
|
|
43
|
+
snare: boolean;
|
|
44
|
+
hat: boolean;
|
|
45
|
+
};
|
|
46
|
+
events: Array<{
|
|
47
|
+
type: 'kick' | 'snare' | 'hat';
|
|
48
|
+
time: number;
|
|
49
|
+
strength: number;
|
|
50
|
+
}>;
|
|
51
|
+
bpm: number;
|
|
52
|
+
phase: number;
|
|
53
|
+
bar: number;
|
|
17
54
|
confidence: number;
|
|
55
|
+
isLocked: boolean;
|
|
56
|
+
};
|
|
57
|
+
spectral: {
|
|
58
|
+
brightness: number;
|
|
59
|
+
flatness: number;
|
|
60
|
+
flux: number;
|
|
18
61
|
};
|
|
19
|
-
bands: Record<string, number>;
|
|
20
62
|
getFrequencyData: () => Uint8Array;
|
|
63
|
+
getWaveform?: (samples?: number) => Float32Array;
|
|
64
|
+
getFFT?: (bins?: number, scale?: 'linear' | 'log') => Float32Array;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Manages audio analysis and processing for the host side.
|
|
69
|
+
* Handles audio stream processing and provides real-time audio analysis.
|
|
70
|
+
*
|
|
71
|
+
* This system provides:
|
|
72
|
+
* - Real-time audio analysis (RMS, peak, frequency bands)
|
|
73
|
+
* - Beat detection with automatic BPM tracking
|
|
74
|
+
* - Onset detection for audio-reactive triggers
|
|
75
|
+
* - Smooth energy curves with envelope followers
|
|
76
|
+
* - Tap tempo and manual BPM control
|
|
77
|
+
* - Auto-gain normalization
|
|
78
|
+
* - Spectral feature extraction
|
|
79
|
+
* - AudioContext management and cleanup
|
|
80
|
+
* - Raw FFT data access for custom analysis
|
|
81
|
+
* - Analysis results sent to worker for artist API
|
|
82
|
+
*/
|
|
83
|
+
export declare class AudioSystem {
|
|
84
|
+
private audioContext;
|
|
85
|
+
private analyser;
|
|
86
|
+
private mediaStreamSource;
|
|
87
|
+
private currentStream;
|
|
88
|
+
private analysisMode;
|
|
89
|
+
private workletNode;
|
|
90
|
+
private workletReady;
|
|
91
|
+
private currentSampleRate;
|
|
92
|
+
private pcmRing;
|
|
93
|
+
private pcmWriteIndex;
|
|
94
|
+
private pcmFilled;
|
|
95
|
+
private pcmHistorySeconds;
|
|
96
|
+
private lastTempoExtraction;
|
|
97
|
+
private tempoExtractionIntervalMs;
|
|
98
|
+
private analysisBackend;
|
|
99
|
+
private bandNoiseFloor;
|
|
100
|
+
/** Tracks the last non-zero BPM chosen for output to avoid dropping to 0 */
|
|
101
|
+
private lastNonZeroBpm;
|
|
102
|
+
/** Tracks which source provided the current BPM (pll | tempo | carry | default) */
|
|
103
|
+
private lastBpmSource;
|
|
104
|
+
private aubioWarningLogged;
|
|
105
|
+
private useEssentiaTempo;
|
|
106
|
+
private workletFrameCount;
|
|
107
|
+
private forceAnalyser;
|
|
108
|
+
private statusLogTimer;
|
|
109
|
+
private isAudioLab;
|
|
110
|
+
private analysisTicks;
|
|
111
|
+
private lastLoopWarn;
|
|
112
|
+
private verboseLabLogs;
|
|
113
|
+
private lastPhaseLogTime;
|
|
114
|
+
private onsetLogBuffer;
|
|
115
|
+
private debugMode;
|
|
116
|
+
private diagnosticLogger;
|
|
117
|
+
private onsetDetection;
|
|
118
|
+
private essentiaOnsetDetection;
|
|
119
|
+
private tempoInduction;
|
|
120
|
+
private pll;
|
|
121
|
+
private stateManager;
|
|
122
|
+
private lastKickDetected;
|
|
123
|
+
private volumeAutoGain;
|
|
124
|
+
private bandAutoGain;
|
|
125
|
+
/** Raw band snapshot before auto-gain (for debug) */
|
|
126
|
+
private rawBandsPreGain;
|
|
127
|
+
/** Last dt used in analysis loop (ms) */
|
|
128
|
+
private lastDtMs;
|
|
129
|
+
/** Flag to disable auto-gain for debugging */
|
|
130
|
+
private debugDisableAutoGain;
|
|
131
|
+
/** Flag to track if we've logged detection method (to avoid spam) */
|
|
132
|
+
private readonly bandNames;
|
|
133
|
+
private essentiaBandHistories;
|
|
134
|
+
private readonly essentiaHistoryWindowMs;
|
|
135
|
+
private beatMode;
|
|
136
|
+
private manualBPM;
|
|
137
|
+
private tapHistory;
|
|
138
|
+
private tapTimeout;
|
|
139
|
+
private envelopeFollowers;
|
|
140
|
+
private sensitivity;
|
|
141
|
+
private beatDetectionEnabled;
|
|
142
|
+
private onsetDetectionEnabled;
|
|
143
|
+
private autoGainEnabled;
|
|
144
|
+
/**
|
|
145
|
+
* Enable or disable comprehensive debug logging for all layers
|
|
146
|
+
* Enables enhanced logging in: MultiOnsetDetection, BeatStateManager
|
|
147
|
+
*/
|
|
148
|
+
setDebugMode(enabled: boolean): void;
|
|
149
|
+
/**
|
|
150
|
+
* Reset Essentia band onset histories (used to feed tempo induction when using the Essentia backend)
|
|
151
|
+
*/
|
|
152
|
+
private resetEssentiaBandHistories;
|
|
153
|
+
/**
|
|
154
|
+
* Update Essentia band onset histories and trim old entries
|
|
155
|
+
*/
|
|
156
|
+
private updateEssentiaBandHistories;
|
|
157
|
+
private getEssentiaBandHistory;
|
|
158
|
+
private getEssentiaAllHistories;
|
|
159
|
+
private logVerbose;
|
|
160
|
+
/**
|
|
161
|
+
* Start/stop periodic status logging. If maxSamples provided, stops after that many ticks.
|
|
162
|
+
*/
|
|
163
|
+
private toggleStatusLogger;
|
|
164
|
+
/**
|
|
165
|
+
* Handle frames pushed from AudioWorklet
|
|
166
|
+
*/
|
|
167
|
+
private handleWorkletFrame;
|
|
168
|
+
/**
|
|
169
|
+
* Unified analysis pipeline (worklet and analyser paths)
|
|
170
|
+
*/
|
|
171
|
+
private analyzeFrame;
|
|
172
|
+
/**
|
|
173
|
+
* Compute FFT and derived arrays
|
|
174
|
+
*/
|
|
175
|
+
private computeFFT;
|
|
176
|
+
/**
|
|
177
|
+
* Calculate RMS/peak from float PCM frame (-1..1)
|
|
178
|
+
*/
|
|
179
|
+
private calculateVolumeMetrics;
|
|
180
|
+
/**
|
|
181
|
+
* Calculate perceptual/log-ish bands (pre-gain), normalized by max magnitude
|
|
182
|
+
*/
|
|
183
|
+
private calculateFrequencyBandsFromMagnitude;
|
|
184
|
+
/**
|
|
185
|
+
* Spectral features from magnitude spectrum
|
|
186
|
+
*/
|
|
187
|
+
private calculateSpectralFeaturesFromMagnitude;
|
|
188
|
+
/**
|
|
189
|
+
* Append PCM frame to ring buffer for periodic Essentia tempo extraction
|
|
190
|
+
*/
|
|
191
|
+
private appendPcmFrame;
|
|
192
|
+
/**
|
|
193
|
+
* Periodically estimate tempo using Essentia's RhythmExtractor2013 (offline chunk)
|
|
194
|
+
*/
|
|
195
|
+
private runEssentiaTempoEstimate;
|
|
196
|
+
/**
|
|
197
|
+
* Run onset + beat detection pipeline and return BeatState
|
|
198
|
+
*/
|
|
199
|
+
private runBeatPipeline;
|
|
200
|
+
/**
|
|
201
|
+
* Debug logging helper
|
|
202
|
+
*/
|
|
203
|
+
private debugLog;
|
|
204
|
+
private fftSize;
|
|
205
|
+
private smoothingTimeConstant;
|
|
206
|
+
private analysisInterval;
|
|
207
|
+
private analysisIntervalMs;
|
|
208
|
+
private frequencyData;
|
|
209
|
+
private timeDomainData;
|
|
210
|
+
private fftEngine;
|
|
211
|
+
private fftInput;
|
|
212
|
+
private fftOutput;
|
|
213
|
+
private fftMagnitude;
|
|
214
|
+
private fftMagnitudeDb;
|
|
215
|
+
private fftPhase;
|
|
216
|
+
private hannWindow;
|
|
217
|
+
private audioState;
|
|
218
|
+
private analysisLoopId;
|
|
219
|
+
private isAnalysisRunning;
|
|
220
|
+
private lastAnalysisTimestamp;
|
|
221
|
+
private sendAnalysisResults;
|
|
222
|
+
private prevSpectralCentroid;
|
|
223
|
+
constructor(sendAnalysisResultsCallback?: (data: any) => void);
|
|
224
|
+
/**
|
|
225
|
+
* Prepare FFT buffers and windowing for the selected fftSize
|
|
226
|
+
*/
|
|
227
|
+
private refreshFFTResources;
|
|
228
|
+
/**
|
|
229
|
+
* Get the current audio analysis state (for host-side usage)
|
|
230
|
+
*/
|
|
231
|
+
getAudioState(): {
|
|
232
|
+
isConnected: boolean;
|
|
233
|
+
volume: {
|
|
234
|
+
current: number;
|
|
235
|
+
peak: number;
|
|
236
|
+
smoothed: number;
|
|
237
|
+
};
|
|
238
|
+
bands: {
|
|
239
|
+
low: number;
|
|
240
|
+
lowMid: number;
|
|
241
|
+
mid: number;
|
|
242
|
+
highMid: number;
|
|
243
|
+
high: number;
|
|
244
|
+
lowSmoothed: number;
|
|
245
|
+
lowMidSmoothed: number;
|
|
246
|
+
midSmoothed: number;
|
|
247
|
+
highMidSmoothed: number;
|
|
248
|
+
highSmoothed: number;
|
|
249
|
+
};
|
|
250
|
+
beat: {
|
|
251
|
+
kick: number;
|
|
252
|
+
snare: number;
|
|
253
|
+
hat: number;
|
|
254
|
+
any: number;
|
|
255
|
+
kickSmoothed: number;
|
|
256
|
+
snareSmoothed: number;
|
|
257
|
+
anySmoothed: number;
|
|
258
|
+
events: BeatEvent[];
|
|
259
|
+
bpm: number;
|
|
260
|
+
phase: number;
|
|
261
|
+
bar: number;
|
|
262
|
+
confidence: number;
|
|
263
|
+
isLocked: boolean;
|
|
264
|
+
};
|
|
265
|
+
spectral: {
|
|
266
|
+
brightness: number;
|
|
267
|
+
flatness: number;
|
|
268
|
+
flux: number;
|
|
269
|
+
};
|
|
270
|
+
};
|
|
271
|
+
/**
|
|
272
|
+
* Initialize Essentia.js (async WASM loading)
|
|
273
|
+
*/
|
|
274
|
+
private initializeEssentia;
|
|
275
|
+
/**
|
|
276
|
+
* Wait for Essentia.js to initialize (for testing/benchmarking)
|
|
277
|
+
* Returns immediately if already initialized or if initialization failed
|
|
278
|
+
*/
|
|
279
|
+
waitForEssentia(timeoutMs?: number): Promise<boolean>;
|
|
280
|
+
/**
|
|
281
|
+
* Handle audio stream update (called from VijiCore)
|
|
282
|
+
*/
|
|
283
|
+
handleAudioStreamUpdate(data: {
|
|
284
|
+
audioStream?: MediaStream | null;
|
|
285
|
+
analysisConfig?: AnalysisConfiguration;
|
|
286
|
+
timestamp: number;
|
|
287
|
+
}): void;
|
|
288
|
+
/**
|
|
289
|
+
* Set the audio stream for analysis
|
|
290
|
+
*/
|
|
291
|
+
private setAudioStream;
|
|
292
|
+
/**
|
|
293
|
+
* Disconnect current audio stream and clean up resources
|
|
294
|
+
*/
|
|
295
|
+
private disconnectAudioStream;
|
|
296
|
+
/**
|
|
297
|
+
* Update analysis configuration
|
|
298
|
+
*/
|
|
299
|
+
private updateAnalysisConfig;
|
|
300
|
+
/**
|
|
301
|
+
* Initialize audio worklet for high-quality capture (complex STFT path)
|
|
302
|
+
*/
|
|
303
|
+
private setupAudioWorklet;
|
|
304
|
+
/**
|
|
305
|
+
* Start the audio analysis loop at high speed (8ms intervals for transient capture)
|
|
306
|
+
*/
|
|
307
|
+
private startAnalysisLoop;
|
|
308
|
+
/**
|
|
309
|
+
* Stop the audio analysis loop
|
|
310
|
+
*/
|
|
311
|
+
private stopAnalysisLoop;
|
|
312
|
+
/**
|
|
313
|
+
* Pause audio analysis (for tests or temporary suspension)
|
|
314
|
+
* The setInterval continues but performAnalysis() exits early
|
|
315
|
+
*/
|
|
316
|
+
pauseAnalysis(): void;
|
|
317
|
+
/**
|
|
318
|
+
* Resume audio analysis after pause
|
|
319
|
+
*/
|
|
320
|
+
resumeAnalysis(): void;
|
|
321
|
+
/**
|
|
322
|
+
* Perform audio analysis (called every frame)
|
|
323
|
+
* Uses industry-grade 4-layer architecture:
|
|
324
|
+
* Layer 1: MultiOnsetDetection (per-band onset detection)
|
|
325
|
+
* Layer 2: TempoInduction (dual-method BPM detection)
|
|
326
|
+
* Layer 3: PhaseLockedLoop (stable phase tracking)
|
|
327
|
+
* Layer 4: BeatStateManager (state machine + confidence)
|
|
328
|
+
*/
|
|
329
|
+
private performAnalysis;
|
|
330
|
+
private applyAutoGain;
|
|
331
|
+
/**
|
|
332
|
+
* Update smooth versions of frequency bands
|
|
333
|
+
*/
|
|
334
|
+
private updateSmoothBands;
|
|
335
|
+
/**
|
|
336
|
+
* Send analysis results to worker
|
|
337
|
+
*/
|
|
338
|
+
private sendAnalysisResultsToWorker;
|
|
339
|
+
/**
|
|
340
|
+
* Reset audio values to defaults
|
|
341
|
+
*/
|
|
342
|
+
private resetAudioValues;
|
|
343
|
+
/**
|
|
344
|
+
* Reset all audio state (called when destroying)
|
|
345
|
+
*/
|
|
346
|
+
resetAudioState(): void;
|
|
347
|
+
/**
|
|
348
|
+
* Get current analysis configuration
|
|
349
|
+
*/
|
|
350
|
+
getAnalysisConfig(): {
|
|
351
|
+
fftSize: number;
|
|
352
|
+
smoothing: number;
|
|
353
|
+
};
|
|
354
|
+
/**
|
|
355
|
+
* Set analysis backend preference
|
|
356
|
+
*/
|
|
357
|
+
setAnalysisBackend(backend: 'auto' | 'essentia' | 'custom' | 'aubio'): void;
|
|
358
|
+
getAnalysisBackend(): 'auto' | 'essentia' | 'custom' | 'aubio';
|
|
359
|
+
/**
|
|
360
|
+
* Force analyser path (skip worklet) for debugging
|
|
361
|
+
*/
|
|
362
|
+
setForceAnalyser(enabled: boolean): void;
|
|
363
|
+
isForceAnalyser(): boolean;
|
|
364
|
+
/**
|
|
365
|
+
* Enable/disable Essentia tempo extraction (disabled by default due to WASM exception config)
|
|
366
|
+
*/
|
|
367
|
+
setEssentiaTempoEnabled(enabled: boolean): void;
|
|
368
|
+
isEssentiaTempoEnabled(): boolean;
|
|
369
|
+
/**
|
|
370
|
+
* Set global sensitivity multiplier
|
|
371
|
+
* @param value - Sensitivity (0.5-2.0, default 1.0)
|
|
372
|
+
*/
|
|
373
|
+
setSensitivity(value: number): void;
|
|
374
|
+
/**
|
|
375
|
+
* Get current sensitivity
|
|
376
|
+
*/
|
|
377
|
+
getSensitivity(): number;
|
|
378
|
+
/**
|
|
379
|
+
* Tap tempo - record tap for manual BPM
|
|
380
|
+
*/
|
|
381
|
+
tapTempo(): void;
|
|
382
|
+
/**
|
|
383
|
+
* Calculate BPM from tap history
|
|
384
|
+
*/
|
|
385
|
+
private calculateBPMFromTaps;
|
|
386
|
+
/**
|
|
387
|
+
* Start auto-clear timeout for tap tempo
|
|
388
|
+
*/
|
|
389
|
+
private startTapClearTimeout;
|
|
390
|
+
/**
|
|
391
|
+
* Clear tap tempo history
|
|
392
|
+
*/
|
|
393
|
+
clearTaps(): void;
|
|
394
|
+
/**
|
|
395
|
+
* Get tap count
|
|
396
|
+
*/
|
|
397
|
+
getTapCount(): number;
|
|
398
|
+
/**
|
|
399
|
+
* Set beat sync mode
|
|
400
|
+
*/
|
|
401
|
+
setBeatMode(mode: 'auto' | 'manual'): void;
|
|
402
|
+
/**
|
|
403
|
+
* Get beat sync mode
|
|
404
|
+
*/
|
|
405
|
+
getBeatMode(): 'auto' | 'manual';
|
|
406
|
+
/**
|
|
407
|
+
* Set manual BPM
|
|
408
|
+
*/
|
|
409
|
+
setManualBPM(bpm: number): void;
|
|
410
|
+
/**
|
|
411
|
+
* Get current BPM (manual or auto-detected)
|
|
412
|
+
*/
|
|
413
|
+
getCurrentBPM(): number;
|
|
414
|
+
/**
|
|
415
|
+
* Nudge beat phase
|
|
416
|
+
*/
|
|
417
|
+
nudgeBeatPhase(amount: number): void;
|
|
418
|
+
/**
|
|
419
|
+
* Reset beat phase to next beat
|
|
420
|
+
*/
|
|
421
|
+
resetBeatPhase(): void;
|
|
422
|
+
/**
|
|
423
|
+
* Set FFT size
|
|
424
|
+
*/
|
|
425
|
+
setFFTSize(size: 2048 | 4096 | 8192): void;
|
|
426
|
+
/**
|
|
427
|
+
* Set smoothing time constant
|
|
428
|
+
*/
|
|
429
|
+
setSmoothing(value: number): void;
|
|
430
|
+
/**
|
|
431
|
+
* Enable/disable auto-gain
|
|
432
|
+
*/
|
|
433
|
+
setAutoGain(enabled: boolean): void;
|
|
434
|
+
/**
|
|
435
|
+
* Enable/disable beat detection
|
|
436
|
+
*/
|
|
437
|
+
setBeatDetection(enabled: boolean): void;
|
|
438
|
+
/**
|
|
439
|
+
* Enable/disable onset detection
|
|
440
|
+
*/
|
|
441
|
+
setOnsetDetection(enabled: boolean): void;
|
|
442
|
+
/**
|
|
443
|
+
* Get complete audio analysis state
|
|
444
|
+
*/
|
|
445
|
+
getState(): {
|
|
446
|
+
isConnected: boolean;
|
|
447
|
+
currentBPM: number;
|
|
448
|
+
confidence: number;
|
|
449
|
+
mode: 'auto' | 'manual';
|
|
450
|
+
tapCount: number;
|
|
451
|
+
isLocked: boolean;
|
|
452
|
+
sensitivity: number;
|
|
453
|
+
trackingState: string;
|
|
454
|
+
};
|
|
455
|
+
/**
|
|
456
|
+
* Get current per-frame audio analysis data (for UI display)
|
|
457
|
+
* Returns a snapshot of the latest audio analysis values
|
|
458
|
+
*/
|
|
459
|
+
getCurrentAudioData(): {
|
|
460
|
+
isConnected: boolean;
|
|
461
|
+
volume: {
|
|
462
|
+
current: number;
|
|
463
|
+
peak: number;
|
|
464
|
+
smoothed: number;
|
|
465
|
+
};
|
|
466
|
+
bands: {
|
|
467
|
+
low: number;
|
|
468
|
+
lowMid: number;
|
|
469
|
+
mid: number;
|
|
470
|
+
highMid: number;
|
|
471
|
+
high: number;
|
|
472
|
+
lowSmoothed: number;
|
|
473
|
+
lowMidSmoothed: number;
|
|
474
|
+
midSmoothed: number;
|
|
475
|
+
highMidSmoothed: number;
|
|
476
|
+
highSmoothed: number;
|
|
477
|
+
};
|
|
478
|
+
beat: {
|
|
479
|
+
kick: number;
|
|
480
|
+
snare: number;
|
|
481
|
+
hat: number;
|
|
482
|
+
any: number;
|
|
483
|
+
kickSmoothed: number;
|
|
484
|
+
snareSmoothed: number;
|
|
485
|
+
anySmoothed: number;
|
|
486
|
+
events: BeatEvent[];
|
|
487
|
+
bpm: number;
|
|
488
|
+
phase: number;
|
|
489
|
+
bar: number;
|
|
490
|
+
confidence: number;
|
|
491
|
+
isLocked: boolean;
|
|
492
|
+
};
|
|
493
|
+
spectral: {
|
|
494
|
+
brightness: number;
|
|
495
|
+
flatness: number;
|
|
496
|
+
flux: number;
|
|
497
|
+
};
|
|
498
|
+
};
|
|
499
|
+
/**
|
|
500
|
+
* Get enhanced debug snapshot from all layers
|
|
501
|
+
*/
|
|
502
|
+
getEnhancedDebugSnapshot(): {
|
|
503
|
+
onset: {
|
|
504
|
+
currentBPM: number;
|
|
505
|
+
debugMode: boolean;
|
|
506
|
+
totalOnsets: number;
|
|
507
|
+
currentCluster: {
|
|
508
|
+
primaryBands: string[];
|
|
509
|
+
ageMssinceStart: number;
|
|
510
|
+
} | null;
|
|
511
|
+
bandStates: Record<string, {
|
|
512
|
+
lastOnsetTime: number;
|
|
513
|
+
onsetCount: number;
|
|
514
|
+
cutoff: number;
|
|
515
|
+
minEnergy: number;
|
|
516
|
+
}>;
|
|
517
|
+
};
|
|
518
|
+
tempo: {
|
|
519
|
+
bpm: number;
|
|
520
|
+
confidence: number;
|
|
521
|
+
};
|
|
522
|
+
pll: PLLState;
|
|
523
|
+
state: {
|
|
524
|
+
trackingState: TrackingState;
|
|
525
|
+
isLocked: boolean;
|
|
526
|
+
};
|
|
527
|
+
};
|
|
528
|
+
/**
|
|
529
|
+
* Get comprehensive debug info for testing/debugging
|
|
530
|
+
* Exposes internal state of all analysis layers
|
|
531
|
+
*/
|
|
532
|
+
getDebugInfo(): {
|
|
533
|
+
onset: Record<BandName, {
|
|
534
|
+
energy: number;
|
|
535
|
+
prevEnergy: number;
|
|
536
|
+
prevEnergy2: number;
|
|
537
|
+
minEnergy: number;
|
|
538
|
+
flux: number;
|
|
539
|
+
cutoff: number;
|
|
540
|
+
minThreshold: number;
|
|
541
|
+
minFlux: number;
|
|
542
|
+
wouldTrigger: boolean;
|
|
543
|
+
reason: string;
|
|
544
|
+
debounceMs: number;
|
|
545
|
+
lastOnsetAgo: number;
|
|
546
|
+
baselineAlpha?: number;
|
|
547
|
+
dtMs?: number;
|
|
548
|
+
fluxPrevOnly?: number;
|
|
549
|
+
fluxBaseline?: number;
|
|
550
|
+
initialized?: boolean;
|
|
551
|
+
lastFluxStored?: number;
|
|
552
|
+
fluxCalcNow?: number;
|
|
553
|
+
}>;
|
|
554
|
+
tempo: {
|
|
555
|
+
currentBPM: number;
|
|
556
|
+
confidence: number;
|
|
557
|
+
method: string;
|
|
558
|
+
anchorBand: string | null;
|
|
559
|
+
methodAgreement: number;
|
|
560
|
+
bpmHistory: number[];
|
|
561
|
+
envelopeLength: number;
|
|
562
|
+
lastAutocorrBPM: number;
|
|
563
|
+
lastIOIBPM: number;
|
|
564
|
+
};
|
|
565
|
+
pll: {
|
|
566
|
+
bpm: number;
|
|
567
|
+
phase: number;
|
|
568
|
+
bar: number;
|
|
569
|
+
driftRate: number;
|
|
570
|
+
state: PLLState;
|
|
571
|
+
};
|
|
572
|
+
state: {
|
|
573
|
+
trackingState: TrackingState;
|
|
574
|
+
isLocked: boolean;
|
|
575
|
+
};
|
|
576
|
+
levels: {
|
|
577
|
+
low: number;
|
|
578
|
+
lowMid: number;
|
|
579
|
+
mid: number;
|
|
580
|
+
highMid: number;
|
|
581
|
+
high: number;
|
|
582
|
+
volume: number;
|
|
583
|
+
};
|
|
584
|
+
rawBands: {
|
|
585
|
+
low: number;
|
|
586
|
+
lowMid: number;
|
|
587
|
+
mid: number;
|
|
588
|
+
highMid: number;
|
|
589
|
+
high: number;
|
|
590
|
+
};
|
|
591
|
+
bandGains: {
|
|
592
|
+
low: number;
|
|
593
|
+
lowMid: number;
|
|
594
|
+
mid: number;
|
|
595
|
+
highMid: number;
|
|
596
|
+
high: number;
|
|
597
|
+
};
|
|
598
|
+
volumeGain: number;
|
|
599
|
+
dtMs: number;
|
|
600
|
+
smoothingTimeConstant: number;
|
|
601
|
+
analysisIntervalMs: number;
|
|
602
|
+
events: BeatEvent[];
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Multi-band onset detection with hybrid peak-decay + spectral flux approach
|
|
608
|
+
*
|
|
609
|
+
* Industry-grade onset detection that:
|
|
610
|
+
* - Uses 5 frequency bands for precise instrument detection
|
|
611
|
+
* - Combines peak-decay threshold (proven reliable) with spectral flux (transient detection)
|
|
612
|
+
* - Maintains per-band onset history for tempo pattern analysis
|
|
613
|
+
* - Is frame-rate independent (dt-aware)
|
|
614
|
+
* - Prevents double-triggering with adaptive cooldown
|
|
615
|
+
*/
|
|
616
|
+
/**
|
|
617
|
+
* Band names for the 5-band analysis
|
|
618
|
+
*/
|
|
619
|
+
declare type BandName = 'low' | 'lowMid' | 'mid' | 'highMid' | 'high';
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Beat event (discrete, timestamped)
|
|
623
|
+
*/
|
|
624
|
+
declare interface BeatEvent {
|
|
625
|
+
type: 'kick' | 'snare' | 'hat';
|
|
626
|
+
time: number;
|
|
627
|
+
strength: number;
|
|
628
|
+
confidence?: number;
|
|
629
|
+
phase?: number;
|
|
630
|
+
bar?: number;
|
|
631
|
+
isLayered?: boolean;
|
|
632
|
+
isPredicted?: boolean;
|
|
633
|
+
bpm?: number;
|
|
634
|
+
bands?: string[];
|
|
21
635
|
}
|
|
22
636
|
|
|
23
637
|
export declare interface CaptureFrameOptions {
|
|
24
|
-
/**
|
|
638
|
+
/** Output format: 'blob' for encoded image, 'bitmap' for GPU-friendly ImageBitmap */
|
|
639
|
+
format?: 'blob' | 'bitmap';
|
|
640
|
+
/** MIME type for blob output (ignored for bitmap), e.g., 'image/png', 'image/jpeg', 'image/webp' */
|
|
25
641
|
type?: string;
|
|
26
642
|
/**
|
|
27
643
|
* Target resolution.
|
|
@@ -65,6 +681,67 @@ declare type CVFeature = 'faceDetection' | 'faceMesh' | 'handTracking' | 'poseDe
|
|
|
65
681
|
|
|
66
682
|
declare type CVFrameRateMode = 'full' | 'half' | 'quarter' | 'eighth';
|
|
67
683
|
|
|
684
|
+
/**
|
|
685
|
+
* DeviceMotionEvent acceleration data
|
|
686
|
+
* Matches native DeviceMotionEvent.acceleration structure
|
|
687
|
+
*/
|
|
688
|
+
declare interface DeviceMotionData {
|
|
689
|
+
/** Acceleration without gravity (m/s²) */
|
|
690
|
+
acceleration: {
|
|
691
|
+
x: number | null;
|
|
692
|
+
y: number | null;
|
|
693
|
+
z: number | null;
|
|
694
|
+
} | null;
|
|
695
|
+
/** Acceleration including gravity (m/s²) */
|
|
696
|
+
accelerationIncludingGravity: {
|
|
697
|
+
x: number | null;
|
|
698
|
+
y: number | null;
|
|
699
|
+
z: number | null;
|
|
700
|
+
} | null;
|
|
701
|
+
/** Rotation rate (degrees/second) */
|
|
702
|
+
rotationRate: {
|
|
703
|
+
alpha: number | null;
|
|
704
|
+
beta: number | null;
|
|
705
|
+
gamma: number | null;
|
|
706
|
+
} | null;
|
|
707
|
+
/** Interval between updates (milliseconds) */
|
|
708
|
+
interval: number;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* DeviceOrientationEvent data
|
|
713
|
+
* Matches native DeviceOrientationEvent structure
|
|
714
|
+
*/
|
|
715
|
+
declare interface DeviceOrientationData {
|
|
716
|
+
/** Rotation around Z-axis (0-360 degrees, compass heading) */
|
|
717
|
+
alpha: number | null;
|
|
718
|
+
/** Rotation around X-axis (-180 to 180 degrees, front-to-back tilt) */
|
|
719
|
+
beta: number | null;
|
|
720
|
+
/** Rotation around Y-axis (-90 to 90 degrees, left-to-right tilt) */
|
|
721
|
+
gamma: number | null;
|
|
722
|
+
/** True if using magnetometer (compass) for absolute orientation */
|
|
723
|
+
absolute: boolean;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* Complete device sensor state (internal device - no id/name)
|
|
728
|
+
*/
|
|
729
|
+
declare interface DeviceSensorState {
|
|
730
|
+
motion: DeviceMotionData | null;
|
|
731
|
+
orientation: DeviceOrientationData | null;
|
|
732
|
+
geolocation: GeolocationData | null;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* External device state (includes id and name)
|
|
737
|
+
*/
|
|
738
|
+
declare interface DeviceState extends DeviceSensorState {
|
|
739
|
+
/** Unique device identifier */
|
|
740
|
+
id: string;
|
|
741
|
+
/** User-friendly device name */
|
|
742
|
+
name: string;
|
|
743
|
+
}
|
|
744
|
+
|
|
68
745
|
export declare interface FaceData {
|
|
69
746
|
id: number;
|
|
70
747
|
bounds: {
|
|
@@ -109,6 +786,27 @@ export declare interface FrequencyBand {
|
|
|
109
786
|
max: number;
|
|
110
787
|
}
|
|
111
788
|
|
|
789
|
+
/**
|
|
790
|
+
* Geolocation API data
|
|
791
|
+
* Matches native GeolocationPosition.coords structure
|
|
792
|
+
*/
|
|
793
|
+
declare interface GeolocationData {
|
|
794
|
+
/** Latitude in decimal degrees */
|
|
795
|
+
latitude: number | null;
|
|
796
|
+
/** Longitude in decimal degrees */
|
|
797
|
+
longitude: number | null;
|
|
798
|
+
/** Altitude in meters above sea level */
|
|
799
|
+
altitude: number | null;
|
|
800
|
+
/** Accuracy of latitude/longitude in meters */
|
|
801
|
+
accuracy: number | null;
|
|
802
|
+
/** Accuracy of altitude in meters */
|
|
803
|
+
altitudeAccuracy: number | null;
|
|
804
|
+
/** Direction of travel (0-360 degrees, 0=North, 90=East) */
|
|
805
|
+
heading: number | null;
|
|
806
|
+
/** Speed in meters per second */
|
|
807
|
+
speed: number | null;
|
|
808
|
+
}
|
|
809
|
+
|
|
112
810
|
export declare interface HandData {
|
|
113
811
|
id: number;
|
|
114
812
|
handedness: 'left' | 'right';
|
|
@@ -210,6 +908,16 @@ export declare interface KeyboardAPI {
|
|
|
210
908
|
meta: boolean;
|
|
211
909
|
}
|
|
212
910
|
|
|
911
|
+
export declare interface KeyboardEventData {
|
|
912
|
+
type: 'keydown' | 'keyup';
|
|
913
|
+
key: string;
|
|
914
|
+
code: string;
|
|
915
|
+
shiftKey: boolean;
|
|
916
|
+
ctrlKey: boolean;
|
|
917
|
+
altKey: boolean;
|
|
918
|
+
metaKey: boolean;
|
|
919
|
+
}
|
|
920
|
+
|
|
213
921
|
export declare interface MouseAPI {
|
|
214
922
|
x: number;
|
|
215
923
|
y: number;
|
|
@@ -232,6 +940,17 @@ export declare interface MouseAPI {
|
|
|
232
940
|
wasMoved: boolean;
|
|
233
941
|
}
|
|
234
942
|
|
|
943
|
+
export declare interface MouseEventData {
|
|
944
|
+
x: number;
|
|
945
|
+
y: number;
|
|
946
|
+
buttons: number;
|
|
947
|
+
deltaX?: number;
|
|
948
|
+
deltaY?: number;
|
|
949
|
+
wheelDeltaX?: number;
|
|
950
|
+
wheelDeltaY?: number;
|
|
951
|
+
isInCanvas?: boolean;
|
|
952
|
+
}
|
|
953
|
+
|
|
235
954
|
declare interface NumberConfig {
|
|
236
955
|
min?: number;
|
|
237
956
|
max?: number;
|
|
@@ -312,6 +1031,35 @@ export declare interface PerformanceStats {
|
|
|
312
1031
|
};
|
|
313
1032
|
}
|
|
314
1033
|
|
|
1034
|
+
/**
|
|
1035
|
+
* Phase-Locked Loop for stable beat phase tracking
|
|
1036
|
+
*
|
|
1037
|
+
* Industry-grade phase tracking that:
|
|
1038
|
+
* - Maintains expected beat times based on current BPM
|
|
1039
|
+
* - Compares actual onsets to expected times (phase error)
|
|
1040
|
+
* - Corrects phase gradually to avoid jumps
|
|
1041
|
+
* - Handles breakdowns by extrapolating phase
|
|
1042
|
+
* - Detects tempo drift in DJ sets
|
|
1043
|
+
* - Provides stable bar position (0-3 for 4/4 time)
|
|
1044
|
+
*/
|
|
1045
|
+
/**
|
|
1046
|
+
* PLL state for external access
|
|
1047
|
+
*/
|
|
1048
|
+
declare interface PLLState {
|
|
1049
|
+
/** Current phase (0-1, where 0 = beat) */
|
|
1050
|
+
phase: number;
|
|
1051
|
+
/** Current bar position (0-3 for 4/4 time) */
|
|
1052
|
+
bar: number;
|
|
1053
|
+
/** Current BPM being tracked */
|
|
1054
|
+
bpm: number;
|
|
1055
|
+
/** Time since last confirmed beat (ms) */
|
|
1056
|
+
timeSinceLastBeat: number;
|
|
1057
|
+
/** Whether tempo is drifting (DJ transition) */
|
|
1058
|
+
isDrifting: boolean;
|
|
1059
|
+
/** Drift rate (BPM per second, positive = speeding up) */
|
|
1060
|
+
driftRate: number;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
315
1063
|
declare interface PoseData {
|
|
316
1064
|
confidence: number;
|
|
317
1065
|
landmarks: {
|
|
@@ -439,6 +1187,20 @@ export declare interface TouchAPI {
|
|
|
439
1187
|
gestures: TouchGestureAPI;
|
|
440
1188
|
}
|
|
441
1189
|
|
|
1190
|
+
export declare interface TouchEventData {
|
|
1191
|
+
type: 'touchstart' | 'touchmove' | 'touchend' | 'touchcancel';
|
|
1192
|
+
touches: Array<{
|
|
1193
|
+
identifier: number;
|
|
1194
|
+
clientX: number;
|
|
1195
|
+
clientY: number;
|
|
1196
|
+
pressure: number;
|
|
1197
|
+
radiusX: number;
|
|
1198
|
+
radiusY: number;
|
|
1199
|
+
rotationAngle: number;
|
|
1200
|
+
force: number;
|
|
1201
|
+
}>;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
442
1204
|
declare interface TouchGestureAPI {
|
|
443
1205
|
isPinching: boolean;
|
|
444
1206
|
isRotating: boolean;
|
|
@@ -481,7 +1243,13 @@ declare interface TouchPoint {
|
|
|
481
1243
|
isEnding: boolean;
|
|
482
1244
|
}
|
|
483
1245
|
|
|
484
|
-
|
|
1246
|
+
/**
|
|
1247
|
+
* State machine states
|
|
1248
|
+
* NOTE: LEARNING state removed - system now uses continuous rolling window adaptation
|
|
1249
|
+
*/
|
|
1250
|
+
declare type TrackingState = 'TRACKING' | 'LOCKED' | 'BREAKDOWN' | 'LOST';
|
|
1251
|
+
|
|
1252
|
+
export declare const VERSION = "0.2.20";
|
|
485
1253
|
|
|
486
1254
|
export declare interface VideoAPI {
|
|
487
1255
|
isConnected: boolean;
|
|
@@ -518,9 +1286,12 @@ export declare interface VijiAPI {
|
|
|
518
1286
|
fps: number;
|
|
519
1287
|
audio: AudioAPI;
|
|
520
1288
|
video: VideoAPI;
|
|
1289
|
+
streams: VideoAPI[];
|
|
521
1290
|
mouse: MouseAPI;
|
|
522
1291
|
keyboard: KeyboardAPI;
|
|
523
1292
|
touches: TouchAPI;
|
|
1293
|
+
device: DeviceSensorState;
|
|
1294
|
+
devices: DeviceState[];
|
|
524
1295
|
slider: (defaultValue: number, config: SliderConfig) => SliderParameter;
|
|
525
1296
|
color: (defaultValue: string, config: ColorConfig) => ColorParameter;
|
|
526
1297
|
toggle: (defaultValue: boolean, config: ToggleConfig) => ToggleParameter;
|
|
@@ -541,8 +1312,8 @@ export declare class VijiCore {
|
|
|
541
1312
|
private iframeManager;
|
|
542
1313
|
private workerManager;
|
|
543
1314
|
private interactionManager;
|
|
1315
|
+
private deviceSensorManager;
|
|
544
1316
|
private audioSystem;
|
|
545
|
-
private videoCoordinator;
|
|
546
1317
|
private isInitialized;
|
|
547
1318
|
private isDestroyed;
|
|
548
1319
|
private isInitializing;
|
|
@@ -554,8 +1325,19 @@ export declare class VijiCore {
|
|
|
554
1325
|
*/
|
|
555
1326
|
private debugLog;
|
|
556
1327
|
private config;
|
|
1328
|
+
private isHeadless;
|
|
557
1329
|
private currentAudioStream;
|
|
558
|
-
private
|
|
1330
|
+
private videoStream;
|
|
1331
|
+
private videoStreams;
|
|
1332
|
+
private mainVideoCoordinator;
|
|
1333
|
+
private additionalCoordinators;
|
|
1334
|
+
private directFrameSlots;
|
|
1335
|
+
private latestFrameBuffer;
|
|
1336
|
+
private autoCaptureEnabled;
|
|
1337
|
+
private eventSourceCore;
|
|
1338
|
+
private frameSourceCores;
|
|
1339
|
+
private eventSourceCleanup;
|
|
1340
|
+
private resizeSyncEnabled;
|
|
559
1341
|
private currentInteractionEnabled;
|
|
560
1342
|
private parameterGroups;
|
|
561
1343
|
private parameterValues;
|
|
@@ -567,10 +1349,33 @@ export declare class VijiCore {
|
|
|
567
1349
|
private stats;
|
|
568
1350
|
constructor(config: VijiCoreConfig);
|
|
569
1351
|
/**
|
|
570
|
-
* Capture current scene frame
|
|
571
|
-
*
|
|
1352
|
+
* Capture current scene frame
|
|
1353
|
+
* @param options.format 'blob' = encoded image, 'bitmap' = GPU-friendly ImageBitmap
|
|
572
1354
|
*/
|
|
1355
|
+
captureFrame(options: {
|
|
1356
|
+
format: 'bitmap';
|
|
1357
|
+
} & Partial<CaptureFrameOptions>): Promise<ImageBitmap>;
|
|
573
1358
|
captureFrame(options?: CaptureFrameOptions): Promise<Blob>;
|
|
1359
|
+
/**
|
|
1360
|
+
* Update frame buffer (internal, called by worker message)
|
|
1361
|
+
*/
|
|
1362
|
+
private updateFrameBuffer;
|
|
1363
|
+
/**
|
|
1364
|
+
* Get latest frame (transfers ownership, zero-copy)
|
|
1365
|
+
*/
|
|
1366
|
+
getLatestFrame(): ImageBitmap | null;
|
|
1367
|
+
/**
|
|
1368
|
+
* Get latest frames from all linked sources
|
|
1369
|
+
*/
|
|
1370
|
+
getLatestFramesFromSources(): (ImageBitmap | null)[];
|
|
1371
|
+
/**
|
|
1372
|
+
* Enable auto-capture with optional format (internal, called by linkFrameSources)
|
|
1373
|
+
*/
|
|
1374
|
+
private enableAutoCapture;
|
|
1375
|
+
/**
|
|
1376
|
+
* Disable auto-capture (internal)
|
|
1377
|
+
*/
|
|
1378
|
+
private disableAutoCapture;
|
|
574
1379
|
/**
|
|
575
1380
|
* Enable or disable debug logging
|
|
576
1381
|
*/
|
|
@@ -579,6 +1384,11 @@ export declare class VijiCore {
|
|
|
579
1384
|
* Get current debug mode status
|
|
580
1385
|
*/
|
|
581
1386
|
getDebugMode(): boolean;
|
|
1387
|
+
/**
|
|
1388
|
+
* Select audio analysis backend
|
|
1389
|
+
*/
|
|
1390
|
+
setAudioAnalysisBackend(backend: 'auto' | 'essentia' | 'custom' | 'aubio'): void;
|
|
1391
|
+
getAudioAnalysisBackend(): 'auto' | 'essentia' | 'custom' | 'aubio';
|
|
582
1392
|
/**
|
|
583
1393
|
* Initializes the core components in sequence
|
|
584
1394
|
*/
|
|
@@ -591,6 +1401,14 @@ export declare class VijiCore {
|
|
|
591
1401
|
* Sets up the interaction system for Phase 7
|
|
592
1402
|
*/
|
|
593
1403
|
private setupInteractionSystem;
|
|
1404
|
+
/**
|
|
1405
|
+
* Sets up device sensor system for internal device sensors
|
|
1406
|
+
*/
|
|
1407
|
+
private setupDeviceSensors;
|
|
1408
|
+
/**
|
|
1409
|
+
* Syncs device sensor state to worker
|
|
1410
|
+
*/
|
|
1411
|
+
private syncDeviceStateToWorker;
|
|
594
1412
|
/**
|
|
595
1413
|
* Sets up communication between components
|
|
596
1414
|
*/
|
|
@@ -639,6 +1457,39 @@ export declare class VijiCore {
|
|
|
639
1457
|
* Get current core capabilities (what's currently active)
|
|
640
1458
|
*/
|
|
641
1459
|
getCapabilities(): CoreCapabilities;
|
|
1460
|
+
/**
|
|
1461
|
+
* Inject mouse event (for headless cores or event forwarding)
|
|
1462
|
+
*/
|
|
1463
|
+
injectMouseEvent(data: MouseEventData): void;
|
|
1464
|
+
/**
|
|
1465
|
+
* Inject keyboard event
|
|
1466
|
+
*/
|
|
1467
|
+
injectKeyboardEvent(data: KeyboardEventData): void;
|
|
1468
|
+
/**
|
|
1469
|
+
* Inject touch event
|
|
1470
|
+
*/
|
|
1471
|
+
injectTouchEvent(data: TouchEventData): void;
|
|
1472
|
+
/**
|
|
1473
|
+
* Inject frames directly (compositor pipeline)
|
|
1474
|
+
*/
|
|
1475
|
+
injectFrames(bitmaps: ImageBitmap[]): void;
|
|
1476
|
+
/**
|
|
1477
|
+
* Link this core to receive events from a source core
|
|
1478
|
+
* @param syncResolution Smart default: true for headless, false for visible
|
|
1479
|
+
*/
|
|
1480
|
+
linkEventSource(sourceCore: VijiCore, syncResolution?: boolean): void;
|
|
1481
|
+
/**
|
|
1482
|
+
* Unlink from event source
|
|
1483
|
+
*/
|
|
1484
|
+
unlinkEventSource(): void;
|
|
1485
|
+
/**
|
|
1486
|
+
* Link source cores that this core will pull frames from
|
|
1487
|
+
*/
|
|
1488
|
+
linkFrameSources(...sourceCores: VijiCore[]): void;
|
|
1489
|
+
/**
|
|
1490
|
+
* Unlink all frame sources
|
|
1491
|
+
*/
|
|
1492
|
+
unlinkFrameSources(): void;
|
|
642
1493
|
/**
|
|
643
1494
|
* Get parameter groups filtered by active capabilities
|
|
644
1495
|
*/
|
|
@@ -725,17 +1576,49 @@ export declare class VijiCore {
|
|
|
725
1576
|
*/
|
|
726
1577
|
setAudioStream(audioStream: MediaStream | null): Promise<void>;
|
|
727
1578
|
/**
|
|
728
|
-
* Sets the video stream
|
|
1579
|
+
* Sets the main video stream (CV enabled)
|
|
729
1580
|
*/
|
|
730
|
-
setVideoStream(
|
|
1581
|
+
setVideoStream(stream: MediaStream | null): Promise<void>;
|
|
731
1582
|
/**
|
|
732
|
-
* Gets the
|
|
1583
|
+
* Gets the main video stream
|
|
733
1584
|
*/
|
|
734
|
-
|
|
1585
|
+
getVideoStream(): MediaStream | null;
|
|
735
1586
|
/**
|
|
736
|
-
*
|
|
1587
|
+
* Sets all additional video streams (no CV)
|
|
737
1588
|
*/
|
|
738
|
-
|
|
1589
|
+
setVideoStreams(streams: MediaStream[]): Promise<void>;
|
|
1590
|
+
/**
|
|
1591
|
+
* Gets all additional video streams
|
|
1592
|
+
*/
|
|
1593
|
+
getVideoStreams(): MediaStream[];
|
|
1594
|
+
/**
|
|
1595
|
+
* Gets video stream at specific index
|
|
1596
|
+
*/
|
|
1597
|
+
getVideoStreamAt(index: number): MediaStream | null;
|
|
1598
|
+
/**
|
|
1599
|
+
* Adds a video stream
|
|
1600
|
+
*/
|
|
1601
|
+
addVideoStream(stream: MediaStream): Promise<number>;
|
|
1602
|
+
/**
|
|
1603
|
+
* Removes video stream at index
|
|
1604
|
+
*/
|
|
1605
|
+
removeVideoStreamAt(index: number): Promise<void>;
|
|
1606
|
+
/**
|
|
1607
|
+
* Removes video stream by reference
|
|
1608
|
+
*/
|
|
1609
|
+
removeVideoStream(stream: MediaStream): Promise<boolean>;
|
|
1610
|
+
/**
|
|
1611
|
+
* Updates video stream at index
|
|
1612
|
+
*/
|
|
1613
|
+
setVideoStreamAt(index: number, stream: MediaStream): Promise<void>;
|
|
1614
|
+
/**
|
|
1615
|
+
* Reinitializes all additional coordinators
|
|
1616
|
+
*/
|
|
1617
|
+
private reinitializeAdditionalCoordinators;
|
|
1618
|
+
/**
|
|
1619
|
+
* Gets the current audio stream
|
|
1620
|
+
*/
|
|
1621
|
+
getAudioStream(): MediaStream | null;
|
|
739
1622
|
/**
|
|
740
1623
|
* Enables or disables user interactions (mouse, keyboard, touch) at runtime
|
|
741
1624
|
*/
|
|
@@ -744,17 +1627,183 @@ export declare class VijiCore {
|
|
|
744
1627
|
* Gets the current interaction enabled state
|
|
745
1628
|
*/
|
|
746
1629
|
getInteractionEnabled(): boolean;
|
|
1630
|
+
readonly audio: {
|
|
1631
|
+
/**
|
|
1632
|
+
* Set global audio sensitivity (0.5-2.0, default 1.0)
|
|
1633
|
+
*/
|
|
1634
|
+
setSensitivity: (value: number) => void;
|
|
1635
|
+
/**
|
|
1636
|
+
* Get current sensitivity
|
|
1637
|
+
*/
|
|
1638
|
+
getSensitivity: () => number;
|
|
1639
|
+
/**
|
|
1640
|
+
* Beat control namespace
|
|
1641
|
+
*/
|
|
1642
|
+
beat: {
|
|
1643
|
+
/**
|
|
1644
|
+
* Tap tempo - record tap for manual BPM
|
|
1645
|
+
*/
|
|
1646
|
+
tap: () => void;
|
|
1647
|
+
/**
|
|
1648
|
+
* Clear tap tempo history
|
|
1649
|
+
*/
|
|
1650
|
+
clearTaps: () => void;
|
|
1651
|
+
/**
|
|
1652
|
+
* Get tap count
|
|
1653
|
+
*/
|
|
1654
|
+
getTapCount: () => number;
|
|
1655
|
+
/**
|
|
1656
|
+
* Set beat sync mode
|
|
1657
|
+
*/
|
|
1658
|
+
setMode: (mode: "auto" | "manual") => void;
|
|
1659
|
+
/**
|
|
1660
|
+
* Get beat sync mode
|
|
1661
|
+
*/
|
|
1662
|
+
getMode: () => "auto" | "manual";
|
|
1663
|
+
/**
|
|
1664
|
+
* Set manual BPM
|
|
1665
|
+
*/
|
|
1666
|
+
setBPM: (bpm: number) => void;
|
|
1667
|
+
/**
|
|
1668
|
+
* Get current BPM (manual or auto-detected)
|
|
1669
|
+
*/
|
|
1670
|
+
getBPM: () => number;
|
|
1671
|
+
/**
|
|
1672
|
+
* Nudge beat phase
|
|
1673
|
+
*/
|
|
1674
|
+
nudge: (amount: number) => void;
|
|
1675
|
+
/**
|
|
1676
|
+
* Reset beat phase to next beat
|
|
1677
|
+
*/
|
|
1678
|
+
resetPhase: () => void;
|
|
1679
|
+
};
|
|
1680
|
+
/**
|
|
1681
|
+
* Advanced audio controls
|
|
1682
|
+
*/
|
|
1683
|
+
advanced: {
|
|
1684
|
+
/**
|
|
1685
|
+
* Set FFT size (2048, 4096, or 8192)
|
|
1686
|
+
*/
|
|
1687
|
+
setFFTSize: (size: 2048 | 4096 | 8192) => void;
|
|
1688
|
+
/**
|
|
1689
|
+
* Set smoothing time constant (0-1)
|
|
1690
|
+
*/
|
|
1691
|
+
setSmoothing: (value: number) => void;
|
|
1692
|
+
/**
|
|
1693
|
+
* Enable/disable auto-gain
|
|
1694
|
+
*/
|
|
1695
|
+
setAutoGain: (enabled: boolean) => void;
|
|
1696
|
+
/**
|
|
1697
|
+
* Enable/disable beat detection
|
|
1698
|
+
*/
|
|
1699
|
+
setBeatDetection: (enabled: boolean) => void;
|
|
1700
|
+
/**
|
|
1701
|
+
* Enable/disable onset detection
|
|
1702
|
+
*/
|
|
1703
|
+
setOnsetDetection: (enabled: boolean) => void;
|
|
1704
|
+
};
|
|
1705
|
+
/**
|
|
1706
|
+
* Get audio analysis state (metadata)
|
|
1707
|
+
*/
|
|
1708
|
+
getState: () => AudioAnalysisState;
|
|
1709
|
+
/**
|
|
1710
|
+
* Get current per-frame audio analysis data
|
|
1711
|
+
* Returns volume, bands, beat energies, triggers, and spectral features
|
|
1712
|
+
* Useful for UI displays and visualizations
|
|
1713
|
+
*/
|
|
1714
|
+
getCurrentAudioData: () => {
|
|
1715
|
+
isConnected: boolean;
|
|
1716
|
+
volume: {
|
|
1717
|
+
current: number;
|
|
1718
|
+
peak: number;
|
|
1719
|
+
smoothed: number;
|
|
1720
|
+
};
|
|
1721
|
+
bands: {
|
|
1722
|
+
low: number;
|
|
1723
|
+
lowMid: number;
|
|
1724
|
+
mid: number;
|
|
1725
|
+
highMid: number;
|
|
1726
|
+
high: number;
|
|
1727
|
+
lowSmoothed: number;
|
|
1728
|
+
lowMidSmoothed: number;
|
|
1729
|
+
midSmoothed: number;
|
|
1730
|
+
highMidSmoothed: number;
|
|
1731
|
+
highSmoothed: number;
|
|
1732
|
+
};
|
|
1733
|
+
beat: {
|
|
1734
|
+
kick: number;
|
|
1735
|
+
snare: number;
|
|
1736
|
+
hat: number;
|
|
1737
|
+
any: number;
|
|
1738
|
+
kickSmoothed: number;
|
|
1739
|
+
snareSmoothed: number;
|
|
1740
|
+
anySmoothed: number;
|
|
1741
|
+
events: BeatEvent[];
|
|
1742
|
+
bpm: number;
|
|
1743
|
+
phase: number;
|
|
1744
|
+
bar: number;
|
|
1745
|
+
confidence: number;
|
|
1746
|
+
isLocked: boolean;
|
|
1747
|
+
};
|
|
1748
|
+
spectral: {
|
|
1749
|
+
brightness: number;
|
|
1750
|
+
flatness: number;
|
|
1751
|
+
flux: number;
|
|
1752
|
+
};
|
|
1753
|
+
} | {
|
|
1754
|
+
isConnected: false;
|
|
1755
|
+
volume: {
|
|
1756
|
+
current: number;
|
|
1757
|
+
peak: number;
|
|
1758
|
+
smoothed: number;
|
|
1759
|
+
};
|
|
1760
|
+
bands: {
|
|
1761
|
+
low: number;
|
|
1762
|
+
lowMid: number;
|
|
1763
|
+
mid: number;
|
|
1764
|
+
highMid: number;
|
|
1765
|
+
high: number;
|
|
1766
|
+
lowSmoothed: number;
|
|
1767
|
+
lowMidSmoothed: number;
|
|
1768
|
+
midSmoothed: number;
|
|
1769
|
+
highMidSmoothed: number;
|
|
1770
|
+
highSmoothed: number;
|
|
1771
|
+
};
|
|
1772
|
+
beat: {
|
|
1773
|
+
kick: number;
|
|
1774
|
+
snare: number;
|
|
1775
|
+
hat: number;
|
|
1776
|
+
any: number;
|
|
1777
|
+
kickSmoothed: number;
|
|
1778
|
+
snareSmoothed: number;
|
|
1779
|
+
anySmoothed: number;
|
|
1780
|
+
triggers: {
|
|
1781
|
+
any: boolean;
|
|
1782
|
+
kick: boolean;
|
|
1783
|
+
snare: boolean;
|
|
1784
|
+
hat: boolean;
|
|
1785
|
+
};
|
|
1786
|
+
bpm: number;
|
|
1787
|
+
phase: number;
|
|
1788
|
+
bar: number;
|
|
1789
|
+
confidence: number;
|
|
1790
|
+
isLocked: false;
|
|
1791
|
+
};
|
|
1792
|
+
spectral: {
|
|
1793
|
+
brightness: number;
|
|
1794
|
+
flatness: number;
|
|
1795
|
+
flux: number;
|
|
1796
|
+
};
|
|
1797
|
+
};
|
|
1798
|
+
};
|
|
747
1799
|
/**
|
|
748
|
-
* Updates
|
|
749
|
-
|
|
750
|
-
setAudioAnalysisConfig(config: {
|
|
751
|
-
fftSize?: number;
|
|
752
|
-
smoothing?: number;
|
|
753
|
-
}): Promise<void>;
|
|
754
|
-
/**
|
|
755
|
-
* Updates the canvas resolution by scale
|
|
1800
|
+
* Updates the canvas resolution (scale or explicit dimensions)
|
|
1801
|
+
* Works in both headless and normal modes
|
|
756
1802
|
*/
|
|
757
|
-
setResolution(
|
|
1803
|
+
setResolution(resolution: number | {
|
|
1804
|
+
width: number;
|
|
1805
|
+
height: number;
|
|
1806
|
+
}): void;
|
|
758
1807
|
/**
|
|
759
1808
|
* Detects the screen refresh rate
|
|
760
1809
|
*/
|
|
@@ -767,6 +1816,42 @@ export declare class VijiCore {
|
|
|
767
1816
|
* Gets current performance statistics
|
|
768
1817
|
*/
|
|
769
1818
|
getStats(): PerformanceStats;
|
|
1819
|
+
/**
|
|
1820
|
+
* Register a new external device
|
|
1821
|
+
* @param device Device metadata (id and name)
|
|
1822
|
+
* @returns Device index in the devices array
|
|
1823
|
+
*/
|
|
1824
|
+
addExternalDevice(device: {
|
|
1825
|
+
id: string;
|
|
1826
|
+
name: string;
|
|
1827
|
+
}): number;
|
|
1828
|
+
/**
|
|
1829
|
+
* Update sensor data for an external device
|
|
1830
|
+
* @param update Device sensor update (must include id)
|
|
1831
|
+
* @returns true if updated, false if device not found (not registered or removed)
|
|
1832
|
+
*/
|
|
1833
|
+
updateExternalDevice(update: {
|
|
1834
|
+
id: string;
|
|
1835
|
+
name?: string;
|
|
1836
|
+
motion?: DeviceMotionData | null;
|
|
1837
|
+
orientation?: DeviceOrientationData | null;
|
|
1838
|
+
geolocation?: GeolocationData | null;
|
|
1839
|
+
}): boolean;
|
|
1840
|
+
/**
|
|
1841
|
+
* Remove/ban an external device
|
|
1842
|
+
* Further updates for this device will be ignored
|
|
1843
|
+
* @param deviceId Device identifier to remove
|
|
1844
|
+
*/
|
|
1845
|
+
removeExternalDevice(deviceId: string): void;
|
|
1846
|
+
/**
|
|
1847
|
+
* Get list of connected external devices (for host UI)
|
|
1848
|
+
* @returns Array of device metadata with id, name, and array index
|
|
1849
|
+
*/
|
|
1850
|
+
getConnectedDevices(): Array<{
|
|
1851
|
+
id: string;
|
|
1852
|
+
name: string;
|
|
1853
|
+
index: number;
|
|
1854
|
+
}>;
|
|
770
1855
|
/**
|
|
771
1856
|
* Checks if the core is ready for use
|
|
772
1857
|
*/
|
|
@@ -794,26 +1879,33 @@ export declare class VijiCore {
|
|
|
794
1879
|
}
|
|
795
1880
|
|
|
796
1881
|
export declare interface VijiCoreConfig {
|
|
797
|
-
/** Container element where the scene will be rendered */
|
|
798
|
-
hostContainer
|
|
1882
|
+
/** Container element where the scene will be rendered (optional for headless mode) */
|
|
1883
|
+
hostContainer?: HTMLElement;
|
|
799
1884
|
/** Artist scene code to execute */
|
|
800
1885
|
sceneCode: string;
|
|
801
1886
|
/** Frame rate mode - 'full' for every animation frame, 'half' for every second frame */
|
|
802
1887
|
frameRateMode?: FrameRateMode;
|
|
803
|
-
/**
|
|
804
|
-
|
|
1888
|
+
/** Resolution: scale (number) or explicit dimensions (object). Required for headless, must be object form */
|
|
1889
|
+
resolution?: number | {
|
|
1890
|
+
width: number;
|
|
1891
|
+
height: number;
|
|
1892
|
+
};
|
|
805
1893
|
/** Audio input stream */
|
|
806
1894
|
audioStream?: MediaStream;
|
|
807
|
-
/** Video input stream */
|
|
1895
|
+
/** Video input stream (main stream, CV enabled) */
|
|
808
1896
|
videoStream?: MediaStream;
|
|
1897
|
+
/** Additional video input streams (no CV processing) */
|
|
1898
|
+
videoStreams?: MediaStream[];
|
|
809
1899
|
/** Audio analysis configuration */
|
|
810
1900
|
analysisConfig?: AnalysisConfiguration;
|
|
811
1901
|
/** Initial parameter values */
|
|
812
1902
|
parameters?: ParameterGroup[];
|
|
813
1903
|
/** Disable input processing (for preview instances) */
|
|
814
1904
|
noInputs?: boolean;
|
|
815
|
-
/** Enable user interaction events */
|
|
1905
|
+
/** Enable user interaction events (DOM event capture, disabled in headless by default) */
|
|
816
1906
|
allowUserInteraction?: boolean;
|
|
1907
|
+
/** Enable device sensor APIs (motion, orientation, geolocation) */
|
|
1908
|
+
allowDeviceInteraction?: boolean;
|
|
817
1909
|
}
|
|
818
1910
|
|
|
819
1911
|
export declare class VijiCoreError extends Error {
|