@nodetool-ai/game-renderer 0.8.1 → 0.8.2

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 (273) hide show
  1. package/README.md +46 -0
  2. package/dist/.nodetool-build-stamp +1 -1
  3. package/dist/audio/mixer.d.ts +75 -0
  4. package/dist/audio/mixer.d.ts.map +1 -0
  5. package/dist/audio/mixer.js +345 -0
  6. package/dist/audio/mixer.js.map +1 -0
  7. package/dist/audio/player.d.ts +67 -0
  8. package/dist/audio/player.d.ts.map +1 -0
  9. package/dist/audio/player.js +337 -0
  10. package/dist/audio/player.js.map +1 -0
  11. package/dist/audio/spatial.d.ts +50 -0
  12. package/dist/audio/spatial.d.ts.map +1 -0
  13. package/dist/audio/spatial.js +166 -0
  14. package/dist/audio/spatial.js.map +1 -0
  15. package/dist/audio/voices.d.ts +11 -0
  16. package/dist/audio/voices.d.ts.map +1 -0
  17. package/dist/audio/voices.js +22 -0
  18. package/dist/audio/voices.js.map +1 -0
  19. package/dist/audio.d.ts +6 -38
  20. package/dist/audio.d.ts.map +1 -1
  21. package/dist/audio.js +3 -226
  22. package/dist/audio.js.map +1 -1
  23. package/dist/browser.d.ts +2 -1
  24. package/dist/browser.d.ts.map +1 -1
  25. package/dist/browser.js +5 -5
  26. package/dist/browser.js.map +1 -1
  27. package/dist/browser3d.d.ts +2 -0
  28. package/dist/browser3d.d.ts.map +1 -0
  29. package/dist/browser3d.js +2 -0
  30. package/dist/browser3d.js.map +1 -0
  31. package/dist/build.d.ts.map +1 -1
  32. package/dist/build.js +29 -19
  33. package/dist/build.js.map +1 -1
  34. package/dist/build3d.d.ts +11 -0
  35. package/dist/build3d.d.ts.map +1 -0
  36. package/dist/build3d.js +126 -0
  37. package/dist/build3d.js.map +1 -0
  38. package/dist/canvas2d.d.ts +12 -3
  39. package/dist/canvas2d.d.ts.map +1 -1
  40. package/dist/canvas2d.js +59 -12
  41. package/dist/canvas2d.js.map +1 -1
  42. package/dist/fixed-tick-host.d.ts +10 -0
  43. package/dist/fixed-tick-host.d.ts.map +1 -0
  44. package/dist/fixed-tick-host.js +29 -0
  45. package/dist/fixed-tick-host.js.map +1 -0
  46. package/dist/frame-budget.d.ts +34 -0
  47. package/dist/frame-budget.d.ts.map +1 -0
  48. package/dist/frame-budget.js +52 -0
  49. package/dist/frame-budget.js.map +1 -0
  50. package/dist/frame.d.ts +20 -1
  51. package/dist/frame.d.ts.map +1 -1
  52. package/dist/frame.js +69 -1
  53. package/dist/frame.js.map +1 -1
  54. package/dist/game3d-capture-page.js +5834 -0
  55. package/dist/game3d-player.js +6001 -0
  56. package/dist/imageDiff.d.ts +9 -0
  57. package/dist/imageDiff.d.ts.map +1 -0
  58. package/dist/imageDiff.js +30 -0
  59. package/dist/imageDiff.js.map +1 -0
  60. package/dist/index.d.ts +12 -1
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +9 -0
  63. package/dist/index.js.map +1 -1
  64. package/dist/input-bindings.d.ts +76 -0
  65. package/dist/input-bindings.d.ts.map +1 -0
  66. package/dist/input-bindings.js +377 -0
  67. package/dist/input-bindings.js.map +1 -0
  68. package/dist/input.d.ts +1 -1
  69. package/dist/input.d.ts.map +1 -1
  70. package/dist/input.js +1 -14
  71. package/dist/input.js.map +1 -1
  72. package/dist/input3d.d.ts +3 -0
  73. package/dist/input3d.d.ts.map +1 -0
  74. package/dist/input3d.js +3 -0
  75. package/dist/input3d.js.map +1 -0
  76. package/dist/node.d.ts +5 -0
  77. package/dist/node.d.ts.map +1 -1
  78. package/dist/node.js +28 -11
  79. package/dist/node.js.map +1 -1
  80. package/dist/node3d.d.ts +29 -0
  81. package/dist/node3d.d.ts.map +1 -0
  82. package/dist/node3d.js +160 -0
  83. package/dist/node3d.js.map +1 -0
  84. package/dist/particles/curves.d.ts +16 -0
  85. package/dist/particles/curves.d.ts.map +1 -0
  86. package/dist/particles/curves.js +49 -0
  87. package/dist/particles/curves.js.map +1 -0
  88. package/dist/particles/index.d.ts +6 -0
  89. package/dist/particles/index.d.ts.map +1 -0
  90. package/dist/particles/index.js +6 -0
  91. package/dist/particles/index.js.map +1 -0
  92. package/dist/particles/random.d.ts +10 -0
  93. package/dist/particles/random.d.ts.map +1 -0
  94. package/dist/particles/random.js +26 -0
  95. package/dist/particles/random.js.map +1 -0
  96. package/dist/particles/render2d.d.ts +40 -0
  97. package/dist/particles/render2d.d.ts.map +1 -0
  98. package/dist/particles/render2d.js +70 -0
  99. package/dist/particles/render2d.js.map +1 -0
  100. package/dist/particles/shapes.d.ts +18 -0
  101. package/dist/particles/shapes.d.ts.map +1 -0
  102. package/dist/particles/shapes.js +92 -0
  103. package/dist/particles/shapes.js.map +1 -0
  104. package/dist/particles/simulator.d.ts +88 -0
  105. package/dist/particles/simulator.d.ts.map +1 -0
  106. package/dist/particles/simulator.js +371 -0
  107. package/dist/particles/simulator.js.map +1 -0
  108. package/dist/player-v1.js +2502 -0
  109. package/dist/preparation3d.d.ts +3 -0
  110. package/dist/preparation3d.d.ts.map +1 -0
  111. package/dist/preparation3d.js +3 -0
  112. package/dist/preparation3d.js.map +1 -0
  113. package/dist/renderPipeline.d.ts +12 -0
  114. package/dist/renderPipeline.d.ts.map +1 -0
  115. package/dist/renderPipeline.js +17 -0
  116. package/dist/renderPipeline.js.map +1 -0
  117. package/dist/renderer3d/animation/index.d.ts +11 -0
  118. package/dist/renderer3d/animation/index.d.ts.map +1 -0
  119. package/dist/renderer3d/animation/index.js +212 -0
  120. package/dist/renderer3d/animation/index.js.map +1 -0
  121. package/dist/renderer3d/assets/cache.d.ts +14 -0
  122. package/dist/renderer3d/assets/cache.d.ts.map +1 -0
  123. package/dist/renderer3d/assets/cache.js +74 -0
  124. package/dist/renderer3d/assets/cache.js.map +1 -0
  125. package/dist/renderer3d/assets/dispose.d.ts +4 -0
  126. package/dist/renderer3d/assets/dispose.d.ts.map +1 -0
  127. package/dist/renderer3d/assets/dispose.js +41 -0
  128. package/dist/renderer3d/assets/dispose.js.map +1 -0
  129. package/dist/renderer3d/assets/hdri-contract.d.ts +23 -0
  130. package/dist/renderer3d/assets/hdri-contract.d.ts.map +1 -0
  131. package/dist/renderer3d/assets/hdri-contract.js +2 -0
  132. package/dist/renderer3d/assets/hdri-contract.js.map +1 -0
  133. package/dist/renderer3d/assets/instances.d.ts +5 -0
  134. package/dist/renderer3d/assets/instances.d.ts.map +1 -0
  135. package/dist/renderer3d/assets/instances.js +86 -0
  136. package/dist/renderer3d/assets/instances.js.map +1 -0
  137. package/dist/renderer3d/capture-driver-types.d.ts +42 -0
  138. package/dist/renderer3d/capture-driver-types.d.ts.map +1 -0
  139. package/dist/renderer3d/capture-driver-types.js +2 -0
  140. package/dist/renderer3d/capture-driver-types.js.map +1 -0
  141. package/dist/renderer3d/capture-page.d.ts +36 -0
  142. package/dist/renderer3d/capture-page.d.ts.map +1 -0
  143. package/dist/renderer3d/capture-page.js +68 -0
  144. package/dist/renderer3d/capture-page.js.map +1 -0
  145. package/dist/renderer3d/culling.d.ts +10 -0
  146. package/dist/renderer3d/culling.d.ts.map +1 -0
  147. package/dist/renderer3d/culling.js +27 -0
  148. package/dist/renderer3d/culling.js.map +1 -0
  149. package/dist/renderer3d/environment/index.d.ts +4 -0
  150. package/dist/renderer3d/environment/index.d.ts.map +1 -0
  151. package/dist/renderer3d/environment/index.js +9 -0
  152. package/dist/renderer3d/environment/index.js.map +1 -0
  153. package/dist/renderer3d/environment/sky.d.ts +45 -0
  154. package/dist/renderer3d/environment/sky.d.ts.map +1 -0
  155. package/dist/renderer3d/environment/sky.js +221 -0
  156. package/dist/renderer3d/environment/sky.js.map +1 -0
  157. package/dist/renderer3d/hud/fonts.d.ts +13 -0
  158. package/dist/renderer3d/hud/fonts.d.ts.map +1 -0
  159. package/dist/renderer3d/hud/fonts.js +69 -0
  160. package/dist/renderer3d/hud/fonts.js.map +1 -0
  161. package/dist/renderer3d/hud/paint.d.ts +4 -0
  162. package/dist/renderer3d/hud/paint.d.ts.map +1 -0
  163. package/dist/renderer3d/hud/paint.js +22 -0
  164. package/dist/renderer3d/hud/paint.js.map +1 -0
  165. package/dist/renderer3d/import.d.ts +34 -0
  166. package/dist/renderer3d/import.d.ts.map +1 -0
  167. package/dist/renderer3d/import.js +408 -0
  168. package/dist/renderer3d/import.js.map +1 -0
  169. package/dist/renderer3d/index.d.ts +74 -0
  170. package/dist/renderer3d/index.d.ts.map +1 -0
  171. package/dist/renderer3d/index.js +338 -0
  172. package/dist/renderer3d/index.js.map +1 -0
  173. package/dist/renderer3d/lights/index.d.ts +7 -0
  174. package/dist/renderer3d/lights/index.d.ts.map +1 -0
  175. package/dist/renderer3d/lights/index.js +67 -0
  176. package/dist/renderer3d/lights/index.js.map +1 -0
  177. package/dist/renderer3d/materials/index.d.ts +4 -0
  178. package/dist/renderer3d/materials/index.d.ts.map +1 -0
  179. package/dist/renderer3d/materials/index.js +8 -0
  180. package/dist/renderer3d/materials/index.js.map +1 -0
  181. package/dist/renderer3d/passes/post-processing.d.ts +44 -0
  182. package/dist/renderer3d/passes/post-processing.d.ts.map +1 -0
  183. package/dist/renderer3d/passes/post-processing.js +213 -0
  184. package/dist/renderer3d/passes/post-processing.js.map +1 -0
  185. package/dist/renderer3d/pipeline.d.ts +15 -0
  186. package/dist/renderer3d/pipeline.d.ts.map +1 -0
  187. package/dist/renderer3d/pipeline.js +10 -0
  188. package/dist/renderer3d/pipeline.js.map +1 -0
  189. package/dist/renderer3d/playwright-contract.d.ts +3 -0
  190. package/dist/renderer3d/playwright-contract.d.ts.map +1 -0
  191. package/dist/renderer3d/playwright-contract.js +4 -0
  192. package/dist/renderer3d/playwright-contract.js.map +1 -0
  193. package/dist/renderer3d/preparation.d.ts +79 -0
  194. package/dist/renderer3d/preparation.d.ts.map +1 -0
  195. package/dist/renderer3d/preparation.js +458 -0
  196. package/dist/renderer3d/preparation.js.map +1 -0
  197. package/dist/renderer3d/scene-sync.d.ts +8 -0
  198. package/dist/renderer3d/scene-sync.d.ts.map +1 -0
  199. package/dist/renderer3d/scene-sync.js +96 -0
  200. package/dist/renderer3d/scene-sync.js.map +1 -0
  201. package/dist/renderer3d/shadows/cascades.d.ts +40 -0
  202. package/dist/renderer3d/shadows/cascades.d.ts.map +1 -0
  203. package/dist/renderer3d/shadows/cascades.js +244 -0
  204. package/dist/renderer3d/shadows/cascades.js.map +1 -0
  205. package/dist/renderer3d/shadows/index.d.ts +44 -0
  206. package/dist/renderer3d/shadows/index.d.ts.map +1 -0
  207. package/dist/renderer3d/shadows/index.js +129 -0
  208. package/dist/renderer3d/shadows/index.js.map +1 -0
  209. package/dist/renderer3d/types.d.ts +18 -0
  210. package/dist/renderer3d/types.d.ts.map +1 -0
  211. package/dist/renderer3d/types.js +2 -0
  212. package/dist/renderer3d/types.js.map +1 -0
  213. package/dist/smoke.d.ts +15 -0
  214. package/dist/smoke.d.ts.map +1 -0
  215. package/dist/smoke.js +138 -0
  216. package/dist/smoke.js.map +1 -0
  217. package/dist/standalone-player.d.ts +11 -1
  218. package/dist/standalone-player.d.ts.map +1 -1
  219. package/dist/standalone-player.js +67 -41
  220. package/dist/standalone-player.js.map +1 -1
  221. package/dist/standalone-player3d.d.ts +14 -0
  222. package/dist/standalone-player3d.d.ts.map +1 -0
  223. package/dist/standalone-player3d.js +255 -0
  224. package/dist/standalone-player3d.js.map +1 -0
  225. package/dist/touch-controls.d.ts +22 -8
  226. package/dist/touch-controls.d.ts.map +1 -1
  227. package/dist/touch-controls.js +88 -21
  228. package/dist/touch-controls.js.map +1 -1
  229. package/dist/ui/controller.d.ts +59 -0
  230. package/dist/ui/controller.d.ts.map +1 -0
  231. package/dist/ui/controller.js +201 -0
  232. package/dist/ui/controller.js.map +1 -0
  233. package/dist/ui/hud2d.d.ts +11 -0
  234. package/dist/ui/hud2d.d.ts.map +1 -0
  235. package/dist/ui/hud2d.js +25 -0
  236. package/dist/ui/hud2d.js.map +1 -0
  237. package/dist/ui/layout.d.ts +42 -0
  238. package/dist/ui/layout.d.ts.map +1 -0
  239. package/dist/ui/layout.js +182 -0
  240. package/dist/ui/layout.js.map +1 -0
  241. package/dist/ui/paint.d.ts +45 -0
  242. package/dist/ui/paint.d.ts.map +1 -0
  243. package/dist/ui/paint.js +121 -0
  244. package/dist/ui/paint.js.map +1 -0
  245. package/dist/webgpu/effects.d.ts +22 -0
  246. package/dist/webgpu/effects.d.ts.map +1 -0
  247. package/dist/webgpu/effects.js +69 -0
  248. package/dist/webgpu/effects.js.map +1 -0
  249. package/dist/webgpu/hud.d.ts +4 -0
  250. package/dist/webgpu/hud.d.ts.map +1 -0
  251. package/dist/webgpu/hud.js +27 -0
  252. package/dist/webgpu/hud.js.map +1 -0
  253. package/dist/webgpu/lighting.d.ts +4 -0
  254. package/dist/webgpu/lighting.d.ts.map +1 -0
  255. package/dist/webgpu/lighting.js +47 -0
  256. package/dist/webgpu/lighting.js.map +1 -0
  257. package/dist/webgpu/pipeline.d.ts +11 -0
  258. package/dist/webgpu/pipeline.d.ts.map +1 -0
  259. package/dist/webgpu/pipeline.js +11 -0
  260. package/dist/webgpu/pipeline.js.map +1 -0
  261. package/dist/webgpu/sprites.d.ts +6 -0
  262. package/dist/webgpu/sprites.d.ts.map +1 -0
  263. package/dist/webgpu/sprites.js +74 -0
  264. package/dist/webgpu/sprites.js.map +1 -0
  265. package/dist/webgpu/types.d.ts +14 -0
  266. package/dist/webgpu/types.d.ts.map +1 -0
  267. package/dist/webgpu/types.js +2 -0
  268. package/dist/webgpu/types.js.map +1 -0
  269. package/dist/webgpu.d.ts +4 -3
  270. package/dist/webgpu.d.ts.map +1 -1
  271. package/dist/webgpu.js +119 -279
  272. package/dist/webgpu.js.map +1 -1
  273. package/package.json +47 -10
@@ -0,0 +1,337 @@
1
+ import { gameAudioMixer } from "@nodetool-ai/protocol";
2
+ import { GameAudioMixer } from "./mixer.js";
3
+ import { createGameAudioPanner, gameAudioDopplerRate, gameAudioVelocity, placeGameAudioListener, placeGameAudioPanner, setGameAudioDopplerRate } from "./spatial.js";
4
+ import { playBuiltinGameVoice, stopGameVoice } from "./voices.js";
5
+ const MAX_VOICES = 32;
6
+ /** Shares Web Audio voice, decoding, and lifecycle behavior across browser players. */
7
+ export class GameAudioPlayer {
8
+ options;
9
+ context;
10
+ mixer;
11
+ buffers = new Map();
12
+ voices = new Map();
13
+ fading = new Set();
14
+ pending = new Map();
15
+ voiceAssets = new WeakMap();
16
+ spatialVoices = new Set();
17
+ view = null;
18
+ listenerSample;
19
+ listenerVelocity = { x: 0, y: 0, z: 0 };
20
+ desiredMusic = null;
21
+ sceneId = null;
22
+ tick = 0;
23
+ generation = 0;
24
+ legacySequence = 0;
25
+ disposed = false;
26
+ paused = false;
27
+ constructor(options) {
28
+ this.options = options;
29
+ this.context = options.context ?? new AudioContext();
30
+ this.mixer = new GameAudioMixer(this.context, this.mixerSettings(options.mixer), options.tickRate);
31
+ }
32
+ mixerSettings(settings) {
33
+ const parsed = gameAudioMixer.safeParse(settings ?? {});
34
+ if (parsed.success) {
35
+ return settings;
36
+ }
37
+ this.options.status(`Audio mixer settings are invalid, so the default mix is used: ${parsed.error.issues[0]?.message ?? "unknown issue"}`);
38
+ return undefined;
39
+ }
40
+ /** Applies edited mixer settings. Playing voices keep playing on their buses. */
41
+ updateMixer(settings) {
42
+ if (this.disposed)
43
+ return;
44
+ this.mixer.update(this.mixerSettings(settings));
45
+ }
46
+ /** Player-facing bus volume, for example from a settings screen. */
47
+ setBusVolume(busId, volume) {
48
+ if (!this.disposed)
49
+ this.mixer.setUserVolume(busId, volume);
50
+ }
51
+ setBusMuted(busId, muted) {
52
+ if (!this.disposed)
53
+ this.mixer.setUserMuted(busId, muted);
54
+ }
55
+ mixerState() {
56
+ return this.mixer.state();
57
+ }
58
+ buffer(assetId) {
59
+ const cached = this.buffers.get(assetId);
60
+ if (cached)
61
+ return cached;
62
+ const binding = this.options.assets[assetId];
63
+ if (!binding) {
64
+ this.options.status(`Audio asset ${assetId} is missing`);
65
+ return Promise.resolve(null);
66
+ }
67
+ const pending = this.options.resolveAsset(binding).then(async (url) => {
68
+ if (!url)
69
+ throw new Error("asset URL is unavailable");
70
+ const response = await fetch(url, { cache: "force-cache" });
71
+ if (!response.ok)
72
+ throw new Error(`HTTP ${response.status}`);
73
+ return this.context.decodeAudioData(await response.arrayBuffer());
74
+ }).catch((error) => {
75
+ this.options.status(`Audio ${assetId} could not be decoded: ${error instanceof Error ? error.message : String(error)}`);
76
+ return null;
77
+ });
78
+ this.buffers.set(assetId, pending);
79
+ return pending;
80
+ }
81
+ /** Keeps decoded audio for unchanged bindings when the editor document changes. */
82
+ updateAssets(assets) {
83
+ if (this.disposed)
84
+ return;
85
+ const changed = new Set();
86
+ for (const slot of new Set([...Object.keys(this.options.assets), ...Object.keys(assets)])) {
87
+ if (JSON.stringify(this.options.assets[slot]) !== JSON.stringify(assets[slot])) {
88
+ this.buffers.delete(slot);
89
+ changed.add(slot);
90
+ }
91
+ }
92
+ for (const [id, pending] of this.pending) {
93
+ if (changed.has(pending.assetId))
94
+ this.pending.delete(id);
95
+ }
96
+ for (const [id, voice] of this.voices) {
97
+ if (changed.has(this.voiceAssets.get(voice) ?? ""))
98
+ this.stop(id, 0);
99
+ }
100
+ for (const voice of this.fading) {
101
+ if (changed.has(this.voiceAssets.get(voice) ?? "")) {
102
+ voice.source.stop();
103
+ this.fading.delete(voice);
104
+ }
105
+ }
106
+ this.options = { ...this.options, assets };
107
+ this.preload();
108
+ this.startDesiredMusic();
109
+ }
110
+ preload() {
111
+ for (const [id, binding] of Object.entries(this.options.assets)) {
112
+ if (binding.mediaKind === "audio" && !binding.assetId.startsWith("builtin:"))
113
+ void this.buffer(id);
114
+ }
115
+ }
116
+ async unlock() {
117
+ if (this.disposed || this.paused)
118
+ return;
119
+ try {
120
+ await this.context.resume();
121
+ this.startDesiredMusic();
122
+ }
123
+ catch {
124
+ this.options.status("Audio is blocked. Tap Play to enable sound in this browser.");
125
+ }
126
+ }
127
+ pause() {
128
+ if (this.disposed || this.paused)
129
+ return;
130
+ this.paused = true;
131
+ void this.context.suspend().catch(() => this.options.status("Audio could not pause"));
132
+ }
133
+ resume() {
134
+ this.paused = false;
135
+ void this.unlock();
136
+ }
137
+ sync(snapshot) {
138
+ if (this.disposed)
139
+ return;
140
+ this.tick = snapshot.tick;
141
+ if (this.sceneId && this.sceneId !== snapshot.sceneId) {
142
+ for (const id of this.pending.keys()) {
143
+ if (!id.startsWith(`effect:${snapshot.sceneId}:`))
144
+ this.pending.delete(id);
145
+ }
146
+ for (const id of this.voices.keys()) {
147
+ if (id.startsWith(`effect:${this.sceneId}:`))
148
+ this.stop(id, 0);
149
+ }
150
+ }
151
+ this.sceneId = snapshot.sceneId;
152
+ this.mixer.enterScene(snapshot.sceneId);
153
+ const next = snapshot.music;
154
+ if (this.desiredMusic?.voiceId !== next?.voiceId || this.desiredMusic?.startTick !== next?.startTick ||
155
+ this.desiredMusic?.assetId !== next?.assetId || this.desiredMusic?.volume !== next?.volume ||
156
+ this.desiredMusic?.fadeInTicks !== next?.fadeInTicks || this.desiredMusic?.fadeOutTicks !== next?.fadeOutTicks) {
157
+ if (this.desiredMusic)
158
+ this.stop(this.desiredMusic.voiceId, this.desiredMusic.fadeOutTicks);
159
+ this.desiredMusic = next;
160
+ }
161
+ this.startDesiredMusic();
162
+ }
163
+ startDesiredMusic() {
164
+ const music = this.desiredMusic;
165
+ if (!music || !this.options.assets[music.assetId] || this.paused || this.context.state !== "running" || this.voices.has(music.voiceId) || this.pending.has(music.voiceId))
166
+ return;
167
+ const token = Symbol();
168
+ this.pending.set(music.voiceId, { token, assetId: music.assetId });
169
+ void this.start(music.voiceId, music.assetId, true, music.volume, music.fadeInTicks, music.fadeOutTicks, token, music.startTick)
170
+ .catch((error) => this.options.status(`Music could not start: ${error instanceof Error ? error.message : String(error)}`))
171
+ .finally(() => { if (this.pending.get(music.voiceId)?.token === token)
172
+ this.pending.delete(music.voiceId); });
173
+ }
174
+ /**
175
+ * Moves the listener and every spatial voice to a rendered frame. Players call it once per rendered frame with the view
176
+ * built from the interpolated frame, so positions follow what is on screen. Emitters missing from the view keep their last position.
177
+ */
178
+ updateSpatial(view) {
179
+ if (this.disposed)
180
+ return;
181
+ this.view = view;
182
+ const now = this.context.currentTime;
183
+ const listenerSample = { position: view.listener.position, time: now };
184
+ this.listenerVelocity = gameAudioVelocity(this.listenerSample, listenerSample) ?? this.listenerVelocity;
185
+ this.listenerSample = listenerSample;
186
+ placeGameAudioListener(this.context.listener, view.listener, now, true);
187
+ for (const voice of this.spatialVoices) {
188
+ const pose = view.emitter(voice.emitter.entityId);
189
+ if (!pose)
190
+ continue;
191
+ placeGameAudioPanner(voice.panner, voice.emitter, pose, now, true);
192
+ const sample = { position: pose.position, time: now };
193
+ const velocity = gameAudioVelocity(voice.sample, sample);
194
+ voice.sample = sample;
195
+ if (voice.rate && voice.emitter.doppler > 0 && velocity) {
196
+ setGameAudioDopplerRate(voice.rate, gameAudioDopplerRate(view.listener.position, this.listenerVelocity, pose.position, velocity, voice.emitter.doppler), now);
197
+ }
198
+ }
199
+ }
200
+ /** Creates the panner for a voice and connects it to the bus. The voice connects to the returned node. */
201
+ spatialOutput(emitter, bus, rate) {
202
+ const input = this.mixer.input(bus);
203
+ if (!emitter)
204
+ return { node: input, release: () => { } };
205
+ const now = this.context.currentTime;
206
+ const panner = createGameAudioPanner(this.context, emitter, this.options.spatialQuality ?? "high", now);
207
+ const pose = this.view?.emitter(emitter.entityId);
208
+ if (pose)
209
+ placeGameAudioPanner(panner, emitter, pose, now, false);
210
+ panner.connect(input);
211
+ const voice = { emitter, panner, rate, sample: pose ? { position: pose.position, time: now } : undefined };
212
+ this.spatialVoices.add(voice);
213
+ return { node: panner, release: () => { this.spatialVoices.delete(voice); panner.disconnect(); } };
214
+ }
215
+ /** Plays audio events and lets other simulation events drive mixer snapshot transitions. */
216
+ handle(event) {
217
+ if (this.disposed)
218
+ return;
219
+ if (event.kind !== "audio") {
220
+ this.mixer.observe(event);
221
+ return;
222
+ }
223
+ if (event.action === "stop") {
224
+ if (event.voiceId)
225
+ this.stop(event.voiceId, event.fadeOutTicks);
226
+ return;
227
+ }
228
+ if (this.paused || this.context.state !== "running")
229
+ return;
230
+ const voiceId = event.voiceId ?? `legacy:${this.tick}:${this.legacySequence++}`;
231
+ if (this.pending.has(voiceId))
232
+ return;
233
+ const token = Symbol();
234
+ this.pending.set(voiceId, { token, assetId: event.assetId });
235
+ void this.start(voiceId, event.assetId, event.loop, event.volume, event.fadeInTicks, event.fadeOutTicks, token, undefined, event.emitter)
236
+ .catch((error) => this.options.status(`Audio effect could not start: ${error instanceof Error ? error.message : String(error)}`))
237
+ .finally(() => { if (this.pending.get(voiceId)?.token === token)
238
+ this.pending.delete(voiceId); });
239
+ }
240
+ async start(id, assetId, loop, volume, fadeInTicks, fadeOutTicks, token, logicalStartTick, emitter) {
241
+ const generation = this.generation;
242
+ const binding = this.options.assets[assetId];
243
+ const bus = this.mixer.busFor(assetId, logicalStartTick !== undefined);
244
+ if (binding?.assetId.startsWith("builtin:")) {
245
+ if (loop)
246
+ this.options.status(`Audio ${assetId} cannot loop a built-in effect`);
247
+ else {
248
+ this.mixer.voiceStarted(bus);
249
+ const output = this.spatialOutput(emitter, bus);
250
+ playBuiltinGameVoice(this.context, volume, output.node, () => { output.release(); this.mixer.voiceEnded(bus); });
251
+ }
252
+ return;
253
+ }
254
+ const buffer = await this.buffer(assetId);
255
+ if (!buffer || this.disposed || this.paused || this.context.state !== "running" || generation !== this.generation ||
256
+ this.pending.get(id)?.token !== token || this.voices.has(id))
257
+ return;
258
+ if (this.voices.size + this.fading.size >= MAX_VOICES && this.fading.size > 0) {
259
+ const fading = this.fading.values().next().value;
260
+ if (fading) {
261
+ fading.source.stop();
262
+ this.fading.delete(fading);
263
+ }
264
+ }
265
+ if (this.voices.size + this.fading.size >= MAX_VOICES) {
266
+ const oldestEffect = [...this.voices.values()].find((voice) => !voice.loop);
267
+ if (!oldestEffect)
268
+ return;
269
+ this.stop(oldestEffect.id, 0);
270
+ }
271
+ const source = this.context.createBufferSource();
272
+ const gain = this.context.createGain();
273
+ source.buffer = buffer;
274
+ source.loop = loop;
275
+ const output = this.spatialOutput(emitter, bus, source.playbackRate);
276
+ source.connect(gain).connect(output.node);
277
+ const now = this.context.currentTime;
278
+ gain.gain.setValueAtTime(fadeInTicks > 0 ? 0 : volume, now);
279
+ if (fadeInTicks > 0)
280
+ gain.gain.linearRampToValueAtTime(volume, now + fadeInTicks / this.options.tickRate);
281
+ const voice = { id, source, gain, loop, fadeOutTicks, bus };
282
+ this.voices.set(id, voice);
283
+ this.voiceAssets.set(voice, assetId);
284
+ this.mixer.voiceStarted(bus);
285
+ let ended = false;
286
+ source.onended = () => {
287
+ if (!ended) {
288
+ ended = true;
289
+ this.mixer.voiceEnded(bus);
290
+ }
291
+ if (this.voices.get(id) === voice)
292
+ this.voices.delete(id);
293
+ this.fading.delete(voice);
294
+ source.disconnect();
295
+ gain.disconnect();
296
+ output.release();
297
+ };
298
+ const offset = logicalStartTick === undefined ? 0 : Math.max(0, this.tick - logicalStartTick) / this.options.tickRate;
299
+ source.start(0, loop && buffer.duration > 0 ? offset % buffer.duration : 0);
300
+ }
301
+ stop(id, fadeTicks) {
302
+ this.pending.delete(id);
303
+ const voice = this.voices.get(id);
304
+ if (!voice)
305
+ return;
306
+ this.voices.delete(id);
307
+ stopGameVoice(voice, this.context, fadeTicks, this.options.tickRate, this.fading);
308
+ }
309
+ reset(snapshot) {
310
+ this.generation += 1;
311
+ this.pending.clear();
312
+ for (const id of this.voices.keys())
313
+ this.stop(id, 0);
314
+ for (const voice of this.fading)
315
+ voice.source.stop();
316
+ this.fading.clear();
317
+ this.desiredMusic = null;
318
+ this.mixer.reset(snapshot.sceneId);
319
+ this.sync(snapshot);
320
+ }
321
+ dispose() {
322
+ if (this.disposed)
323
+ return;
324
+ this.disposed = true;
325
+ this.generation += 1;
326
+ this.pending.clear();
327
+ for (const id of this.voices.keys())
328
+ this.stop(id, 0);
329
+ for (const voice of this.fading)
330
+ voice.source.stop();
331
+ this.fading.clear();
332
+ this.buffers.clear();
333
+ this.mixer.dispose();
334
+ void this.context.close();
335
+ }
336
+ }
337
+ //# sourceMappingURL=player.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"player.js","sourceRoot":"","sources":["../../src/audio/player.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { GameAudioEmitter, GameRenderFrame, GameRenderFrame3D } from "@nodetool-ai/protocol";
2
+ export interface GameAudioVector {
3
+ readonly x: number;
4
+ readonly y: number;
5
+ readonly z: number;
6
+ }
7
+ /** A listener or emitter position. `forward` orients a directional emitter and the listener. */
8
+ export interface GameAudioPose {
9
+ readonly position: GameAudioVector;
10
+ readonly forward?: GameAudioVector;
11
+ readonly up?: GameAudioVector;
12
+ }
13
+ /** Where the listener and emitters are on one rendered frame. Emitter poses are looked up by entity id. */
14
+ export interface GameAudioSpatialView {
15
+ readonly listener: Required<GameAudioPose>;
16
+ emitter(entityId: string): GameAudioPose | undefined;
17
+ }
18
+ /** `high` uses HRTF panning. `low` uses equal-power panning, which costs far less CPU per voice. */
19
+ export type GameAudioSpatialQuality = "high" | "low";
20
+ /** Builds a view from a 3D frame at the renderer's interpolation `alpha`. The listener is the active camera. */
21
+ export declare function gameAudioSpatialView3D(frame: GameRenderFrame3D, alpha: number): GameAudioSpatialView;
22
+ /**
23
+ * Builds a view from a 2D frame. The listener sits at the camera on the z = 0 plane, facing -z with +y up,
24
+ * so +x is to the right. Spatial sources carry their simulation positions and have no facing.
25
+ */
26
+ export declare function gameAudioSpatialView2D(frame: GameRenderFrame, alpha: number): GameAudioSpatialView;
27
+ /** Creates the panner for one spatial voice at the emitter's position when it played. */
28
+ export declare function createGameAudioPanner(context: BaseAudioContext, emitter: GameAudioEmitter, quality: GameAudioSpatialQuality, time: number): PannerNode;
29
+ /**
30
+ * Moves a panner to an emitter pose. The cone applies only once the pose has a facing, so 2D emitters stay omnidirectional.
31
+ * `smooth` glides to the new values for per-frame updates.
32
+ */
33
+ export declare function placeGameAudioPanner(panner: PannerNode, emitter: GameAudioEmitter, pose: GameAudioPose, time: number, smooth: boolean): void;
34
+ /** Moves the context's listener. Falls back to the legacy setters where a browser lacks listener AudioParams. */
35
+ export declare function placeGameAudioListener(listener: AudioListener, pose: Required<GameAudioPose>, time: number, smooth: boolean): void;
36
+ /** A position at a context time, for velocity estimates. */
37
+ export interface GameAudioSample {
38
+ readonly position: GameAudioVector;
39
+ readonly time: number;
40
+ }
41
+ /** Velocity between two samples, or null when the gap is empty or too long to be motion. */
42
+ export declare function gameAudioVelocity(previous: GameAudioSample | undefined, current: GameAudioSample): GameAudioVector | null;
43
+ /**
44
+ * Playback rate for the doppler shift heard by a listener from an emitter. `factor` scales both velocities: 0 is no shift, 1 is physical.
45
+ * An approaching emitter or listener raises the pitch.
46
+ */
47
+ export declare function gameAudioDopplerRate(listener: GameAudioVector, listenerVelocity: GameAudioVector, emitter: GameAudioVector, emitterVelocity: GameAudioVector, factor: number): number;
48
+ /** Glides a source's playback rate to the doppler rate. */
49
+ export declare function setGameAudioDopplerRate(param: AudioParam, rate: number, time: number): void;
50
+ //# sourceMappingURL=spatial.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spatial.d.ts","sourceRoot":"","sources":["../../src/audio/spatial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,iBAAiB,EAAmB,MAAM,uBAAuB,CAAC;AAEnH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,gGAAgG;AAChG,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,EAAE,eAAe,CAAC;CAC/B;AAED,2GAA2G;AAC3G,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC3C,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAC;CACtD;AAED,oGAAoG;AACpG,MAAM,MAAM,uBAAuB,GAAG,MAAM,GAAG,KAAK,CAAC;AA4CrD,gHAAgH;AAChH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,GAAG,oBAAoB,CAWpG;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,oBAAoB,CAuBlG;AAOD,yFAAyF;AACzF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,uBAAuB,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CAStJ;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAY5I;AAED,iHAAiH;AACjH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAelI;AAED,4DAA4D;AAC5D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,4FAA4F;AAC5F,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,GAAG,SAAS,EAAE,OAAO,EAAE,eAAe,GAAG,eAAe,GAAG,IAAI,CAMzH;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,eAAe,EAAE,gBAAgB,EAAE,eAAe,EAAE,OAAO,EAAE,eAAe,EACzH,eAAe,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAU1D;AAED,2DAA2D;AAC3D,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAE3F"}
@@ -0,0 +1,166 @@
1
+ /** Speed of sound in world units per second, with one world unit as one metre. */
2
+ const SPEED_OF_SOUND = 343;
3
+ /** Doppler pitch stays within one octave of the original. */
4
+ const MIN_DOPPLER_RATE = 0.5;
5
+ const MAX_DOPPLER_RATE = 2;
6
+ /** Time constant for per-frame position and pitch changes, so 60 Hz updates do not click. */
7
+ const SMOOTHING_SECONDS = 0.02;
8
+ /** Frame gaps longer than this, such as a paused tab, do not count as motion for doppler. */
9
+ const MAX_DOPPLER_GAP_SECONDS = 0.25;
10
+ const FORWARD = { x: 0, y: 0, z: -1 };
11
+ const UP = { x: 0, y: 1, z: 0 };
12
+ function lerp(from, to, alpha) {
13
+ return from + (to - from) * alpha;
14
+ }
15
+ function rotate(rotation, vector) {
16
+ const [qx, qy, qz, qw] = rotation;
17
+ const tx = 2 * (qy * vector.z - qz * vector.y);
18
+ const ty = 2 * (qz * vector.x - qx * vector.z);
19
+ const tz = 2 * (qx * vector.y - qy * vector.x);
20
+ return { x: vector.x + qw * tx + (qy * tz - qz * ty), y: vector.y + qw * ty + (qz * tx - qx * tz), z: vector.z + qw * tz + (qx * ty - qy * tx) };
21
+ }
22
+ /** Normalised linear interpolation. Close enough to slerp for one tick of rotation. */
23
+ function interpolateRotation(previous, current, alpha) {
24
+ const sign = previous[0] * current[0] + previous[1] * current[1] + previous[2] * current[2] + previous[3] * current[3] < 0 ? -1 : 1;
25
+ const mixed = [0, 1, 2, 3].map((index) => lerp(previous[index], current[index] * sign, alpha));
26
+ const length = Math.hypot(...mixed) || 1;
27
+ return [mixed[0] / length, mixed[1] / length, mixed[2] / length, mixed[3] / length];
28
+ }
29
+ function pose3D(previous, current, alpha) {
30
+ const rotation = interpolateRotation(previous.rotation, current.rotation, alpha);
31
+ return {
32
+ position: { x: lerp(previous.position.x, current.position.x, alpha), y: lerp(previous.position.y, current.position.y, alpha),
33
+ z: lerp(previous.position.z, current.position.z, alpha) },
34
+ forward: rotate(rotation, FORWARD), up: rotate(rotation, UP)
35
+ };
36
+ }
37
+ /** Builds a view from a 3D frame at the renderer's interpolation `alpha`. The listener is the active camera. */
38
+ export function gameAudioSpatialView3D(frame, alpha) {
39
+ const amount = Math.max(0, Math.min(1, alpha));
40
+ let entities;
41
+ return {
42
+ listener: pose3D(frame.camera.previousTransform ?? frame.camera.transform, frame.camera.transform, amount),
43
+ emitter(entityId) {
44
+ entities ??= new Map(frame.entities.map((entity) => [entity.entityId, entity]));
45
+ const entity = entities.get(entityId);
46
+ return entity ? pose3D(entity.previousTransform, entity.transform, amount) : undefined;
47
+ }
48
+ };
49
+ }
50
+ /**
51
+ * Builds a view from a 2D frame. The listener sits at the camera on the z = 0 plane, facing -z with +y up,
52
+ * so +x is to the right. Spatial sources carry their simulation positions and have no facing.
53
+ */
54
+ export function gameAudioSpatialView2D(frame, alpha) {
55
+ const amount = Math.max(0, Math.min(1, alpha));
56
+ let positions;
57
+ return {
58
+ listener: {
59
+ position: { x: lerp(frame.camera.previousX ?? frame.camera.x, frame.camera.x, amount), y: lerp(frame.camera.previousY ?? frame.camera.y, frame.camera.y, amount), z: 0 },
60
+ forward: FORWARD, up: UP
61
+ },
62
+ emitter(entityId) {
63
+ if (!positions) {
64
+ positions = new Map();
65
+ for (const particles of frame.particles ?? []) {
66
+ positions.set(particles.entityId, { x: particles.x, y: particles.y, z: 0 });
67
+ }
68
+ for (const sprite of frame.sprites) {
69
+ positions.set(sprite.entityId, { x: lerp(sprite.previousX, sprite.x, amount), y: lerp(sprite.previousY, sprite.y, amount), z: 0 });
70
+ }
71
+ for (const emitter of frame.audioEmitters ?? []) {
72
+ positions.set(emitter.entityId, { x: lerp(emitter.previousX, emitter.x, amount), y: lerp(emitter.previousY, emitter.y, amount), z: 0 });
73
+ }
74
+ }
75
+ const position = positions.get(entityId);
76
+ return position ? { position } : undefined;
77
+ }
78
+ };
79
+ }
80
+ function setParam(param, value, time, smooth) {
81
+ if (smooth) {
82
+ param.setTargetAtTime(value, time, SMOOTHING_SECONDS);
83
+ }
84
+ else {
85
+ param.setValueAtTime(value, time);
86
+ }
87
+ }
88
+ /** Creates the panner for one spatial voice at the emitter's position when it played. */
89
+ export function createGameAudioPanner(context, emitter, quality, time) {
90
+ const panner = context.createPanner();
91
+ panner.panningModel = quality === "high" ? "HRTF" : "equalpower";
92
+ panner.distanceModel = emitter.distanceModel;
93
+ panner.refDistance = emitter.minDistance;
94
+ panner.maxDistance = emitter.maxDistance;
95
+ panner.rolloffFactor = emitter.distanceModel === "linear" ? Math.min(1, emitter.rolloff) : emitter.rolloff;
96
+ placeGameAudioPanner(panner, emitter, { position: emitter.position }, time, false);
97
+ return panner;
98
+ }
99
+ /**
100
+ * Moves a panner to an emitter pose. The cone applies only once the pose has a facing, so 2D emitters stay omnidirectional.
101
+ * `smooth` glides to the new values for per-frame updates.
102
+ */
103
+ export function placeGameAudioPanner(panner, emitter, pose, time, smooth) {
104
+ setParam(panner.positionX, pose.position.x, time, smooth);
105
+ setParam(panner.positionY, pose.position.y, time, smooth);
106
+ setParam(panner.positionZ, pose.position.z, time, smooth);
107
+ if (emitter.cone && pose.forward) {
108
+ panner.coneInnerAngle = emitter.cone.innerAngle;
109
+ panner.coneOuterAngle = emitter.cone.outerAngle;
110
+ panner.coneOuterGain = emitter.cone.outerGain;
111
+ setParam(panner.orientationX, pose.forward.x, time, smooth);
112
+ setParam(panner.orientationY, pose.forward.y, time, smooth);
113
+ setParam(panner.orientationZ, pose.forward.z, time, smooth);
114
+ }
115
+ }
116
+ /** Moves the context's listener. Falls back to the legacy setters where a browser lacks listener AudioParams. */
117
+ export function placeGameAudioListener(listener, pose, time, smooth) {
118
+ if (!listener.positionX) {
119
+ listener.setPosition(pose.position.x, pose.position.y, pose.position.z);
120
+ listener.setOrientation(pose.forward.x, pose.forward.y, pose.forward.z, pose.up.x, pose.up.y, pose.up.z);
121
+ return;
122
+ }
123
+ setParam(listener.positionX, pose.position.x, time, smooth);
124
+ setParam(listener.positionY, pose.position.y, time, smooth);
125
+ setParam(listener.positionZ, pose.position.z, time, smooth);
126
+ setParam(listener.forwardX, pose.forward.x, time, smooth);
127
+ setParam(listener.forwardY, pose.forward.y, time, smooth);
128
+ setParam(listener.forwardZ, pose.forward.z, time, smooth);
129
+ setParam(listener.upX, pose.up.x, time, smooth);
130
+ setParam(listener.upY, pose.up.y, time, smooth);
131
+ setParam(listener.upZ, pose.up.z, time, smooth);
132
+ }
133
+ /** Velocity between two samples, or null when the gap is empty or too long to be motion. */
134
+ export function gameAudioVelocity(previous, current) {
135
+ if (!previous) {
136
+ return null;
137
+ }
138
+ const seconds = current.time - previous.time;
139
+ if (seconds <= 0 || seconds > MAX_DOPPLER_GAP_SECONDS) {
140
+ return null;
141
+ }
142
+ return { x: (current.position.x - previous.position.x) / seconds, y: (current.position.y - previous.position.y) / seconds,
143
+ z: (current.position.z - previous.position.z) / seconds };
144
+ }
145
+ /**
146
+ * Playback rate for the doppler shift heard by a listener from an emitter. `factor` scales both velocities: 0 is no shift, 1 is physical.
147
+ * An approaching emitter or listener raises the pitch.
148
+ */
149
+ export function gameAudioDopplerRate(listener, listenerVelocity, emitter, emitterVelocity, factor) {
150
+ const dx = emitter.x - listener.x;
151
+ const dy = emitter.y - listener.y;
152
+ const dz = emitter.z - listener.z;
153
+ const distance = Math.hypot(dx, dy, dz);
154
+ if (factor <= 0 || distance === 0) {
155
+ return 1;
156
+ }
157
+ const listenerToward = factor * (listenerVelocity.x * dx + listenerVelocity.y * dy + listenerVelocity.z * dz) / distance;
158
+ const emitterAway = factor * (emitterVelocity.x * dx + emitterVelocity.y * dy + emitterVelocity.z * dz) / distance;
159
+ const rate = (SPEED_OF_SOUND + listenerToward) / Math.max(1, SPEED_OF_SOUND + emitterAway);
160
+ return Math.min(MAX_DOPPLER_RATE, Math.max(MIN_DOPPLER_RATE, rate));
161
+ }
162
+ /** Glides a source's playback rate to the doppler rate. */
163
+ export function setGameAudioDopplerRate(param, rate, time) {
164
+ param.setTargetAtTime(rate, time, SMOOTHING_SECONDS * 2.5);
165
+ }
166
+ //# sourceMappingURL=spatial.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spatial.js","sourceRoot":"","sources":["../../src/audio/spatial.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface Voice {
2
+ readonly id: string;
3
+ readonly source: AudioBufferSourceNode;
4
+ readonly gain: GainNode;
5
+ readonly loop: boolean;
6
+ readonly fadeOutTicks: number;
7
+ readonly bus: string;
8
+ }
9
+ export declare function playBuiltinGameVoice(context: BaseAudioContext, volume: number, destination: AudioNode, onEnded: () => void): void;
10
+ export declare function stopGameVoice(voice: Voice, context: AudioContext, fadeTicks: number, tickRate: number, fading: Set<Voice>): void;
11
+ //# sourceMappingURL=voices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voices.d.ts","sourceRoot":"","sources":["../../src/audio/voices.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAUjI;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAShI"}
@@ -0,0 +1,22 @@
1
+ export function playBuiltinGameVoice(context, volume, destination, onEnded) {
2
+ const oscillator = context.createOscillator();
3
+ const gain = context.createGain();
4
+ oscillator.frequency.value = 660;
5
+ gain.gain.setValueAtTime(volume * 0.08, context.currentTime);
6
+ gain.gain.exponentialRampToValueAtTime(0.001, context.currentTime + 0.12);
7
+ oscillator.connect(gain).connect(destination);
8
+ oscillator.onended = () => { oscillator.disconnect(); gain.disconnect(); onEnded(); };
9
+ oscillator.start();
10
+ oscillator.stop(context.currentTime + 0.12);
11
+ }
12
+ export function stopGameVoice(voice, context, fadeTicks, tickRate, fading) {
13
+ const now = context.currentTime;
14
+ voice.gain.gain.cancelScheduledValues(now);
15
+ if (fadeTicks > 0) {
16
+ fading.add(voice);
17
+ voice.gain.gain.setValueAtTime(voice.gain.gain.value, now);
18
+ voice.gain.gain.linearRampToValueAtTime(0, now + fadeTicks / tickRate);
19
+ }
20
+ voice.source.stop(now + fadeTicks / tickRate);
21
+ }
22
+ //# sourceMappingURL=voices.js.map