@onerjs/core 8.32.0 → 8.32.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 (315) hide show
  1. package/Audio/Interfaces/ISoundOptions.d.ts +1 -1
  2. package/Audio/Interfaces/ISoundOptions.js.map +1 -1
  3. package/Audio/audioEngine.d.ts +3 -4
  4. package/Audio/audioEngine.js +9 -6
  5. package/Audio/audioEngine.js.map +1 -1
  6. package/Audio/sound.d.ts +33 -54
  7. package/Audio/sound.js +450 -718
  8. package/Audio/sound.js.map +1 -1
  9. package/AudioV2/abstractAudio/abstractAudioOutNode.d.ts +1 -1
  10. package/AudioV2/abstractAudio/abstractAudioOutNode.js +1 -1
  11. package/AudioV2/abstractAudio/abstractAudioOutNode.js.map +1 -1
  12. package/AudioV2/abstractAudio/abstractSound.d.ts +1 -1
  13. package/AudioV2/abstractAudio/abstractSound.js +2 -2
  14. package/AudioV2/abstractAudio/abstractSound.js.map +1 -1
  15. package/AudioV2/abstractAudio/abstractSoundSource.d.ts +11 -3
  16. package/AudioV2/abstractAudio/abstractSoundSource.js +37 -1
  17. package/AudioV2/abstractAudio/abstractSoundSource.js.map +1 -1
  18. package/AudioV2/abstractAudio/audioBus.d.ts +8 -3
  19. package/AudioV2/abstractAudio/audioBus.js +24 -1
  20. package/AudioV2/abstractAudio/audioBus.js.map +1 -1
  21. package/AudioV2/abstractAudio/staticSound.d.ts +1 -1
  22. package/AudioV2/abstractAudio/staticSound.js +2 -2
  23. package/AudioV2/abstractAudio/staticSound.js.map +1 -1
  24. package/AudioV2/abstractAudio/streamingSound.d.ts +1 -1
  25. package/AudioV2/abstractAudio/streamingSound.js +2 -2
  26. package/AudioV2/abstractAudio/streamingSound.js.map +1 -1
  27. package/AudioV2/abstractAudio/subNodes/abstractAudioSubGraph.d.ts +1 -1
  28. package/AudioV2/abstractAudio/subNodes/abstractAudioSubGraph.js +3 -0
  29. package/AudioV2/abstractAudio/subNodes/abstractAudioSubGraph.js.map +1 -1
  30. package/AudioV2/abstractAudio/subNodes/spatialAudioSubNode.d.ts +1 -0
  31. package/AudioV2/abstractAudio/subNodes/spatialAudioSubNode.js +1 -0
  32. package/AudioV2/abstractAudio/subNodes/spatialAudioSubNode.js.map +1 -1
  33. package/AudioV2/abstractAudio/subProperties/abstractSpatialAudio.d.ts +12 -2
  34. package/AudioV2/abstractAudio/subProperties/abstractSpatialAudio.js +2 -0
  35. package/AudioV2/abstractAudio/subProperties/abstractSpatialAudio.js.map +1 -1
  36. package/AudioV2/abstractAudio/subProperties/spatialAudio.d.ts +6 -0
  37. package/AudioV2/abstractAudio/subProperties/spatialAudio.js +25 -0
  38. package/AudioV2/abstractAudio/subProperties/spatialAudio.js.map +1 -1
  39. package/AudioV2/webAudio/components/webAudioParameterComponent.js +2 -2
  40. package/AudioV2/webAudio/components/webAudioParameterComponent.js.map +1 -1
  41. package/AudioV2/webAudio/subNodes/spatialWebAudioSubNode.d.ts +3 -0
  42. package/AudioV2/webAudio/subNodes/spatialWebAudioSubNode.js +14 -17
  43. package/AudioV2/webAudio/subNodes/spatialWebAudioSubNode.js.map +1 -1
  44. package/AudioV2/webAudio/subNodes/webAudioBusAndSoundSubGraph.js +1 -0
  45. package/AudioV2/webAudio/subNodes/webAudioBusAndSoundSubGraph.js.map +1 -1
  46. package/AudioV2/webAudio/subProperties/spatialWebAudio.js +1 -0
  47. package/AudioV2/webAudio/subProperties/spatialWebAudio.js.map +1 -1
  48. package/AudioV2/webAudio/webAudioBus.d.ts +2 -7
  49. package/AudioV2/webAudio/webAudioBus.js +4 -24
  50. package/AudioV2/webAudio/webAudioBus.js.map +1 -1
  51. package/AudioV2/webAudio/webAudioEngine.js +1 -0
  52. package/AudioV2/webAudio/webAudioEngine.js.map +1 -1
  53. package/AudioV2/webAudio/webAudioSoundSource.d.ts +2 -7
  54. package/AudioV2/webAudio/webAudioSoundSource.js +3 -24
  55. package/AudioV2/webAudio/webAudioSoundSource.js.map +1 -1
  56. package/AudioV2/webAudio/webAudioStaticSound.d.ts +3 -7
  57. package/AudioV2/webAudio/webAudioStaticSound.js +13 -26
  58. package/AudioV2/webAudio/webAudioStaticSound.js.map +1 -1
  59. package/AudioV2/webAudio/webAudioStreamingSound.d.ts +3 -7
  60. package/AudioV2/webAudio/webAudioStreamingSound.js +6 -23
  61. package/AudioV2/webAudio/webAudioStreamingSound.js.map +1 -1
  62. package/Cameras/arcRotateCamera.js +4 -5
  63. package/Cameras/arcRotateCamera.js.map +1 -1
  64. package/Compute/computeEffect.js +5 -1
  65. package/Compute/computeEffect.js.map +1 -1
  66. package/Compute/computeShader.d.ts +4 -0
  67. package/Compute/computeShader.js +9 -3
  68. package/Compute/computeShader.js.map +1 -1
  69. package/Debug/debugLayer.d.ts +1 -1
  70. package/Debug/debugLayer.js.map +1 -1
  71. package/Engines/abstractEngine.d.ts +2 -2
  72. package/Engines/abstractEngine.js +2 -2
  73. package/Engines/abstractEngine.js.map +1 -1
  74. package/Engines/thinEngine.js +1 -1
  75. package/Engines/thinEngine.js.map +1 -1
  76. package/Engines/webgpuEngine.js +8 -9
  77. package/Engines/webgpuEngine.js.map +1 -1
  78. package/FrameGraph/Node/Blocks/PostProcesses/volumetricLightingBlock.d.ts +74 -0
  79. package/FrameGraph/Node/Blocks/PostProcesses/volumetricLightingBlock.js +179 -0
  80. package/FrameGraph/Node/Blocks/PostProcesses/volumetricLightingBlock.js.map +1 -0
  81. package/FrameGraph/Node/Blocks/index.d.ts +2 -0
  82. package/FrameGraph/Node/Blocks/index.js +2 -0
  83. package/FrameGraph/Node/Blocks/index.js.map +1 -1
  84. package/FrameGraph/Node/Blocks/lightingVolumeBlock.d.ts +43 -0
  85. package/FrameGraph/Node/Blocks/lightingVolumeBlock.js +93 -0
  86. package/FrameGraph/Node/Blocks/lightingVolumeBlock.js.map +1 -0
  87. package/FrameGraph/Passes/renderPass.js +2 -2
  88. package/FrameGraph/Passes/renderPass.js.map +1 -1
  89. package/FrameGraph/Tasks/Layers/baseLayerTask.d.ts +2 -0
  90. package/FrameGraph/Tasks/Layers/baseLayerTask.js +6 -0
  91. package/FrameGraph/Tasks/Layers/baseLayerTask.js.map +1 -1
  92. package/FrameGraph/Tasks/Layers/glowLayerTask.d.ts +1 -0
  93. package/FrameGraph/Tasks/Layers/glowLayerTask.js +3 -0
  94. package/FrameGraph/Tasks/Layers/glowLayerTask.js.map +1 -1
  95. package/FrameGraph/Tasks/Layers/highlightLayerTask.d.ts +1 -0
  96. package/FrameGraph/Tasks/Layers/highlightLayerTask.js +3 -0
  97. package/FrameGraph/Tasks/Layers/highlightLayerTask.js.map +1 -1
  98. package/FrameGraph/Tasks/Misc/computeShaderTask.d.ts +1 -0
  99. package/FrameGraph/Tasks/Misc/computeShaderTask.js +3 -0
  100. package/FrameGraph/Tasks/Misc/computeShaderTask.js.map +1 -1
  101. package/FrameGraph/Tasks/Misc/cullObjectsTask.d.ts +1 -0
  102. package/FrameGraph/Tasks/Misc/cullObjectsTask.js +3 -0
  103. package/FrameGraph/Tasks/Misc/cullObjectsTask.js.map +1 -1
  104. package/FrameGraph/Tasks/Misc/executeTask.d.ts +1 -0
  105. package/FrameGraph/Tasks/Misc/executeTask.js +3 -0
  106. package/FrameGraph/Tasks/Misc/executeTask.js.map +1 -1
  107. package/FrameGraph/Tasks/Misc/lightingVolumeTask.d.ts +32 -0
  108. package/FrameGraph/Tasks/Misc/lightingVolumeTask.js +63 -0
  109. package/FrameGraph/Tasks/Misc/lightingVolumeTask.js.map +1 -0
  110. package/FrameGraph/Tasks/PostProcesses/anaglyphTask.d.ts +1 -0
  111. package/FrameGraph/Tasks/PostProcesses/anaglyphTask.js +3 -0
  112. package/FrameGraph/Tasks/PostProcesses/anaglyphTask.js.map +1 -1
  113. package/FrameGraph/Tasks/PostProcesses/blackAndWhiteTask.d.ts +1 -0
  114. package/FrameGraph/Tasks/PostProcesses/blackAndWhiteTask.js +3 -0
  115. package/FrameGraph/Tasks/PostProcesses/blackAndWhiteTask.js.map +1 -1
  116. package/FrameGraph/Tasks/PostProcesses/bloomMergeTask.d.ts +1 -0
  117. package/FrameGraph/Tasks/PostProcesses/bloomMergeTask.js +3 -0
  118. package/FrameGraph/Tasks/PostProcesses/bloomMergeTask.js.map +1 -1
  119. package/FrameGraph/Tasks/PostProcesses/bloomTask.d.ts +1 -0
  120. package/FrameGraph/Tasks/PostProcesses/bloomTask.js +3 -0
  121. package/FrameGraph/Tasks/PostProcesses/bloomTask.js.map +1 -1
  122. package/FrameGraph/Tasks/PostProcesses/blurTask.d.ts +1 -0
  123. package/FrameGraph/Tasks/PostProcesses/blurTask.js +3 -0
  124. package/FrameGraph/Tasks/PostProcesses/blurTask.js.map +1 -1
  125. package/FrameGraph/Tasks/PostProcesses/chromaticAberrationTask.d.ts +1 -0
  126. package/FrameGraph/Tasks/PostProcesses/chromaticAberrationTask.js +3 -0
  127. package/FrameGraph/Tasks/PostProcesses/chromaticAberrationTask.js.map +1 -1
  128. package/FrameGraph/Tasks/PostProcesses/circleOfConfusionTask.d.ts +1 -0
  129. package/FrameGraph/Tasks/PostProcesses/circleOfConfusionTask.js +3 -0
  130. package/FrameGraph/Tasks/PostProcesses/circleOfConfusionTask.js.map +1 -1
  131. package/FrameGraph/Tasks/PostProcesses/colorCorrectionTask.d.ts +1 -0
  132. package/FrameGraph/Tasks/PostProcesses/colorCorrectionTask.js +3 -0
  133. package/FrameGraph/Tasks/PostProcesses/colorCorrectionTask.js.map +1 -1
  134. package/FrameGraph/Tasks/PostProcesses/convolutionTask.d.ts +1 -0
  135. package/FrameGraph/Tasks/PostProcesses/convolutionTask.js +3 -0
  136. package/FrameGraph/Tasks/PostProcesses/convolutionTask.js.map +1 -1
  137. package/FrameGraph/Tasks/PostProcesses/customPostProcessTask.d.ts +1 -0
  138. package/FrameGraph/Tasks/PostProcesses/customPostProcessTask.js +3 -0
  139. package/FrameGraph/Tasks/PostProcesses/customPostProcessTask.js.map +1 -1
  140. package/FrameGraph/Tasks/PostProcesses/depthOfFieldBlurTask.d.ts +1 -0
  141. package/FrameGraph/Tasks/PostProcesses/depthOfFieldBlurTask.js +3 -0
  142. package/FrameGraph/Tasks/PostProcesses/depthOfFieldBlurTask.js.map +1 -1
  143. package/FrameGraph/Tasks/PostProcesses/depthOfFieldMergeTask.d.ts +1 -0
  144. package/FrameGraph/Tasks/PostProcesses/depthOfFieldMergeTask.js +3 -0
  145. package/FrameGraph/Tasks/PostProcesses/depthOfFieldMergeTask.js.map +1 -1
  146. package/FrameGraph/Tasks/PostProcesses/depthOfFieldTask.d.ts +1 -0
  147. package/FrameGraph/Tasks/PostProcesses/depthOfFieldTask.js +3 -0
  148. package/FrameGraph/Tasks/PostProcesses/depthOfFieldTask.js.map +1 -1
  149. package/FrameGraph/Tasks/PostProcesses/extractHighlightsTask.d.ts +1 -0
  150. package/FrameGraph/Tasks/PostProcesses/extractHighlightsTask.js +3 -0
  151. package/FrameGraph/Tasks/PostProcesses/extractHighlightsTask.js.map +1 -1
  152. package/FrameGraph/Tasks/PostProcesses/filterTask.d.ts +1 -0
  153. package/FrameGraph/Tasks/PostProcesses/filterTask.js +3 -0
  154. package/FrameGraph/Tasks/PostProcesses/filterTask.js.map +1 -1
  155. package/FrameGraph/Tasks/PostProcesses/fxaaTask.d.ts +1 -0
  156. package/FrameGraph/Tasks/PostProcesses/fxaaTask.js +3 -0
  157. package/FrameGraph/Tasks/PostProcesses/fxaaTask.js.map +1 -1
  158. package/FrameGraph/Tasks/PostProcesses/grainTask.d.ts +1 -0
  159. package/FrameGraph/Tasks/PostProcesses/grainTask.js +3 -0
  160. package/FrameGraph/Tasks/PostProcesses/grainTask.js.map +1 -1
  161. package/FrameGraph/Tasks/PostProcesses/imageProcessingTask.d.ts +1 -0
  162. package/FrameGraph/Tasks/PostProcesses/imageProcessingTask.js +3 -0
  163. package/FrameGraph/Tasks/PostProcesses/imageProcessingTask.js.map +1 -1
  164. package/FrameGraph/Tasks/PostProcesses/motionBlurTask.d.ts +1 -0
  165. package/FrameGraph/Tasks/PostProcesses/motionBlurTask.js +3 -0
  166. package/FrameGraph/Tasks/PostProcesses/motionBlurTask.js.map +1 -1
  167. package/FrameGraph/Tasks/PostProcesses/passTask.d.ts +2 -0
  168. package/FrameGraph/Tasks/PostProcesses/passTask.js +6 -0
  169. package/FrameGraph/Tasks/PostProcesses/passTask.js.map +1 -1
  170. package/FrameGraph/Tasks/PostProcesses/postProcessTask.d.ts +3 -2
  171. package/FrameGraph/Tasks/PostProcesses/postProcessTask.js +3 -0
  172. package/FrameGraph/Tasks/PostProcesses/postProcessTask.js.map +1 -1
  173. package/FrameGraph/Tasks/PostProcesses/screenSpaceCurvatureTask.d.ts +1 -0
  174. package/FrameGraph/Tasks/PostProcesses/screenSpaceCurvatureTask.js +3 -0
  175. package/FrameGraph/Tasks/PostProcesses/screenSpaceCurvatureTask.js.map +1 -1
  176. package/FrameGraph/Tasks/PostProcesses/sharpenTask.d.ts +1 -0
  177. package/FrameGraph/Tasks/PostProcesses/sharpenTask.js +3 -0
  178. package/FrameGraph/Tasks/PostProcesses/sharpenTask.js.map +1 -1
  179. package/FrameGraph/Tasks/PostProcesses/ssao2BlurTask.d.ts +1 -0
  180. package/FrameGraph/Tasks/PostProcesses/ssao2BlurTask.js +3 -0
  181. package/FrameGraph/Tasks/PostProcesses/ssao2BlurTask.js.map +1 -1
  182. package/FrameGraph/Tasks/PostProcesses/ssao2RenderingPipelineTask.d.ts +1 -0
  183. package/FrameGraph/Tasks/PostProcesses/ssao2RenderingPipelineTask.js +3 -0
  184. package/FrameGraph/Tasks/PostProcesses/ssao2RenderingPipelineTask.js.map +1 -1
  185. package/FrameGraph/Tasks/PostProcesses/ssao2Task.d.ts +1 -0
  186. package/FrameGraph/Tasks/PostProcesses/ssao2Task.js +3 -0
  187. package/FrameGraph/Tasks/PostProcesses/ssao2Task.js.map +1 -1
  188. package/FrameGraph/Tasks/PostProcesses/ssrBlurTask.d.ts +1 -0
  189. package/FrameGraph/Tasks/PostProcesses/ssrBlurTask.js +3 -0
  190. package/FrameGraph/Tasks/PostProcesses/ssrBlurTask.js.map +1 -1
  191. package/FrameGraph/Tasks/PostProcesses/ssrRenderingPipelineTask.d.ts +1 -0
  192. package/FrameGraph/Tasks/PostProcesses/ssrRenderingPipelineTask.js +3 -0
  193. package/FrameGraph/Tasks/PostProcesses/ssrRenderingPipelineTask.js.map +1 -1
  194. package/FrameGraph/Tasks/PostProcesses/ssrTask.d.ts +1 -0
  195. package/FrameGraph/Tasks/PostProcesses/ssrTask.js +3 -0
  196. package/FrameGraph/Tasks/PostProcesses/ssrTask.js.map +1 -1
  197. package/FrameGraph/Tasks/PostProcesses/taaTask.d.ts +1 -0
  198. package/FrameGraph/Tasks/PostProcesses/taaTask.js +3 -0
  199. package/FrameGraph/Tasks/PostProcesses/taaTask.js.map +1 -1
  200. package/FrameGraph/Tasks/PostProcesses/tonemapTask.d.ts +1 -0
  201. package/FrameGraph/Tasks/PostProcesses/tonemapTask.js +3 -0
  202. package/FrameGraph/Tasks/PostProcesses/tonemapTask.js.map +1 -1
  203. package/FrameGraph/Tasks/PostProcesses/volumetricLightingBlendVolumeTask.d.ts +31 -0
  204. package/FrameGraph/Tasks/PostProcesses/volumetricLightingBlendVolumeTask.js +60 -0
  205. package/FrameGraph/Tasks/PostProcesses/volumetricLightingBlendVolumeTask.js.map +1 -0
  206. package/FrameGraph/Tasks/PostProcesses/volumetricLightingTask.d.ts +93 -0
  207. package/FrameGraph/Tasks/PostProcesses/volumetricLightingTask.js +183 -0
  208. package/FrameGraph/Tasks/PostProcesses/volumetricLightingTask.js.map +1 -0
  209. package/FrameGraph/Tasks/Rendering/csmShadowGeneratorTask.d.ts +1 -0
  210. package/FrameGraph/Tasks/Rendering/csmShadowGeneratorTask.js +3 -0
  211. package/FrameGraph/Tasks/Rendering/csmShadowGeneratorTask.js.map +1 -1
  212. package/FrameGraph/Tasks/Rendering/geometryRendererTask.d.ts +1 -0
  213. package/FrameGraph/Tasks/Rendering/geometryRendererTask.js +3 -0
  214. package/FrameGraph/Tasks/Rendering/geometryRendererTask.js.map +1 -1
  215. package/FrameGraph/Tasks/Rendering/objectRendererTask.d.ts +1 -0
  216. package/FrameGraph/Tasks/Rendering/objectRendererTask.js +4 -1
  217. package/FrameGraph/Tasks/Rendering/objectRendererTask.js.map +1 -1
  218. package/FrameGraph/Tasks/Rendering/shadowGeneratorTask.d.ts +1 -0
  219. package/FrameGraph/Tasks/Rendering/shadowGeneratorTask.js +3 -0
  220. package/FrameGraph/Tasks/Rendering/shadowGeneratorTask.js.map +1 -1
  221. package/FrameGraph/Tasks/Rendering/utilityLayerRendererTask.d.ts +1 -0
  222. package/FrameGraph/Tasks/Rendering/utilityLayerRendererTask.js +3 -0
  223. package/FrameGraph/Tasks/Rendering/utilityLayerRendererTask.js.map +1 -1
  224. package/FrameGraph/Tasks/Texture/clearTextureTask.d.ts +1 -0
  225. package/FrameGraph/Tasks/Texture/clearTextureTask.js +4 -1
  226. package/FrameGraph/Tasks/Texture/clearTextureTask.js.map +1 -1
  227. package/FrameGraph/Tasks/Texture/copyToBackbufferColorTask.d.ts +1 -0
  228. package/FrameGraph/Tasks/Texture/copyToBackbufferColorTask.js +3 -0
  229. package/FrameGraph/Tasks/Texture/copyToBackbufferColorTask.js.map +1 -1
  230. package/FrameGraph/Tasks/Texture/copyToTextureTask.d.ts +1 -0
  231. package/FrameGraph/Tasks/Texture/copyToTextureTask.js +21 -4
  232. package/FrameGraph/Tasks/Texture/copyToTextureTask.js.map +1 -1
  233. package/FrameGraph/Tasks/Texture/generateMipMapsTask.d.ts +1 -0
  234. package/FrameGraph/Tasks/Texture/generateMipMapsTask.js +3 -0
  235. package/FrameGraph/Tasks/Texture/generateMipMapsTask.js.map +1 -1
  236. package/FrameGraph/frameGraphRenderContext.d.ts +3 -2
  237. package/FrameGraph/frameGraphRenderContext.js +14 -5
  238. package/FrameGraph/frameGraphRenderContext.js.map +1 -1
  239. package/FrameGraph/frameGraphTask.d.ts +5 -0
  240. package/FrameGraph/frameGraphTask.js +11 -2
  241. package/FrameGraph/frameGraphTask.js.map +1 -1
  242. package/FrameGraph/index.d.ts +2 -0
  243. package/FrameGraph/index.js +2 -0
  244. package/FrameGraph/index.js.map +1 -1
  245. package/Inputs/scene.inputManager.d.ts +8 -0
  246. package/Inputs/scene.inputManager.js +33 -2
  247. package/Inputs/scene.inputManager.js.map +1 -1
  248. package/Lights/lightingVolume.d.ts +12 -6
  249. package/Lights/lightingVolume.js +218 -108
  250. package/Lights/lightingVolume.js.map +1 -1
  251. package/Loading/Plugins/babylonFileLoader.js.map +1 -1
  252. package/Materials/GaussianSplatting/gaussianSplattingMaterial.js +2 -0
  253. package/Materials/GaussianSplatting/gaussianSplattingMaterial.js.map +1 -1
  254. package/Meshes/GaussianSplatting/gaussianSplattingMesh.js +2 -2
  255. package/Meshes/GaussianSplatting/gaussianSplattingMesh.js.map +1 -1
  256. package/Meshes/geometry.d.ts +2 -1
  257. package/Meshes/geometry.js +6 -2
  258. package/Meshes/geometry.js.map +1 -1
  259. package/Meshes/mesh.d.ts +2 -1
  260. package/Meshes/mesh.js +4 -3
  261. package/Meshes/mesh.js.map +1 -1
  262. package/Particles/Node/Blocks/Update/updateFlowMapBlock.d.ts +9 -1
  263. package/Particles/Node/Blocks/Update/updateFlowMapBlock.js +8 -0
  264. package/Particles/Node/Blocks/Update/updateFlowMapBlock.js.map +1 -1
  265. package/Particles/Node/Blocks/Update/updateNoiseBlock.d.ts +39 -0
  266. package/Particles/Node/Blocks/Update/updateNoiseBlock.js +102 -0
  267. package/Particles/Node/Blocks/Update/updateNoiseBlock.js.map +1 -0
  268. package/Particles/Node/Blocks/index.d.ts +1 -0
  269. package/Particles/Node/Blocks/index.js +1 -0
  270. package/Particles/Node/Blocks/index.js.map +1 -1
  271. package/Particles/Node/Blocks/particleSourceTextureBlock.d.ts +9 -5
  272. package/Particles/Node/Blocks/particleSourceTextureBlock.js +31 -13
  273. package/Particles/Node/Blocks/particleSourceTextureBlock.js.map +1 -1
  274. package/Particles/Node/nodeParticleSystemSet.helper.js +39 -21
  275. package/Particles/Node/nodeParticleSystemSet.helper.js.map +1 -1
  276. package/Particles/particle.d.ts +2 -2
  277. package/Particles/particle.js +4 -2
  278. package/Particles/particle.js.map +1 -1
  279. package/Particles/thinParticleSystem.d.ts +1 -1
  280. package/Particles/thinParticleSystem.function.js +2 -2
  281. package/Particles/thinParticleSystem.function.js.map +1 -1
  282. package/Particles/thinParticleSystem.js.map +1 -1
  283. package/Physics/v2/characterController.d.ts +42 -2
  284. package/Physics/v2/characterController.js +140 -46
  285. package/Physics/v2/characterController.js.map +1 -1
  286. package/Shaders/gaussianSplatting.vertex.js +2 -2
  287. package/Shaders/gaussianSplatting.vertex.js.map +1 -1
  288. package/Shaders/volumetricLightingBlendVolume.fragment.d.ts +5 -0
  289. package/Shaders/volumetricLightingBlendVolume.fragment.js +21 -0
  290. package/Shaders/volumetricLightingBlendVolume.fragment.js.map +1 -0
  291. package/Shaders/volumetricLightingRenderVolume.fragment.d.ts +7 -0
  292. package/Shaders/volumetricLightingRenderVolume.fragment.js +25 -0
  293. package/Shaders/volumetricLightingRenderVolume.fragment.js.map +1 -0
  294. package/Shaders/volumetricLightingRenderVolume.vertex.d.ts +9 -0
  295. package/Shaders/volumetricLightingRenderVolume.vertex.js +18 -0
  296. package/Shaders/volumetricLightingRenderVolume.vertex.js.map +1 -0
  297. package/ShadersWGSL/gaussianSplatting.vertex.js +3 -3
  298. package/ShadersWGSL/gaussianSplatting.vertex.js.map +1 -1
  299. package/ShadersWGSL/lightingVolume.compute.js +10 -4
  300. package/ShadersWGSL/lightingVolume.compute.js.map +1 -1
  301. package/ShadersWGSL/volumetricLightingBlendVolume.fragment.d.ts +5 -0
  302. package/ShadersWGSL/volumetricLightingBlendVolume.fragment.js +22 -0
  303. package/ShadersWGSL/volumetricLightingBlendVolume.fragment.js.map +1 -0
  304. package/ShadersWGSL/volumetricLightingRenderVolume.fragment.d.ts +7 -0
  305. package/ShadersWGSL/volumetricLightingRenderVolume.fragment.js +27 -0
  306. package/ShadersWGSL/volumetricLightingRenderVolume.fragment.js.map +1 -0
  307. package/ShadersWGSL/volumetricLightingRenderVolume.vertex.d.ts +7 -0
  308. package/ShadersWGSL/volumetricLightingRenderVolume.vertex.js +17 -0
  309. package/ShadersWGSL/volumetricLightingRenderVolume.vertex.js.map +1 -0
  310. package/States/IStencilState.d.ts +48 -2
  311. package/States/IStencilState.js.map +1 -1
  312. package/States/alphaCullingState.d.ts +1 -0
  313. package/States/alphaCullingState.js +3 -0
  314. package/States/alphaCullingState.js.map +1 -1
  315. package/package.json +1 -1
package/Audio/sound.js CHANGED
@@ -1,73 +1,146 @@
1
- import { Tools } from "../Misc/tools.js";
2
- import { Observable } from "../Misc/observable.js";
1
+ import { _HasSpatialAudioOptions, _SpatialAudioDefaults } from "../AudioV2/abstractAudio/subProperties/abstractSpatialAudio.js";
2
+ import { _WebAudioSoundSource } from "../AudioV2/webAudio/webAudioSoundSource.js";
3
+ import { _WebAudioStaticSound } from "../AudioV2/webAudio/webAudioStaticSound.js";
4
+ import { _WebAudioStreamingSound } from "../AudioV2/webAudio/webAudioStreamingSound.js";
5
+ import { AbstractEngine } from "../Engines/abstractEngine.js";
6
+ import { EngineStore } from "../Engines/engineStore.js";
3
7
  import { Vector3 } from "../Maths/math.vector.js";
4
- import { Logger } from "../Misc/logger.js";
5
8
  import { _WarnImport } from "../Misc/devTools.js";
6
- import { EngineStore } from "../Engines/engineStore.js";
7
- import { RegisterClass } from "../Misc/typeStore.js";
8
- import { AbstractEngine } from "../Engines/abstractEngine.js";
9
+ import { Logger } from "../Misc/logger.js";
10
+ import { Observable } from "../Misc/observable.js";
9
11
  import { _RetryWithInterval } from "../Misc/timingTools.js";
12
+ import { RegisterClass } from "../Misc/typeStore.js";
13
+ const TmpRampOptions = {
14
+ duration: 0,
15
+ shape: "linear" /* AudioParameterRampShape.Linear */,
16
+ };
17
+ const TmpPlayOptions = {
18
+ duration: 0,
19
+ startOffset: 0,
20
+ waitTime: 0,
21
+ };
22
+ const TmpStopOptions = {
23
+ waitTime: 0,
24
+ };
25
+ function D2r(degrees) {
26
+ return (degrees * Math.PI) / 180;
27
+ }
28
+ function R2d(radians) {
29
+ return (radians * 180) / Math.PI;
30
+ }
10
31
  /**
11
32
  * Defines a sound that can be played in the application.
12
33
  * The sound can either be an ambient track or a simple sound played in reaction to a user action.
13
- * @see https://doc.babylonjs.com/features/featuresDeepDive/audio/playingSoundsMusic
34
+ * @see https://doc.babylonjs.com/legacy/audio
14
35
  */
15
36
  export class Sound {
37
+ /**
38
+ * The name of the sound in the scene.
39
+ */
40
+ get name() {
41
+ return this._soundV2.name;
42
+ }
43
+ set name(value) {
44
+ this._soundV2.name = value;
45
+ }
46
+ /**
47
+ * Does the sound autoplay once loaded.
48
+ */
49
+ get autoplay() {
50
+ return this._soundV2 instanceof _WebAudioSoundSource ? true : this._optionsV2.autoplay;
51
+ }
52
+ set autoplay(value) {
53
+ this._optionsV2.autoplay = value;
54
+ }
16
55
  /**
17
56
  * Does the sound loop after it finishes playing once.
18
57
  */
19
58
  get loop() {
20
- return this._loop;
59
+ return this._soundV2 instanceof _WebAudioSoundSource ? true : this._soundV2.loop;
21
60
  }
22
61
  set loop(value) {
23
- if (value === this._loop) {
62
+ if (this._soundV2 instanceof _WebAudioSoundSource) {
24
63
  return;
25
64
  }
26
- this._loop = value;
27
- this.updateOptions({ loop: value });
65
+ if (this._soundV2) {
66
+ this._soundV2.loop = value;
67
+ }
28
68
  }
29
69
  /**
30
- * Gets the current time for the sound.
70
+ * Is this sound currently played.
31
71
  */
32
- get currentTime() {
33
- if (this._htmlAudioElement) {
34
- return this._htmlAudioElement.currentTime;
72
+ get isPlaying() {
73
+ return this._soundV2 instanceof _WebAudioSoundSource ? true : this._soundV2?.state === 3 /* SoundState.Started */ || (!this.isReady() && this._optionsV2.autoplay);
74
+ }
75
+ /**
76
+ * Is this sound currently paused.
77
+ */
78
+ get isPaused() {
79
+ return this._soundV2 instanceof _WebAudioSoundSource ? false : this._soundV2.state === 5 /* SoundState.Paused */;
80
+ }
81
+ /**
82
+ * Define the max distance the sound should be heard (intensity just became 0 at this point).
83
+ * @see https://doc.babylonjs.com/legacy/audio#creating-a-spatial-3d-sound
84
+ */
85
+ get maxDistance() {
86
+ return this._optionsV2.spatialMaxDistance || 100;
87
+ }
88
+ set maxDistance(value) {
89
+ this._optionsV2.spatialMaxDistance = value;
90
+ if (this.useCustomAttenuation) {
91
+ return;
92
+ }
93
+ if (this._soundV2) {
94
+ this._initSpatial();
95
+ this._soundV2.spatial.maxDistance = value;
35
96
  }
36
- if (AbstractEngine.audioEngine?.audioContext && (this.isPlaying || this.isPaused)) {
37
- // The `_currentTime` member is only updated when the sound is paused. Add the time since the last start
38
- // to get the actual current time.
39
- const timeSinceLastStart = this.isPaused ? 0 : AbstractEngine.audioEngine.audioContext.currentTime - this._startTime;
40
- return this._currentTime + timeSinceLastStart;
97
+ }
98
+ /**
99
+ * Define the distance attenuation model the sound will follow.
100
+ * @see https://doc.babylonjs.com/legacy/audio#creating-a-spatial-3d-sound
101
+ */
102
+ get distanceModel() {
103
+ return this._optionsV2.spatialDistanceModel || "linear";
104
+ }
105
+ set distanceModel(value) {
106
+ this._optionsV2.spatialDistanceModel = value;
107
+ if (this._soundV2) {
108
+ this._initSpatial();
109
+ this._soundV2.spatial.distanceModel = value;
41
110
  }
42
- return 0;
111
+ }
112
+ /**
113
+ * Gets the current time for the sound.
114
+ */
115
+ get currentTime() {
116
+ return this._soundV2 instanceof _WebAudioSoundSource ? this._soundV2.engine.currentTime : this._soundV2.currentTime;
43
117
  }
44
118
  /**
45
119
  * Does this sound enables spatial sound.
46
- * @see https://doc.babylonjs.com/features/featuresDeepDive/audio/playingSoundsMusic#creating-a-spatial-3d-sound
120
+ * @see https://doc.babylonjs.com/legacy/audio#creating-a-spatial-3d-sound
47
121
  */
48
122
  get spatialSound() {
49
- return this._spatialSound;
123
+ return this._soundV2?._isSpatial ?? false;
50
124
  }
51
125
  /**
52
126
  * Does this sound enables spatial sound.
53
- * @see https://doc.babylonjs.com/features/featuresDeepDive/audio/playingSoundsMusic#creating-a-spatial-3d-sound
127
+ * @see https://doc.babylonjs.com/legacy/audio#creating-a-spatial-3d-sound
54
128
  */
55
129
  set spatialSound(newValue) {
56
- if (newValue == this._spatialSound) {
57
- return;
58
- }
59
- const wasPlaying = this.isPlaying;
60
- this.pause();
61
- if (newValue) {
62
- this._spatialSound = newValue;
63
- this._updateSpatialParameters();
64
- }
65
- else {
66
- this._disableSpatialSound();
130
+ if (this._soundV2) {
131
+ if (newValue) {
132
+ this._initSpatial();
133
+ }
134
+ else {
135
+ this._soundV2._isSpatial = false;
136
+ }
67
137
  }
68
- if (wasPlaying) {
69
- this.play();
138
+ }
139
+ get _onReady() {
140
+ if (!this._onReadyObservable) {
141
+ this._onReadyObservable = new Observable();
70
142
  }
143
+ return this._onReadyObservable;
71
144
  }
72
145
  /**
73
146
  * Create a sound and attach it to a scene
@@ -78,45 +151,26 @@ export class Sound {
78
151
  * @param options Objects to provide with the current available options: autoplay, loop, volume, spatialSound, maxDistance, rolloffFactor, refDistance, distanceModel, panningModel, streaming
79
152
  */
80
153
  constructor(name, urlOrArrayBuffer, scene, readyToPlayCallback = null, options) {
81
- /**
82
- * Does the sound autoplay once loaded.
83
- */
84
- this.autoplay = false;
85
- this._loop = false;
86
154
  /**
87
155
  * Does the sound use a custom attenuation curve to simulate the falloff
88
156
  * happening when the source gets further away from the camera.
89
- * @see https://doc.babylonjs.com/features/featuresDeepDive/audio/playingSoundsMusic#creating-your-own-custom-attenuation-function
157
+ * @see https://doc.babylonjs.com/legacy/audio#creating-your-own-custom-attenuation-function
90
158
  */
91
159
  this.useCustomAttenuation = false;
92
160
  /**
93
- * Is this sound currently played.
161
+ * The sound track id this sound belongs to.
94
162
  */
95
- this.isPlaying = false;
96
- /**
97
- * Is this sound currently paused.
98
- */
99
- this.isPaused = false;
163
+ this.soundTrackId = -1;
100
164
  /**
101
165
  * Define the reference distance the sound should be heard perfectly.
102
- * @see https://doc.babylonjs.com/features/featuresDeepDive/audio/playingSoundsMusic#creating-a-spatial-3d-sound
166
+ * @see https://doc.babylonjs.com/legacy/audio#creating-a-spatial-3d-sound
103
167
  */
104
168
  this.refDistance = 1;
105
169
  /**
106
170
  * Define the roll off factor of spatial sounds.
107
- * @see https://doc.babylonjs.com/features/featuresDeepDive/audio/playingSoundsMusic#creating-a-spatial-3d-sound
171
+ * @see https://doc.babylonjs.com/legacy/audio#creating-a-spatial-3d-sound
108
172
  */
109
173
  this.rolloffFactor = 1;
110
- /**
111
- * Define the max distance the sound should be heard (intensity just became 0 at this point).
112
- * @see https://doc.babylonjs.com/features/featuresDeepDive/audio/playingSoundsMusic#creating-a-spatial-3d-sound
113
- */
114
- this.maxDistance = 100;
115
- /**
116
- * Define the distance attenuation model the sound will follow.
117
- * @see https://doc.babylonjs.com/features/featuresDeepDive/audio/playingSoundsMusic#creating-a-spatial-3d-sound
118
- */
119
- this.distanceModel = "linear";
120
174
  /**
121
175
  * Gets or sets an object used to store user defined information for the sound.
122
176
  */
@@ -125,32 +179,37 @@ export class Sound {
125
179
  * Observable event when the current playing sound finishes.
126
180
  */
127
181
  this.onEndedObservable = new Observable();
128
- this._spatialSound = false;
129
- this._panningModel = "equalpower";
130
- this._playbackRate = 1;
131
- this._streaming = false;
132
- this._startTime = 0;
133
- this._currentTime = 0;
134
- this._position = Vector3.Zero();
135
182
  this._localDirection = new Vector3(1, 0, 0);
136
183
  this._volume = 1;
137
184
  this._isReadyToPlay = false;
138
185
  this._isDirectional = false;
139
- // Used if you'd like to create a directional sound.
140
- // If not set, the sound will be omnidirectional
141
- this._coneInnerAngle = 360;
142
- this._coneOuterAngle = 360;
143
- this._coneOuterGain = 0;
144
186
  this._isOutputConnected = false;
145
- this._urlType = "Unknown";
146
- this.name = name;
187
+ this._url = null;
188
+ this._onReadyObservable = null;
189
+ this._onReadyToPlay = () => {
190
+ this._scene.mainSoundTrack.addSound(this);
191
+ this._isReadyToPlay = true;
192
+ this._readyToPlayCallback();
193
+ if (this._onReadyObservable) {
194
+ this._onReadyObservable.notifyObservers();
195
+ }
196
+ if (this._optionsV2.autoplay) {
197
+ this.play();
198
+ }
199
+ };
200
+ this._onended = () => {
201
+ if (this.onended) {
202
+ this.onended();
203
+ }
204
+ this.onEndedObservable.notifyObservers(this);
205
+ };
147
206
  scene = scene || EngineStore.LastCreatedScene;
148
207
  if (!scene) {
149
208
  return;
150
209
  }
151
210
  this._scene = scene;
152
211
  Sound._SceneComponentInitialization(scene);
153
- this._readyToPlayCallback = readyToPlayCallback;
212
+ this._readyToPlayCallback = readyToPlayCallback || (() => { });
154
213
  // Default custom attenuation function is a linear attenuation
155
214
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
156
215
  this._customAttenuationFunction = (currentVolume, currentDistance, maxDistance, refDistance, rolloffFactor) => {
@@ -161,232 +220,136 @@ export class Sound {
161
220
  return 0;
162
221
  }
163
222
  };
164
- if (options) {
165
- this.autoplay = options.autoplay || false;
166
- this._loop = options.loop || false;
167
- // if volume === 0, we need another way to check this option
168
- if (options.volume !== undefined) {
169
- this._volume = options.volume;
170
- }
171
- this._spatialSound = options.spatialSound ?? false;
172
- this.maxDistance = options.maxDistance ?? 100;
173
- this.useCustomAttenuation = options.useCustomAttenuation ?? false;
174
- this.rolloffFactor = options.rolloffFactor || 1;
175
- this.refDistance = options.refDistance || 1;
176
- this.distanceModel = options.distanceModel || "linear";
177
- this._playbackRate = options.playbackRate || 1;
178
- this._streaming = options.streaming ?? false;
179
- this._length = options.length;
180
- this._offset = options.offset;
181
- }
182
- if (AbstractEngine.audioEngine?.canUseWebAudio && AbstractEngine.audioEngine.audioContext) {
183
- this._soundGain = AbstractEngine.audioEngine.audioContext.createGain();
184
- this._soundGain.gain.value = this._volume;
185
- this._inputAudioNode = this._soundGain;
186
- this._outputAudioNode = this._soundGain;
187
- if (this._spatialSound) {
188
- this._createSpatialParameters();
189
- }
190
- this._scene.mainSoundTrack.addSound(this);
191
- let validParameter = true;
192
- // if no parameter is passed, you need to call setAudioBuffer yourself to prepare the sound
193
- if (urlOrArrayBuffer) {
194
- try {
195
- if (typeof urlOrArrayBuffer === "string") {
196
- this._urlType = "String";
197
- this._url = urlOrArrayBuffer;
198
- }
199
- else if (urlOrArrayBuffer instanceof ArrayBuffer) {
200
- this._urlType = "ArrayBuffer";
201
- }
202
- else if (urlOrArrayBuffer instanceof HTMLMediaElement) {
203
- this._urlType = "MediaElement";
204
- }
205
- else if (urlOrArrayBuffer instanceof MediaStream) {
206
- this._urlType = "MediaStream";
207
- }
208
- else if (urlOrArrayBuffer instanceof AudioBuffer) {
209
- this._urlType = "AudioBuffer";
210
- }
211
- else if (Array.isArray(urlOrArrayBuffer)) {
212
- this._urlType = "Array";
213
- }
214
- let urls = [];
215
- let codecSupportedFound = false;
216
- switch (this._urlType) {
217
- case "MediaElement":
218
- this._streaming = true;
219
- this._isReadyToPlay = true;
220
- this._streamingSource = AbstractEngine.audioEngine.audioContext.createMediaElementSource(urlOrArrayBuffer);
221
- if (this.autoplay) {
222
- this.play(0, this._offset, this._length);
223
- }
224
- if (this._readyToPlayCallback) {
225
- this._readyToPlayCallback();
226
- }
227
- break;
228
- case "MediaStream":
229
- this._streaming = true;
230
- this._isReadyToPlay = true;
231
- this._streamingSource = AbstractEngine.audioEngine.audioContext.createMediaStreamSource(urlOrArrayBuffer);
232
- if (this.autoplay) {
233
- this.play(0, this._offset, this._length);
234
- }
235
- if (this._readyToPlayCallback) {
236
- this._readyToPlayCallback();
237
- }
238
- break;
239
- case "ArrayBuffer":
240
- if (urlOrArrayBuffer.byteLength > 0) {
241
- codecSupportedFound = true;
242
- this._soundLoaded(urlOrArrayBuffer);
243
- }
244
- break;
245
- case "AudioBuffer":
246
- this._audioBufferLoaded(urlOrArrayBuffer);
247
- break;
248
- case "String":
249
- urls.push(urlOrArrayBuffer);
250
- // eslint-disable-next-line no-fallthrough
251
- case "Array":
252
- if (urls.length === 0) {
253
- urls = urlOrArrayBuffer;
254
- }
255
- // If we found a supported format, we load it immediately and stop the loop
256
- for (let i = 0; i < urls.length; i++) {
257
- const url = urls[i];
258
- codecSupportedFound =
259
- (options && options.skipCodecCheck) ||
260
- (url.indexOf(".mp3", url.length - 4) !== -1 && AbstractEngine.audioEngine.isMP3supported) ||
261
- (url.indexOf(".ogg", url.length - 4) !== -1 && AbstractEngine.audioEngine.isOGGsupported) ||
262
- url.indexOf(".wav", url.length - 4) !== -1 ||
263
- url.indexOf(".m4a", url.length - 4) !== -1 ||
264
- url.indexOf(".mp4", url.length - 4) !== -1 ||
265
- url.indexOf("blob:") !== -1;
266
- if (codecSupportedFound) {
267
- // Loading sound
268
- if (!this._streaming) {
269
- this._scene._loadFile(url, (data) => {
270
- this._soundLoaded(data);
271
- }, undefined, true, true, (exception) => {
272
- if (exception) {
273
- Logger.Error("XHR " + exception.status + " error on: " + url + ".");
274
- }
275
- Logger.Error("Sound creation aborted.");
276
- this._scene.mainSoundTrack.removeSound(this);
277
- });
278
- }
279
- // Streaming sound using HTML5 Audio tag
280
- else {
281
- this._htmlAudioElement = new Audio(url);
282
- this._htmlAudioElement.controls = false;
283
- this._htmlAudioElement.loop = this.loop;
284
- Tools.SetCorsBehavior(url, this._htmlAudioElement);
285
- this._htmlAudioElement.preload = "auto";
286
- this._htmlAudioElement.addEventListener("canplaythrough", () => {
287
- this._isReadyToPlay = true;
288
- if (this.autoplay) {
289
- this.play(0, this._offset, this._length);
290
- }
291
- if (this._readyToPlayCallback) {
292
- this._readyToPlayCallback();
293
- }
294
- }, { once: true });
295
- document.body.appendChild(this._htmlAudioElement);
296
- this._htmlAudioElement.load();
297
- }
298
- break;
299
- }
300
- }
301
- break;
302
- default:
303
- validParameter = false;
304
- break;
305
- }
306
- if (!validParameter) {
307
- Logger.Error("Parameter must be a URL to the sound, an Array of URLs (.mp3 & .ogg) or an ArrayBuffer of the sound.");
308
- }
309
- else {
310
- if (!codecSupportedFound) {
311
- this._isReadyToPlay = true;
312
- // Simulating a ready to play event to avoid breaking code path
313
- if (this._readyToPlayCallback) {
314
- setTimeout(() => {
315
- if (this._readyToPlayCallback) {
316
- this._readyToPlayCallback();
317
- }
318
- }, 1000);
319
- }
320
- }
321
- }
322
- }
323
- catch (ex) {
324
- Logger.Error("Unexpected error. Sound creation aborted.");
325
- this._scene.mainSoundTrack.removeSound(this);
326
- }
327
- }
223
+ options = options || {};
224
+ const optionsV2 = {
225
+ analyzerEnabled: false,
226
+ autoplay: false, // `false` for now, but will be set to given option later
227
+ duration: options.length || 0,
228
+ loop: options.loop || false,
229
+ loopEnd: 0,
230
+ loopStart: 0,
231
+ maxInstances: 1,
232
+ outBus: null,
233
+ outBusAutoDefault: false,
234
+ playbackRate: options.playbackRate || 1,
235
+ pitch: 0,
236
+ skipCodecCheck: options.skipCodecCheck || false,
237
+ spatialDistanceModel: options.distanceModel,
238
+ spatialEnabled: options.spatialSound,
239
+ spatialMaxDistance: options.maxDistance,
240
+ spatialMinDistance: options.refDistance,
241
+ spatialRolloffFactor: options.rolloffFactor,
242
+ stereoEnabled: false,
243
+ startOffset: options.offset || 0,
244
+ volume: options.volume ?? 1,
245
+ };
246
+ this._volume = options.volume ?? 1;
247
+ if (_HasSpatialAudioOptions(optionsV2)) {
248
+ optionsV2.spatialAutoUpdate = false;
249
+ optionsV2.spatialConeInnerAngle = _SpatialAudioDefaults.coneInnerAngle;
250
+ optionsV2.spatialConeOuterAngle = _SpatialAudioDefaults.coneOuterAngle;
251
+ optionsV2.spatialConeOuterVolume = _SpatialAudioDefaults.coneOuterVolume;
252
+ optionsV2.spatialMinUpdateTime = 0;
253
+ optionsV2.spatialOrientation = _SpatialAudioDefaults.orientation.clone();
254
+ optionsV2.spatialPanningModel = (this._scene.headphone ? "HRTF" : "equalpower");
255
+ optionsV2.spatialPosition = _SpatialAudioDefaults.position.clone();
256
+ optionsV2.spatialRotation = _SpatialAudioDefaults.rotation.clone();
257
+ optionsV2.spatialRotationQuaternion = _SpatialAudioDefaults.rotationQuaternion.clone();
258
+ if (optionsV2.spatialMaxDistance === undefined) {
259
+ optionsV2.spatialMaxDistance = 100;
260
+ }
261
+ }
262
+ this._optionsV2 = { ...optionsV2 };
263
+ this._optionsV2.autoplay = options.autoplay || false;
264
+ this.useCustomAttenuation = options.useCustomAttenuation ?? false;
265
+ if (this.useCustomAttenuation) {
266
+ optionsV2.spatialMaxDistance = Number.MAX_VALUE;
267
+ optionsV2.volume = 0;
268
+ }
269
+ let streaming = options?.streaming || false;
270
+ const audioEngine = AbstractEngine.audioEngine;
271
+ if (!audioEngine) {
272
+ return;
328
273
  }
329
- else {
330
- // Adding an empty sound to avoid breaking audio calls for non Web Audio browsers
331
- this._scene.mainSoundTrack.addSound(this);
332
- if (AbstractEngine.audioEngine && !AbstractEngine.audioEngine.WarnedWebAudioUnsupported) {
333
- Logger.Error("Web Audio is not supported by your browser.");
334
- AbstractEngine.audioEngine.WarnedWebAudioUnsupported = true;
274
+ const audioEngineV2 = AbstractEngine.audioEngine._v2;
275
+ const createSoundV2 = () => {
276
+ if (streaming) {
277
+ const streamingOptionsV2 = {
278
+ preloadCount: 0,
279
+ ...optionsV2,
280
+ };
281
+ const sound = new _WebAudioStreamingSound(name, audioEngineV2, streamingOptionsV2);
282
+ // eslint-disable-next-line github/no-then
283
+ void sound._initAsync(urlOrArrayBuffer, optionsV2).then(() => {
284
+ // eslint-disable-next-line github/no-then
285
+ void sound.preloadInstancesAsync(1).then(this._onReadyToPlay);
286
+ });
287
+ return sound;
335
288
  }
336
- // Simulating a ready to play event to avoid breaking code for non web audio browsers
337
- if (this._readyToPlayCallback) {
338
- setTimeout(() => {
339
- if (this._readyToPlayCallback) {
340
- this._readyToPlayCallback();
341
- }
342
- }, 1000);
289
+ else {
290
+ const sound = new _WebAudioStaticSound(name, audioEngineV2, optionsV2);
291
+ // eslint-disable-next-line github/no-then
292
+ void sound._initAsync(urlOrArrayBuffer, optionsV2).then(this._onReadyToPlay);
293
+ return sound;
343
294
  }
295
+ };
296
+ // If no parameter is passed then the setAudioBuffer should be called to prepare the sound.
297
+ if (!urlOrArrayBuffer) {
298
+ // Create the sound but don't call _initAsync on it, yet. Call it later when `setAudioBuffer` is called.
299
+ this._soundV2 = new _WebAudioStaticSound(name, audioEngineV2, optionsV2);
300
+ }
301
+ else if (typeof urlOrArrayBuffer === "string") {
302
+ this._url = urlOrArrayBuffer;
303
+ this._soundV2 = createSoundV2();
304
+ }
305
+ else if (urlOrArrayBuffer instanceof ArrayBuffer) {
306
+ streaming = false;
307
+ this._soundV2 = createSoundV2();
308
+ }
309
+ else if (urlOrArrayBuffer instanceof HTMLMediaElement) {
310
+ streaming = true;
311
+ this._soundV2 = createSoundV2();
312
+ }
313
+ else if (urlOrArrayBuffer instanceof MediaStream) {
314
+ const node = new MediaStreamAudioSourceNode(audioEngineV2._audioContext, { mediaStream: urlOrArrayBuffer });
315
+ this._soundV2 = new _WebAudioSoundSource(name, node, audioEngineV2, optionsV2);
316
+ // eslint-disable-next-line github/no-then
317
+ void this._soundV2._initAsync(optionsV2).then(this._onReadyToPlay);
318
+ }
319
+ else if (urlOrArrayBuffer instanceof AudioBuffer) {
320
+ streaming = false;
321
+ this._soundV2 = createSoundV2();
322
+ }
323
+ else if (Array.isArray(urlOrArrayBuffer)) {
324
+ this._soundV2 = createSoundV2();
325
+ }
326
+ if (!this._soundV2) {
327
+ Logger.Error("Parameter must be a URL to the sound, an Array of URLs (.mp3 & .ogg) or an ArrayBuffer of the sound.");
328
+ return;
329
+ }
330
+ if (!(this._soundV2 instanceof _WebAudioSoundSource)) {
331
+ this._soundV2.onEndedObservable.add(this._onended);
344
332
  }
345
333
  }
346
334
  /**
347
335
  * Release the sound and its associated resources
348
336
  */
349
337
  dispose() {
350
- if (AbstractEngine.audioEngine?.canUseWebAudio) {
351
- if (this.isPlaying) {
352
- this.stop();
353
- }
354
- this._isReadyToPlay = false;
355
- if (this.soundTrackId === -1) {
356
- this._scene.mainSoundTrack.removeSound(this);
357
- }
358
- else if (this._scene.soundTracks) {
359
- this._scene.soundTracks[this.soundTrackId].removeSound(this);
360
- }
361
- if (this._soundGain) {
362
- this._soundGain.disconnect();
363
- this._soundGain = null;
364
- }
365
- if (this._soundPanner) {
366
- this._soundPanner.disconnect();
367
- this._soundPanner = null;
368
- }
369
- if (this._soundSource) {
370
- this._soundSource.disconnect();
371
- this._soundSource = null;
372
- }
373
- this._audioBuffer = null;
374
- if (this._htmlAudioElement) {
375
- this._htmlAudioElement.pause();
376
- this._htmlAudioElement.src = "";
377
- document.body.removeChild(this._htmlAudioElement);
378
- this._htmlAudioElement = null;
379
- }
380
- if (this._streamingSource) {
381
- this._streamingSource.disconnect();
382
- this._streamingSource = null;
383
- }
384
- if (this._connectedTransformNode && this._registerFunc) {
385
- this._connectedTransformNode.unregisterAfterWorldMatrixUpdate(this._registerFunc);
386
- this._connectedTransformNode = null;
387
- }
388
- this._clearTimeoutsAndObservers();
338
+ if (this.isPlaying) {
339
+ this.stop();
340
+ }
341
+ this._isReadyToPlay = false;
342
+ if (this.soundTrackId === -1) {
343
+ this._scene.mainSoundTrack.removeSound(this);
344
+ }
345
+ else if (this._scene.soundTracks) {
346
+ this._scene.soundTracks[this.soundTrackId].removeSound(this);
389
347
  }
348
+ if (this._connectedTransformNode && this._registerFunc) {
349
+ this._connectedTransformNode.unregisterAfterWorldMatrixUpdate(this._registerFunc);
350
+ this._connectedTransformNode = null;
351
+ }
352
+ this._soundV2.dispose();
390
353
  }
391
354
  /**
392
355
  * Gets if the sounds is ready to be played or not.
@@ -402,38 +365,17 @@ export class Sound {
402
365
  getClassName() {
403
366
  return "Sound";
404
367
  }
405
- _audioBufferLoaded(buffer) {
406
- if (!AbstractEngine.audioEngine?.audioContext) {
407
- return;
408
- }
409
- this._audioBuffer = buffer;
410
- this._isReadyToPlay = true;
411
- if (this.autoplay) {
412
- this.play(0, this._offset, this._length);
413
- }
414
- if (this._readyToPlayCallback) {
415
- this._readyToPlayCallback();
416
- }
417
- }
418
- _soundLoaded(audioData) {
419
- if (!AbstractEngine.audioEngine?.audioContext) {
420
- return;
421
- }
422
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
423
- AbstractEngine.audioEngine.audioContext.decodeAudioData(audioData, (buffer) => {
424
- this._audioBufferLoaded(buffer);
425
- }, (err) => {
426
- Logger.Error("Error while decoding audio data for: " + this.name + " / Error: " + err);
427
- });
428
- }
429
368
  /**
430
369
  * Sets the data of the sound from an audiobuffer
431
370
  * @param audioBuffer The audioBuffer containing the data
432
371
  */
433
372
  setAudioBuffer(audioBuffer) {
434
- if (AbstractEngine.audioEngine?.canUseWebAudio) {
435
- this._audioBuffer = audioBuffer;
436
- this._isReadyToPlay = true;
373
+ if (this._isReadyToPlay) {
374
+ return;
375
+ }
376
+ if (this._soundV2 instanceof _WebAudioStaticSound) {
377
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then
378
+ this._soundV2._initAsync(audioBuffer, this._optionsV2).then(this._onReadyToPlay);
437
379
  }
438
380
  }
439
381
  /**
@@ -448,104 +390,73 @@ export class Sound {
448
390
  this.rolloffFactor = options.rolloffFactor ?? this.rolloffFactor;
449
391
  this.refDistance = options.refDistance ?? this.refDistance;
450
392
  this.distanceModel = options.distanceModel ?? this.distanceModel;
451
- this._playbackRate = options.playbackRate ?? this._playbackRate;
452
- this._length = options.length ?? undefined;
453
- this.spatialSound = options.spatialSound ?? this._spatialSound;
454
- this._setOffset(options.offset ?? undefined);
455
- this.setVolume(options.volume ?? this._volume);
456
- this._updateSpatialParameters();
457
- if (this.isPlaying) {
458
- if (this._streaming && this._htmlAudioElement) {
459
- this._htmlAudioElement.playbackRate = this._playbackRate;
460
- if (this._htmlAudioElement.loop !== this.loop) {
461
- this._htmlAudioElement.loop = this.loop;
462
- }
463
- }
464
- else {
465
- if (this._soundSource) {
466
- this._soundSource.playbackRate.value = this._playbackRate;
467
- if (this._soundSource.loop !== this.loop) {
468
- this._soundSource.loop = this.loop;
469
- }
470
- if (this._offset !== undefined && this._soundSource.loopStart !== this._offset) {
471
- this._soundSource.loopStart = this._offset;
472
- }
473
- if (this._length !== undefined && this._length !== this._soundSource.loopEnd) {
474
- this._soundSource.loopEnd = (this._offset | 0) + this._length;
475
- }
476
- }
477
- }
393
+ if (options.playbackRate !== undefined) {
394
+ this.setPlaybackRate(options.playbackRate);
478
395
  }
479
- }
480
- }
481
- _createSpatialParameters() {
482
- if (AbstractEngine.audioEngine?.canUseWebAudio && AbstractEngine.audioEngine.audioContext) {
483
- if (this._scene.headphone) {
484
- this._panningModel = "HRTF";
396
+ if (options.spatialSound !== undefined) {
397
+ this.spatialSound = options.spatialSound;
485
398
  }
486
- this._soundPanner = this._soundPanner ?? AbstractEngine.audioEngine.audioContext.createPanner();
487
- if (this._soundPanner && this._outputAudioNode) {
488
- this._updateSpatialParameters();
489
- this._soundPanner.connect(this._outputAudioNode);
490
- this._inputAudioNode = this._soundPanner;
399
+ if (options.volume !== undefined) {
400
+ this.setVolume(options.volume);
491
401
  }
402
+ if (this._soundV2 instanceof _WebAudioStaticSound) {
403
+ let updated = false;
404
+ if (options.offset !== undefined) {
405
+ this._optionsV2.startOffset = options.offset;
406
+ updated = true;
407
+ }
408
+ if (options.length !== undefined) {
409
+ this._soundV2.duration = options.length;
410
+ updated = true;
411
+ }
412
+ if (updated && this.isPaused) {
413
+ this.stop();
414
+ }
415
+ }
416
+ this._updateSpatialParameters();
492
417
  }
493
418
  }
494
- _disableSpatialSound() {
495
- if (!this._spatialSound) {
496
- return;
497
- }
498
- this._inputAudioNode = this._soundGain;
499
- this._soundPanner?.disconnect();
500
- this._soundPanner = null;
501
- this._spatialSound = false;
502
- }
503
419
  _updateSpatialParameters() {
504
- if (!this._spatialSound) {
420
+ if (!this.spatialSound) {
505
421
  return;
506
422
  }
507
- if (this._soundPanner) {
508
- if (this.useCustomAttenuation) {
509
- // Tricks to disable in a way embedded Web Audio attenuation
510
- this._soundPanner.distanceModel = "linear";
511
- this._soundPanner.maxDistance = Number.MAX_VALUE;
512
- this._soundPanner.refDistance = 1;
513
- this._soundPanner.rolloffFactor = 1;
514
- this._soundPanner.panningModel = this._panningModel;
515
- }
516
- else {
517
- this._soundPanner.distanceModel = this.distanceModel;
518
- this._soundPanner.maxDistance = this.maxDistance;
519
- this._soundPanner.refDistance = this.refDistance;
520
- this._soundPanner.rolloffFactor = this.rolloffFactor;
521
- this._soundPanner.panningModel = this._panningModel;
522
- }
423
+ const spatial = this._soundV2.spatial;
424
+ if (this.useCustomAttenuation) {
425
+ // Disable WebAudio attenuation.
426
+ spatial.distanceModel = "linear";
427
+ spatial.minDistance = 1;
428
+ spatial.maxDistance = Number.MAX_VALUE;
429
+ spatial.rolloffFactor = 1;
430
+ spatial.panningModel = "equalpower";
523
431
  }
524
432
  else {
525
- this._createSpatialParameters();
433
+ spatial.distanceModel = this.distanceModel;
434
+ spatial.minDistance = this.refDistance;
435
+ spatial.maxDistance = this.maxDistance;
436
+ spatial.rolloffFactor = this.rolloffFactor;
437
+ spatial.panningModel = this._optionsV2.spatialPanningModel || "equalpower";
526
438
  }
527
439
  }
528
440
  /**
529
441
  * Switch the panning model to HRTF:
530
442
  * Renders a stereo output of higher quality than equalpower — it uses a convolution with measured impulse responses from human subjects.
531
- * @see https://doc.babylonjs.com/features/featuresDeepDive/audio/playingSoundsMusic#creating-a-spatial-3d-sound
443
+ * @see https://doc.babylonjs.com/legacy/audio#creating-a-spatial-3d-sound
532
444
  */
533
445
  switchPanningModelToHRTF() {
534
- this._panningModel = "HRTF";
535
- this._switchPanningModel();
446
+ if (this.spatialSound) {
447
+ this._initSpatial();
448
+ this._soundV2.spatial.panningModel = "HRTF";
449
+ }
536
450
  }
537
451
  /**
538
452
  * Switch the panning model to Equal Power:
539
453
  * Represents the equal-power panning algorithm, generally regarded as simple and efficient. equalpower is the default value.
540
- * @see https://doc.babylonjs.com/features/featuresDeepDive/audio/playingSoundsMusic#creating-a-spatial-3d-sound
454
+ * @see https://doc.babylonjs.com/legacy/audio#creating-a-spatial-3d-sound
541
455
  */
542
456
  switchPanningModelToEqualPower() {
543
- this._panningModel = "equalpower";
544
- this._switchPanningModel();
545
- }
546
- _switchPanningModel() {
547
- if (AbstractEngine.audioEngine?.canUseWebAudio && this._spatialSound && this._soundPanner) {
548
- this._soundPanner.panningModel = this._panningModel;
457
+ if (this.spatialSound) {
458
+ this._initSpatial();
459
+ this._soundV2.spatial.panningModel = "equalpower";
549
460
  }
550
461
  }
551
462
  /**
@@ -553,11 +464,12 @@ export class Sound {
553
464
  * @param soundTrackAudioNode the sound track audio node to connect to
554
465
  */
555
466
  connectToSoundTrackAudioNode(soundTrackAudioNode) {
556
- if (AbstractEngine.audioEngine?.canUseWebAudio && this._outputAudioNode) {
467
+ const outputNode = this._soundV2._outNode;
468
+ if (outputNode) {
557
469
  if (this._isOutputConnected) {
558
- this._outputAudioNode.disconnect();
470
+ outputNode.disconnect();
559
471
  }
560
- this._outputAudioNode.connect(soundTrackAudioNode);
472
+ outputNode.connect(soundTrackAudioNode);
561
473
  this._isOutputConnected = true;
562
474
  }
563
475
  }
@@ -572,33 +484,39 @@ export class Sound {
572
484
  Logger.Error("setDirectionalCone(): outer angle of the cone must be superior or equal to the inner angle.");
573
485
  return;
574
486
  }
575
- this._coneInnerAngle = coneInnerAngle;
576
- this._coneOuterAngle = coneOuterAngle;
577
- this._coneOuterGain = coneOuterGain;
487
+ this._optionsV2.spatialConeInnerAngle = D2r(coneInnerAngle);
488
+ this._optionsV2.spatialConeOuterAngle = D2r(coneOuterAngle);
489
+ this._optionsV2.spatialConeOuterVolume = coneOuterGain;
490
+ this._initSpatial();
491
+ this._soundV2.spatial.coneInnerAngle = this._optionsV2.spatialConeInnerAngle;
492
+ this._soundV2.spatial.coneOuterAngle = this._optionsV2.spatialConeOuterAngle;
493
+ this._soundV2.spatial.coneOuterVolume = coneOuterGain;
578
494
  this._isDirectional = true;
579
495
  if (this.isPlaying && this.loop) {
580
496
  this.stop();
581
- this.play(0, this._offset, this._length);
497
+ this.play(0, this._optionsV2.startOffset, this._optionsV2.duration);
582
498
  }
583
499
  }
584
500
  /**
585
501
  * Gets or sets the inner angle for the directional cone.
586
502
  */
587
503
  get directionalConeInnerAngle() {
588
- return this._coneInnerAngle;
504
+ return R2d(typeof this._optionsV2.spatialConeInnerAngle === "number" ? this._optionsV2.spatialConeInnerAngle : _SpatialAudioDefaults.coneInnerAngle);
589
505
  }
590
506
  /**
591
507
  * Gets or sets the inner angle for the directional cone.
592
508
  */
593
509
  set directionalConeInnerAngle(value) {
594
- if (value != this._coneInnerAngle) {
595
- if (this._coneOuterAngle < value) {
510
+ value = D2r(value);
511
+ if (value != this._optionsV2.spatialConeInnerAngle) {
512
+ if (this.directionalConeOuterAngle < value) {
596
513
  Logger.Error("directionalConeInnerAngle: outer angle of the cone must be superior or equal to the inner angle.");
597
514
  return;
598
515
  }
599
- this._coneInnerAngle = value;
600
- if (AbstractEngine.audioEngine?.canUseWebAudio && this._spatialSound && this._soundPanner) {
601
- this._soundPanner.coneInnerAngle = this._coneInnerAngle;
516
+ this._optionsV2.spatialConeInnerAngle = value;
517
+ if (this.spatialSound) {
518
+ this._initSpatial();
519
+ this._soundV2.spatial.coneInnerAngle = value;
602
520
  }
603
521
  }
604
522
  }
@@ -606,20 +524,22 @@ export class Sound {
606
524
  * Gets or sets the outer angle for the directional cone.
607
525
  */
608
526
  get directionalConeOuterAngle() {
609
- return this._coneOuterAngle;
527
+ return R2d(typeof this._optionsV2.spatialConeOuterAngle === "number" ? this._optionsV2.spatialConeOuterAngle : _SpatialAudioDefaults.coneOuterAngle);
610
528
  }
611
529
  /**
612
530
  * Gets or sets the outer angle for the directional cone.
613
531
  */
614
532
  set directionalConeOuterAngle(value) {
615
- if (value != this._coneOuterAngle) {
616
- if (value < this._coneInnerAngle) {
533
+ value = D2r(value);
534
+ if (value != this._optionsV2.spatialConeOuterAngle) {
535
+ if (value < this.directionalConeInnerAngle) {
617
536
  Logger.Error("directionalConeOuterAngle: outer angle of the cone must be superior or equal to the inner angle.");
618
537
  return;
619
538
  }
620
- this._coneOuterAngle = value;
621
- if (AbstractEngine.audioEngine?.canUseWebAudio && this._spatialSound && this._soundPanner) {
622
- this._soundPanner.coneOuterAngle = this._coneOuterAngle;
539
+ this._optionsV2.spatialConeOuterAngle = value;
540
+ if (this.spatialSound) {
541
+ this._initSpatial();
542
+ this._soundV2.spatial.coneOuterAngle = value;
623
543
  }
624
544
  }
625
545
  }
@@ -628,19 +548,16 @@ export class Sound {
628
548
  * @param newPosition Defines the new position
629
549
  */
630
550
  setPosition(newPosition) {
631
- if (newPosition.equals(this._position)) {
551
+ if (this._optionsV2.spatialPosition && newPosition.equals(this._optionsV2.spatialPosition)) {
632
552
  return;
633
553
  }
634
- this._position.copyFrom(newPosition);
635
- if (AbstractEngine.audioEngine?.canUseWebAudio &&
636
- this._spatialSound &&
637
- this._soundPanner &&
638
- !isNaN(this._position.x) &&
639
- !isNaN(this._position.y) &&
640
- !isNaN(this._position.z)) {
641
- this._soundPanner.positionX.value = this._position.x;
642
- this._soundPanner.positionY.value = this._position.y;
643
- this._soundPanner.positionZ.value = this._position.z;
554
+ if (!this._optionsV2.spatialPosition) {
555
+ this._optionsV2.spatialPosition = Vector3.Zero();
556
+ }
557
+ this._optionsV2.spatialPosition.copyFrom(newPosition);
558
+ if (this.spatialSound && !isNaN(newPosition.x) && !isNaN(newPosition.y) && !isNaN(newPosition.z)) {
559
+ this._initSpatial();
560
+ this._soundV2.spatial.position = newPosition;
644
561
  }
645
562
  }
646
563
  /**
@@ -649,34 +566,44 @@ export class Sound {
649
566
  */
650
567
  setLocalDirectionToMesh(newLocalDirection) {
651
568
  this._localDirection = newLocalDirection;
652
- if (AbstractEngine.audioEngine?.canUseWebAudio && this._connectedTransformNode && this.isPlaying) {
569
+ if (this._connectedTransformNode && this.isPlaying) {
653
570
  this._updateDirection();
654
571
  }
655
572
  }
656
573
  _updateDirection() {
657
- if (!this._connectedTransformNode || !this._soundPanner) {
574
+ if (!this._connectedTransformNode || !this.spatialSound) {
658
575
  return;
659
576
  }
660
577
  const mat = this._connectedTransformNode.getWorldMatrix();
661
578
  const direction = Vector3.TransformNormal(this._localDirection, mat);
662
579
  direction.normalize();
663
- this._soundPanner.orientationX.value = direction.x;
664
- this._soundPanner.orientationY.value = direction.y;
665
- this._soundPanner.orientationZ.value = direction.z;
580
+ this._initSpatial();
581
+ this._soundV2.spatial.orientation = direction;
582
+ }
583
+ _initSpatial() {
584
+ this._soundV2._isSpatial = true;
585
+ if (this._optionsV2.spatialDistanceModel === undefined) {
586
+ this._optionsV2.spatialDistanceModel = "linear";
587
+ this._soundV2.spatial.distanceModel = "linear";
588
+ }
589
+ if (this._optionsV2.spatialMaxDistance === undefined) {
590
+ this._optionsV2.spatialMaxDistance = 100;
591
+ this._soundV2.spatial.maxDistance = 100;
592
+ }
666
593
  }
667
594
  /** @internal */
668
595
  updateDistanceFromListener() {
669
- if (AbstractEngine.audioEngine?.canUseWebAudio && this._connectedTransformNode && this.useCustomAttenuation && this._soundGain && this._scene.activeCamera) {
596
+ if (this._soundV2._outNode && this._connectedTransformNode && this.useCustomAttenuation && this._scene.activeCamera) {
670
597
  const distance = this._scene.audioListenerPositionProvider
671
598
  ? this._connectedTransformNode.position.subtract(this._scene.audioListenerPositionProvider()).length()
672
599
  : this._connectedTransformNode.getDistanceToCamera(this._scene.activeCamera);
673
- this._soundGain.gain.value = this._customAttenuationFunction(this._volume, distance, this.maxDistance, this.refDistance, this.rolloffFactor);
600
+ this._soundV2.volume = this._customAttenuationFunction(this._volume, distance, this.maxDistance, this.refDistance, this.rolloffFactor);
674
601
  }
675
602
  }
676
603
  /**
677
604
  * Sets a new custom attenuation function for the sound.
678
605
  * @param callback Defines the function used for the attenuation
679
- * @see https://doc.babylonjs.com/features/featuresDeepDive/audio/playingSoundsMusic#creating-your-own-custom-attenuation-function
606
+ * @see https://doc.babylonjs.com/legacy/audio#creating-your-own-custom-attenuation-function
680
607
  */
681
608
  setAttenuationFunction(callback) {
682
609
  this._customAttenuationFunction = callback;
@@ -688,225 +615,63 @@ export class Sound {
688
615
  * @param length (optional) Sound duration (in seconds)
689
616
  */
690
617
  play(time, offset, length) {
691
- if (this._isReadyToPlay && this._scene.audioEnabled && AbstractEngine.audioEngine?.audioContext) {
618
+ const audioEngine = AbstractEngine.audioEngine;
619
+ audioEngine?.unlock();
620
+ // WebAudio sound sources have no `play` function because they are always playing.
621
+ if (this._soundV2 instanceof _WebAudioSoundSource) {
622
+ return;
623
+ }
624
+ if (this._isReadyToPlay && this._scene.audioEnabled) {
625
+ // The sound can only resume from pause when the `time`, `offset` and `length` args are not set.
626
+ if (this._soundV2.state === 5 /* SoundState.Paused */ && (time !== undefined || offset !== undefined || length !== undefined)) {
627
+ this._soundV2.stop();
628
+ }
692
629
  try {
693
- this._clearTimeoutsAndObservers();
694
- let startTime = time ? AbstractEngine.audioEngine?.audioContext.currentTime + time : AbstractEngine.audioEngine?.audioContext.currentTime;
695
- if (!this._soundSource || !this._streamingSource) {
696
- if (this._spatialSound && this._soundPanner) {
697
- if (!isNaN(this._position.x) && !isNaN(this._position.y) && !isNaN(this._position.z)) {
698
- this._soundPanner.positionX.value = this._position.x;
699
- this._soundPanner.positionY.value = this._position.y;
700
- this._soundPanner.positionZ.value = this._position.z;
701
- }
702
- if (this._isDirectional) {
703
- this._soundPanner.coneInnerAngle = this._coneInnerAngle;
704
- this._soundPanner.coneOuterAngle = this._coneOuterAngle;
705
- this._soundPanner.coneOuterGain = this._coneOuterGain;
706
- if (this._connectedTransformNode) {
707
- this._updateDirection();
708
- }
709
- else {
710
- this._soundPanner.setOrientation(this._localDirection.x, this._localDirection.y, this._localDirection.z);
711
- }
712
- }
713
- }
714
- }
715
- if (this._streaming) {
716
- if (!this._streamingSource && this._htmlAudioElement) {
717
- this._streamingSource = AbstractEngine.audioEngine.audioContext.createMediaElementSource(this._htmlAudioElement);
718
- this._htmlAudioElement.onended = () => {
719
- this._onended();
720
- };
721
- this._htmlAudioElement.playbackRate = this._playbackRate;
722
- }
723
- if (this._streamingSource) {
724
- this._streamingSource.disconnect();
725
- if (this._inputAudioNode) {
726
- this._streamingSource.connect(this._inputAudioNode);
727
- }
728
- }
729
- if (this._htmlAudioElement) {
730
- // required to manage properly the new suspended default state of Chrome
731
- // When the option 'streaming: true' is used, we need first to wait for
732
- // the audio engine to be unlocked by a user gesture before trying to play
733
- // an HTML Audio element
734
- const tryToPlay = () => {
735
- if (AbstractEngine.audioEngine?.unlocked) {
736
- if (!this._htmlAudioElement) {
737
- return;
738
- }
739
- this._htmlAudioElement.currentTime = offset ?? 0;
740
- const playPromise = this._htmlAudioElement.play();
741
- // In browsers that don’t yet support this functionality,
742
- // playPromise won’t be defined.
743
- if (playPromise !== undefined) {
744
- // eslint-disable-next-line github/no-then
745
- playPromise.catch(() => {
746
- // Automatic playback failed.
747
- // Waiting for the audio engine to be unlocked by user click on unmute
748
- AbstractEngine.audioEngine?.lock();
749
- if (this.loop || this.autoplay) {
750
- this._audioUnlockedObserver = AbstractEngine.audioEngine?.onAudioUnlockedObservable.addOnce(() => {
751
- tryToPlay();
752
- });
753
- }
754
- });
755
- }
756
- }
757
- else {
758
- if (this.loop || this.autoplay) {
759
- this._audioUnlockedObserver = AbstractEngine.audioEngine?.onAudioUnlockedObservable.addOnce(() => {
760
- tryToPlay();
761
- });
762
- }
763
- }
764
- };
765
- tryToPlay();
766
- }
630
+ TmpPlayOptions.duration = length || 0;
631
+ TmpPlayOptions.startOffset = offset !== undefined ? offset || this._optionsV2.startOffset : this._optionsV2.startOffset;
632
+ TmpPlayOptions.waitTime = time || 0;
633
+ if (audioEngine?.unlocked) {
634
+ this._soundV2.play(TmpPlayOptions);
767
635
  }
768
636
  else {
769
- const tryToPlay = () => {
770
- if (AbstractEngine.audioEngine?.audioContext) {
771
- length = length || this._length;
772
- if (offset !== undefined) {
773
- this._setOffset(offset);
774
- }
775
- if (this._soundSource) {
776
- const oldSource = this._soundSource;
777
- oldSource.onended = () => {
778
- oldSource.disconnect();
779
- };
780
- }
781
- this._soundSource = AbstractEngine.audioEngine?.audioContext.createBufferSource();
782
- if (this._soundSource && this._inputAudioNode) {
783
- this._soundSource.buffer = this._audioBuffer;
784
- this._soundSource.connect(this._inputAudioNode);
785
- this._soundSource.loop = this.loop;
786
- if (offset !== undefined) {
787
- this._soundSource.loopStart = offset;
788
- }
789
- if (length !== undefined) {
790
- this._soundSource.loopEnd = (offset | 0) + length;
791
- }
792
- this._soundSource.playbackRate.value = this._playbackRate;
793
- this._soundSource.onended = () => {
794
- this._onended();
795
- };
796
- startTime = time ? AbstractEngine.audioEngine?.audioContext.currentTime + time : AbstractEngine.audioEngine.audioContext.currentTime;
797
- const actualOffset = ((this.isPaused ? this.currentTime : 0) + (this._offset ?? 0)) % this._soundSource.buffer.duration;
798
- this._soundSource.start(startTime, actualOffset, this.loop ? undefined : length);
799
- }
800
- }
801
- };
802
- if (AbstractEngine.audioEngine?.audioContext.state === "suspended") {
803
- // Wait a bit for FF as context seems late to be ready.
804
- this._tryToPlayTimeout = setTimeout(() => {
805
- if (AbstractEngine.audioEngine?.audioContext.state === "suspended") {
806
- // Automatic playback failed.
807
- // Waiting for the audio engine to be unlocked by user click on unmute
808
- AbstractEngine.audioEngine.lock();
809
- if (this.loop || this.autoplay) {
810
- this._audioUnlockedObserver = AbstractEngine.audioEngine.onAudioUnlockedObservable.addOnce(() => {
811
- tryToPlay();
812
- });
813
- }
814
- }
815
- else {
816
- tryToPlay();
817
- }
818
- }, 500);
819
- }
820
- else {
821
- tryToPlay();
822
- }
637
+ // Wait a bit for FF as context seems late to be ready.
638
+ setTimeout(() => {
639
+ this._soundV2.play(TmpPlayOptions);
640
+ }, 500);
823
641
  }
824
- this._startTime = startTime;
825
- this.isPlaying = true;
826
- this.isPaused = false;
827
642
  }
828
643
  catch (ex) {
829
644
  Logger.Error("Error while trying to play audio: " + this.name + ", " + ex.message);
830
645
  }
831
646
  }
832
647
  }
833
- _onended() {
834
- this.isPlaying = false;
835
- this._startTime = 0;
836
- this._currentTime = 0;
837
- if (this.onended) {
838
- this.onended();
839
- }
840
- this.onEndedObservable.notifyObservers(this);
841
- }
842
648
  /**
843
649
  * Stop the sound
844
650
  * @param time (optional) Stop the sound after X seconds. Stop immediately (0) by default.
845
651
  */
846
652
  stop(time) {
847
- if (this.isPlaying) {
848
- this._clearTimeoutsAndObservers();
849
- if (this._streaming) {
850
- if (this._htmlAudioElement) {
851
- this._htmlAudioElement.pause();
852
- // Test needed for Firefox or it will generate an Invalid State Error
853
- if (this._htmlAudioElement.currentTime > 0) {
854
- this._htmlAudioElement.currentTime = 0;
855
- }
856
- }
857
- else {
858
- this._streamingSource?.disconnect();
859
- }
860
- this.isPlaying = false;
861
- }
862
- else if (AbstractEngine.audioEngine?.audioContext && this._soundSource) {
863
- const stopTime = time ? AbstractEngine.audioEngine.audioContext.currentTime + time : undefined;
864
- this._soundSource.onended = () => {
865
- this.isPlaying = false;
866
- this.isPaused = false;
867
- this._startTime = 0;
868
- this._currentTime = 0;
869
- if (this._soundSource) {
870
- this._soundSource.onended = () => void 0;
871
- }
872
- this._onended();
873
- };
874
- this._soundSource.stop(stopTime);
875
- }
876
- else {
877
- this.isPlaying = false;
878
- }
653
+ if (!this._soundV2) {
654
+ return;
879
655
  }
880
- else if (this.isPaused) {
881
- this.isPaused = false;
882
- this._startTime = 0;
883
- this._currentTime = 0;
656
+ // WebAudio sound sources have no `stop` function because they are always playing.
657
+ if (this._soundV2 instanceof _WebAudioSoundSource) {
658
+ return;
884
659
  }
660
+ TmpStopOptions.waitTime = time || 0;
661
+ this._soundV2.stop(TmpStopOptions);
885
662
  }
886
663
  /**
887
664
  * Put the sound in pause
888
665
  */
889
666
  pause() {
890
- if (this.isPlaying) {
891
- this._clearTimeoutsAndObservers();
892
- if (this._streaming) {
893
- if (this._htmlAudioElement) {
894
- this._htmlAudioElement.pause();
895
- }
896
- else {
897
- this._streamingSource?.disconnect();
898
- }
899
- this.isPlaying = false;
900
- this.isPaused = true;
901
- }
902
- else if (AbstractEngine.audioEngine?.audioContext && this._soundSource) {
903
- this._soundSource.onended = () => void 0;
904
- this._soundSource.stop();
905
- this.isPlaying = false;
906
- this.isPaused = true;
907
- this._currentTime += AbstractEngine.audioEngine.audioContext.currentTime - this._startTime;
908
- }
667
+ if (!this._soundV2) {
668
+ return;
909
669
  }
670
+ // WebAudio sound sources have no `pause` function because they are always playing.
671
+ if (this._soundV2 instanceof _WebAudioSoundSource) {
672
+ return;
673
+ }
674
+ this._soundV2.pause();
910
675
  }
911
676
  /**
912
677
  * Sets a dedicated volume for this sounds
@@ -914,16 +679,14 @@ export class Sound {
914
679
  * @param time Define time for gradual change to new volume
915
680
  */
916
681
  setVolume(newVolume, time) {
917
- if (AbstractEngine.audioEngine?.canUseWebAudio && this._soundGain) {
918
- if (time && AbstractEngine.audioEngine.audioContext) {
919
- this._soundGain.gain.cancelScheduledValues(AbstractEngine.audioEngine.audioContext.currentTime);
920
- this._soundGain.gain.setValueAtTime(this._soundGain.gain.value, AbstractEngine.audioEngine.audioContext.currentTime);
921
- this._soundGain.gain.linearRampToValueAtTime(newVolume, AbstractEngine.audioEngine.audioContext.currentTime + time);
922
- }
923
- else {
924
- this._soundGain.gain.value = newVolume;
925
- }
682
+ if (!this.isReady()) {
683
+ this._onReady.addOnce(() => {
684
+ this.setVolume(newVolume, time);
685
+ });
686
+ return;
926
687
  }
688
+ TmpRampOptions.duration = time || 0;
689
+ this._soundV2.setVolume(newVolume, TmpRampOptions);
927
690
  this._volume = newVolume;
928
691
  }
929
692
  /**
@@ -931,14 +694,8 @@ export class Sound {
931
694
  * @param newPlaybackRate Define the playback rate the sound should be played at
932
695
  */
933
696
  setPlaybackRate(newPlaybackRate) {
934
- this._playbackRate = newPlaybackRate;
935
- if (this.isPlaying) {
936
- if (this._streaming && this._htmlAudioElement) {
937
- this._htmlAudioElement.playbackRate = this._playbackRate;
938
- }
939
- else if (this._soundSource) {
940
- this._soundSource.playbackRate.value = this._playbackRate;
941
- }
697
+ if (this._soundV2 instanceof _WebAudioStaticSound) {
698
+ this._soundV2.playbackRate = newPlaybackRate;
942
699
  }
943
700
  }
944
701
  /**
@@ -946,7 +703,10 @@ export class Sound {
946
703
  * @returns the play back rate of the sound
947
704
  */
948
705
  getPlaybackRate() {
949
- return this._playbackRate;
706
+ if (this._soundV2 instanceof _WebAudioStaticSound) {
707
+ return this._soundV2.playbackRate;
708
+ }
709
+ return 1;
950
710
  }
951
711
  /**
952
712
  * Gets the volume of the sound.
@@ -958,7 +718,7 @@ export class Sound {
958
718
  /**
959
719
  * Attach the sound to a dedicated mesh
960
720
  * @param transformNode The transform node to connect the sound with
961
- * @see https://doc.babylonjs.com/features/featuresDeepDive/audio/playingSoundsMusic#attaching-a-sound-to-a-mesh
721
+ * @see https://doc.babylonjs.com/legacy/audio#attaching-a-sound-to-a-mesh
962
722
  */
963
723
  attachToMesh(transformNode) {
964
724
  if (this._connectedTransformNode && this._registerFunc) {
@@ -966,12 +726,11 @@ export class Sound {
966
726
  this._registerFunc = null;
967
727
  }
968
728
  this._connectedTransformNode = transformNode;
969
- if (!this._spatialSound) {
970
- this._spatialSound = true;
971
- this._createSpatialParameters();
729
+ if (!this.spatialSound) {
730
+ this.spatialSound = true;
972
731
  if (this.isPlaying && this.loop) {
973
732
  this.stop();
974
- this.play(0, this._offset, this._length);
733
+ this.play(0, this._optionsV2.startOffset, this._optionsV2.duration);
975
734
  }
976
735
  }
977
736
  this._onRegisterAfterWorldMatrixUpdate(this._connectedTransformNode);
@@ -980,7 +739,7 @@ export class Sound {
980
739
  }
981
740
  /**
982
741
  * Detach the sound from the previously attached mesh
983
- * @see https://doc.babylonjs.com/features/featuresDeepDive/audio/playingSoundsMusic#attaching-a-sound-to-a-mesh
742
+ * @see https://doc.babylonjs.com/legacy/audio#attaching-a-sound-to-a-mesh
984
743
  */
985
744
  detachFromMesh() {
986
745
  if (this._connectedTransformNode && this._registerFunc) {
@@ -998,7 +757,7 @@ export class Sound {
998
757
  const boundingInfo = mesh.getBoundingInfo();
999
758
  this.setPosition(boundingInfo.boundingSphere.centerWorld);
1000
759
  }
1001
- if (AbstractEngine.audioEngine?.canUseWebAudio && this._isDirectional && this.isPlaying) {
760
+ if (this._isDirectional && this.isPlaying) {
1002
761
  this._updateDirection();
1003
762
  }
1004
763
  }
@@ -1007,61 +766,51 @@ export class Sound {
1007
766
  * @returns the new sound clone
1008
767
  */
1009
768
  clone() {
1010
- if (!this._streaming) {
1011
- const setBufferAndRun = () => {
1012
- _RetryWithInterval(() => this._isReadyToPlay, () => {
1013
- clonedSound._audioBuffer = this.getAudioBuffer();
1014
- clonedSound._isReadyToPlay = true;
1015
- if (clonedSound.autoplay) {
1016
- clonedSound.play(0, this._offset, this._length);
1017
- }
1018
- }, undefined, 300);
1019
- };
1020
- const currentOptions = {
1021
- autoplay: this.autoplay,
1022
- loop: this.loop,
1023
- volume: this._volume,
1024
- spatialSound: this._spatialSound,
1025
- maxDistance: this.maxDistance,
1026
- useCustomAttenuation: this.useCustomAttenuation,
1027
- rolloffFactor: this.rolloffFactor,
1028
- refDistance: this.refDistance,
1029
- distanceModel: this.distanceModel,
1030
- };
1031
- const clonedSound = new Sound(this.name + "_cloned", new ArrayBuffer(0), this._scene, null, currentOptions);
1032
- if (this.useCustomAttenuation) {
1033
- clonedSound.setAttenuationFunction(this._customAttenuationFunction);
1034
- }
1035
- clonedSound.setPosition(this._position);
1036
- clonedSound.setPlaybackRate(this._playbackRate);
1037
- setBufferAndRun();
1038
- return clonedSound;
1039
- }
1040
- // Can't clone a streaming sound
1041
- else {
769
+ if (!(this._soundV2 instanceof _WebAudioStaticSound)) {
1042
770
  return null;
1043
771
  }
772
+ const currentOptions = {
773
+ autoplay: this.autoplay,
774
+ loop: this.loop,
775
+ volume: this._volume,
776
+ spatialSound: this.spatialSound,
777
+ maxDistance: this.maxDistance,
778
+ useCustomAttenuation: this.useCustomAttenuation,
779
+ rolloffFactor: this.rolloffFactor,
780
+ refDistance: this.refDistance,
781
+ distanceModel: this.distanceModel,
782
+ };
783
+ const clonedSound = new Sound(this.name + "_cloned", this._soundV2.buffer, this._scene, null, currentOptions);
784
+ clonedSound._optionsV2 = this._optionsV2;
785
+ if (this.useCustomAttenuation) {
786
+ clonedSound.setAttenuationFunction(this._customAttenuationFunction);
787
+ }
788
+ return clonedSound;
1044
789
  }
1045
790
  /**
1046
791
  * Gets the current underlying audio buffer containing the data
1047
792
  * @returns the audio buffer
1048
793
  */
1049
794
  getAudioBuffer() {
1050
- return this._audioBuffer;
795
+ if (this._soundV2 instanceof _WebAudioStaticSound) {
796
+ return this._soundV2.buffer._audioBuffer;
797
+ }
798
+ return null;
1051
799
  }
1052
800
  /**
1053
801
  * Gets the WebAudio AudioBufferSourceNode, lets you keep track of and stop instances of this Sound.
1054
802
  * @returns the source node
1055
803
  */
1056
804
  getSoundSource() {
1057
- return this._soundSource;
805
+ // return this._soundSource;
806
+ return null;
1058
807
  }
1059
808
  /**
1060
809
  * Gets the WebAudio GainNode, gives you precise control over the gain of instances of this Sound.
1061
810
  * @returns the gain node
1062
811
  */
1063
812
  getSoundGain() {
1064
- return this._soundGain;
813
+ return this._soundV2._outNode;
1065
814
  }
1066
815
  /**
1067
816
  * Serializes the Sound in a JSON representation
@@ -1074,28 +823,28 @@ export class Sound {
1074
823
  autoplay: this.autoplay,
1075
824
  loop: this.loop,
1076
825
  volume: this._volume,
1077
- spatialSound: this._spatialSound,
826
+ spatialSound: this.spatialSound,
1078
827
  maxDistance: this.maxDistance,
1079
828
  rolloffFactor: this.rolloffFactor,
1080
829
  refDistance: this.refDistance,
1081
830
  distanceModel: this.distanceModel,
1082
- playbackRate: this._playbackRate,
1083
- panningModel: this._panningModel,
831
+ playbackRate: this.getPlaybackRate(),
832
+ panningModel: this._soundV2.spatial.panningModel,
1084
833
  soundTrackId: this.soundTrackId,
1085
834
  metadata: this.metadata,
1086
835
  };
1087
- if (this._spatialSound) {
836
+ if (this.spatialSound) {
1088
837
  if (this._connectedTransformNode) {
1089
838
  serializationObject.connectedMeshId = this._connectedTransformNode.id;
1090
839
  }
1091
- serializationObject.position = this._position.asArray();
840
+ serializationObject.position = this._soundV2.spatial.position.asArray();
1092
841
  serializationObject.refDistance = this.refDistance;
1093
842
  serializationObject.distanceModel = this.distanceModel;
1094
843
  serializationObject.isDirectional = this._isDirectional;
1095
844
  serializationObject.localDirectionToMesh = this._localDirection.asArray();
1096
- serializationObject.coneInnerAngle = this._coneInnerAngle;
1097
- serializationObject.coneOuterAngle = this._coneOuterAngle;
1098
- serializationObject.coneOuterGain = this._coneOuterGain;
845
+ serializationObject.coneInnerAngle = this.directionalConeInnerAngle;
846
+ serializationObject.coneOuterAngle = this.directionalConeOuterAngle;
847
+ serializationObject.coneOuterGain = this._soundV2.spatial.coneOuterVolume;
1099
848
  }
1100
849
  return serializationObject;
1101
850
  }
@@ -1137,10 +886,13 @@ export class Sound {
1137
886
  else {
1138
887
  const setBufferAndRun = () => {
1139
888
  _RetryWithInterval(() => sourceSound._isReadyToPlay, () => {
1140
- newSound._audioBuffer = sourceSound.getAudioBuffer();
889
+ const audioBuffer = sourceSound.getAudioBuffer();
890
+ if (audioBuffer) {
891
+ newSound.setAudioBuffer(audioBuffer);
892
+ }
1141
893
  newSound._isReadyToPlay = true;
1142
894
  if (newSound.autoplay) {
1143
- newSound.play(0, newSound._offset, newSound._length);
895
+ newSound.play(0, sourceSound._optionsV2.startOffset, sourceSound._optionsV2.duration);
1144
896
  }
1145
897
  }, undefined, 300);
1146
898
  };
@@ -1169,26 +921,6 @@ export class Sound {
1169
921
  }
1170
922
  return newSound;
1171
923
  }
1172
- _setOffset(value) {
1173
- if (this._offset === value) {
1174
- return;
1175
- }
1176
- if (this.isPaused) {
1177
- this.stop();
1178
- this.isPaused = false;
1179
- }
1180
- this._offset = value;
1181
- }
1182
- _clearTimeoutsAndObservers() {
1183
- if (this._tryToPlayTimeout) {
1184
- clearTimeout(this._tryToPlayTimeout);
1185
- this._tryToPlayTimeout = null;
1186
- }
1187
- if (this._audioUnlockedObserver) {
1188
- AbstractEngine.audioEngine?.onAudioUnlockedObservable.remove(this._audioUnlockedObserver);
1189
- this._audioUnlockedObserver = null;
1190
- }
1191
- }
1192
924
  }
1193
925
  /**
1194
926
  * @internal