@codexo/exojs 0.6.11 → 0.7.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/CHANGELOG.md +1356 -0
  2. package/dist/esm/audio/AbstractMedia.d.ts +18 -0
  3. package/dist/esm/audio/AbstractMedia.js +66 -0
  4. package/dist/esm/audio/AbstractMedia.js.map +1 -1
  5. package/dist/esm/audio/AudioAnalyser.d.ts +62 -23
  6. package/dist/esm/audio/AudioAnalyser.js +261 -57
  7. package/dist/esm/audio/AudioAnalyser.js.map +1 -1
  8. package/dist/esm/audio/AudioBus.d.ts +45 -0
  9. package/dist/esm/audio/AudioBus.js +219 -0
  10. package/dist/esm/audio/AudioBus.js.map +1 -0
  11. package/dist/esm/audio/AudioFilter.d.ts +9 -0
  12. package/dist/esm/audio/AudioFilter.js +7 -0
  13. package/dist/esm/audio/AudioFilter.js.map +1 -0
  14. package/dist/esm/audio/AudioListener.d.ts +20 -0
  15. package/dist/esm/audio/AudioListener.js +86 -0
  16. package/dist/esm/audio/AudioListener.js.map +1 -0
  17. package/dist/esm/audio/AudioManager.d.ts +31 -0
  18. package/dist/esm/audio/AudioManager.js +102 -0
  19. package/dist/esm/audio/AudioManager.js.map +1 -0
  20. package/dist/esm/audio/BeatDetector.d.ts +121 -0
  21. package/dist/esm/audio/BeatDetector.js +936 -0
  22. package/dist/esm/audio/BeatDetector.js.map +1 -0
  23. package/dist/esm/audio/Envelope.d.ts +44 -0
  24. package/dist/esm/audio/Envelope.js +60 -0
  25. package/dist/esm/audio/Envelope.js.map +1 -0
  26. package/dist/esm/audio/Music.d.ts +8 -0
  27. package/dist/esm/audio/Music.js +33 -4
  28. package/dist/esm/audio/Music.js.map +1 -1
  29. package/dist/esm/audio/OscillatorSound.d.ts +98 -0
  30. package/dist/esm/audio/OscillatorSound.js +342 -0
  31. package/dist/esm/audio/OscillatorSound.js.map +1 -0
  32. package/dist/esm/audio/Sound.d.ts +94 -9
  33. package/dist/esm/audio/Sound.js +283 -117
  34. package/dist/esm/audio/Sound.js.map +1 -1
  35. package/dist/esm/audio/crossFade.d.ts +19 -0
  36. package/dist/esm/audio/crossFade.js +26 -0
  37. package/dist/esm/audio/crossFade.js.map +1 -0
  38. package/dist/esm/audio/dsp/fft.d.ts +22 -0
  39. package/dist/esm/audio/dsp/mel.d.ts +43 -0
  40. package/dist/esm/audio/dsp/tempogram.d.ts +51 -0
  41. package/dist/esm/audio/filters/ChorusFilter.d.ts +47 -0
  42. package/dist/esm/audio/filters/ChorusFilter.js +139 -0
  43. package/dist/esm/audio/filters/ChorusFilter.js.map +1 -0
  44. package/dist/esm/audio/filters/CompressorFilter.d.ts +31 -0
  45. package/dist/esm/audio/filters/CompressorFilter.js +97 -0
  46. package/dist/esm/audio/filters/CompressorFilter.js.map +1 -0
  47. package/dist/esm/audio/filters/DelayFilter.d.ts +23 -0
  48. package/dist/esm/audio/filters/DelayFilter.js +100 -0
  49. package/dist/esm/audio/filters/DelayFilter.js.map +1 -0
  50. package/dist/esm/audio/filters/DuckingFilter.d.ts +31 -0
  51. package/dist/esm/audio/filters/DuckingFilter.js +152 -0
  52. package/dist/esm/audio/filters/DuckingFilter.js.map +1 -0
  53. package/dist/esm/audio/filters/EqualizerFilter.d.ts +29 -0
  54. package/dist/esm/audio/filters/EqualizerFilter.js +94 -0
  55. package/dist/esm/audio/filters/EqualizerFilter.js.map +1 -0
  56. package/dist/esm/audio/filters/GranularFilter.d.ts +56 -0
  57. package/dist/esm/audio/filters/GranularFilter.js +170 -0
  58. package/dist/esm/audio/filters/GranularFilter.js.map +1 -0
  59. package/dist/esm/audio/filters/HighpassFilter.d.ts +19 -0
  60. package/dist/esm/audio/filters/HighpassFilter.js +62 -0
  61. package/dist/esm/audio/filters/HighpassFilter.js.map +1 -0
  62. package/dist/esm/audio/filters/LowpassFilter.d.ts +19 -0
  63. package/dist/esm/audio/filters/LowpassFilter.js +62 -0
  64. package/dist/esm/audio/filters/LowpassFilter.js.map +1 -0
  65. package/dist/esm/audio/filters/PitchShiftFilter.d.ts +42 -0
  66. package/dist/esm/audio/filters/PitchShiftFilter.js +130 -0
  67. package/dist/esm/audio/filters/PitchShiftFilter.js.map +1 -0
  68. package/dist/esm/audio/filters/ReverbFilter.d.ts +24 -0
  69. package/dist/esm/audio/filters/ReverbFilter.js +107 -0
  70. package/dist/esm/audio/filters/ReverbFilter.js.map +1 -0
  71. package/dist/esm/audio/filters/VocoderFilter.d.ts +38 -0
  72. package/dist/esm/audio/filters/VocoderFilter.js +163 -0
  73. package/dist/esm/audio/filters/VocoderFilter.js.map +1 -0
  74. package/dist/esm/audio/filters/WorkletFilter.d.ts +46 -0
  75. package/dist/esm/audio/filters/WorkletFilter.js +101 -0
  76. package/dist/esm/audio/filters/WorkletFilter.js.map +1 -0
  77. package/dist/esm/audio/filters/index.d.ts +12 -0
  78. package/dist/esm/audio/index.d.ts +15 -1
  79. package/dist/esm/audio/worklet/registerWorklet.d.ts +10 -0
  80. package/dist/esm/audio/worklet/registerWorklet.js +44 -0
  81. package/dist/esm/audio/worklet/registerWorklet.js.map +1 -0
  82. package/dist/esm/core/Application.d.ts +19 -0
  83. package/dist/esm/core/Application.js +76 -2
  84. package/dist/esm/core/Application.js.map +1 -1
  85. package/dist/esm/core/SceneNode.d.ts +9 -1
  86. package/dist/esm/core/SceneNode.js +44 -6
  87. package/dist/esm/core/SceneNode.js.map +1 -1
  88. package/dist/esm/core/Time.js +1 -1
  89. package/dist/esm/core/index.d.ts +0 -1
  90. package/dist/esm/debug/BoundingBoxesLayer.d.ts +18 -0
  91. package/dist/esm/debug/BoundingBoxesLayer.js +128 -0
  92. package/dist/esm/debug/BoundingBoxesLayer.js.map +1 -0
  93. package/dist/esm/debug/DebugLayer.d.ts +29 -0
  94. package/dist/esm/debug/DebugLayer.js +26 -0
  95. package/dist/esm/debug/DebugLayer.js.map +1 -0
  96. package/dist/esm/debug/DebugOverlay.d.ts +48 -0
  97. package/dist/esm/debug/DebugOverlay.js +117 -0
  98. package/dist/esm/debug/DebugOverlay.js.map +1 -0
  99. package/dist/esm/debug/HitTestLayer.d.ts +23 -0
  100. package/dist/esm/debug/HitTestLayer.js +109 -0
  101. package/dist/esm/debug/HitTestLayer.js.map +1 -0
  102. package/dist/esm/debug/PerformanceLayer.d.ts +21 -0
  103. package/dist/esm/debug/PerformanceLayer.js +175 -0
  104. package/dist/esm/debug/PerformanceLayer.js.map +1 -0
  105. package/dist/esm/debug/PointerStackLayer.d.ts +23 -0
  106. package/dist/esm/debug/PointerStackLayer.js +152 -0
  107. package/dist/esm/debug/PointerStackLayer.js.map +1 -0
  108. package/dist/esm/debug/index.d.ts +6 -0
  109. package/dist/esm/debug/index.js +7 -0
  110. package/dist/esm/debug/index.js.map +1 -0
  111. package/dist/esm/index.js +29 -2
  112. package/dist/esm/index.js.map +1 -1
  113. package/dist/esm/input/InputManager.d.ts +10 -0
  114. package/dist/esm/input/InputManager.js +35 -5
  115. package/dist/esm/input/InputManager.js.map +1 -1
  116. package/dist/esm/input/InteractionEvent.d.ts +18 -0
  117. package/dist/esm/input/InteractionEvent.js +29 -0
  118. package/dist/esm/input/InteractionEvent.js.map +1 -0
  119. package/dist/esm/input/InteractionManager.d.ts +134 -0
  120. package/dist/esm/input/InteractionManager.js +546 -0
  121. package/dist/esm/input/InteractionManager.js.map +1 -0
  122. package/dist/esm/input/index.d.ts +2 -0
  123. package/dist/esm/input/interaction-hooks.d.ts +34 -0
  124. package/dist/esm/input/interaction-hooks.js +35 -0
  125. package/dist/esm/input/interaction-hooks.js.map +1 -0
  126. package/dist/esm/math/Circle.d.ts +12 -2
  127. package/dist/esm/math/Circle.js +82 -14
  128. package/dist/esm/math/Circle.js.map +1 -1
  129. package/dist/esm/math/Interval.js +1 -1
  130. package/dist/esm/math/ObservableVector.d.ts +2 -2
  131. package/dist/esm/math/ObservableVector.js +4 -2
  132. package/dist/esm/math/ObservableVector.js.map +1 -1
  133. package/dist/esm/math/Polygon.d.ts +15 -1
  134. package/dist/esm/math/Polygon.js +58 -6
  135. package/dist/esm/math/Polygon.js.map +1 -1
  136. package/dist/esm/math/Quadtree.d.ts +47 -0
  137. package/dist/esm/math/Quadtree.js +168 -0
  138. package/dist/esm/math/Quadtree.js.map +1 -0
  139. package/dist/esm/math/Random.js +1 -1
  140. package/dist/esm/math/Size.js +1 -1
  141. package/dist/esm/math/Vector.js +1 -1
  142. package/dist/esm/math/collision-detection.js +4 -1
  143. package/dist/esm/math/collision-detection.js.map +1 -1
  144. package/dist/esm/math/index.d.ts +2 -0
  145. package/dist/esm/math/swept-collision.d.ts +90 -0
  146. package/dist/esm/math/swept-collision.js +255 -0
  147. package/dist/esm/math/swept-collision.js.map +1 -0
  148. package/dist/esm/particles/ParticleSystem.js +1 -0
  149. package/dist/esm/particles/ParticleSystem.js.map +1 -1
  150. package/dist/esm/particles/affectors/TorqueAffector.js +1 -1
  151. package/dist/esm/rendering/Container.d.ts +1 -0
  152. package/dist/esm/rendering/Container.js +19 -0
  153. package/dist/esm/rendering/Container.js.map +1 -1
  154. package/dist/esm/rendering/RenderNode.d.ts +27 -0
  155. package/dist/esm/rendering/RenderNode.js +44 -0
  156. package/dist/esm/rendering/RenderNode.js.map +1 -1
  157. package/dist/esm/rendering/View.d.ts +6 -4
  158. package/dist/esm/rendering/View.js +12 -2
  159. package/dist/esm/rendering/View.js.map +1 -1
  160. package/dist/esm/rendering/filters/WebGl2ShaderFilter.d.ts +109 -0
  161. package/dist/esm/rendering/filters/WebGl2ShaderFilter.js +268 -0
  162. package/dist/esm/rendering/filters/WebGl2ShaderFilter.js.map +1 -0
  163. package/dist/esm/rendering/filters/WebGpuShaderFilter.d.ts +111 -0
  164. package/dist/esm/rendering/filters/WebGpuShaderFilter.js +397 -0
  165. package/dist/esm/rendering/filters/WebGpuShaderFilter.js.map +1 -0
  166. package/dist/esm/rendering/index.d.ts +3 -0
  167. package/dist/esm/rendering/mesh/Mesh.js +1 -0
  168. package/dist/esm/rendering/mesh/Mesh.js.map +1 -1
  169. package/dist/esm/rendering/shader/upgradeFragmentShaderToGl300.d.ts +34 -0
  170. package/dist/esm/rendering/shader/upgradeFragmentShaderToGl300.js +60 -0
  171. package/dist/esm/rendering/shader/upgradeFragmentShaderToGl300.js.map +1 -0
  172. package/dist/esm/rendering/sprite/Sprite.d.ts +6 -1
  173. package/dist/esm/rendering/sprite/Sprite.js +41 -19
  174. package/dist/esm/rendering/sprite/Sprite.js.map +1 -1
  175. package/dist/esm/rendering/video/Video.d.ts +4 -0
  176. package/dist/esm/rendering/video/Video.js +32 -4
  177. package/dist/esm/rendering/video/Video.js.map +1 -1
  178. package/dist/esm/rendering/webgl2/WebGl2Backend.d.ts +4 -4
  179. package/dist/esm/rendering/webgl2/WebGl2Backend.js +7 -16
  180. package/dist/esm/rendering/webgl2/WebGl2Backend.js.map +1 -1
  181. package/dist/esm/rendering/webgpu/WebGpuBackend.d.ts +10 -8
  182. package/dist/esm/rendering/webgpu/WebGpuBackend.js +30 -40
  183. package/dist/esm/rendering/webgpu/WebGpuBackend.js.map +1 -1
  184. package/dist/exo.esm.js +8021 -2459
  185. package/dist/exo.esm.js.map +1 -1
  186. package/package.json +14 -2
  187. package/dist/esm/core/Quadtree.d.ts +0 -20
  188. package/dist/esm/core/Quadtree.js +0 -86
  189. package/dist/esm/core/Quadtree.js.map +0 -1
@@ -1,6 +1,7 @@
1
1
  import type { Media } from '@/audio/Media';
2
2
  import { Signal } from '@/core/Signal';
3
3
  import type { PlaybackOptions } from '@/core/types';
4
+ import type { AudioBus } from '@/audio/AudioBus';
4
5
  export interface AbstractMediaInitialState extends Omit<PlaybackOptions, 'time'> {
5
6
  duration: number;
6
7
  }
@@ -12,9 +13,16 @@ export declare abstract class AbstractMedia implements Media {
12
13
  protected _playbackRate: number;
13
14
  protected _loop: boolean;
14
15
  protected _muted: boolean;
16
+ protected _bus: AudioBus | null;
15
17
  abstract get paused(): boolean;
16
18
  abstract set paused(paused: boolean);
17
19
  abstract get analyserTarget(): AudioNode | null;
20
+ get bus(): AudioBus;
21
+ set bus(bus: AudioBus);
22
+ /** Returns the default bus for this media type. Subclasses override. */
23
+ protected abstract _defaultBus(): AudioBus;
24
+ protected abstract _disconnectFromBus(): void;
25
+ protected abstract _connectToBus(): void;
18
26
  get duration(): number;
19
27
  get volume(): number;
20
28
  set volume(volume: number);
@@ -38,6 +46,16 @@ export declare abstract class AbstractMedia implements Media {
38
46
  abstract getTime(): number;
39
47
  abstract setTime(time: number): this;
40
48
  abstract setMuted(muted: boolean): this;
49
+ protected abstract _getAudioSetup(): {
50
+ audioContext: AudioContext;
51
+ gainNode: GainNode;
52
+ } | null;
53
+ private _scheduledStopId;
54
+ private _clearScheduledStop;
55
+ fadeIn(durationMs: number): this;
56
+ fadeOut(durationMs: number, options?: {
57
+ stopAfter?: boolean;
58
+ }): this;
41
59
  stop(options?: Partial<PlaybackOptions>): this;
42
60
  toggle(options?: Partial<PlaybackOptions>): this;
43
61
  applyOptions(options?: Partial<PlaybackOptions>): this;
@@ -8,6 +8,17 @@ class AbstractMedia {
8
8
  _playbackRate;
9
9
  _loop;
10
10
  _muted;
11
+ _bus = null;
12
+ get bus() {
13
+ return this._bus ?? this._defaultBus();
14
+ }
15
+ set bus(bus) {
16
+ if (this._bus === bus)
17
+ return;
18
+ this._disconnectFromBus();
19
+ this._bus = bus;
20
+ this._connectToBus();
21
+ }
11
22
  get duration() {
12
23
  return this._duration;
13
24
  }
@@ -65,6 +76,60 @@ class AbstractMedia {
65
76
  this._loop = loop;
66
77
  this._muted = muted;
67
78
  }
79
+ _scheduledStopId = null;
80
+ _clearScheduledStop() {
81
+ if (this._scheduledStopId !== null) {
82
+ clearTimeout(this._scheduledStopId);
83
+ this._scheduledStopId = null;
84
+ }
85
+ }
86
+ fadeIn(durationMs) {
87
+ this._clearScheduledStop();
88
+ if (durationMs <= 0) {
89
+ if (this.paused)
90
+ this.play();
91
+ return this;
92
+ }
93
+ const setup = this._getAudioSetup();
94
+ if (!setup)
95
+ return this;
96
+ if (this.paused)
97
+ this.play();
98
+ const ctx = setup.audioContext;
99
+ const target = this.muted ? 0 : this._volume;
100
+ const node = setup.gainNode;
101
+ node.gain.cancelScheduledValues(ctx.currentTime);
102
+ node.gain.setValueAtTime(0, ctx.currentTime);
103
+ node.gain.linearRampToValueAtTime(target, ctx.currentTime + durationMs / 1000);
104
+ return this;
105
+ }
106
+ fadeOut(durationMs, options = {}) {
107
+ const stopAfter = options.stopAfter ?? true;
108
+ if (durationMs <= 0) {
109
+ if (stopAfter)
110
+ this.pause();
111
+ return this;
112
+ }
113
+ const setup = this._getAudioSetup();
114
+ if (!setup) {
115
+ if (stopAfter)
116
+ this.pause();
117
+ return this;
118
+ }
119
+ const ctx = setup.audioContext;
120
+ const node = setup.gainNode;
121
+ node.gain.cancelScheduledValues(ctx.currentTime);
122
+ node.gain.setValueAtTime(node.gain.value, ctx.currentTime);
123
+ node.gain.linearRampToValueAtTime(0, ctx.currentTime + durationMs / 1000);
124
+ if (stopAfter) {
125
+ this._clearScheduledStop();
126
+ this._scheduledStopId = setTimeout(() => {
127
+ this._scheduledStopId = null;
128
+ this.pause();
129
+ }, durationMs);
130
+ }
131
+ return this;
132
+ }
68
133
  stop(options) {
69
134
  this.pause(options);
70
135
  this.currentTime = 0;
@@ -93,6 +158,7 @@ class AbstractMedia {
93
158
  return this;
94
159
  }
95
160
  destroy() {
161
+ this._clearScheduledStop();
96
162
  this.stop();
97
163
  this.onStart.destroy();
98
164
  this.onStop.destroy();
@@ -1 +1 @@
1
- {"version":3,"file":"AbstractMedia.js","sources":["../../../../src/audio/AbstractMedia.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AbstractMedia.js","sources":["../../../../src/audio/AbstractMedia.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -1,29 +1,68 @@
1
- import type { Media } from '@/audio/Media';
1
+ import type { AudioBus } from '@/audio/AudioBus';
2
+ import type { Sound } from '@/audio/Sound';
3
+ import type { Music } from '@/audio/Music';
4
+ export type AudioAnalyserSource = AudioBus | Sound | Music | MediaStream | AudioNode | null;
2
5
  export interface AudioAnalyserOptions {
3
- fftSize: number;
4
- minDecibels: number;
5
- maxDecibels: number;
6
- smoothingTimeConstant: number;
6
+ fftSize?: number;
7
+ smoothingTimeConstant?: number;
8
+ minDecibels?: number;
9
+ maxDecibels?: number;
7
10
  }
11
+ /**
12
+ * Lightweight visualisation analyser backed by a Web Audio AnalyserNode.
13
+ *
14
+ * Accepts any of: AudioBus, Sound, Music, MediaStream, AudioNode, or null.
15
+ * The tap is a parallel branch — it does not affect the source's main routing.
16
+ *
17
+ * Migration from 0.7.1: the old constructor was `new AudioAnalyser(media, options)`.
18
+ * The new API is `new AudioAnalyser(options?); analyser.source = media`.
19
+ */
8
20
  export declare class AudioAnalyser {
9
- private readonly _media;
10
- private readonly _fftSize;
11
- private readonly _minDecibels;
12
- private readonly _maxDecibels;
13
- private readonly _smoothingTimeConstant;
14
- private readonly _frequencyBinCount;
15
- private readonly _timeDomainData;
16
- private readonly _frequencyData;
17
- private readonly _preciseTimeDomainData;
18
- private readonly _preciseFrequencyData;
19
21
  private _analyser;
20
- private _analyserTarget;
21
- constructor(media: Media, options?: Partial<AudioAnalyserOptions>);
22
- connect(): this;
23
- get timeDomainData(): Uint8Array;
24
- get frequencyData(): Uint8Array;
25
- get preciseTimeDomainData(): Float32Array;
26
- get preciseFrequencyData(): Float32Array;
22
+ private readonly _options;
23
+ private _source;
24
+ private _tapSource;
25
+ private _streamSource;
26
+ private _byteSpectrum;
27
+ private _floatSpectrum;
28
+ private _byteWaveform;
29
+ private _floatWaveform;
30
+ constructor(options?: AudioAnalyserOptions);
31
+ get source(): AudioAnalyserSource;
32
+ set source(value: AudioAnalyserSource);
33
+ get fftSize(): number;
34
+ get frequencyBinCount(): number;
35
+ get smoothingTimeConstant(): number;
36
+ set smoothingTimeConstant(v: number);
37
+ get minDecibels(): number;
38
+ set minDecibels(v: number);
39
+ get maxDecibels(): number;
40
+ set maxDecibels(v: number);
41
+ /** Fill and return the byte frequency spectrum (0..255 per bin). */
42
+ getSpectrum(into?: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>;
43
+ /** Fill and return the float frequency spectrum (dB per bin). */
44
+ getSpectrumFloat(into?: Float32Array<ArrayBuffer>): Float32Array<ArrayBuffer>;
45
+ /** Fill and return the byte time-domain waveform (0..255 per sample). */
46
+ getWaveform(into?: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>;
47
+ /** Fill and return the float time-domain waveform (-1..1 per sample). */
48
+ getWaveformFloat(into?: Float32Array<ArrayBuffer>): Float32Array<ArrayBuffer>;
49
+ /**
50
+ * Return the mean energy of frequency bins in the given Hz range, normalised 0..1.
51
+ * Uses the byte spectrum (0..255), normalised by dividing by 255.
52
+ */
53
+ getBandEnergy(fromHz: number, toHz: number): number;
54
+ /** Return low (0-250 Hz), mid (250-2 kHz), and high (2 k-20 kHz) band energies (0..1 each). */
55
+ getLowMidHigh(): {
56
+ low: number;
57
+ mid: number;
58
+ high: number;
59
+ };
60
+ /** Return overall RMS energy across all bins, normalised 0..1. */
61
+ getRms(): number;
27
62
  destroy(): void;
28
- private setupWithAudioContext;
63
+ private _setupAnalyser;
64
+ private _connectSource;
65
+ private _resolveToAudioNode;
66
+ private _deferConnectionViaBus;
67
+ private _disconnectTap;
29
68
  }
@@ -1,88 +1,292 @@
1
1
  import { isAudioContextReady, getAudioContext, onAudioContextReady } from './audio-context.js';
2
2
 
3
+ /**
4
+ * Lightweight visualisation analyser backed by a Web Audio AnalyserNode.
5
+ *
6
+ * Accepts any of: AudioBus, Sound, Music, MediaStream, AudioNode, or null.
7
+ * The tap is a parallel branch — it does not affect the source's main routing.
8
+ *
9
+ * Migration from 0.7.1: the old constructor was `new AudioAnalyser(media, options)`.
10
+ * The new API is `new AudioAnalyser(options?); analyser.source = media`.
11
+ */
3
12
  class AudioAnalyser {
4
- _media;
5
- _fftSize;
6
- _minDecibels;
7
- _maxDecibels;
8
- _smoothingTimeConstant;
9
- _frequencyBinCount;
10
- _timeDomainData;
11
- _frequencyData;
12
- _preciseTimeDomainData;
13
- _preciseFrequencyData;
14
13
  _analyser = null;
15
- _analyserTarget = null;
16
- constructor(media, options = {}) {
17
- const { fftSize, minDecibels, maxDecibels, smoothingTimeConstant } = options;
18
- this._media = media;
19
- this._fftSize = fftSize ?? 2048;
20
- this._minDecibels = minDecibels ?? -100;
21
- this._maxDecibels = maxDecibels ?? -30;
22
- this._smoothingTimeConstant = smoothingTimeConstant ?? 0.8;
23
- this._frequencyBinCount = this._fftSize / 2;
24
- this._timeDomainData = new Uint8Array(this._frequencyBinCount);
25
- this._frequencyData = new Uint8Array(this._frequencyBinCount);
26
- this._preciseTimeDomainData = new Float32Array(this._frequencyBinCount);
27
- this._preciseFrequencyData = new Float32Array(this._frequencyBinCount);
14
+ _options;
15
+ _source = null;
16
+ _tapSource = null;
17
+ _streamSource = null;
18
+ // Pre-allocated buffers
19
+ _byteSpectrum;
20
+ _floatSpectrum;
21
+ _byteWaveform;
22
+ _floatWaveform;
23
+ constructor(options) {
24
+ this._options = {
25
+ fftSize: options?.fftSize ?? 2048,
26
+ smoothingTimeConstant: options?.smoothingTimeConstant ?? 0.8,
27
+ minDecibels: options?.minDecibels ?? -100,
28
+ maxDecibels: options?.maxDecibels ?? -30,
29
+ };
30
+ const binCount = this._options.fftSize >> 1;
31
+ this._byteSpectrum = new Uint8Array(binCount);
32
+ this._floatSpectrum = new Float32Array(binCount);
33
+ this._byteWaveform = new Uint8Array(binCount);
34
+ this._floatWaveform = new Float32Array(binCount);
28
35
  if (isAudioContextReady()) {
29
- this.setupWithAudioContext(getAudioContext());
36
+ this._setupAnalyser(getAudioContext());
30
37
  }
31
38
  else {
32
- onAudioContextReady.once(this.setupWithAudioContext, this);
39
+ onAudioContextReady.once(this._setupAnalyser, this);
33
40
  }
34
41
  }
35
- connect() {
36
- if (!this._analyser || this._analyserTarget !== null) {
37
- return this;
42
+ // -----------------------------------------------------------------------
43
+ // Source setter
44
+ // -----------------------------------------------------------------------
45
+ get source() {
46
+ return this._source;
47
+ }
48
+ set source(value) {
49
+ if (value === this._source)
50
+ return;
51
+ // 1. Disconnect current tap
52
+ this._disconnectTap();
53
+ this._source = value;
54
+ if (value === null)
55
+ return;
56
+ // 2. Resolve and connect new tap
57
+ if (isAudioContextReady()) {
58
+ this._connectSource(value, getAudioContext());
38
59
  }
39
- const analyserTarget = this._media.analyserTarget;
40
- if (!analyserTarget) {
41
- throw new Error('No AudioNode on property analyserTarget.');
60
+ else {
61
+ onAudioContextReady.once((ctx) => {
62
+ if (this._source === value) {
63
+ this._connectSource(value, ctx);
64
+ }
65
+ }, this);
42
66
  }
43
- this._analyserTarget = analyserTarget;
44
- analyserTarget.connect(this._analyser);
45
- return this;
46
67
  }
47
- get timeDomainData() {
68
+ // -----------------------------------------------------------------------
69
+ // AnalyserNode property pass-throughs
70
+ // -----------------------------------------------------------------------
71
+ get fftSize() {
72
+ return this._options.fftSize;
73
+ }
74
+ get frequencyBinCount() {
75
+ return this._options.fftSize >> 1;
76
+ }
77
+ get smoothingTimeConstant() {
78
+ return this._analyser?.smoothingTimeConstant ?? this._options.smoothingTimeConstant;
79
+ }
80
+ set smoothingTimeConstant(v) {
81
+ this._options.smoothingTimeConstant = v;
82
+ if (this._analyser)
83
+ this._analyser.smoothingTimeConstant = v;
84
+ }
85
+ get minDecibels() {
86
+ return this._analyser?.minDecibels ?? this._options.minDecibels;
87
+ }
88
+ set minDecibels(v) {
89
+ this._options.minDecibels = v;
90
+ if (this._analyser)
91
+ this._analyser.minDecibels = v;
92
+ }
93
+ get maxDecibels() {
94
+ return this._analyser?.maxDecibels ?? this._options.maxDecibels;
95
+ }
96
+ set maxDecibels(v) {
97
+ this._options.maxDecibels = v;
98
+ if (this._analyser)
99
+ this._analyser.maxDecibels = v;
100
+ }
101
+ // -----------------------------------------------------------------------
102
+ // Raw data
103
+ // -----------------------------------------------------------------------
104
+ /** Fill and return the byte frequency spectrum (0..255 per bin). */
105
+ getSpectrum(into) {
106
+ const buf = into ?? this._byteSpectrum;
48
107
  if (this._analyser) {
49
- this.connect();
50
- this._analyser.getByteTimeDomainData(this._timeDomainData);
108
+ this._analyser.getByteFrequencyData(buf);
51
109
  }
52
- return this._timeDomainData;
110
+ else {
111
+ buf.fill(0);
112
+ }
113
+ return buf;
53
114
  }
54
- get frequencyData() {
115
+ /** Fill and return the float frequency spectrum (dB per bin). */
116
+ getSpectrumFloat(into) {
117
+ const buf = into ?? this._floatSpectrum;
55
118
  if (this._analyser) {
56
- this.connect();
57
- this._analyser.getByteFrequencyData(this._frequencyData);
119
+ this._analyser.getFloatFrequencyData(buf);
58
120
  }
59
- return this._frequencyData;
121
+ else {
122
+ buf.fill(0);
123
+ }
124
+ return buf;
60
125
  }
61
- get preciseTimeDomainData() {
126
+ /** Fill and return the byte time-domain waveform (0..255 per sample). */
127
+ getWaveform(into) {
128
+ const buf = into ?? this._byteWaveform;
62
129
  if (this._analyser) {
63
- this.connect();
64
- this._analyser.getFloatTimeDomainData(this._preciseTimeDomainData);
130
+ this._analyser.getByteTimeDomainData(buf);
131
+ }
132
+ else {
133
+ buf.fill(0);
65
134
  }
66
- return this._preciseTimeDomainData;
135
+ return buf;
67
136
  }
68
- get preciseFrequencyData() {
137
+ /** Fill and return the float time-domain waveform (-1..1 per sample). */
138
+ getWaveformFloat(into) {
139
+ const buf = into ?? this._floatWaveform;
69
140
  if (this._analyser) {
70
- this.connect();
71
- this._analyser.getFloatFrequencyData(this._preciseFrequencyData);
141
+ this._analyser.getFloatTimeDomainData(buf);
142
+ }
143
+ else {
144
+ buf.fill(0);
145
+ }
146
+ return buf;
147
+ }
148
+ // -----------------------------------------------------------------------
149
+ // Convenience helpers
150
+ // -----------------------------------------------------------------------
151
+ /**
152
+ * Return the mean energy of frequency bins in the given Hz range, normalised 0..1.
153
+ * Uses the byte spectrum (0..255), normalised by dividing by 255.
154
+ */
155
+ getBandEnergy(fromHz, toHz) {
156
+ if (!this._analyser)
157
+ return 0;
158
+ const ctx = getAudioContext();
159
+ const nyquist = ctx.sampleRate / 2;
160
+ const binCount = this.frequencyBinCount;
161
+ const fromBin = Math.max(0, Math.min(binCount - 1, Math.round(fromHz / nyquist * binCount)));
162
+ const toBin = Math.max(0, Math.min(binCount - 1, Math.round(toHz / nyquist * binCount)));
163
+ const lo = Math.min(fromBin, toBin);
164
+ const hi = Math.max(fromBin, toBin);
165
+ const spectrum = this.getSpectrum();
166
+ let sum = 0;
167
+ const count = hi - lo + 1;
168
+ for (let i = lo; i <= hi; i++) {
169
+ sum += spectrum[i];
72
170
  }
73
- return this._preciseFrequencyData;
171
+ return sum / (count * 255);
172
+ }
173
+ /** Return low (0-250 Hz), mid (250-2 kHz), and high (2 k-20 kHz) band energies (0..1 each). */
174
+ getLowMidHigh() {
175
+ return {
176
+ low: this.getBandEnergy(0, 250),
177
+ mid: this.getBandEnergy(250, 2000),
178
+ high: this.getBandEnergy(2000, 20000),
179
+ };
180
+ }
181
+ /** Return overall RMS energy across all bins, normalised 0..1. */
182
+ getRms() {
183
+ if (!this._analyser)
184
+ return 0;
185
+ const ctx = getAudioContext();
186
+ const nyquist = ctx.sampleRate / 2;
187
+ return this.getBandEnergy(0, nyquist);
74
188
  }
189
+ // -----------------------------------------------------------------------
190
+ // Lifecycle
191
+ // -----------------------------------------------------------------------
75
192
  destroy() {
76
193
  onAudioContextReady.clearByContext(this);
77
- this._analyserTarget?.disconnect();
194
+ this._disconnectTap();
78
195
  this._analyser?.disconnect();
196
+ this._analyser = null;
197
+ this._source = null;
198
+ }
199
+ // -----------------------------------------------------------------------
200
+ // Private helpers
201
+ // -----------------------------------------------------------------------
202
+ _setupAnalyser(audioContext) {
203
+ const node = audioContext.createAnalyser();
204
+ node.fftSize = this._options.fftSize;
205
+ node.minDecibels = this._options.minDecibels;
206
+ node.maxDecibels = this._options.maxDecibels;
207
+ node.smoothingTimeConstant = this._options.smoothingTimeConstant;
208
+ this._analyser = node;
209
+ // If a source was set before the context was ready, connect it now.
210
+ if (this._source !== null) {
211
+ this._connectSource(this._source, audioContext);
212
+ }
213
+ }
214
+ _connectSource(source, audioContext) {
215
+ if (!this._analyser)
216
+ return;
217
+ const tap = this._resolveToAudioNode(source, audioContext);
218
+ if (!tap) {
219
+ // AudioBus/Sound/Music not ready — defer via their own onceSetup
220
+ this._deferConnectionViaBus(source);
221
+ return;
222
+ }
223
+ this._tapSource = tap;
224
+ tap.connect(this._analyser);
79
225
  }
80
- setupWithAudioContext(audioContext) {
81
- this._analyser = audioContext.createAnalyser();
82
- this._analyser.fftSize = this._fftSize;
83
- this._analyser.minDecibels = this._minDecibels;
84
- this._analyser.maxDecibels = this._maxDecibels;
85
- this._analyser.smoothingTimeConstant = this._smoothingTimeConstant;
226
+ _resolveToAudioNode(source, audioContext) {
227
+ if (source === null)
228
+ return null;
229
+ // MediaStream — detect by getTracks (duck-type, since AudioNode also doesn't exist in jsdom)
230
+ const asStream = source;
231
+ if (typeof asStream.getTracks === 'function') {
232
+ if (this._streamSource) {
233
+ this._streamSource.disconnect();
234
+ this._streamSource = null;
235
+ }
236
+ const msNode = audioContext.createMediaStreamSource(source);
237
+ this._streamSource = msNode;
238
+ return msNode;
239
+ }
240
+ // AudioBus — has _getOutputNode (checked first since bus nodes also have connect/disconnect)
241
+ const asBus = source;
242
+ if (typeof asBus._getOutputNode === 'function') {
243
+ return asBus._getOutputNode();
244
+ }
245
+ // Sound / Music — tap analyserTarget
246
+ const asMedia = source;
247
+ if ('analyserTarget' in asMedia) {
248
+ return asMedia.analyserTarget ?? null;
249
+ }
250
+ // Raw AudioNode — duck-type: has connect & disconnect
251
+ const asNode = source;
252
+ if (typeof asNode.connect === 'function' && typeof asNode.disconnect === 'function') {
253
+ return source;
254
+ }
255
+ return null;
256
+ }
257
+ _deferConnectionViaBus(source) {
258
+ // AudioBus exposes onceSetup
259
+ const asBus = source;
260
+ if (typeof asBus.onceSetup === 'function') {
261
+ asBus.onceSetup(() => {
262
+ if (this._source === source && this._analyser && isAudioContextReady()) {
263
+ this._connectSource(source, getAudioContext());
264
+ }
265
+ });
266
+ return;
267
+ }
268
+ // Sound/Music — they set up when audioContext is ready (same signal)
269
+ onAudioContextReady.once(() => {
270
+ if (this._source === source && this._analyser && isAudioContextReady()) {
271
+ this._connectSource(source, getAudioContext());
272
+ }
273
+ }, this);
274
+ }
275
+ _disconnectTap() {
276
+ if (this._tapSource && this._analyser) {
277
+ try {
278
+ this._tapSource.disconnect(this._analyser);
279
+ }
280
+ catch {
281
+ // Ignore if already disconnected
282
+ }
283
+ }
284
+ this._tapSource = null;
285
+ // Clean up cached stream source
286
+ if (this._streamSource) {
287
+ this._streamSource.disconnect();
288
+ this._streamSource = null;
289
+ }
86
290
  }
87
291
  }
88
292
 
@@ -1 +1 @@
1
- {"version":3,"file":"AudioAnalyser.js","sources":["../../../../src/audio/AudioAnalyser.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AudioAnalyser.js","sources":["../../../../src/audio/AudioAnalyser.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}