melonjs 17.4.0 → 18.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (702) hide show
  1. package/{dist/types → build}/application/application.d.ts +9 -10
  2. package/build/application/application.d.ts.map +1 -0
  3. package/build/application/defaultApplicationSettings.d.ts +18 -0
  4. package/build/application/defaultApplicationSettings.d.ts.map +1 -0
  5. package/{dist/types → build}/application/header.d.ts +1 -0
  6. package/build/application/header.d.ts.map +1 -0
  7. package/{dist/types → build}/application/resize.d.ts +1 -0
  8. package/build/application/resize.d.ts.map +1 -0
  9. package/build/application/scaleMethods.d.ts +44 -0
  10. package/build/application/scaleMethods.d.ts.map +1 -0
  11. package/build/application/settings.d.ts +85 -0
  12. package/build/application/settings.d.ts.map +1 -0
  13. package/{dist/types → build}/audio/audio.d.ts +35 -58
  14. package/build/audio/audio.d.ts.map +1 -0
  15. package/{dist/types → build}/camera/camera2d.d.ts +38 -76
  16. package/build/camera/camera2d.d.ts.map +1 -0
  17. package/build/const.d.ts +14 -0
  18. package/build/const.d.ts.map +1 -0
  19. package/build/geometries/earcut.d.ts +3 -0
  20. package/build/geometries/earcut.d.ts.map +1 -0
  21. package/build/geometries/ellipse.d.ts +117 -0
  22. package/build/geometries/ellipse.d.ts.map +1 -0
  23. package/build/geometries/line.d.ts +39 -0
  24. package/build/geometries/line.d.ts.map +1 -0
  25. package/build/geometries/observablePoint.d.ts +75 -0
  26. package/build/geometries/observablePoint.d.ts.map +1 -0
  27. package/{dist/types → build}/geometries/path2d.d.ts +8 -7
  28. package/build/geometries/path2d.d.ts.map +1 -0
  29. package/build/geometries/point.d.ts +44 -0
  30. package/build/geometries/point.d.ts.map +1 -0
  31. package/build/geometries/polygon.d.ts +182 -0
  32. package/build/geometries/polygon.d.ts.map +1 -0
  33. package/build/geometries/rectangle.d.ts +135 -0
  34. package/build/geometries/rectangle.d.ts.map +1 -0
  35. package/build/geometries/roundrect.d.ts +67 -0
  36. package/build/geometries/roundrect.d.ts.map +1 -0
  37. package/build/geometries/toarccanvas.d.ts +28 -0
  38. package/build/geometries/toarccanvas.d.ts.map +1 -0
  39. package/{dist/types → build}/index.d.ts +41 -45
  40. package/build/index.d.ts.map +1 -0
  41. package/build/index.js +28318 -0
  42. package/build/index.js.map +7 -0
  43. package/{dist/types → build}/input/gamepad.d.ts +3 -11
  44. package/build/input/gamepad.d.ts.map +1 -0
  45. package/{dist/types → build}/input/input.d.ts +4 -2
  46. package/build/input/input.d.ts.map +1 -0
  47. package/build/input/key.d.ts +105 -0
  48. package/build/input/key.d.ts.map +1 -0
  49. package/build/input/keyboard.d.ts +72 -0
  50. package/build/input/keyboard.d.ts.map +1 -0
  51. package/build/input/pointer.d.ts +180 -0
  52. package/build/input/pointer.d.ts.map +1 -0
  53. package/{dist/types → build}/input/pointerevent.d.ts +17 -16
  54. package/build/input/pointerevent.d.ts.map +1 -0
  55. package/{dist/types → build}/lang/console.d.ts +1 -0
  56. package/build/lang/console.d.ts.map +1 -0
  57. package/build/lang/deprecated.d.ts +24 -0
  58. package/build/lang/deprecated.d.ts.map +1 -0
  59. package/{dist/types → build}/level/level.d.ts +7 -7
  60. package/build/level/level.d.ts.map +1 -0
  61. package/{dist/types → build}/level/tiled/TMXGroup.d.ts +2 -2
  62. package/build/level/tiled/TMXGroup.d.ts.map +1 -0
  63. package/{dist/types → build}/level/tiled/TMXLayer.d.ts +4 -4
  64. package/build/level/tiled/TMXLayer.d.ts.map +1 -0
  65. package/{dist/types → build}/level/tiled/TMXObject.d.ts +3 -3
  66. package/build/level/tiled/TMXObject.d.ts.map +1 -0
  67. package/{dist/types → build}/level/tiled/TMXTile.d.ts +4 -5
  68. package/build/level/tiled/TMXTile.d.ts.map +1 -0
  69. package/{dist/types → build}/level/tiled/TMXTileMap.d.ts +4 -4
  70. package/build/level/tiled/TMXTileMap.d.ts.map +1 -0
  71. package/{dist/types → build}/level/tiled/TMXTileset.d.ts +2 -2
  72. package/build/level/tiled/TMXTileset.d.ts.map +1 -0
  73. package/{dist/types → build}/level/tiled/TMXTilesetGroup.d.ts +1 -1
  74. package/build/level/tiled/TMXTilesetGroup.d.ts.map +1 -0
  75. package/{dist/types → build}/level/tiled/TMXUtils.d.ts +2 -1
  76. package/build/level/tiled/TMXUtils.d.ts.map +1 -0
  77. package/{dist/types → build}/level/tiled/constants.d.ts +1 -0
  78. package/build/level/tiled/constants.d.ts.map +1 -0
  79. package/{dist/types → build}/level/tiled/renderer/TMXHexagonalRenderer.d.ts +3 -4
  80. package/build/level/tiled/renderer/TMXHexagonalRenderer.d.ts.map +1 -0
  81. package/{dist/types → build}/level/tiled/renderer/TMXIsometricRenderer.d.ts +2 -3
  82. package/build/level/tiled/renderer/TMXIsometricRenderer.d.ts.map +1 -0
  83. package/{dist/types → build}/level/tiled/renderer/TMXOrthogonalRenderer.d.ts +1 -2
  84. package/build/level/tiled/renderer/TMXOrthogonalRenderer.d.ts.map +1 -0
  85. package/{dist/types → build}/level/tiled/renderer/TMXRenderer.d.ts +7 -7
  86. package/build/level/tiled/renderer/TMXRenderer.d.ts.map +1 -0
  87. package/{dist/types → build}/level/tiled/renderer/TMXStaggeredRenderer.d.ts +1 -2
  88. package/build/level/tiled/renderer/TMXStaggeredRenderer.d.ts.map +1 -0
  89. package/{dist/types → build}/level/tiled/renderer/autodetect.d.ts +4 -3
  90. package/build/level/tiled/renderer/autodetect.d.ts.map +1 -0
  91. package/build/loader/cache.d.ts +10 -0
  92. package/build/loader/cache.d.ts.map +1 -0
  93. package/{dist/types → build}/loader/loader.d.ts +19 -13
  94. package/build/loader/loader.d.ts.map +1 -0
  95. package/{dist/types → build}/loader/loadingscreen.d.ts +1 -0
  96. package/build/loader/loadingscreen.d.ts.map +1 -0
  97. package/{dist/types → build}/loader/parsers/binary.d.ts +2 -1
  98. package/build/loader/parsers/binary.d.ts.map +1 -0
  99. package/{dist/types → build}/loader/parsers/compressed_textures/compressed_image.d.ts +1 -0
  100. package/build/loader/parsers/compressed_textures/compressed_image.d.ts.map +1 -0
  101. package/build/loader/parsers/compressed_textures/parseDDS.d.ts +2 -0
  102. package/build/loader/parsers/compressed_textures/parseDDS.d.ts.map +1 -0
  103. package/build/loader/parsers/compressed_textures/parseKTX.d.ts +2 -0
  104. package/build/loader/parsers/compressed_textures/parseKTX.d.ts.map +1 -0
  105. package/build/loader/parsers/compressed_textures/parseKTX2.d.ts +2 -0
  106. package/build/loader/parsers/compressed_textures/parseKTX2.d.ts.map +1 -0
  107. package/build/loader/parsers/compressed_textures/parsePKM.d.ts +2 -0
  108. package/build/loader/parsers/compressed_textures/parsePKM.d.ts.map +1 -0
  109. package/build/loader/parsers/compressed_textures/parsePVR.d.ts +2 -0
  110. package/build/loader/parsers/compressed_textures/parsePVR.d.ts.map +1 -0
  111. package/{dist/types → build}/loader/parsers/fetchdata.d.ts +2 -1
  112. package/build/loader/parsers/fetchdata.d.ts.map +1 -0
  113. package/{dist/types → build}/loader/parsers/fontface.d.ts +2 -1
  114. package/build/loader/parsers/fontface.d.ts.map +1 -0
  115. package/{dist/types → build}/loader/parsers/image.d.ts +2 -1
  116. package/build/loader/parsers/image.d.ts.map +1 -0
  117. package/{dist/types → build}/loader/parsers/json.d.ts +2 -1
  118. package/build/loader/parsers/json.d.ts.map +1 -0
  119. package/{dist/types → build}/loader/parsers/script.d.ts +2 -1
  120. package/build/loader/parsers/script.d.ts.map +1 -0
  121. package/{dist/types → build}/loader/parsers/tmx.d.ts +2 -1
  122. package/build/loader/parsers/tmx.d.ts.map +1 -0
  123. package/{dist/types → build}/loader/parsers/video.d.ts +2 -1
  124. package/build/loader/parsers/video.d.ts.map +1 -0
  125. package/build/math/color.d.ts +192 -0
  126. package/build/math/color.d.ts.map +1 -0
  127. package/build/math/math.d.ts +128 -0
  128. package/build/math/math.d.ts.map +1 -0
  129. package/build/math/matrix2d.d.ts +163 -0
  130. package/build/math/matrix2d.d.ts.map +1 -0
  131. package/build/math/matrix3d.d.ts +188 -0
  132. package/build/math/matrix3d.d.ts.map +1 -0
  133. package/build/math/observableVector2d.d.ts +286 -0
  134. package/build/math/observableVector2d.d.ts.map +1 -0
  135. package/build/math/observableVector2d_old.d.ts +76 -0
  136. package/build/math/observableVector2d_old.d.ts.map +1 -0
  137. package/build/math/observableVector3d.d.ts +283 -0
  138. package/build/math/observableVector3d.d.ts.map +1 -0
  139. package/build/math/observableVector3d_old.d.ts +81 -0
  140. package/build/math/observableVector3d_old.d.ts.map +1 -0
  141. package/build/math/vector2d.d.ts +253 -0
  142. package/build/math/vector2d.d.ts.map +1 -0
  143. package/build/math/vector3d.d.ts +242 -0
  144. package/build/math/vector3d.d.ts.map +1 -0
  145. package/{dist/types → build}/particles/emitter.d.ts +7 -10
  146. package/build/particles/emitter.d.ts.map +1 -0
  147. package/build/particles/particle.d.ts +47 -0
  148. package/build/particles/particle.d.ts.map +1 -0
  149. package/{dist/types → build}/particles/settings.d.ts +1 -0
  150. package/build/particles/settings.d.ts.map +1 -0
  151. package/{dist/types → build}/physics/body.d.ts +27 -27
  152. package/build/physics/body.d.ts.map +1 -0
  153. package/build/physics/bounds.d.ts +192 -0
  154. package/build/physics/bounds.d.ts.map +1 -0
  155. package/{dist/types → build}/physics/collision.d.ts +5 -5
  156. package/build/physics/collision.d.ts.map +1 -0
  157. package/{dist/types → build}/physics/detector.d.ts +8 -6
  158. package/build/physics/detector.d.ts.map +1 -0
  159. package/{dist/types → build}/physics/quadtree.d.ts +5 -19
  160. package/build/physics/quadtree.d.ts.map +1 -0
  161. package/{dist/types → build}/physics/response.d.ts +46 -5
  162. package/build/physics/response.d.ts.map +1 -0
  163. package/{dist/types → build}/physics/sat.d.ts +3 -2
  164. package/build/physics/sat.d.ts.map +1 -0
  165. package/{dist/types → build}/physics/world.d.ts +5 -4
  166. package/build/physics/world.d.ts.map +1 -0
  167. package/{dist/types → build}/plugin/plugin.d.ts +8 -19
  168. package/build/plugin/plugin.d.ts.map +1 -0
  169. package/build/polyfill/console.d.ts +2 -0
  170. package/build/polyfill/console.d.ts.map +1 -0
  171. package/build/polyfill/index.d.ts +6 -0
  172. package/build/polyfill/index.d.ts.map +1 -0
  173. package/build/polyfill/roundrect.d.ts +2 -0
  174. package/build/polyfill/roundrect.d.ts.map +1 -0
  175. package/build/pool.d.ts +39 -0
  176. package/build/pool.d.ts.map +1 -0
  177. package/{dist/types → build}/renderable/collectable.d.ts +2 -2
  178. package/build/renderable/collectable.d.ts.map +1 -0
  179. package/{dist/types → build}/renderable/colorlayer.d.ts +6 -10
  180. package/build/renderable/colorlayer.d.ts.map +1 -0
  181. package/{dist/types → build}/renderable/container.d.ts +14 -15
  182. package/build/renderable/container.d.ts.map +1 -0
  183. package/{dist/types → build}/renderable/draggable.d.ts +5 -13
  184. package/build/renderable/draggable.d.ts.map +1 -0
  185. package/{dist/types → build}/renderable/dragndrop.d.ts +7 -21
  186. package/build/renderable/dragndrop.d.ts.map +1 -0
  187. package/{dist/types → build}/renderable/entity/entity.d.ts +12 -13
  188. package/build/renderable/entity/entity.d.ts.map +1 -0
  189. package/{dist/types → build}/renderable/imagelayer.d.ts +17 -9
  190. package/build/renderable/imagelayer.d.ts.map +1 -0
  191. package/build/renderable/light2d.d.ts +73 -0
  192. package/build/renderable/light2d.d.ts.map +1 -0
  193. package/{dist/types → build}/renderable/nineslicesprite.d.ts +3 -4
  194. package/build/renderable/nineslicesprite.d.ts.map +1 -0
  195. package/{dist/types → build}/renderable/renderable.d.ts +57 -60
  196. package/build/renderable/renderable.d.ts.map +1 -0
  197. package/{dist/types → build}/renderable/sprite.d.ts +28 -14
  198. package/build/renderable/sprite.d.ts.map +1 -0
  199. package/{dist/types → build}/renderable/text/bitmaptext.d.ts +6 -7
  200. package/build/renderable/text/bitmaptext.d.ts.map +1 -0
  201. package/build/renderable/text/bitmaptextdata.d.ts +17 -0
  202. package/build/renderable/text/bitmaptextdata.d.ts.map +1 -0
  203. package/{dist/types → build}/renderable/text/glyph.d.ts +15 -3
  204. package/build/renderable/text/glyph.d.ts.map +1 -0
  205. package/{dist/types → build}/renderable/text/text.d.ts +7 -16
  206. package/build/renderable/text/text.d.ts.map +1 -0
  207. package/{dist/types → build}/renderable/text/textmetrics.d.ts +8 -9
  208. package/build/renderable/text/textmetrics.d.ts.map +1 -0
  209. package/{dist/types → build}/renderable/text/textstyle.d.ts +1 -0
  210. package/build/renderable/text/textstyle.d.ts.map +1 -0
  211. package/{dist/types → build}/renderable/trigger.d.ts +18 -7
  212. package/build/renderable/trigger.d.ts.map +1 -0
  213. package/{dist/types → build}/renderable/ui/uibaseelement.d.ts +7 -7
  214. package/build/renderable/ui/uibaseelement.d.ts.map +1 -0
  215. package/{dist/types → build}/renderable/ui/uispriteelement.d.ts +4 -6
  216. package/build/renderable/ui/uispriteelement.d.ts.map +1 -0
  217. package/{dist/types → build}/renderable/ui/uitextbutton.d.ts +17 -4
  218. package/build/renderable/ui/uitextbutton.d.ts.map +1 -0
  219. package/{dist/types → build}/state/stage.d.ts +3 -3
  220. package/build/state/stage.d.ts.map +1 -0
  221. package/{dist/types → build}/state/state.d.ts +10 -9
  222. package/build/state/state.d.ts.map +1 -0
  223. package/{dist/types → build}/system/device.d.ts +49 -80
  224. package/build/system/device.d.ts.map +1 -0
  225. package/build/system/dom.d.ts +2 -0
  226. package/build/system/dom.d.ts.map +1 -0
  227. package/{dist/types → build}/system/event.d.ts +124 -291
  228. package/build/system/event.d.ts.map +1 -0
  229. package/build/system/eventEmitter.d.ts +19 -0
  230. package/build/system/eventEmitter.d.ts.map +1 -0
  231. package/build/system/eventEmitter.spec.d.ts +2 -0
  232. package/build/system/eventEmitter.spec.d.ts.map +1 -0
  233. package/{dist/types/system/pooling.d.ts → build/system/legacy_pool.d.ts} +22 -7
  234. package/build/system/legacy_pool.d.ts.map +1 -0
  235. package/build/system/platform.d.ts +34 -0
  236. package/build/system/platform.d.ts.map +1 -0
  237. package/build/system/pool.d.ts +26 -0
  238. package/build/system/pool.d.ts.map +1 -0
  239. package/build/system/save.d.ts +3 -0
  240. package/build/system/save.d.ts.map +1 -0
  241. package/build/system/timer.d.ts +118 -0
  242. package/build/system/timer.d.ts.map +1 -0
  243. package/build/tweens/easing.d.ts +93 -0
  244. package/build/tweens/easing.d.ts.map +1 -0
  245. package/build/tweens/interpolation.d.ts +7 -0
  246. package/build/tweens/interpolation.d.ts.map +1 -0
  247. package/build/tweens/tween.d.ts +234 -0
  248. package/build/tweens/tween.d.ts.map +1 -0
  249. package/build/utils/agent.d.ts +16 -0
  250. package/build/utils/agent.d.ts.map +1 -0
  251. package/build/utils/array-multimap.d.ts +14 -0
  252. package/build/utils/array-multimap.d.ts.map +1 -0
  253. package/build/utils/array.d.ts +30 -0
  254. package/build/utils/array.d.ts.map +1 -0
  255. package/build/utils/file.d.ts +16 -0
  256. package/build/utils/file.d.ts.map +1 -0
  257. package/build/utils/function.d.ts +24 -0
  258. package/build/utils/function.d.ts.map +1 -0
  259. package/build/utils/semver.d.ts +2 -0
  260. package/build/utils/semver.d.ts.map +1 -0
  261. package/build/utils/string.d.ts +35 -0
  262. package/build/utils/string.d.ts.map +1 -0
  263. package/build/utils/types.d.ts +5 -0
  264. package/build/utils/types.d.ts.map +1 -0
  265. package/build/utils/utils.d.ts +49 -0
  266. package/build/utils/utils.d.ts.map +1 -0
  267. package/build/version.d.ts +5 -0
  268. package/build/version.d.ts.map +1 -0
  269. package/{dist/types → build}/video/canvas/canvas_renderer.d.ts +40 -32
  270. package/build/video/canvas/canvas_renderer.d.ts.map +1 -0
  271. package/{dist/types → build}/video/renderer.d.ts +36 -29
  272. package/build/video/renderer.d.ts.map +1 -0
  273. package/{dist/types → build}/video/rendertarget/canvasrendertarget.d.ts +8 -26
  274. package/build/video/rendertarget/canvasrendertarget.d.ts.map +1 -0
  275. package/{dist/types → build}/video/texture/atlas.d.ts +8 -8
  276. package/build/video/texture/atlas.d.ts.map +1 -0
  277. package/{dist/types → build}/video/texture/cache.d.ts +4 -3
  278. package/build/video/texture/cache.d.ts.map +1 -0
  279. package/{dist/types → build}/video/texture/parser/aseprite.d.ts +1 -0
  280. package/build/video/texture/parser/aseprite.d.ts.map +1 -0
  281. package/{dist/types → build}/video/texture/parser/spritesheet.d.ts +1 -0
  282. package/build/video/texture/parser/spritesheet.d.ts.map +1 -0
  283. package/{dist/types → build}/video/texture/parser/texturepacker.d.ts +1 -0
  284. package/build/video/texture/parser/texturepacker.d.ts.map +1 -0
  285. package/build/video/utils/autodetect.d.ts +8 -0
  286. package/build/video/utils/autodetect.d.ts.map +1 -0
  287. package/{dist/types → build}/video/video.d.ts +4 -3
  288. package/build/video/video.d.ts.map +1 -0
  289. package/{dist/types → build}/video/webgl/buffer/vertex.d.ts +5 -6
  290. package/build/video/webgl/buffer/vertex.d.ts.map +1 -0
  291. package/{dist/types → build}/video/webgl/compositors/compositor.d.ts +4 -4
  292. package/build/video/webgl/compositors/compositor.d.ts.map +1 -0
  293. package/{dist/types → build}/video/webgl/compositors/primitive_compositor.d.ts +4 -5
  294. package/build/video/webgl/compositors/primitive_compositor.d.ts.map +1 -0
  295. package/{dist/types → build}/video/webgl/compositors/quad_compositor.d.ts +4 -5
  296. package/build/video/webgl/compositors/quad_compositor.d.ts.map +1 -0
  297. package/{dist/types → build}/video/webgl/glshader.d.ts +2 -2
  298. package/build/video/webgl/glshader.d.ts.map +1 -0
  299. package/{dist/types → build}/video/webgl/utils/attributes.d.ts +1 -0
  300. package/build/video/webgl/utils/attributes.d.ts.map +1 -0
  301. package/{dist/types → build}/video/webgl/utils/precision.d.ts +1 -0
  302. package/build/video/webgl/utils/precision.d.ts.map +1 -0
  303. package/{dist/types → build}/video/webgl/utils/program.d.ts +1 -0
  304. package/build/video/webgl/utils/program.d.ts.map +1 -0
  305. package/{dist/types → build}/video/webgl/utils/string.d.ts +1 -0
  306. package/build/video/webgl/utils/string.d.ts.map +1 -0
  307. package/{dist/types → build}/video/webgl/utils/uniforms.d.ts +1 -0
  308. package/build/video/webgl/utils/uniforms.d.ts.map +1 -0
  309. package/{dist/types → build}/video/webgl/webgl_renderer.d.ts +37 -29
  310. package/build/video/webgl/webgl_renderer.d.ts.map +1 -0
  311. package/package.json +83 -104
  312. package/LICENSE.md +0 -21
  313. package/README.md +0 -223
  314. package/dist/melonjs.mjs/_virtual/_commonjsHelpers.js +0 -14
  315. package/dist/melonjs.mjs/_virtual/earcut.js +0 -10
  316. package/dist/melonjs.mjs/_virtual/howler.js +0 -10
  317. package/dist/melonjs.mjs/_virtual/index.js +0 -10
  318. package/dist/melonjs.mjs/_virtual/re.js +0 -10
  319. package/dist/melonjs.mjs/application/application.js +0 -443
  320. package/dist/melonjs.mjs/application/header.js +0 -40
  321. package/dist/melonjs.mjs/application/resize.js +0 -128
  322. package/dist/melonjs.mjs/application/settings.js +0 -70
  323. package/dist/melonjs.mjs/audio/audio.js +0 -623
  324. package/dist/melonjs.mjs/camera/camera2d.js +0 -737
  325. package/dist/melonjs.mjs/const.js +0 -32
  326. package/dist/melonjs.mjs/geometries/ellipse.js +0 -253
  327. package/dist/melonjs.mjs/geometries/line.js +0 -113
  328. package/dist/melonjs.mjs/geometries/path2d.js +0 -479
  329. package/dist/melonjs.mjs/geometries/point.js +0 -85
  330. package/dist/melonjs.mjs/geometries/poly.js +0 -441
  331. package/dist/melonjs.mjs/geometries/rectangle.js +0 -335
  332. package/dist/melonjs.mjs/geometries/roundrect.js +0 -165
  333. package/dist/melonjs.mjs/geometries/toarccanvas.js +0 -103
  334. package/dist/melonjs.mjs/index.js +0 -239
  335. package/dist/melonjs.mjs/input/gamepad.js +0 -495
  336. package/dist/melonjs.mjs/input/input.js +0 -26
  337. package/dist/melonjs.mjs/input/keyboard.js +0 -470
  338. package/dist/melonjs.mjs/input/pointer.js +0 -393
  339. package/dist/melonjs.mjs/input/pointerevent.js +0 -807
  340. package/dist/melonjs.mjs/lang/console.js +0 -44
  341. package/dist/melonjs.mjs/lang/deprecated.js +0 -200
  342. package/dist/melonjs.mjs/level/level.js +0 -298
  343. package/dist/melonjs.mjs/level/tiled/TMXGroup.js +0 -120
  344. package/dist/melonjs.mjs/level/tiled/TMXLayer.js +0 -432
  345. package/dist/melonjs.mjs/level/tiled/TMXObject.js +0 -295
  346. package/dist/melonjs.mjs/level/tiled/TMXTile.js +0 -177
  347. package/dist/melonjs.mjs/level/tiled/TMXTileMap.js +0 -574
  348. package/dist/melonjs.mjs/level/tiled/TMXTileset.js +0 -292
  349. package/dist/melonjs.mjs/level/tiled/TMXTilesetGroup.js +0 -74
  350. package/dist/melonjs.mjs/level/tiled/TMXUtils.js +0 -417
  351. package/dist/melonjs.mjs/level/tiled/constants.js +0 -17
  352. package/dist/melonjs.mjs/level/tiled/renderer/TMXHexagonalRenderer.js +0 -503
  353. package/dist/melonjs.mjs/level/tiled/renderer/TMXIsometricRenderer.js +0 -215
  354. package/dist/melonjs.mjs/level/tiled/renderer/TMXOrthogonalRenderer.js +0 -155
  355. package/dist/melonjs.mjs/level/tiled/renderer/TMXRenderer.js +0 -113
  356. package/dist/melonjs.mjs/level/tiled/renderer/TMXStaggeredRenderer.js +0 -107
  357. package/dist/melonjs.mjs/level/tiled/renderer/autodetect.js +0 -38
  358. package/dist/melonjs.mjs/loader/cache.js +0 -30
  359. package/dist/melonjs.mjs/loader/loader.js +0 -729
  360. package/dist/melonjs.mjs/loader/loadingscreen.js +0 -118
  361. package/dist/melonjs.mjs/loader/melonjs_logo.png.js +0 -10
  362. package/dist/melonjs.mjs/loader/parsers/binary.js +0 -42
  363. package/dist/melonjs.mjs/loader/parsers/compressed_textures/compressed_image.js +0 -58
  364. package/dist/melonjs.mjs/loader/parsers/compressed_textures/parseDDS.js +0 -13
  365. package/dist/melonjs.mjs/loader/parsers/compressed_textures/parseKTX.js +0 -13
  366. package/dist/melonjs.mjs/loader/parsers/compressed_textures/parseKTX2.js +0 -13
  367. package/dist/melonjs.mjs/loader/parsers/compressed_textures/parsePKM.js +0 -13
  368. package/dist/melonjs.mjs/loader/parsers/compressed_textures/parsePVR.js +0 -136
  369. package/dist/melonjs.mjs/loader/parsers/fetchdata.js +0 -62
  370. package/dist/melonjs.mjs/loader/parsers/fontface.js +0 -62
  371. package/dist/melonjs.mjs/loader/parsers/image.js +0 -129
  372. package/dist/melonjs.mjs/loader/parsers/json.js +0 -43
  373. package/dist/melonjs.mjs/loader/parsers/script.js +0 -46
  374. package/dist/melonjs.mjs/loader/parsers/tmx.js +0 -103
  375. package/dist/melonjs.mjs/loader/parsers/video.js +0 -99
  376. package/dist/melonjs.mjs/math/color.js +0 -635
  377. package/dist/melonjs.mjs/math/math.js +0 -221
  378. package/dist/melonjs.mjs/math/matrix2.js +0 -495
  379. package/dist/melonjs.mjs/math/matrix3.js +0 -628
  380. package/dist/melonjs.mjs/math/observable_vector2.js +0 -468
  381. package/dist/melonjs.mjs/math/observable_vector3.js +0 -564
  382. package/dist/melonjs.mjs/math/vector2.js +0 -431
  383. package/dist/melonjs.mjs/math/vector3.js +0 -473
  384. package/dist/melonjs.mjs/node_modules/@teppeis/multimaps/dist/esm/arraymultimap.js +0 -45
  385. package/dist/melonjs.mjs/node_modules/@teppeis/multimaps/dist/esm/multimap.js +0 -130
  386. package/dist/melonjs.mjs/node_modules/earcut/src/earcut.js +0 -694
  387. package/dist/melonjs.mjs/node_modules/eventemitter3/index.js +0 -352
  388. package/dist/melonjs.mjs/node_modules/eventemitter3/index2.js +0 -12
  389. package/dist/melonjs.mjs/node_modules/howler/dist/howler.js +0 -3246
  390. package/dist/melonjs.mjs/node_modules/semver/classes/comparator.js +0 -165
  391. package/dist/melonjs.mjs/node_modules/semver/classes/range.js +0 -565
  392. package/dist/melonjs.mjs/node_modules/semver/classes/semver.js +0 -317
  393. package/dist/melonjs.mjs/node_modules/semver/functions/clean.js +0 -17
  394. package/dist/melonjs.mjs/node_modules/semver/functions/cmp.js +0 -68
  395. package/dist/melonjs.mjs/node_modules/semver/functions/coerce.js +0 -73
  396. package/dist/melonjs.mjs/node_modules/semver/functions/compare-build.js +0 -18
  397. package/dist/melonjs.mjs/node_modules/semver/functions/compare-loose.js +0 -14
  398. package/dist/melonjs.mjs/node_modules/semver/functions/compare.js +0 -16
  399. package/dist/melonjs.mjs/node_modules/semver/functions/diff.js +0 -76
  400. package/dist/melonjs.mjs/node_modules/semver/functions/eq.js +0 -14
  401. package/dist/melonjs.mjs/node_modules/semver/functions/gt.js +0 -14
  402. package/dist/melonjs.mjs/node_modules/semver/functions/gte.js +0 -14
  403. package/dist/melonjs.mjs/node_modules/semver/functions/inc.js +0 -30
  404. package/dist/melonjs.mjs/node_modules/semver/functions/lt.js +0 -14
  405. package/dist/melonjs.mjs/node_modules/semver/functions/lte.js +0 -14
  406. package/dist/melonjs.mjs/node_modules/semver/functions/major.js +0 -14
  407. package/dist/melonjs.mjs/node_modules/semver/functions/minor.js +0 -14
  408. package/dist/melonjs.mjs/node_modules/semver/functions/neq.js +0 -14
  409. package/dist/melonjs.mjs/node_modules/semver/functions/parse.js +0 -27
  410. package/dist/melonjs.mjs/node_modules/semver/functions/patch.js +0 -14
  411. package/dist/melonjs.mjs/node_modules/semver/functions/prerelease.js +0 -17
  412. package/dist/melonjs.mjs/node_modules/semver/functions/rcompare.js +0 -14
  413. package/dist/melonjs.mjs/node_modules/semver/functions/rsort.js +0 -14
  414. package/dist/melonjs.mjs/node_modules/semver/functions/satisfies.js +0 -21
  415. package/dist/melonjs.mjs/node_modules/semver/functions/sort.js +0 -14
  416. package/dist/melonjs.mjs/node_modules/semver/functions/valid.js +0 -17
  417. package/dist/melonjs.mjs/node_modules/semver/index.js +0 -140
  418. package/dist/melonjs.mjs/node_modules/semver/internal/constants.js +0 -44
  419. package/dist/melonjs.mjs/node_modules/semver/internal/debug.js +0 -18
  420. package/dist/melonjs.mjs/node_modules/semver/internal/identifiers.js +0 -32
  421. package/dist/melonjs.mjs/node_modules/semver/internal/lrucache.js +0 -49
  422. package/dist/melonjs.mjs/node_modules/semver/internal/parse-options.js +0 -24
  423. package/dist/melonjs.mjs/node_modules/semver/internal/re.js +0 -234
  424. package/dist/melonjs.mjs/node_modules/semver/ranges/gtr.js +0 -15
  425. package/dist/melonjs.mjs/node_modules/semver/ranges/intersects.js +0 -18
  426. package/dist/melonjs.mjs/node_modules/semver/ranges/ltr.js +0 -15
  427. package/dist/melonjs.mjs/node_modules/semver/ranges/max-satisfying.js +0 -37
  428. package/dist/melonjs.mjs/node_modules/semver/ranges/min-satisfying.js +0 -36
  429. package/dist/melonjs.mjs/node_modules/semver/ranges/min-version.js +0 -74
  430. package/dist/melonjs.mjs/node_modules/semver/ranges/outside.js +0 -98
  431. package/dist/melonjs.mjs/node_modules/semver/ranges/simplify.js +0 -59
  432. package/dist/melonjs.mjs/node_modules/semver/ranges/subset.js +0 -261
  433. package/dist/melonjs.mjs/node_modules/semver/ranges/to-comparators.js +0 -19
  434. package/dist/melonjs.mjs/node_modules/semver/ranges/valid.js +0 -22
  435. package/dist/melonjs.mjs/particles/emitter.js +0 -265
  436. package/dist/melonjs.mjs/particles/particle.js +0 -190
  437. package/dist/melonjs.mjs/particles/settings.js +0 -317
  438. package/dist/melonjs.mjs/physics/body.js +0 -717
  439. package/dist/melonjs.mjs/physics/bounds.js +0 -415
  440. package/dist/melonjs.mjs/physics/collision.js +0 -135
  441. package/dist/melonjs.mjs/physics/detector.js +0 -227
  442. package/dist/melonjs.mjs/physics/quadtree.js +0 -402
  443. package/dist/melonjs.mjs/physics/response.js +0 -57
  444. package/dist/melonjs.mjs/physics/sat.js +0 -492
  445. package/dist/melonjs.mjs/physics/world.js +0 -228
  446. package/dist/melonjs.mjs/plugin/plugin.js +0 -172
  447. package/dist/melonjs.mjs/renderable/collectable.js +0 -60
  448. package/dist/melonjs.mjs/renderable/colorlayer.js +0 -83
  449. package/dist/melonjs.mjs/renderable/container.js +0 -1016
  450. package/dist/melonjs.mjs/renderable/draggable.js +0 -121
  451. package/dist/melonjs.mjs/renderable/dragndrop.js +0 -119
  452. package/dist/melonjs.mjs/renderable/entity/entity.js +0 -263
  453. package/dist/melonjs.mjs/renderable/imagelayer.js +0 -293
  454. package/dist/melonjs.mjs/renderable/light2d.js +0 -172
  455. package/dist/melonjs.mjs/renderable/nineslicesprite.js +0 -248
  456. package/dist/melonjs.mjs/renderable/renderable.js +0 -878
  457. package/dist/melonjs.mjs/renderable/sprite.js +0 -700
  458. package/dist/melonjs.mjs/renderable/text/bitmaptext.js +0 -421
  459. package/dist/melonjs.mjs/renderable/text/bitmaptextdata.js +0 -195
  460. package/dist/melonjs.mjs/renderable/text/glyph.js +0 -65
  461. package/dist/melonjs.mjs/renderable/text/text.js +0 -424
  462. package/dist/melonjs.mjs/renderable/text/textmetrics.js +0 -176
  463. package/dist/melonjs.mjs/renderable/text/textstyle.js +0 -21
  464. package/dist/melonjs.mjs/renderable/trigger.js +0 -163
  465. package/dist/melonjs.mjs/renderable/ui/uibaseelement.js +0 -285
  466. package/dist/melonjs.mjs/renderable/ui/uispriteelement.js +0 -231
  467. package/dist/melonjs.mjs/renderable/ui/uitextbutton.js +0 -146
  468. package/dist/melonjs.mjs/state/stage.js +0 -235
  469. package/dist/melonjs.mjs/state/state.js +0 -548
  470. package/dist/melonjs.mjs/system/device.js +0 -872
  471. package/dist/melonjs.mjs/system/dom.js +0 -79
  472. package/dist/melonjs.mjs/system/event.js +0 -606
  473. package/dist/melonjs.mjs/system/platform.js +0 -43
  474. package/dist/melonjs.mjs/system/pooling.js +0 -182
  475. package/dist/melonjs.mjs/system/save.js +0 -157
  476. package/dist/melonjs.mjs/system/timer.js +0 -274
  477. package/dist/melonjs.mjs/tweens/easing.js +0 -334
  478. package/dist/melonjs.mjs/tweens/interpolation.js +0 -112
  479. package/dist/melonjs.mjs/tweens/tween.js +0 -479
  480. package/dist/melonjs.mjs/utils/agent.js +0 -77
  481. package/dist/melonjs.mjs/utils/array.js +0 -63
  482. package/dist/melonjs.mjs/utils/file.js +0 -54
  483. package/dist/melonjs.mjs/utils/function.js +0 -69
  484. package/dist/melonjs.mjs/utils/string.js +0 -82
  485. package/dist/melonjs.mjs/utils/utils.js +0 -139
  486. package/dist/melonjs.mjs/video/canvas/canvas_renderer.js +0 -914
  487. package/dist/melonjs.mjs/video/renderer.js +0 -402
  488. package/dist/melonjs.mjs/video/rendertarget/canvasrendertarget.js +0 -316
  489. package/dist/melonjs.mjs/video/texture/atlas.js +0 -465
  490. package/dist/melonjs.mjs/video/texture/cache.js +0 -186
  491. package/dist/melonjs.mjs/video/texture/parser/aseprite.js +0 -78
  492. package/dist/melonjs.mjs/video/texture/parser/spritesheet.js +0 -77
  493. package/dist/melonjs.mjs/video/texture/parser/texturepacker.js +0 -64
  494. package/dist/melonjs.mjs/video/utils/autodetect.js +0 -27
  495. package/dist/melonjs.mjs/video/video.js +0 -142
  496. package/dist/melonjs.mjs/video/webgl/buffer/vertex.js +0 -146
  497. package/dist/melonjs.mjs/video/webgl/compositors/compositor.js +0 -240
  498. package/dist/melonjs.mjs/video/webgl/compositors/primitive_compositor.js +0 -82
  499. package/dist/melonjs.mjs/video/webgl/compositors/quad_compositor.js +0 -259
  500. package/dist/melonjs.mjs/video/webgl/glshader.js +0 -166
  501. package/dist/melonjs.mjs/video/webgl/shaders/primitive.frag.js +0 -10
  502. package/dist/melonjs.mjs/video/webgl/shaders/primitive.vert.js +0 -10
  503. package/dist/melonjs.mjs/video/webgl/shaders/quad.frag.js +0 -10
  504. package/dist/melonjs.mjs/video/webgl/shaders/quad.vert.js +0 -10
  505. package/dist/melonjs.mjs/video/webgl/utils/attributes.js +0 -25
  506. package/dist/melonjs.mjs/video/webgl/utils/precision.js +0 -38
  507. package/dist/melonjs.mjs/video/webgl/utils/program.js +0 -67
  508. package/dist/melonjs.mjs/video/webgl/utils/string.js +0 -25
  509. package/dist/melonjs.mjs/video/webgl/utils/uniforms.js +0 -92
  510. package/dist/melonjs.mjs/video/webgl/webgl_renderer.js +0 -1246
  511. package/dist/melonjs.module.js +0 -43200
  512. package/dist/types/application/settings.d.ts +0 -106
  513. package/dist/types/const.d.ts +0 -21
  514. package/dist/types/geometries/ellipse.d.ts +0 -138
  515. package/dist/types/geometries/line.d.ts +0 -15
  516. package/dist/types/geometries/point.d.ts +0 -50
  517. package/dist/types/geometries/poly.d.ts +0 -186
  518. package/dist/types/geometries/rectangle.d.ts +0 -135
  519. package/dist/types/geometries/roundrect.d.ts +0 -43
  520. package/dist/types/geometries/toarccanvas.d.ts +0 -10
  521. package/dist/types/input/keyboard.d.ts +0 -205
  522. package/dist/types/input/pointer.d.ts +0 -261
  523. package/dist/types/lang/deprecated.d.ts +0 -68
  524. package/dist/types/loader/cache.d.ts +0 -9
  525. package/dist/types/loader/parsers/compressed_textures/parseDDS.d.ts +0 -1
  526. package/dist/types/loader/parsers/compressed_textures/parseKTX.d.ts +0 -1
  527. package/dist/types/loader/parsers/compressed_textures/parseKTX2.d.ts +0 -1
  528. package/dist/types/loader/parsers/compressed_textures/parsePKM.d.ts +0 -1
  529. package/dist/types/loader/parsers/compressed_textures/parsePVR.d.ts +0 -1
  530. package/dist/types/math/color.d.ts +0 -179
  531. package/dist/types/math/math.d.ts +0 -149
  532. package/dist/types/math/matrix2.d.ts +0 -174
  533. package/dist/types/math/matrix3.d.ts +0 -186
  534. package/dist/types/math/observable_vector2.d.ts +0 -278
  535. package/dist/types/math/observable_vector3.d.ts +0 -300
  536. package/dist/types/math/vector2.d.ts +0 -255
  537. package/dist/types/math/vector3.d.ts +0 -271
  538. package/dist/types/particles/particle.d.ts +0 -36
  539. package/dist/types/physics/bounds.d.ts +0 -203
  540. package/dist/types/polyfill/console.d.ts +0 -1
  541. package/dist/types/polyfill/index.d.ts +0 -1
  542. package/dist/types/polyfill/roundrect.d.ts +0 -1
  543. package/dist/types/renderable/light2d.d.ts +0 -60
  544. package/dist/types/renderable/text/bitmaptextdata.d.ts +0 -35
  545. package/dist/types/system/dom.d.ts +0 -1
  546. package/dist/types/system/platform.d.ts +0 -33
  547. package/dist/types/system/save.d.ts +0 -25
  548. package/dist/types/system/timer.d.ts +0 -126
  549. package/dist/types/tweens/easing.d.ts +0 -46
  550. package/dist/types/tweens/interpolation.d.ts +0 -18
  551. package/dist/types/tweens/tween.d.ts +0 -195
  552. package/dist/types/utils/agent.d.ts +0 -21
  553. package/dist/types/utils/array.d.ts +0 -39
  554. package/dist/types/utils/file.d.ts +0 -27
  555. package/dist/types/utils/function.d.ts +0 -31
  556. package/dist/types/utils/string.d.ts +0 -50
  557. package/dist/types/utils/utils.d.ts +0 -54
  558. package/dist/types/video/utils/autodetect.d.ts +0 -5
  559. package/src/application/application.js +0 -435
  560. package/src/application/header.js +0 -31
  561. package/src/application/resize.js +0 -119
  562. package/src/application/settings.js +0 -61
  563. package/src/audio/audio.js +0 -622
  564. package/src/camera/camera2d.js +0 -731
  565. package/src/const.js +0 -23
  566. package/src/geometries/ellipse.js +0 -244
  567. package/src/geometries/line.js +0 -104
  568. package/src/geometries/path2d.js +0 -470
  569. package/src/geometries/point.js +0 -76
  570. package/src/geometries/poly.js +0 -432
  571. package/src/geometries/rectangle.js +0 -326
  572. package/src/geometries/roundrect.js +0 -156
  573. package/src/geometries/toarccanvas.js +0 -94
  574. package/src/index.js +0 -315
  575. package/src/input/gamepad.js +0 -487
  576. package/src/input/input.js +0 -17
  577. package/src/input/keyboard.js +0 -461
  578. package/src/input/pointer.js +0 -386
  579. package/src/input/pointerevent.js +0 -798
  580. package/src/lang/console.js +0 -36
  581. package/src/lang/deprecated.js +0 -192
  582. package/src/level/level.js +0 -290
  583. package/src/level/tiled/TMXGroup.js +0 -111
  584. package/src/level/tiled/TMXLayer.js +0 -424
  585. package/src/level/tiled/TMXObject.js +0 -286
  586. package/src/level/tiled/TMXTile.js +0 -168
  587. package/src/level/tiled/TMXTileMap.js +0 -569
  588. package/src/level/tiled/TMXTileset.js +0 -284
  589. package/src/level/tiled/TMXTilesetGroup.js +0 -66
  590. package/src/level/tiled/TMXUtils.js +0 -408
  591. package/src/level/tiled/constants.js +0 -8
  592. package/src/level/tiled/renderer/TMXHexagonalRenderer.js +0 -497
  593. package/src/level/tiled/renderer/TMXIsometricRenderer.js +0 -208
  594. package/src/level/tiled/renderer/TMXOrthogonalRenderer.js +0 -149
  595. package/src/level/tiled/renderer/TMXRenderer.js +0 -103
  596. package/src/level/tiled/renderer/TMXStaggeredRenderer.js +0 -100
  597. package/src/level/tiled/renderer/autodetect.js +0 -29
  598. package/src/loader/cache.js +0 -22
  599. package/src/loader/loader.js +0 -728
  600. package/src/loader/loadingscreen.js +0 -112
  601. package/src/loader/melonjs_logo.png +0 -0
  602. package/src/loader/parsers/binary.js +0 -33
  603. package/src/loader/parsers/compressed_textures/compressed_image.js +0 -49
  604. package/src/loader/parsers/compressed_textures/parseDDS.js +0 -5
  605. package/src/loader/parsers/compressed_textures/parseKTX.js +0 -5
  606. package/src/loader/parsers/compressed_textures/parseKTX2.js +0 -5
  607. package/src/loader/parsers/compressed_textures/parsePKM.js +0 -5
  608. package/src/loader/parsers/compressed_textures/parsePVR.js +0 -127
  609. package/src/loader/parsers/fetchdata.js +0 -53
  610. package/src/loader/parsers/fontface.js +0 -54
  611. package/src/loader/parsers/image.js +0 -120
  612. package/src/loader/parsers/json.js +0 -35
  613. package/src/loader/parsers/script.js +0 -37
  614. package/src/loader/parsers/tmx.js +0 -95
  615. package/src/loader/parsers/video.js +0 -90
  616. package/src/math/color.js +0 -627
  617. package/src/math/math.js +0 -212
  618. package/src/math/matrix2.js +0 -487
  619. package/src/math/matrix3.js +0 -620
  620. package/src/math/observable_vector2.js +0 -460
  621. package/src/math/observable_vector3.js +0 -556
  622. package/src/math/vector2.js +0 -423
  623. package/src/math/vector3.js +0 -465
  624. package/src/particles/emitter.js +0 -258
  625. package/src/particles/particle.js +0 -182
  626. package/src/particles/settings.js +0 -310
  627. package/src/physics/body.js +0 -709
  628. package/src/physics/bounds.js +0 -407
  629. package/src/physics/collision.js +0 -128
  630. package/src/physics/detector.js +0 -218
  631. package/src/physics/quadtree.js +0 -393
  632. package/src/physics/response.js +0 -48
  633. package/src/physics/sat.js +0 -483
  634. package/src/physics/world.js +0 -220
  635. package/src/plugin/plugin.js +0 -163
  636. package/src/polyfill/console.js +0 -11
  637. package/src/polyfill/index.js +0 -13
  638. package/src/polyfill/roundrect.js +0 -237
  639. package/src/renderable/collectable.js +0 -51
  640. package/src/renderable/colorlayer.js +0 -74
  641. package/src/renderable/container.js +0 -1008
  642. package/src/renderable/draggable.js +0 -114
  643. package/src/renderable/dragndrop.js +0 -110
  644. package/src/renderable/entity/entity.js +0 -254
  645. package/src/renderable/imagelayer.js +0 -284
  646. package/src/renderable/light2d.js +0 -163
  647. package/src/renderable/nineslicesprite.js +0 -239
  648. package/src/renderable/renderable.js +0 -869
  649. package/src/renderable/sprite.js +0 -691
  650. package/src/renderable/text/bitmaptext.js +0 -418
  651. package/src/renderable/text/bitmaptextdata.js +0 -186
  652. package/src/renderable/text/glyph.js +0 -57
  653. package/src/renderable/text/text.js +0 -415
  654. package/src/renderable/text/textmetrics.js +0 -167
  655. package/src/renderable/text/textstyle.js +0 -12
  656. package/src/renderable/trigger.js +0 -154
  657. package/src/renderable/ui/uibaseelement.js +0 -276
  658. package/src/renderable/ui/uispriteelement.js +0 -223
  659. package/src/renderable/ui/uitextbutton.js +0 -140
  660. package/src/state/stage.js +0 -226
  661. package/src/state/state.js +0 -541
  662. package/src/system/device.js +0 -863
  663. package/src/system/dom.js +0 -70
  664. package/src/system/event.js +0 -597
  665. package/src/system/platform.js +0 -34
  666. package/src/system/pooling.js +0 -190
  667. package/src/system/save.js +0 -148
  668. package/src/system/timer.js +0 -281
  669. package/src/tweens/easing.js +0 -325
  670. package/src/tweens/interpolation.js +0 -103
  671. package/src/tweens/tween.js +0 -470
  672. package/src/utils/agent.js +0 -68
  673. package/src/utils/array.js +0 -54
  674. package/src/utils/file.js +0 -46
  675. package/src/utils/function.js +0 -60
  676. package/src/utils/string.js +0 -73
  677. package/src/utils/utils.js +0 -127
  678. package/src/video/canvas/canvas_renderer.js +0 -905
  679. package/src/video/renderer.js +0 -393
  680. package/src/video/rendertarget/canvasrendertarget.js +0 -309
  681. package/src/video/texture/atlas.js +0 -456
  682. package/src/video/texture/cache.js +0 -178
  683. package/src/video/texture/parser/aseprite.js +0 -69
  684. package/src/video/texture/parser/spritesheet.js +0 -68
  685. package/src/video/texture/parser/texturepacker.js +0 -55
  686. package/src/video/utils/autodetect.js +0 -18
  687. package/src/video/video.js +0 -160
  688. package/src/video/webgl/buffer/vertex.js +0 -137
  689. package/src/video/webgl/compositors/compositor.js +0 -231
  690. package/src/video/webgl/compositors/primitive_compositor.js +0 -73
  691. package/src/video/webgl/compositors/quad_compositor.js +0 -250
  692. package/src/video/webgl/glshader.js +0 -158
  693. package/src/video/webgl/shaders/primitive.frag +0 -5
  694. package/src/video/webgl/shaders/primitive.vert +0 -15
  695. package/src/video/webgl/shaders/quad.frag +0 -7
  696. package/src/video/webgl/shaders/quad.vert +0 -18
  697. package/src/video/webgl/utils/attributes.js +0 -16
  698. package/src/video/webgl/utils/precision.js +0 -29
  699. package/src/video/webgl/utils/program.js +0 -58
  700. package/src/video/webgl/utils/string.js +0 -16
  701. package/src/video/webgl/utils/uniforms.js +0 -84
  702. package/src/video/webgl/webgl_renderer.js +0 -1237
@@ -1,3246 +0,0 @@
1
- /*!
2
- * melonJS Game Engine - v17.4.0
3
- * http://www.melonjs.org
4
- * melonjs is licensed under the MIT License.
5
- * http://www.opensource.org/licenses/mit-license
6
- * @copyright (C) 2011 - 2024 Olivier Biot (AltByte Pte Ltd)
7
- */
8
- import { commonjsGlobal } from '../../../_virtual/_commonjsHelpers.js';
9
- import { __exports as howler } from '../../../_virtual/howler.js';
10
-
11
- /*!
12
- * howler.js v2.2.4
13
- * howlerjs.com
14
- *
15
- * (c) 2013-2020, James Simpson of GoldFire Studios
16
- * goldfirestudios.com
17
- *
18
- * MIT License
19
- */
20
-
21
- (function (exports) {
22
- (function() {
23
-
24
- /** Global Methods **/
25
- /***************************************************************************/
26
-
27
- /**
28
- * Create the global controller. All contained methods and properties apply
29
- * to all sounds that are currently playing or will be in the future.
30
- */
31
- var HowlerGlobal = function() {
32
- this.init();
33
- };
34
- HowlerGlobal.prototype = {
35
- /**
36
- * Initialize the global Howler object.
37
- * @return {Howler}
38
- */
39
- init: function() {
40
- var self = this || Howler;
41
-
42
- // Create a global ID counter.
43
- self._counter = 1000;
44
-
45
- // Pool of unlocked HTML5 Audio objects.
46
- self._html5AudioPool = [];
47
- self.html5PoolSize = 10;
48
-
49
- // Internal properties.
50
- self._codecs = {};
51
- self._howls = [];
52
- self._muted = false;
53
- self._volume = 1;
54
- self._canPlayEvent = 'canplaythrough';
55
- self._navigator = (typeof window !== 'undefined' && window.navigator) ? window.navigator : null;
56
-
57
- // Public properties.
58
- self.masterGain = null;
59
- self.noAudio = false;
60
- self.usingWebAudio = true;
61
- self.autoSuspend = true;
62
- self.ctx = null;
63
-
64
- // Set to false to disable the auto audio unlocker.
65
- self.autoUnlock = true;
66
-
67
- // Setup the various state values for global tracking.
68
- self._setup();
69
-
70
- return self;
71
- },
72
-
73
- /**
74
- * Get/set the global volume for all sounds.
75
- * @param {Float} vol Volume from 0.0 to 1.0.
76
- * @return {Howler/Float} Returns self or current volume.
77
- */
78
- volume: function(vol) {
79
- var self = this || Howler;
80
- vol = parseFloat(vol);
81
-
82
- // If we don't have an AudioContext created yet, run the setup.
83
- if (!self.ctx) {
84
- setupAudioContext();
85
- }
86
-
87
- if (typeof vol !== 'undefined' && vol >= 0 && vol <= 1) {
88
- self._volume = vol;
89
-
90
- // Don't update any of the nodes if we are muted.
91
- if (self._muted) {
92
- return self;
93
- }
94
-
95
- // When using Web Audio, we just need to adjust the master gain.
96
- if (self.usingWebAudio) {
97
- self.masterGain.gain.setValueAtTime(vol, Howler.ctx.currentTime);
98
- }
99
-
100
- // Loop through and change volume for all HTML5 audio nodes.
101
- for (var i=0; i<self._howls.length; i++) {
102
- if (!self._howls[i]._webAudio) {
103
- // Get all of the sounds in this Howl group.
104
- var ids = self._howls[i]._getSoundIds();
105
-
106
- // Loop through all sounds and change the volumes.
107
- for (var j=0; j<ids.length; j++) {
108
- var sound = self._howls[i]._soundById(ids[j]);
109
-
110
- if (sound && sound._node) {
111
- sound._node.volume = sound._volume * vol;
112
- }
113
- }
114
- }
115
- }
116
-
117
- return self;
118
- }
119
-
120
- return self._volume;
121
- },
122
-
123
- /**
124
- * Handle muting and unmuting globally.
125
- * @param {Boolean} muted Is muted or not.
126
- */
127
- mute: function(muted) {
128
- var self = this || Howler;
129
-
130
- // If we don't have an AudioContext created yet, run the setup.
131
- if (!self.ctx) {
132
- setupAudioContext();
133
- }
134
-
135
- self._muted = muted;
136
-
137
- // With Web Audio, we just need to mute the master gain.
138
- if (self.usingWebAudio) {
139
- self.masterGain.gain.setValueAtTime(muted ? 0 : self._volume, Howler.ctx.currentTime);
140
- }
141
-
142
- // Loop through and mute all HTML5 Audio nodes.
143
- for (var i=0; i<self._howls.length; i++) {
144
- if (!self._howls[i]._webAudio) {
145
- // Get all of the sounds in this Howl group.
146
- var ids = self._howls[i]._getSoundIds();
147
-
148
- // Loop through all sounds and mark the audio node as muted.
149
- for (var j=0; j<ids.length; j++) {
150
- var sound = self._howls[i]._soundById(ids[j]);
151
-
152
- if (sound && sound._node) {
153
- sound._node.muted = (muted) ? true : sound._muted;
154
- }
155
- }
156
- }
157
- }
158
-
159
- return self;
160
- },
161
-
162
- /**
163
- * Handle stopping all sounds globally.
164
- */
165
- stop: function() {
166
- var self = this || Howler;
167
-
168
- // Loop through all Howls and stop them.
169
- for (var i=0; i<self._howls.length; i++) {
170
- self._howls[i].stop();
171
- }
172
-
173
- return self;
174
- },
175
-
176
- /**
177
- * Unload and destroy all currently loaded Howl objects.
178
- * @return {Howler}
179
- */
180
- unload: function() {
181
- var self = this || Howler;
182
-
183
- for (var i=self._howls.length-1; i>=0; i--) {
184
- self._howls[i].unload();
185
- }
186
-
187
- // Create a new AudioContext to make sure it is fully reset.
188
- if (self.usingWebAudio && self.ctx && typeof self.ctx.close !== 'undefined') {
189
- self.ctx.close();
190
- self.ctx = null;
191
- setupAudioContext();
192
- }
193
-
194
- return self;
195
- },
196
-
197
- /**
198
- * Check for codec support of specific extension.
199
- * @param {String} ext Audio file extention.
200
- * @return {Boolean}
201
- */
202
- codecs: function(ext) {
203
- return (this || Howler)._codecs[ext.replace(/^x-/, '')];
204
- },
205
-
206
- /**
207
- * Setup various state values for global tracking.
208
- * @return {Howler}
209
- */
210
- _setup: function() {
211
- var self = this || Howler;
212
-
213
- // Keeps track of the suspend/resume state of the AudioContext.
214
- self.state = self.ctx ? self.ctx.state || 'suspended' : 'suspended';
215
-
216
- // Automatically begin the 30-second suspend process
217
- self._autoSuspend();
218
-
219
- // Check if audio is available.
220
- if (!self.usingWebAudio) {
221
- // No audio is available on this system if noAudio is set to true.
222
- if (typeof Audio !== 'undefined') {
223
- try {
224
- var test = new Audio();
225
-
226
- // Check if the canplaythrough event is available.
227
- if (typeof test.oncanplaythrough === 'undefined') {
228
- self._canPlayEvent = 'canplay';
229
- }
230
- } catch(e) {
231
- self.noAudio = true;
232
- }
233
- } else {
234
- self.noAudio = true;
235
- }
236
- }
237
-
238
- // Test to make sure audio isn't disabled in Internet Explorer.
239
- try {
240
- var test = new Audio();
241
- if (test.muted) {
242
- self.noAudio = true;
243
- }
244
- } catch (e) {}
245
-
246
- // Check for supported codecs.
247
- if (!self.noAudio) {
248
- self._setupCodecs();
249
- }
250
-
251
- return self;
252
- },
253
-
254
- /**
255
- * Check for browser support for various codecs and cache the results.
256
- * @return {Howler}
257
- */
258
- _setupCodecs: function() {
259
- var self = this || Howler;
260
- var audioTest = null;
261
-
262
- // Must wrap in a try/catch because IE11 in server mode throws an error.
263
- try {
264
- audioTest = (typeof Audio !== 'undefined') ? new Audio() : null;
265
- } catch (err) {
266
- return self;
267
- }
268
-
269
- if (!audioTest || typeof audioTest.canPlayType !== 'function') {
270
- return self;
271
- }
272
-
273
- var mpegTest = audioTest.canPlayType('audio/mpeg;').replace(/^no$/, '');
274
-
275
- // Opera version <33 has mixed MP3 support, so we need to check for and block it.
276
- var ua = self._navigator ? self._navigator.userAgent : '';
277
- var checkOpera = ua.match(/OPR\/(\d+)/g);
278
- var isOldOpera = (checkOpera && parseInt(checkOpera[0].split('/')[1], 10) < 33);
279
- var checkSafari = ua.indexOf('Safari') !== -1 && ua.indexOf('Chrome') === -1;
280
- var safariVersion = ua.match(/Version\/(.*?) /);
281
- var isOldSafari = (checkSafari && safariVersion && parseInt(safariVersion[1], 10) < 15);
282
-
283
- self._codecs = {
284
- mp3: !!(!isOldOpera && (mpegTest || audioTest.canPlayType('audio/mp3;').replace(/^no$/, ''))),
285
- mpeg: !!mpegTest,
286
- opus: !!audioTest.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/, ''),
287
- ogg: !!audioTest.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, ''),
288
- oga: !!audioTest.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, ''),
289
- wav: !!(audioTest.canPlayType('audio/wav; codecs="1"') || audioTest.canPlayType('audio/wav')).replace(/^no$/, ''),
290
- aac: !!audioTest.canPlayType('audio/aac;').replace(/^no$/, ''),
291
- caf: !!audioTest.canPlayType('audio/x-caf;').replace(/^no$/, ''),
292
- m4a: !!(audioTest.canPlayType('audio/x-m4a;') || audioTest.canPlayType('audio/m4a;') || audioTest.canPlayType('audio/aac;')).replace(/^no$/, ''),
293
- m4b: !!(audioTest.canPlayType('audio/x-m4b;') || audioTest.canPlayType('audio/m4b;') || audioTest.canPlayType('audio/aac;')).replace(/^no$/, ''),
294
- mp4: !!(audioTest.canPlayType('audio/x-mp4;') || audioTest.canPlayType('audio/mp4;') || audioTest.canPlayType('audio/aac;')).replace(/^no$/, ''),
295
- weba: !!(!isOldSafari && audioTest.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/, '')),
296
- webm: !!(!isOldSafari && audioTest.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/, '')),
297
- dolby: !!audioTest.canPlayType('audio/mp4; codecs="ec-3"').replace(/^no$/, ''),
298
- flac: !!(audioTest.canPlayType('audio/x-flac;') || audioTest.canPlayType('audio/flac;')).replace(/^no$/, '')
299
- };
300
-
301
- return self;
302
- },
303
-
304
- /**
305
- * Some browsers/devices will only allow audio to be played after a user interaction.
306
- * Attempt to automatically unlock audio on the first user interaction.
307
- * Concept from: http://paulbakaus.com/tutorials/html5/web-audio-on-ios/
308
- * @return {Howler}
309
- */
310
- _unlockAudio: function() {
311
- var self = this || Howler;
312
-
313
- // Only run this if Web Audio is supported and it hasn't already been unlocked.
314
- if (self._audioUnlocked || !self.ctx) {
315
- return;
316
- }
317
-
318
- self._audioUnlocked = false;
319
- self.autoUnlock = false;
320
-
321
- // Some mobile devices/platforms have distortion issues when opening/closing tabs and/or web views.
322
- // Bugs in the browser (especially Mobile Safari) can cause the sampleRate to change from 44100 to 48000.
323
- // By calling Howler.unload(), we create a new AudioContext with the correct sampleRate.
324
- if (!self._mobileUnloaded && self.ctx.sampleRate !== 44100) {
325
- self._mobileUnloaded = true;
326
- self.unload();
327
- }
328
-
329
- // Scratch buffer for enabling iOS to dispose of web audio buffers correctly, as per:
330
- // http://stackoverflow.com/questions/24119684
331
- self._scratchBuffer = self.ctx.createBuffer(1, 1, 22050);
332
-
333
- // Call this method on touch start to create and play a buffer,
334
- // then check if the audio actually played to determine if
335
- // audio has now been unlocked on iOS, Android, etc.
336
- var unlock = function(e) {
337
- // Create a pool of unlocked HTML5 Audio objects that can
338
- // be used for playing sounds without user interaction. HTML5
339
- // Audio objects must be individually unlocked, as opposed
340
- // to the WebAudio API which only needs a single activation.
341
- // This must occur before WebAudio setup or the source.onended
342
- // event will not fire.
343
- while (self._html5AudioPool.length < self.html5PoolSize) {
344
- try {
345
- var audioNode = new Audio();
346
-
347
- // Mark this Audio object as unlocked to ensure it can get returned
348
- // to the unlocked pool when released.
349
- audioNode._unlocked = true;
350
-
351
- // Add the audio node to the pool.
352
- self._releaseHtml5Audio(audioNode);
353
- } catch (e) {
354
- self.noAudio = true;
355
- break;
356
- }
357
- }
358
-
359
- // Loop through any assigned audio nodes and unlock them.
360
- for (var i=0; i<self._howls.length; i++) {
361
- if (!self._howls[i]._webAudio) {
362
- // Get all of the sounds in this Howl group.
363
- var ids = self._howls[i]._getSoundIds();
364
-
365
- // Loop through all sounds and unlock the audio nodes.
366
- for (var j=0; j<ids.length; j++) {
367
- var sound = self._howls[i]._soundById(ids[j]);
368
-
369
- if (sound && sound._node && !sound._node._unlocked) {
370
- sound._node._unlocked = true;
371
- sound._node.load();
372
- }
373
- }
374
- }
375
- }
376
-
377
- // Fix Android can not play in suspend state.
378
- self._autoResume();
379
-
380
- // Create an empty buffer.
381
- var source = self.ctx.createBufferSource();
382
- source.buffer = self._scratchBuffer;
383
- source.connect(self.ctx.destination);
384
-
385
- // Play the empty buffer.
386
- if (typeof source.start === 'undefined') {
387
- source.noteOn(0);
388
- } else {
389
- source.start(0);
390
- }
391
-
392
- // Calling resume() on a stack initiated by user gesture is what actually unlocks the audio on Android Chrome >= 55.
393
- if (typeof self.ctx.resume === 'function') {
394
- self.ctx.resume();
395
- }
396
-
397
- // Setup a timeout to check that we are unlocked on the next event loop.
398
- source.onended = function() {
399
- source.disconnect(0);
400
-
401
- // Update the unlocked state and prevent this check from happening again.
402
- self._audioUnlocked = true;
403
-
404
- // Remove the touch start listener.
405
- document.removeEventListener('touchstart', unlock, true);
406
- document.removeEventListener('touchend', unlock, true);
407
- document.removeEventListener('click', unlock, true);
408
- document.removeEventListener('keydown', unlock, true);
409
-
410
- // Let all sounds know that audio has been unlocked.
411
- for (var i=0; i<self._howls.length; i++) {
412
- self._howls[i]._emit('unlock');
413
- }
414
- };
415
- };
416
-
417
- // Setup a touch start listener to attempt an unlock in.
418
- document.addEventListener('touchstart', unlock, true);
419
- document.addEventListener('touchend', unlock, true);
420
- document.addEventListener('click', unlock, true);
421
- document.addEventListener('keydown', unlock, true);
422
-
423
- return self;
424
- },
425
-
426
- /**
427
- * Get an unlocked HTML5 Audio object from the pool. If none are left,
428
- * return a new Audio object and throw a warning.
429
- * @return {Audio} HTML5 Audio object.
430
- */
431
- _obtainHtml5Audio: function() {
432
- var self = this || Howler;
433
-
434
- // Return the next object from the pool if one exists.
435
- if (self._html5AudioPool.length) {
436
- return self._html5AudioPool.pop();
437
- }
438
-
439
- //.Check if the audio is locked and throw a warning.
440
- var testPlay = new Audio().play();
441
- if (testPlay && typeof Promise !== 'undefined' && (testPlay instanceof Promise || typeof testPlay.then === 'function')) {
442
- testPlay.catch(function() {
443
- console.warn('HTML5 Audio pool exhausted, returning potentially locked audio object.');
444
- });
445
- }
446
-
447
- return new Audio();
448
- },
449
-
450
- /**
451
- * Return an activated HTML5 Audio object to the pool.
452
- * @return {Howler}
453
- */
454
- _releaseHtml5Audio: function(audio) {
455
- var self = this || Howler;
456
-
457
- // Don't add audio to the pool if we don't know if it has been unlocked.
458
- if (audio._unlocked) {
459
- self._html5AudioPool.push(audio);
460
- }
461
-
462
- return self;
463
- },
464
-
465
- /**
466
- * Automatically suspend the Web Audio AudioContext after no sound has played for 30 seconds.
467
- * This saves processing/energy and fixes various browser-specific bugs with audio getting stuck.
468
- * @return {Howler}
469
- */
470
- _autoSuspend: function() {
471
- var self = this;
472
-
473
- if (!self.autoSuspend || !self.ctx || typeof self.ctx.suspend === 'undefined' || !Howler.usingWebAudio) {
474
- return;
475
- }
476
-
477
- // Check if any sounds are playing.
478
- for (var i=0; i<self._howls.length; i++) {
479
- if (self._howls[i]._webAudio) {
480
- for (var j=0; j<self._howls[i]._sounds.length; j++) {
481
- if (!self._howls[i]._sounds[j]._paused) {
482
- return self;
483
- }
484
- }
485
- }
486
- }
487
-
488
- if (self._suspendTimer) {
489
- clearTimeout(self._suspendTimer);
490
- }
491
-
492
- // If no sound has played after 30 seconds, suspend the context.
493
- self._suspendTimer = setTimeout(function() {
494
- if (!self.autoSuspend) {
495
- return;
496
- }
497
-
498
- self._suspendTimer = null;
499
- self.state = 'suspending';
500
-
501
- // Handle updating the state of the audio context after suspending.
502
- var handleSuspension = function() {
503
- self.state = 'suspended';
504
-
505
- if (self._resumeAfterSuspend) {
506
- delete self._resumeAfterSuspend;
507
- self._autoResume();
508
- }
509
- };
510
-
511
- // Either the state gets suspended or it is interrupted.
512
- // Either way, we need to update the state to suspended.
513
- self.ctx.suspend().then(handleSuspension, handleSuspension);
514
- }, 30000);
515
-
516
- return self;
517
- },
518
-
519
- /**
520
- * Automatically resume the Web Audio AudioContext when a new sound is played.
521
- * @return {Howler}
522
- */
523
- _autoResume: function() {
524
- var self = this;
525
-
526
- if (!self.ctx || typeof self.ctx.resume === 'undefined' || !Howler.usingWebAudio) {
527
- return;
528
- }
529
-
530
- if (self.state === 'running' && self.ctx.state !== 'interrupted' && self._suspendTimer) {
531
- clearTimeout(self._suspendTimer);
532
- self._suspendTimer = null;
533
- } else if (self.state === 'suspended' || self.state === 'running' && self.ctx.state === 'interrupted') {
534
- self.ctx.resume().then(function() {
535
- self.state = 'running';
536
-
537
- // Emit to all Howls that the audio has resumed.
538
- for (var i=0; i<self._howls.length; i++) {
539
- self._howls[i]._emit('resume');
540
- }
541
- });
542
-
543
- if (self._suspendTimer) {
544
- clearTimeout(self._suspendTimer);
545
- self._suspendTimer = null;
546
- }
547
- } else if (self.state === 'suspending') {
548
- self._resumeAfterSuspend = true;
549
- }
550
-
551
- return self;
552
- }
553
- };
554
-
555
- // Setup the global audio controller.
556
- var Howler = new HowlerGlobal();
557
-
558
- /** Group Methods **/
559
- /***************************************************************************/
560
-
561
- /**
562
- * Create an audio group controller.
563
- * @param {Object} o Passed in properties for this group.
564
- */
565
- var Howl = function(o) {
566
- var self = this;
567
-
568
- // Throw an error if no source is provided.
569
- if (!o.src || o.src.length === 0) {
570
- console.error('An array of source files must be passed with any new Howl.');
571
- return;
572
- }
573
-
574
- self.init(o);
575
- };
576
- Howl.prototype = {
577
- /**
578
- * Initialize a new Howl group object.
579
- * @param {Object} o Passed in properties for this group.
580
- * @return {Howl}
581
- */
582
- init: function(o) {
583
- var self = this;
584
-
585
- // If we don't have an AudioContext created yet, run the setup.
586
- if (!Howler.ctx) {
587
- setupAudioContext();
588
- }
589
-
590
- // Setup user-defined default properties.
591
- self._autoplay = o.autoplay || false;
592
- self._format = (typeof o.format !== 'string') ? o.format : [o.format];
593
- self._html5 = o.html5 || false;
594
- self._muted = o.mute || false;
595
- self._loop = o.loop || false;
596
- self._pool = o.pool || 5;
597
- self._preload = (typeof o.preload === 'boolean' || o.preload === 'metadata') ? o.preload : true;
598
- self._rate = o.rate || 1;
599
- self._sprite = o.sprite || {};
600
- self._src = (typeof o.src !== 'string') ? o.src : [o.src];
601
- self._volume = o.volume !== undefined ? o.volume : 1;
602
- self._xhr = {
603
- method: o.xhr && o.xhr.method ? o.xhr.method : 'GET',
604
- headers: o.xhr && o.xhr.headers ? o.xhr.headers : null,
605
- withCredentials: o.xhr && o.xhr.withCredentials ? o.xhr.withCredentials : false,
606
- };
607
-
608
- // Setup all other default properties.
609
- self._duration = 0;
610
- self._state = 'unloaded';
611
- self._sounds = [];
612
- self._endTimers = {};
613
- self._queue = [];
614
- self._playLock = false;
615
-
616
- // Setup event listeners.
617
- self._onend = o.onend ? [{fn: o.onend}] : [];
618
- self._onfade = o.onfade ? [{fn: o.onfade}] : [];
619
- self._onload = o.onload ? [{fn: o.onload}] : [];
620
- self._onloaderror = o.onloaderror ? [{fn: o.onloaderror}] : [];
621
- self._onplayerror = o.onplayerror ? [{fn: o.onplayerror}] : [];
622
- self._onpause = o.onpause ? [{fn: o.onpause}] : [];
623
- self._onplay = o.onplay ? [{fn: o.onplay}] : [];
624
- self._onstop = o.onstop ? [{fn: o.onstop}] : [];
625
- self._onmute = o.onmute ? [{fn: o.onmute}] : [];
626
- self._onvolume = o.onvolume ? [{fn: o.onvolume}] : [];
627
- self._onrate = o.onrate ? [{fn: o.onrate}] : [];
628
- self._onseek = o.onseek ? [{fn: o.onseek}] : [];
629
- self._onunlock = o.onunlock ? [{fn: o.onunlock}] : [];
630
- self._onresume = [];
631
-
632
- // Web Audio or HTML5 Audio?
633
- self._webAudio = Howler.usingWebAudio && !self._html5;
634
-
635
- // Automatically try to enable audio.
636
- if (typeof Howler.ctx !== 'undefined' && Howler.ctx && Howler.autoUnlock) {
637
- Howler._unlockAudio();
638
- }
639
-
640
- // Keep track of this Howl group in the global controller.
641
- Howler._howls.push(self);
642
-
643
- // If they selected autoplay, add a play event to the load queue.
644
- if (self._autoplay) {
645
- self._queue.push({
646
- event: 'play',
647
- action: function() {
648
- self.play();
649
- }
650
- });
651
- }
652
-
653
- // Load the source file unless otherwise specified.
654
- if (self._preload && self._preload !== 'none') {
655
- self.load();
656
- }
657
-
658
- return self;
659
- },
660
-
661
- /**
662
- * Load the audio file.
663
- * @return {Howler}
664
- */
665
- load: function() {
666
- var self = this;
667
- var url = null;
668
-
669
- // If no audio is available, quit immediately.
670
- if (Howler.noAudio) {
671
- self._emit('loaderror', null, 'No audio support.');
672
- return;
673
- }
674
-
675
- // Make sure our source is in an array.
676
- if (typeof self._src === 'string') {
677
- self._src = [self._src];
678
- }
679
-
680
- // Loop through the sources and pick the first one that is compatible.
681
- for (var i=0; i<self._src.length; i++) {
682
- var ext, str;
683
-
684
- if (self._format && self._format[i]) {
685
- // If an extension was specified, use that instead.
686
- ext = self._format[i];
687
- } else {
688
- // Make sure the source is a string.
689
- str = self._src[i];
690
- if (typeof str !== 'string') {
691
- self._emit('loaderror', null, 'Non-string found in selected audio sources - ignoring.');
692
- continue;
693
- }
694
-
695
- // Extract the file extension from the URL or base64 data URI.
696
- ext = /^data:audio\/([^;,]+);/i.exec(str);
697
- if (!ext) {
698
- ext = /\.([^.]+)$/.exec(str.split('?', 1)[0]);
699
- }
700
-
701
- if (ext) {
702
- ext = ext[1].toLowerCase();
703
- }
704
- }
705
-
706
- // Log a warning if no extension was found.
707
- if (!ext) {
708
- console.warn('No file extension was found. Consider using the "format" property or specify an extension.');
709
- }
710
-
711
- // Check if this extension is available.
712
- if (ext && Howler.codecs(ext)) {
713
- url = self._src[i];
714
- break;
715
- }
716
- }
717
-
718
- if (!url) {
719
- self._emit('loaderror', null, 'No codec support for selected audio sources.');
720
- return;
721
- }
722
-
723
- self._src = url;
724
- self._state = 'loading';
725
-
726
- // If the hosting page is HTTPS and the source isn't,
727
- // drop down to HTML5 Audio to avoid Mixed Content errors.
728
- if (window.location.protocol === 'https:' && url.slice(0, 5) === 'http:') {
729
- self._html5 = true;
730
- self._webAudio = false;
731
- }
732
-
733
- // Create a new sound object and add it to the pool.
734
- new Sound(self);
735
-
736
- // Load and decode the audio data for playback.
737
- if (self._webAudio) {
738
- loadBuffer(self);
739
- }
740
-
741
- return self;
742
- },
743
-
744
- /**
745
- * Play a sound or resume previous playback.
746
- * @param {String/Number} sprite Sprite name for sprite playback or sound id to continue previous.
747
- * @param {Boolean} internal Internal Use: true prevents event firing.
748
- * @return {Number} Sound ID.
749
- */
750
- play: function(sprite, internal) {
751
- var self = this;
752
- var id = null;
753
-
754
- // Determine if a sprite, sound id or nothing was passed
755
- if (typeof sprite === 'number') {
756
- id = sprite;
757
- sprite = null;
758
- } else if (typeof sprite === 'string' && self._state === 'loaded' && !self._sprite[sprite]) {
759
- // If the passed sprite doesn't exist, do nothing.
760
- return null;
761
- } else if (typeof sprite === 'undefined') {
762
- // Use the default sound sprite (plays the full audio length).
763
- sprite = '__default';
764
-
765
- // Check if there is a single paused sound that isn't ended.
766
- // If there is, play that sound. If not, continue as usual.
767
- if (!self._playLock) {
768
- var num = 0;
769
- for (var i=0; i<self._sounds.length; i++) {
770
- if (self._sounds[i]._paused && !self._sounds[i]._ended) {
771
- num++;
772
- id = self._sounds[i]._id;
773
- }
774
- }
775
-
776
- if (num === 1) {
777
- sprite = null;
778
- } else {
779
- id = null;
780
- }
781
- }
782
- }
783
-
784
- // Get the selected node, or get one from the pool.
785
- var sound = id ? self._soundById(id) : self._inactiveSound();
786
-
787
- // If the sound doesn't exist, do nothing.
788
- if (!sound) {
789
- return null;
790
- }
791
-
792
- // Select the sprite definition.
793
- if (id && !sprite) {
794
- sprite = sound._sprite || '__default';
795
- }
796
-
797
- // If the sound hasn't loaded, we must wait to get the audio's duration.
798
- // We also need to wait to make sure we don't run into race conditions with
799
- // the order of function calls.
800
- if (self._state !== 'loaded') {
801
- // Set the sprite value on this sound.
802
- sound._sprite = sprite;
803
-
804
- // Mark this sound as not ended in case another sound is played before this one loads.
805
- sound._ended = false;
806
-
807
- // Add the sound to the queue to be played on load.
808
- var soundId = sound._id;
809
- self._queue.push({
810
- event: 'play',
811
- action: function() {
812
- self.play(soundId);
813
- }
814
- });
815
-
816
- return soundId;
817
- }
818
-
819
- // Don't play the sound if an id was passed and it is already playing.
820
- if (id && !sound._paused) {
821
- // Trigger the play event, in order to keep iterating through queue.
822
- if (!internal) {
823
- self._loadQueue('play');
824
- }
825
-
826
- return sound._id;
827
- }
828
-
829
- // Make sure the AudioContext isn't suspended, and resume it if it is.
830
- if (self._webAudio) {
831
- Howler._autoResume();
832
- }
833
-
834
- // Determine how long to play for and where to start playing.
835
- var seek = Math.max(0, sound._seek > 0 ? sound._seek : self._sprite[sprite][0] / 1000);
836
- var duration = Math.max(0, ((self._sprite[sprite][0] + self._sprite[sprite][1]) / 1000) - seek);
837
- var timeout = (duration * 1000) / Math.abs(sound._rate);
838
- var start = self._sprite[sprite][0] / 1000;
839
- var stop = (self._sprite[sprite][0] + self._sprite[sprite][1]) / 1000;
840
- sound._sprite = sprite;
841
-
842
- // Mark the sound as ended instantly so that this async playback
843
- // doesn't get grabbed by another call to play while this one waits to start.
844
- sound._ended = false;
845
-
846
- // Update the parameters of the sound.
847
- var setParams = function() {
848
- sound._paused = false;
849
- sound._seek = seek;
850
- sound._start = start;
851
- sound._stop = stop;
852
- sound._loop = !!(sound._loop || self._sprite[sprite][2]);
853
- };
854
-
855
- // End the sound instantly if seek is at the end.
856
- if (seek >= stop) {
857
- self._ended(sound);
858
- return;
859
- }
860
-
861
- // Begin the actual playback.
862
- var node = sound._node;
863
- if (self._webAudio) {
864
- // Fire this when the sound is ready to play to begin Web Audio playback.
865
- var playWebAudio = function() {
866
- self._playLock = false;
867
- setParams();
868
- self._refreshBuffer(sound);
869
-
870
- // Setup the playback params.
871
- var vol = (sound._muted || self._muted) ? 0 : sound._volume;
872
- node.gain.setValueAtTime(vol, Howler.ctx.currentTime);
873
- sound._playStart = Howler.ctx.currentTime;
874
-
875
- // Play the sound using the supported method.
876
- if (typeof node.bufferSource.start === 'undefined') {
877
- sound._loop ? node.bufferSource.noteGrainOn(0, seek, 86400) : node.bufferSource.noteGrainOn(0, seek, duration);
878
- } else {
879
- sound._loop ? node.bufferSource.start(0, seek, 86400) : node.bufferSource.start(0, seek, duration);
880
- }
881
-
882
- // Start a new timer if none is present.
883
- if (timeout !== Infinity) {
884
- self._endTimers[sound._id] = setTimeout(self._ended.bind(self, sound), timeout);
885
- }
886
-
887
- if (!internal) {
888
- setTimeout(function() {
889
- self._emit('play', sound._id);
890
- self._loadQueue();
891
- }, 0);
892
- }
893
- };
894
-
895
- if (Howler.state === 'running' && Howler.ctx.state !== 'interrupted') {
896
- playWebAudio();
897
- } else {
898
- self._playLock = true;
899
-
900
- // Wait for the audio context to resume before playing.
901
- self.once('resume', playWebAudio);
902
-
903
- // Cancel the end timer.
904
- self._clearTimer(sound._id);
905
- }
906
- } else {
907
- // Fire this when the sound is ready to play to begin HTML5 Audio playback.
908
- var playHtml5 = function() {
909
- node.currentTime = seek;
910
- node.muted = sound._muted || self._muted || Howler._muted || node.muted;
911
- node.volume = sound._volume * Howler.volume();
912
- node.playbackRate = sound._rate;
913
-
914
- // Some browsers will throw an error if this is called without user interaction.
915
- try {
916
- var play = node.play();
917
-
918
- // Support older browsers that don't support promises, and thus don't have this issue.
919
- if (play && typeof Promise !== 'undefined' && (play instanceof Promise || typeof play.then === 'function')) {
920
- // Implements a lock to prevent DOMException: The play() request was interrupted by a call to pause().
921
- self._playLock = true;
922
-
923
- // Set param values immediately.
924
- setParams();
925
-
926
- // Releases the lock and executes queued actions.
927
- play
928
- .then(function() {
929
- self._playLock = false;
930
- node._unlocked = true;
931
- if (!internal) {
932
- self._emit('play', sound._id);
933
- } else {
934
- self._loadQueue();
935
- }
936
- })
937
- .catch(function() {
938
- self._playLock = false;
939
- self._emit('playerror', sound._id, 'Playback was unable to start. This is most commonly an issue ' +
940
- 'on mobile devices and Chrome where playback was not within a user interaction.');
941
-
942
- // Reset the ended and paused values.
943
- sound._ended = true;
944
- sound._paused = true;
945
- });
946
- } else if (!internal) {
947
- self._playLock = false;
948
- setParams();
949
- self._emit('play', sound._id);
950
- }
951
-
952
- // Setting rate before playing won't work in IE, so we set it again here.
953
- node.playbackRate = sound._rate;
954
-
955
- // If the node is still paused, then we can assume there was a playback issue.
956
- if (node.paused) {
957
- self._emit('playerror', sound._id, 'Playback was unable to start. This is most commonly an issue ' +
958
- 'on mobile devices and Chrome where playback was not within a user interaction.');
959
- return;
960
- }
961
-
962
- // Setup the end timer on sprites or listen for the ended event.
963
- if (sprite !== '__default' || sound._loop) {
964
- self._endTimers[sound._id] = setTimeout(self._ended.bind(self, sound), timeout);
965
- } else {
966
- self._endTimers[sound._id] = function() {
967
- // Fire ended on this audio node.
968
- self._ended(sound);
969
-
970
- // Clear this listener.
971
- node.removeEventListener('ended', self._endTimers[sound._id], false);
972
- };
973
- node.addEventListener('ended', self._endTimers[sound._id], false);
974
- }
975
- } catch (err) {
976
- self._emit('playerror', sound._id, err);
977
- }
978
- };
979
-
980
- // If this is streaming audio, make sure the src is set and load again.
981
- if (node.src === 'data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA') {
982
- node.src = self._src;
983
- node.load();
984
- }
985
-
986
- // Play immediately if ready, or wait for the 'canplaythrough'e vent.
987
- var loadedNoReadyState = (window && window.ejecta) || (!node.readyState && Howler._navigator.isCocoonJS);
988
- if (node.readyState >= 3 || loadedNoReadyState) {
989
- playHtml5();
990
- } else {
991
- self._playLock = true;
992
- self._state = 'loading';
993
-
994
- var listener = function() {
995
- self._state = 'loaded';
996
-
997
- // Begin playback.
998
- playHtml5();
999
-
1000
- // Clear this listener.
1001
- node.removeEventListener(Howler._canPlayEvent, listener, false);
1002
- };
1003
- node.addEventListener(Howler._canPlayEvent, listener, false);
1004
-
1005
- // Cancel the end timer.
1006
- self._clearTimer(sound._id);
1007
- }
1008
- }
1009
-
1010
- return sound._id;
1011
- },
1012
-
1013
- /**
1014
- * Pause playback and save current position.
1015
- * @param {Number} id The sound ID (empty to pause all in group).
1016
- * @return {Howl}
1017
- */
1018
- pause: function(id) {
1019
- var self = this;
1020
-
1021
- // If the sound hasn't loaded or a play() promise is pending, add it to the load queue to pause when capable.
1022
- if (self._state !== 'loaded' || self._playLock) {
1023
- self._queue.push({
1024
- event: 'pause',
1025
- action: function() {
1026
- self.pause(id);
1027
- }
1028
- });
1029
-
1030
- return self;
1031
- }
1032
-
1033
- // If no id is passed, get all ID's to be paused.
1034
- var ids = self._getSoundIds(id);
1035
-
1036
- for (var i=0; i<ids.length; i++) {
1037
- // Clear the end timer.
1038
- self._clearTimer(ids[i]);
1039
-
1040
- // Get the sound.
1041
- var sound = self._soundById(ids[i]);
1042
-
1043
- if (sound && !sound._paused) {
1044
- // Reset the seek position.
1045
- sound._seek = self.seek(ids[i]);
1046
- sound._rateSeek = 0;
1047
- sound._paused = true;
1048
-
1049
- // Stop currently running fades.
1050
- self._stopFade(ids[i]);
1051
-
1052
- if (sound._node) {
1053
- if (self._webAudio) {
1054
- // Make sure the sound has been created.
1055
- if (!sound._node.bufferSource) {
1056
- continue;
1057
- }
1058
-
1059
- if (typeof sound._node.bufferSource.stop === 'undefined') {
1060
- sound._node.bufferSource.noteOff(0);
1061
- } else {
1062
- sound._node.bufferSource.stop(0);
1063
- }
1064
-
1065
- // Clean up the buffer source.
1066
- self._cleanBuffer(sound._node);
1067
- } else if (!isNaN(sound._node.duration) || sound._node.duration === Infinity) {
1068
- sound._node.pause();
1069
- }
1070
- }
1071
- }
1072
-
1073
- // Fire the pause event, unless `true` is passed as the 2nd argument.
1074
- if (!arguments[1]) {
1075
- self._emit('pause', sound ? sound._id : null);
1076
- }
1077
- }
1078
-
1079
- return self;
1080
- },
1081
-
1082
- /**
1083
- * Stop playback and reset to start.
1084
- * @param {Number} id The sound ID (empty to stop all in group).
1085
- * @param {Boolean} internal Internal Use: true prevents event firing.
1086
- * @return {Howl}
1087
- */
1088
- stop: function(id, internal) {
1089
- var self = this;
1090
-
1091
- // If the sound hasn't loaded, add it to the load queue to stop when capable.
1092
- if (self._state !== 'loaded' || self._playLock) {
1093
- self._queue.push({
1094
- event: 'stop',
1095
- action: function() {
1096
- self.stop(id);
1097
- }
1098
- });
1099
-
1100
- return self;
1101
- }
1102
-
1103
- // If no id is passed, get all ID's to be stopped.
1104
- var ids = self._getSoundIds(id);
1105
-
1106
- for (var i=0; i<ids.length; i++) {
1107
- // Clear the end timer.
1108
- self._clearTimer(ids[i]);
1109
-
1110
- // Get the sound.
1111
- var sound = self._soundById(ids[i]);
1112
-
1113
- if (sound) {
1114
- // Reset the seek position.
1115
- sound._seek = sound._start || 0;
1116
- sound._rateSeek = 0;
1117
- sound._paused = true;
1118
- sound._ended = true;
1119
-
1120
- // Stop currently running fades.
1121
- self._stopFade(ids[i]);
1122
-
1123
- if (sound._node) {
1124
- if (self._webAudio) {
1125
- // Make sure the sound's AudioBufferSourceNode has been created.
1126
- if (sound._node.bufferSource) {
1127
- if (typeof sound._node.bufferSource.stop === 'undefined') {
1128
- sound._node.bufferSource.noteOff(0);
1129
- } else {
1130
- sound._node.bufferSource.stop(0);
1131
- }
1132
-
1133
- // Clean up the buffer source.
1134
- self._cleanBuffer(sound._node);
1135
- }
1136
- } else if (!isNaN(sound._node.duration) || sound._node.duration === Infinity) {
1137
- sound._node.currentTime = sound._start || 0;
1138
- sound._node.pause();
1139
-
1140
- // If this is a live stream, stop download once the audio is stopped.
1141
- if (sound._node.duration === Infinity) {
1142
- self._clearSound(sound._node);
1143
- }
1144
- }
1145
- }
1146
-
1147
- if (!internal) {
1148
- self._emit('stop', sound._id);
1149
- }
1150
- }
1151
- }
1152
-
1153
- return self;
1154
- },
1155
-
1156
- /**
1157
- * Mute/unmute a single sound or all sounds in this Howl group.
1158
- * @param {Boolean} muted Set to true to mute and false to unmute.
1159
- * @param {Number} id The sound ID to update (omit to mute/unmute all).
1160
- * @return {Howl}
1161
- */
1162
- mute: function(muted, id) {
1163
- var self = this;
1164
-
1165
- // If the sound hasn't loaded, add it to the load queue to mute when capable.
1166
- if (self._state !== 'loaded'|| self._playLock) {
1167
- self._queue.push({
1168
- event: 'mute',
1169
- action: function() {
1170
- self.mute(muted, id);
1171
- }
1172
- });
1173
-
1174
- return self;
1175
- }
1176
-
1177
- // If applying mute/unmute to all sounds, update the group's value.
1178
- if (typeof id === 'undefined') {
1179
- if (typeof muted === 'boolean') {
1180
- self._muted = muted;
1181
- } else {
1182
- return self._muted;
1183
- }
1184
- }
1185
-
1186
- // If no id is passed, get all ID's to be muted.
1187
- var ids = self._getSoundIds(id);
1188
-
1189
- for (var i=0; i<ids.length; i++) {
1190
- // Get the sound.
1191
- var sound = self._soundById(ids[i]);
1192
-
1193
- if (sound) {
1194
- sound._muted = muted;
1195
-
1196
- // Cancel active fade and set the volume to the end value.
1197
- if (sound._interval) {
1198
- self._stopFade(sound._id);
1199
- }
1200
-
1201
- if (self._webAudio && sound._node) {
1202
- sound._node.gain.setValueAtTime(muted ? 0 : sound._volume, Howler.ctx.currentTime);
1203
- } else if (sound._node) {
1204
- sound._node.muted = Howler._muted ? true : muted;
1205
- }
1206
-
1207
- self._emit('mute', sound._id);
1208
- }
1209
- }
1210
-
1211
- return self;
1212
- },
1213
-
1214
- /**
1215
- * Get/set the volume of this sound or of the Howl group. This method can optionally take 0, 1 or 2 arguments.
1216
- * volume() -> Returns the group's volume value.
1217
- * volume(id) -> Returns the sound id's current volume.
1218
- * volume(vol) -> Sets the volume of all sounds in this Howl group.
1219
- * volume(vol, id) -> Sets the volume of passed sound id.
1220
- * @return {Howl/Number} Returns self or current volume.
1221
- */
1222
- volume: function() {
1223
- var self = this;
1224
- var args = arguments;
1225
- var vol, id;
1226
-
1227
- // Determine the values based on arguments.
1228
- if (args.length === 0) {
1229
- // Return the value of the groups' volume.
1230
- return self._volume;
1231
- } else if (args.length === 1 || args.length === 2 && typeof args[1] === 'undefined') {
1232
- // First check if this is an ID, and if not, assume it is a new volume.
1233
- var ids = self._getSoundIds();
1234
- var index = ids.indexOf(args[0]);
1235
- if (index >= 0) {
1236
- id = parseInt(args[0], 10);
1237
- } else {
1238
- vol = parseFloat(args[0]);
1239
- }
1240
- } else if (args.length >= 2) {
1241
- vol = parseFloat(args[0]);
1242
- id = parseInt(args[1], 10);
1243
- }
1244
-
1245
- // Update the volume or return the current volume.
1246
- var sound;
1247
- if (typeof vol !== 'undefined' && vol >= 0 && vol <= 1) {
1248
- // If the sound hasn't loaded, add it to the load queue to change volume when capable.
1249
- if (self._state !== 'loaded'|| self._playLock) {
1250
- self._queue.push({
1251
- event: 'volume',
1252
- action: function() {
1253
- self.volume.apply(self, args);
1254
- }
1255
- });
1256
-
1257
- return self;
1258
- }
1259
-
1260
- // Set the group volume.
1261
- if (typeof id === 'undefined') {
1262
- self._volume = vol;
1263
- }
1264
-
1265
- // Update one or all volumes.
1266
- id = self._getSoundIds(id);
1267
- for (var i=0; i<id.length; i++) {
1268
- // Get the sound.
1269
- sound = self._soundById(id[i]);
1270
-
1271
- if (sound) {
1272
- sound._volume = vol;
1273
-
1274
- // Stop currently running fades.
1275
- if (!args[2]) {
1276
- self._stopFade(id[i]);
1277
- }
1278
-
1279
- if (self._webAudio && sound._node && !sound._muted) {
1280
- sound._node.gain.setValueAtTime(vol, Howler.ctx.currentTime);
1281
- } else if (sound._node && !sound._muted) {
1282
- sound._node.volume = vol * Howler.volume();
1283
- }
1284
-
1285
- self._emit('volume', sound._id);
1286
- }
1287
- }
1288
- } else {
1289
- sound = id ? self._soundById(id) : self._sounds[0];
1290
- return sound ? sound._volume : 0;
1291
- }
1292
-
1293
- return self;
1294
- },
1295
-
1296
- /**
1297
- * Fade a currently playing sound between two volumes (if no id is passed, all sounds will fade).
1298
- * @param {Number} from The value to fade from (0.0 to 1.0).
1299
- * @param {Number} to The volume to fade to (0.0 to 1.0).
1300
- * @param {Number} len Time in milliseconds to fade.
1301
- * @param {Number} id The sound id (omit to fade all sounds).
1302
- * @return {Howl}
1303
- */
1304
- fade: function(from, to, len, id) {
1305
- var self = this;
1306
-
1307
- // If the sound hasn't loaded, add it to the load queue to fade when capable.
1308
- if (self._state !== 'loaded' || self._playLock) {
1309
- self._queue.push({
1310
- event: 'fade',
1311
- action: function() {
1312
- self.fade(from, to, len, id);
1313
- }
1314
- });
1315
-
1316
- return self;
1317
- }
1318
-
1319
- // Make sure the to/from/len values are numbers.
1320
- from = Math.min(Math.max(0, parseFloat(from)), 1);
1321
- to = Math.min(Math.max(0, parseFloat(to)), 1);
1322
- len = parseFloat(len);
1323
-
1324
- // Set the volume to the start position.
1325
- self.volume(from, id);
1326
-
1327
- // Fade the volume of one or all sounds.
1328
- var ids = self._getSoundIds(id);
1329
- for (var i=0; i<ids.length; i++) {
1330
- // Get the sound.
1331
- var sound = self._soundById(ids[i]);
1332
-
1333
- // Create a linear fade or fall back to timeouts with HTML5 Audio.
1334
- if (sound) {
1335
- // Stop the previous fade if no sprite is being used (otherwise, volume handles this).
1336
- if (!id) {
1337
- self._stopFade(ids[i]);
1338
- }
1339
-
1340
- // If we are using Web Audio, let the native methods do the actual fade.
1341
- if (self._webAudio && !sound._muted) {
1342
- var currentTime = Howler.ctx.currentTime;
1343
- var end = currentTime + (len / 1000);
1344
- sound._volume = from;
1345
- sound._node.gain.setValueAtTime(from, currentTime);
1346
- sound._node.gain.linearRampToValueAtTime(to, end);
1347
- }
1348
-
1349
- self._startFadeInterval(sound, from, to, len, ids[i], typeof id === 'undefined');
1350
- }
1351
- }
1352
-
1353
- return self;
1354
- },
1355
-
1356
- /**
1357
- * Starts the internal interval to fade a sound.
1358
- * @param {Object} sound Reference to sound to fade.
1359
- * @param {Number} from The value to fade from (0.0 to 1.0).
1360
- * @param {Number} to The volume to fade to (0.0 to 1.0).
1361
- * @param {Number} len Time in milliseconds to fade.
1362
- * @param {Number} id The sound id to fade.
1363
- * @param {Boolean} isGroup If true, set the volume on the group.
1364
- */
1365
- _startFadeInterval: function(sound, from, to, len, id, isGroup) {
1366
- var self = this;
1367
- var vol = from;
1368
- var diff = to - from;
1369
- var steps = Math.abs(diff / 0.01);
1370
- var stepLen = Math.max(4, (steps > 0) ? len / steps : len);
1371
- var lastTick = Date.now();
1372
-
1373
- // Store the value being faded to.
1374
- sound._fadeTo = to;
1375
-
1376
- // Update the volume value on each interval tick.
1377
- sound._interval = setInterval(function() {
1378
- // Update the volume based on the time since the last tick.
1379
- var tick = (Date.now() - lastTick) / len;
1380
- lastTick = Date.now();
1381
- vol += diff * tick;
1382
-
1383
- // Round to within 2 decimal points.
1384
- vol = Math.round(vol * 100) / 100;
1385
-
1386
- // Make sure the volume is in the right bounds.
1387
- if (diff < 0) {
1388
- vol = Math.max(to, vol);
1389
- } else {
1390
- vol = Math.min(to, vol);
1391
- }
1392
-
1393
- // Change the volume.
1394
- if (self._webAudio) {
1395
- sound._volume = vol;
1396
- } else {
1397
- self.volume(vol, sound._id, true);
1398
- }
1399
-
1400
- // Set the group's volume.
1401
- if (isGroup) {
1402
- self._volume = vol;
1403
- }
1404
-
1405
- // When the fade is complete, stop it and fire event.
1406
- if ((to < from && vol <= to) || (to > from && vol >= to)) {
1407
- clearInterval(sound._interval);
1408
- sound._interval = null;
1409
- sound._fadeTo = null;
1410
- self.volume(to, sound._id);
1411
- self._emit('fade', sound._id);
1412
- }
1413
- }, stepLen);
1414
- },
1415
-
1416
- /**
1417
- * Internal method that stops the currently playing fade when
1418
- * a new fade starts, volume is changed or the sound is stopped.
1419
- * @param {Number} id The sound id.
1420
- * @return {Howl}
1421
- */
1422
- _stopFade: function(id) {
1423
- var self = this;
1424
- var sound = self._soundById(id);
1425
-
1426
- if (sound && sound._interval) {
1427
- if (self._webAudio) {
1428
- sound._node.gain.cancelScheduledValues(Howler.ctx.currentTime);
1429
- }
1430
-
1431
- clearInterval(sound._interval);
1432
- sound._interval = null;
1433
- self.volume(sound._fadeTo, id);
1434
- sound._fadeTo = null;
1435
- self._emit('fade', id);
1436
- }
1437
-
1438
- return self;
1439
- },
1440
-
1441
- /**
1442
- * Get/set the loop parameter on a sound. This method can optionally take 0, 1 or 2 arguments.
1443
- * loop() -> Returns the group's loop value.
1444
- * loop(id) -> Returns the sound id's loop value.
1445
- * loop(loop) -> Sets the loop value for all sounds in this Howl group.
1446
- * loop(loop, id) -> Sets the loop value of passed sound id.
1447
- * @return {Howl/Boolean} Returns self or current loop value.
1448
- */
1449
- loop: function() {
1450
- var self = this;
1451
- var args = arguments;
1452
- var loop, id, sound;
1453
-
1454
- // Determine the values for loop and id.
1455
- if (args.length === 0) {
1456
- // Return the grou's loop value.
1457
- return self._loop;
1458
- } else if (args.length === 1) {
1459
- if (typeof args[0] === 'boolean') {
1460
- loop = args[0];
1461
- self._loop = loop;
1462
- } else {
1463
- // Return this sound's loop value.
1464
- sound = self._soundById(parseInt(args[0], 10));
1465
- return sound ? sound._loop : false;
1466
- }
1467
- } else if (args.length === 2) {
1468
- loop = args[0];
1469
- id = parseInt(args[1], 10);
1470
- }
1471
-
1472
- // If no id is passed, get all ID's to be looped.
1473
- var ids = self._getSoundIds(id);
1474
- for (var i=0; i<ids.length; i++) {
1475
- sound = self._soundById(ids[i]);
1476
-
1477
- if (sound) {
1478
- sound._loop = loop;
1479
- if (self._webAudio && sound._node && sound._node.bufferSource) {
1480
- sound._node.bufferSource.loop = loop;
1481
- if (loop) {
1482
- sound._node.bufferSource.loopStart = sound._start || 0;
1483
- sound._node.bufferSource.loopEnd = sound._stop;
1484
-
1485
- // If playing, restart playback to ensure looping updates.
1486
- if (self.playing(ids[i])) {
1487
- self.pause(ids[i], true);
1488
- self.play(ids[i], true);
1489
- }
1490
- }
1491
- }
1492
- }
1493
- }
1494
-
1495
- return self;
1496
- },
1497
-
1498
- /**
1499
- * Get/set the playback rate of a sound. This method can optionally take 0, 1 or 2 arguments.
1500
- * rate() -> Returns the first sound node's current playback rate.
1501
- * rate(id) -> Returns the sound id's current playback rate.
1502
- * rate(rate) -> Sets the playback rate of all sounds in this Howl group.
1503
- * rate(rate, id) -> Sets the playback rate of passed sound id.
1504
- * @return {Howl/Number} Returns self or the current playback rate.
1505
- */
1506
- rate: function() {
1507
- var self = this;
1508
- var args = arguments;
1509
- var rate, id;
1510
-
1511
- // Determine the values based on arguments.
1512
- if (args.length === 0) {
1513
- // We will simply return the current rate of the first node.
1514
- id = self._sounds[0]._id;
1515
- } else if (args.length === 1) {
1516
- // First check if this is an ID, and if not, assume it is a new rate value.
1517
- var ids = self._getSoundIds();
1518
- var index = ids.indexOf(args[0]);
1519
- if (index >= 0) {
1520
- id = parseInt(args[0], 10);
1521
- } else {
1522
- rate = parseFloat(args[0]);
1523
- }
1524
- } else if (args.length === 2) {
1525
- rate = parseFloat(args[0]);
1526
- id = parseInt(args[1], 10);
1527
- }
1528
-
1529
- // Update the playback rate or return the current value.
1530
- var sound;
1531
- if (typeof rate === 'number') {
1532
- // If the sound hasn't loaded, add it to the load queue to change playback rate when capable.
1533
- if (self._state !== 'loaded' || self._playLock) {
1534
- self._queue.push({
1535
- event: 'rate',
1536
- action: function() {
1537
- self.rate.apply(self, args);
1538
- }
1539
- });
1540
-
1541
- return self;
1542
- }
1543
-
1544
- // Set the group rate.
1545
- if (typeof id === 'undefined') {
1546
- self._rate = rate;
1547
- }
1548
-
1549
- // Update one or all volumes.
1550
- id = self._getSoundIds(id);
1551
- for (var i=0; i<id.length; i++) {
1552
- // Get the sound.
1553
- sound = self._soundById(id[i]);
1554
-
1555
- if (sound) {
1556
- // Keep track of our position when the rate changed and update the playback
1557
- // start position so we can properly adjust the seek position for time elapsed.
1558
- if (self.playing(id[i])) {
1559
- sound._rateSeek = self.seek(id[i]);
1560
- sound._playStart = self._webAudio ? Howler.ctx.currentTime : sound._playStart;
1561
- }
1562
- sound._rate = rate;
1563
-
1564
- // Change the playback rate.
1565
- if (self._webAudio && sound._node && sound._node.bufferSource) {
1566
- sound._node.bufferSource.playbackRate.setValueAtTime(rate, Howler.ctx.currentTime);
1567
- } else if (sound._node) {
1568
- sound._node.playbackRate = rate;
1569
- }
1570
-
1571
- // Reset the timers.
1572
- var seek = self.seek(id[i]);
1573
- var duration = ((self._sprite[sound._sprite][0] + self._sprite[sound._sprite][1]) / 1000) - seek;
1574
- var timeout = (duration * 1000) / Math.abs(sound._rate);
1575
-
1576
- // Start a new end timer if sound is already playing.
1577
- if (self._endTimers[id[i]] || !sound._paused) {
1578
- self._clearTimer(id[i]);
1579
- self._endTimers[id[i]] = setTimeout(self._ended.bind(self, sound), timeout);
1580
- }
1581
-
1582
- self._emit('rate', sound._id);
1583
- }
1584
- }
1585
- } else {
1586
- sound = self._soundById(id);
1587
- return sound ? sound._rate : self._rate;
1588
- }
1589
-
1590
- return self;
1591
- },
1592
-
1593
- /**
1594
- * Get/set the seek position of a sound. This method can optionally take 0, 1 or 2 arguments.
1595
- * seek() -> Returns the first sound node's current seek position.
1596
- * seek(id) -> Returns the sound id's current seek position.
1597
- * seek(seek) -> Sets the seek position of the first sound node.
1598
- * seek(seek, id) -> Sets the seek position of passed sound id.
1599
- * @return {Howl/Number} Returns self or the current seek position.
1600
- */
1601
- seek: function() {
1602
- var self = this;
1603
- var args = arguments;
1604
- var seek, id;
1605
-
1606
- // Determine the values based on arguments.
1607
- if (args.length === 0) {
1608
- // We will simply return the current position of the first node.
1609
- if (self._sounds.length) {
1610
- id = self._sounds[0]._id;
1611
- }
1612
- } else if (args.length === 1) {
1613
- // First check if this is an ID, and if not, assume it is a new seek position.
1614
- var ids = self._getSoundIds();
1615
- var index = ids.indexOf(args[0]);
1616
- if (index >= 0) {
1617
- id = parseInt(args[0], 10);
1618
- } else if (self._sounds.length) {
1619
- id = self._sounds[0]._id;
1620
- seek = parseFloat(args[0]);
1621
- }
1622
- } else if (args.length === 2) {
1623
- seek = parseFloat(args[0]);
1624
- id = parseInt(args[1], 10);
1625
- }
1626
-
1627
- // If there is no ID, bail out.
1628
- if (typeof id === 'undefined') {
1629
- return 0;
1630
- }
1631
-
1632
- // If the sound hasn't loaded, add it to the load queue to seek when capable.
1633
- if (typeof seek === 'number' && (self._state !== 'loaded' || self._playLock)) {
1634
- self._queue.push({
1635
- event: 'seek',
1636
- action: function() {
1637
- self.seek.apply(self, args);
1638
- }
1639
- });
1640
-
1641
- return self;
1642
- }
1643
-
1644
- // Get the sound.
1645
- var sound = self._soundById(id);
1646
-
1647
- if (sound) {
1648
- if (typeof seek === 'number' && seek >= 0) {
1649
- // Pause the sound and update position for restarting playback.
1650
- var playing = self.playing(id);
1651
- if (playing) {
1652
- self.pause(id, true);
1653
- }
1654
-
1655
- // Move the position of the track and cancel timer.
1656
- sound._seek = seek;
1657
- sound._ended = false;
1658
- self._clearTimer(id);
1659
-
1660
- // Update the seek position for HTML5 Audio.
1661
- if (!self._webAudio && sound._node && !isNaN(sound._node.duration)) {
1662
- sound._node.currentTime = seek;
1663
- }
1664
-
1665
- // Seek and emit when ready.
1666
- var seekAndEmit = function() {
1667
- // Restart the playback if the sound was playing.
1668
- if (playing) {
1669
- self.play(id, true);
1670
- }
1671
-
1672
- self._emit('seek', id);
1673
- };
1674
-
1675
- // Wait for the play lock to be unset before emitting (HTML5 Audio).
1676
- if (playing && !self._webAudio) {
1677
- var emitSeek = function() {
1678
- if (!self._playLock) {
1679
- seekAndEmit();
1680
- } else {
1681
- setTimeout(emitSeek, 0);
1682
- }
1683
- };
1684
- setTimeout(emitSeek, 0);
1685
- } else {
1686
- seekAndEmit();
1687
- }
1688
- } else {
1689
- if (self._webAudio) {
1690
- var realTime = self.playing(id) ? Howler.ctx.currentTime - sound._playStart : 0;
1691
- var rateSeek = sound._rateSeek ? sound._rateSeek - sound._seek : 0;
1692
- return sound._seek + (rateSeek + realTime * Math.abs(sound._rate));
1693
- } else {
1694
- return sound._node.currentTime;
1695
- }
1696
- }
1697
- }
1698
-
1699
- return self;
1700
- },
1701
-
1702
- /**
1703
- * Check if a specific sound is currently playing or not (if id is provided), or check if at least one of the sounds in the group is playing or not.
1704
- * @param {Number} id The sound id to check. If none is passed, the whole sound group is checked.
1705
- * @return {Boolean} True if playing and false if not.
1706
- */
1707
- playing: function(id) {
1708
- var self = this;
1709
-
1710
- // Check the passed sound ID (if any).
1711
- if (typeof id === 'number') {
1712
- var sound = self._soundById(id);
1713
- return sound ? !sound._paused : false;
1714
- }
1715
-
1716
- // Otherwise, loop through all sounds and check if any are playing.
1717
- for (var i=0; i<self._sounds.length; i++) {
1718
- if (!self._sounds[i]._paused) {
1719
- return true;
1720
- }
1721
- }
1722
-
1723
- return false;
1724
- },
1725
-
1726
- /**
1727
- * Get the duration of this sound. Passing a sound id will return the sprite duration.
1728
- * @param {Number} id The sound id to check. If none is passed, return full source duration.
1729
- * @return {Number} Audio duration in seconds.
1730
- */
1731
- duration: function(id) {
1732
- var self = this;
1733
- var duration = self._duration;
1734
-
1735
- // If we pass an ID, get the sound and return the sprite length.
1736
- var sound = self._soundById(id);
1737
- if (sound) {
1738
- duration = self._sprite[sound._sprite][1] / 1000;
1739
- }
1740
-
1741
- return duration;
1742
- },
1743
-
1744
- /**
1745
- * Returns the current loaded state of this Howl.
1746
- * @return {String} 'unloaded', 'loading', 'loaded'
1747
- */
1748
- state: function() {
1749
- return this._state;
1750
- },
1751
-
1752
- /**
1753
- * Unload and destroy the current Howl object.
1754
- * This will immediately stop all sound instances attached to this group.
1755
- */
1756
- unload: function() {
1757
- var self = this;
1758
-
1759
- // Stop playing any active sounds.
1760
- var sounds = self._sounds;
1761
- for (var i=0; i<sounds.length; i++) {
1762
- // Stop the sound if it is currently playing.
1763
- if (!sounds[i]._paused) {
1764
- self.stop(sounds[i]._id);
1765
- }
1766
-
1767
- // Remove the source or disconnect.
1768
- if (!self._webAudio) {
1769
- // Set the source to 0-second silence to stop any downloading (except in IE).
1770
- self._clearSound(sounds[i]._node);
1771
-
1772
- // Remove any event listeners.
1773
- sounds[i]._node.removeEventListener('error', sounds[i]._errorFn, false);
1774
- sounds[i]._node.removeEventListener(Howler._canPlayEvent, sounds[i]._loadFn, false);
1775
- sounds[i]._node.removeEventListener('ended', sounds[i]._endFn, false);
1776
-
1777
- // Release the Audio object back to the pool.
1778
- Howler._releaseHtml5Audio(sounds[i]._node);
1779
- }
1780
-
1781
- // Empty out all of the nodes.
1782
- delete sounds[i]._node;
1783
-
1784
- // Make sure all timers are cleared out.
1785
- self._clearTimer(sounds[i]._id);
1786
- }
1787
-
1788
- // Remove the references in the global Howler object.
1789
- var index = Howler._howls.indexOf(self);
1790
- if (index >= 0) {
1791
- Howler._howls.splice(index, 1);
1792
- }
1793
-
1794
- // Delete this sound from the cache (if no other Howl is using it).
1795
- var remCache = true;
1796
- for (i=0; i<Howler._howls.length; i++) {
1797
- if (Howler._howls[i]._src === self._src || self._src.indexOf(Howler._howls[i]._src) >= 0) {
1798
- remCache = false;
1799
- break;
1800
- }
1801
- }
1802
-
1803
- if (cache && remCache) {
1804
- delete cache[self._src];
1805
- }
1806
-
1807
- // Clear global errors.
1808
- Howler.noAudio = false;
1809
-
1810
- // Clear out `self`.
1811
- self._state = 'unloaded';
1812
- self._sounds = [];
1813
- self = null;
1814
-
1815
- return null;
1816
- },
1817
-
1818
- /**
1819
- * Listen to a custom event.
1820
- * @param {String} event Event name.
1821
- * @param {Function} fn Listener to call.
1822
- * @param {Number} id (optional) Only listen to events for this sound.
1823
- * @param {Number} once (INTERNAL) Marks event to fire only once.
1824
- * @return {Howl}
1825
- */
1826
- on: function(event, fn, id, once) {
1827
- var self = this;
1828
- var events = self['_on' + event];
1829
-
1830
- if (typeof fn === 'function') {
1831
- events.push(once ? {id: id, fn: fn, once: once} : {id: id, fn: fn});
1832
- }
1833
-
1834
- return self;
1835
- },
1836
-
1837
- /**
1838
- * Remove a custom event. Call without parameters to remove all events.
1839
- * @param {String} event Event name.
1840
- * @param {Function} fn Listener to remove. Leave empty to remove all.
1841
- * @param {Number} id (optional) Only remove events for this sound.
1842
- * @return {Howl}
1843
- */
1844
- off: function(event, fn, id) {
1845
- var self = this;
1846
- var events = self['_on' + event];
1847
- var i = 0;
1848
-
1849
- // Allow passing just an event and ID.
1850
- if (typeof fn === 'number') {
1851
- id = fn;
1852
- fn = null;
1853
- }
1854
-
1855
- if (fn || id) {
1856
- // Loop through event store and remove the passed function.
1857
- for (i=0; i<events.length; i++) {
1858
- var isId = (id === events[i].id);
1859
- if (fn === events[i].fn && isId || !fn && isId) {
1860
- events.splice(i, 1);
1861
- break;
1862
- }
1863
- }
1864
- } else if (event) {
1865
- // Clear out all events of this type.
1866
- self['_on' + event] = [];
1867
- } else {
1868
- // Clear out all events of every type.
1869
- var keys = Object.keys(self);
1870
- for (i=0; i<keys.length; i++) {
1871
- if ((keys[i].indexOf('_on') === 0) && Array.isArray(self[keys[i]])) {
1872
- self[keys[i]] = [];
1873
- }
1874
- }
1875
- }
1876
-
1877
- return self;
1878
- },
1879
-
1880
- /**
1881
- * Listen to a custom event and remove it once fired.
1882
- * @param {String} event Event name.
1883
- * @param {Function} fn Listener to call.
1884
- * @param {Number} id (optional) Only listen to events for this sound.
1885
- * @return {Howl}
1886
- */
1887
- once: function(event, fn, id) {
1888
- var self = this;
1889
-
1890
- // Setup the event listener.
1891
- self.on(event, fn, id, 1);
1892
-
1893
- return self;
1894
- },
1895
-
1896
- /**
1897
- * Emit all events of a specific type and pass the sound id.
1898
- * @param {String} event Event name.
1899
- * @param {Number} id Sound ID.
1900
- * @param {Number} msg Message to go with event.
1901
- * @return {Howl}
1902
- */
1903
- _emit: function(event, id, msg) {
1904
- var self = this;
1905
- var events = self['_on' + event];
1906
-
1907
- // Loop through event store and fire all functions.
1908
- for (var i=events.length-1; i>=0; i--) {
1909
- // Only fire the listener if the correct ID is used.
1910
- if (!events[i].id || events[i].id === id || event === 'load') {
1911
- setTimeout(function(fn) {
1912
- fn.call(this, id, msg);
1913
- }.bind(self, events[i].fn), 0);
1914
-
1915
- // If this event was setup with `once`, remove it.
1916
- if (events[i].once) {
1917
- self.off(event, events[i].fn, events[i].id);
1918
- }
1919
- }
1920
- }
1921
-
1922
- // Pass the event type into load queue so that it can continue stepping.
1923
- self._loadQueue(event);
1924
-
1925
- return self;
1926
- },
1927
-
1928
- /**
1929
- * Queue of actions initiated before the sound has loaded.
1930
- * These will be called in sequence, with the next only firing
1931
- * after the previous has finished executing (even if async like play).
1932
- * @return {Howl}
1933
- */
1934
- _loadQueue: function(event) {
1935
- var self = this;
1936
-
1937
- if (self._queue.length > 0) {
1938
- var task = self._queue[0];
1939
-
1940
- // Remove this task if a matching event was passed.
1941
- if (task.event === event) {
1942
- self._queue.shift();
1943
- self._loadQueue();
1944
- }
1945
-
1946
- // Run the task if no event type is passed.
1947
- if (!event) {
1948
- task.action();
1949
- }
1950
- }
1951
-
1952
- return self;
1953
- },
1954
-
1955
- /**
1956
- * Fired when playback ends at the end of the duration.
1957
- * @param {Sound} sound The sound object to work with.
1958
- * @return {Howl}
1959
- */
1960
- _ended: function(sound) {
1961
- var self = this;
1962
- var sprite = sound._sprite;
1963
-
1964
- // If we are using IE and there was network latency we may be clipping
1965
- // audio before it completes playing. Lets check the node to make sure it
1966
- // believes it has completed, before ending the playback.
1967
- if (!self._webAudio && sound._node && !sound._node.paused && !sound._node.ended && sound._node.currentTime < sound._stop) {
1968
- setTimeout(self._ended.bind(self, sound), 100);
1969
- return self;
1970
- }
1971
-
1972
- // Should this sound loop?
1973
- var loop = !!(sound._loop || self._sprite[sprite][2]);
1974
-
1975
- // Fire the ended event.
1976
- self._emit('end', sound._id);
1977
-
1978
- // Restart the playback for HTML5 Audio loop.
1979
- if (!self._webAudio && loop) {
1980
- self.stop(sound._id, true).play(sound._id);
1981
- }
1982
-
1983
- // Restart this timer if on a Web Audio loop.
1984
- if (self._webAudio && loop) {
1985
- self._emit('play', sound._id);
1986
- sound._seek = sound._start || 0;
1987
- sound._rateSeek = 0;
1988
- sound._playStart = Howler.ctx.currentTime;
1989
-
1990
- var timeout = ((sound._stop - sound._start) * 1000) / Math.abs(sound._rate);
1991
- self._endTimers[sound._id] = setTimeout(self._ended.bind(self, sound), timeout);
1992
- }
1993
-
1994
- // Mark the node as paused.
1995
- if (self._webAudio && !loop) {
1996
- sound._paused = true;
1997
- sound._ended = true;
1998
- sound._seek = sound._start || 0;
1999
- sound._rateSeek = 0;
2000
- self._clearTimer(sound._id);
2001
-
2002
- // Clean up the buffer source.
2003
- self._cleanBuffer(sound._node);
2004
-
2005
- // Attempt to auto-suspend AudioContext if no sounds are still playing.
2006
- Howler._autoSuspend();
2007
- }
2008
-
2009
- // When using a sprite, end the track.
2010
- if (!self._webAudio && !loop) {
2011
- self.stop(sound._id, true);
2012
- }
2013
-
2014
- return self;
2015
- },
2016
-
2017
- /**
2018
- * Clear the end timer for a sound playback.
2019
- * @param {Number} id The sound ID.
2020
- * @return {Howl}
2021
- */
2022
- _clearTimer: function(id) {
2023
- var self = this;
2024
-
2025
- if (self._endTimers[id]) {
2026
- // Clear the timeout or remove the ended listener.
2027
- if (typeof self._endTimers[id] !== 'function') {
2028
- clearTimeout(self._endTimers[id]);
2029
- } else {
2030
- var sound = self._soundById(id);
2031
- if (sound && sound._node) {
2032
- sound._node.removeEventListener('ended', self._endTimers[id], false);
2033
- }
2034
- }
2035
-
2036
- delete self._endTimers[id];
2037
- }
2038
-
2039
- return self;
2040
- },
2041
-
2042
- /**
2043
- * Return the sound identified by this ID, or return null.
2044
- * @param {Number} id Sound ID
2045
- * @return {Object} Sound object or null.
2046
- */
2047
- _soundById: function(id) {
2048
- var self = this;
2049
-
2050
- // Loop through all sounds and find the one with this ID.
2051
- for (var i=0; i<self._sounds.length; i++) {
2052
- if (id === self._sounds[i]._id) {
2053
- return self._sounds[i];
2054
- }
2055
- }
2056
-
2057
- return null;
2058
- },
2059
-
2060
- /**
2061
- * Return an inactive sound from the pool or create a new one.
2062
- * @return {Sound} Sound playback object.
2063
- */
2064
- _inactiveSound: function() {
2065
- var self = this;
2066
-
2067
- self._drain();
2068
-
2069
- // Find the first inactive node to recycle.
2070
- for (var i=0; i<self._sounds.length; i++) {
2071
- if (self._sounds[i]._ended) {
2072
- return self._sounds[i].reset();
2073
- }
2074
- }
2075
-
2076
- // If no inactive node was found, create a new one.
2077
- return new Sound(self);
2078
- },
2079
-
2080
- /**
2081
- * Drain excess inactive sounds from the pool.
2082
- */
2083
- _drain: function() {
2084
- var self = this;
2085
- var limit = self._pool;
2086
- var cnt = 0;
2087
- var i = 0;
2088
-
2089
- // If there are less sounds than the max pool size, we are done.
2090
- if (self._sounds.length < limit) {
2091
- return;
2092
- }
2093
-
2094
- // Count the number of inactive sounds.
2095
- for (i=0; i<self._sounds.length; i++) {
2096
- if (self._sounds[i]._ended) {
2097
- cnt++;
2098
- }
2099
- }
2100
-
2101
- // Remove excess inactive sounds, going in reverse order.
2102
- for (i=self._sounds.length - 1; i>=0; i--) {
2103
- if (cnt <= limit) {
2104
- return;
2105
- }
2106
-
2107
- if (self._sounds[i]._ended) {
2108
- // Disconnect the audio source when using Web Audio.
2109
- if (self._webAudio && self._sounds[i]._node) {
2110
- self._sounds[i]._node.disconnect(0);
2111
- }
2112
-
2113
- // Remove sounds until we have the pool size.
2114
- self._sounds.splice(i, 1);
2115
- cnt--;
2116
- }
2117
- }
2118
- },
2119
-
2120
- /**
2121
- * Get all ID's from the sounds pool.
2122
- * @param {Number} id Only return one ID if one is passed.
2123
- * @return {Array} Array of IDs.
2124
- */
2125
- _getSoundIds: function(id) {
2126
- var self = this;
2127
-
2128
- if (typeof id === 'undefined') {
2129
- var ids = [];
2130
- for (var i=0; i<self._sounds.length; i++) {
2131
- ids.push(self._sounds[i]._id);
2132
- }
2133
-
2134
- return ids;
2135
- } else {
2136
- return [id];
2137
- }
2138
- },
2139
-
2140
- /**
2141
- * Load the sound back into the buffer source.
2142
- * @param {Sound} sound The sound object to work with.
2143
- * @return {Howl}
2144
- */
2145
- _refreshBuffer: function(sound) {
2146
- var self = this;
2147
-
2148
- // Setup the buffer source for playback.
2149
- sound._node.bufferSource = Howler.ctx.createBufferSource();
2150
- sound._node.bufferSource.buffer = cache[self._src];
2151
-
2152
- // Connect to the correct node.
2153
- if (sound._panner) {
2154
- sound._node.bufferSource.connect(sound._panner);
2155
- } else {
2156
- sound._node.bufferSource.connect(sound._node);
2157
- }
2158
-
2159
- // Setup looping and playback rate.
2160
- sound._node.bufferSource.loop = sound._loop;
2161
- if (sound._loop) {
2162
- sound._node.bufferSource.loopStart = sound._start || 0;
2163
- sound._node.bufferSource.loopEnd = sound._stop || 0;
2164
- }
2165
- sound._node.bufferSource.playbackRate.setValueAtTime(sound._rate, Howler.ctx.currentTime);
2166
-
2167
- return self;
2168
- },
2169
-
2170
- /**
2171
- * Prevent memory leaks by cleaning up the buffer source after playback.
2172
- * @param {Object} node Sound's audio node containing the buffer source.
2173
- * @return {Howl}
2174
- */
2175
- _cleanBuffer: function(node) {
2176
- var self = this;
2177
- var isIOS = Howler._navigator && Howler._navigator.vendor.indexOf('Apple') >= 0;
2178
-
2179
- if (!node.bufferSource) {
2180
- return self;
2181
- }
2182
-
2183
- if (Howler._scratchBuffer && node.bufferSource) {
2184
- node.bufferSource.onended = null;
2185
- node.bufferSource.disconnect(0);
2186
- if (isIOS) {
2187
- try { node.bufferSource.buffer = Howler._scratchBuffer; } catch(e) {}
2188
- }
2189
- }
2190
- node.bufferSource = null;
2191
-
2192
- return self;
2193
- },
2194
-
2195
- /**
2196
- * Set the source to a 0-second silence to stop any downloading (except in IE).
2197
- * @param {Object} node Audio node to clear.
2198
- */
2199
- _clearSound: function(node) {
2200
- var checkIE = /MSIE |Trident\//.test(Howler._navigator && Howler._navigator.userAgent);
2201
- if (!checkIE) {
2202
- node.src = 'data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA';
2203
- }
2204
- }
2205
- };
2206
-
2207
- /** Single Sound Methods **/
2208
- /***************************************************************************/
2209
-
2210
- /**
2211
- * Setup the sound object, which each node attached to a Howl group is contained in.
2212
- * @param {Object} howl The Howl parent group.
2213
- */
2214
- var Sound = function(howl) {
2215
- this._parent = howl;
2216
- this.init();
2217
- };
2218
- Sound.prototype = {
2219
- /**
2220
- * Initialize a new Sound object.
2221
- * @return {Sound}
2222
- */
2223
- init: function() {
2224
- var self = this;
2225
- var parent = self._parent;
2226
-
2227
- // Setup the default parameters.
2228
- self._muted = parent._muted;
2229
- self._loop = parent._loop;
2230
- self._volume = parent._volume;
2231
- self._rate = parent._rate;
2232
- self._seek = 0;
2233
- self._paused = true;
2234
- self._ended = true;
2235
- self._sprite = '__default';
2236
-
2237
- // Generate a unique ID for this sound.
2238
- self._id = ++Howler._counter;
2239
-
2240
- // Add itself to the parent's pool.
2241
- parent._sounds.push(self);
2242
-
2243
- // Create the new node.
2244
- self.create();
2245
-
2246
- return self;
2247
- },
2248
-
2249
- /**
2250
- * Create and setup a new sound object, whether HTML5 Audio or Web Audio.
2251
- * @return {Sound}
2252
- */
2253
- create: function() {
2254
- var self = this;
2255
- var parent = self._parent;
2256
- var volume = (Howler._muted || self._muted || self._parent._muted) ? 0 : self._volume;
2257
-
2258
- if (parent._webAudio) {
2259
- // Create the gain node for controlling volume (the source will connect to this).
2260
- self._node = (typeof Howler.ctx.createGain === 'undefined') ? Howler.ctx.createGainNode() : Howler.ctx.createGain();
2261
- self._node.gain.setValueAtTime(volume, Howler.ctx.currentTime);
2262
- self._node.paused = true;
2263
- self._node.connect(Howler.masterGain);
2264
- } else if (!Howler.noAudio) {
2265
- // Get an unlocked Audio object from the pool.
2266
- self._node = Howler._obtainHtml5Audio();
2267
-
2268
- // Listen for errors (http://dev.w3.org/html5/spec-author-view/spec.html#mediaerror).
2269
- self._errorFn = self._errorListener.bind(self);
2270
- self._node.addEventListener('error', self._errorFn, false);
2271
-
2272
- // Listen for 'canplaythrough' event to let us know the sound is ready.
2273
- self._loadFn = self._loadListener.bind(self);
2274
- self._node.addEventListener(Howler._canPlayEvent, self._loadFn, false);
2275
-
2276
- // Listen for the 'ended' event on the sound to account for edge-case where
2277
- // a finite sound has a duration of Infinity.
2278
- self._endFn = self._endListener.bind(self);
2279
- self._node.addEventListener('ended', self._endFn, false);
2280
-
2281
- // Setup the new audio node.
2282
- self._node.src = parent._src;
2283
- self._node.preload = parent._preload === true ? 'auto' : parent._preload;
2284
- self._node.volume = volume * Howler.volume();
2285
-
2286
- // Begin loading the source.
2287
- self._node.load();
2288
- }
2289
-
2290
- return self;
2291
- },
2292
-
2293
- /**
2294
- * Reset the parameters of this sound to the original state (for recycle).
2295
- * @return {Sound}
2296
- */
2297
- reset: function() {
2298
- var self = this;
2299
- var parent = self._parent;
2300
-
2301
- // Reset all of the parameters of this sound.
2302
- self._muted = parent._muted;
2303
- self._loop = parent._loop;
2304
- self._volume = parent._volume;
2305
- self._rate = parent._rate;
2306
- self._seek = 0;
2307
- self._rateSeek = 0;
2308
- self._paused = true;
2309
- self._ended = true;
2310
- self._sprite = '__default';
2311
-
2312
- // Generate a new ID so that it isn't confused with the previous sound.
2313
- self._id = ++Howler._counter;
2314
-
2315
- return self;
2316
- },
2317
-
2318
- /**
2319
- * HTML5 Audio error listener callback.
2320
- */
2321
- _errorListener: function() {
2322
- var self = this;
2323
-
2324
- // Fire an error event and pass back the code.
2325
- self._parent._emit('loaderror', self._id, self._node.error ? self._node.error.code : 0);
2326
-
2327
- // Clear the event listener.
2328
- self._node.removeEventListener('error', self._errorFn, false);
2329
- },
2330
-
2331
- /**
2332
- * HTML5 Audio canplaythrough listener callback.
2333
- */
2334
- _loadListener: function() {
2335
- var self = this;
2336
- var parent = self._parent;
2337
-
2338
- // Round up the duration to account for the lower precision in HTML5 Audio.
2339
- parent._duration = Math.ceil(self._node.duration * 10) / 10;
2340
-
2341
- // Setup a sprite if none is defined.
2342
- if (Object.keys(parent._sprite).length === 0) {
2343
- parent._sprite = {__default: [0, parent._duration * 1000]};
2344
- }
2345
-
2346
- if (parent._state !== 'loaded') {
2347
- parent._state = 'loaded';
2348
- parent._emit('load');
2349
- parent._loadQueue();
2350
- }
2351
-
2352
- // Clear the event listener.
2353
- self._node.removeEventListener(Howler._canPlayEvent, self._loadFn, false);
2354
- },
2355
-
2356
- /**
2357
- * HTML5 Audio ended listener callback.
2358
- */
2359
- _endListener: function() {
2360
- var self = this;
2361
- var parent = self._parent;
2362
-
2363
- // Only handle the `ended`` event if the duration is Infinity.
2364
- if (parent._duration === Infinity) {
2365
- // Update the parent duration to match the real audio duration.
2366
- // Round up the duration to account for the lower precision in HTML5 Audio.
2367
- parent._duration = Math.ceil(self._node.duration * 10) / 10;
2368
-
2369
- // Update the sprite that corresponds to the real duration.
2370
- if (parent._sprite.__default[1] === Infinity) {
2371
- parent._sprite.__default[1] = parent._duration * 1000;
2372
- }
2373
-
2374
- // Run the regular ended method.
2375
- parent._ended(self);
2376
- }
2377
-
2378
- // Clear the event listener since the duration is now correct.
2379
- self._node.removeEventListener('ended', self._endFn, false);
2380
- }
2381
- };
2382
-
2383
- /** Helper Methods **/
2384
- /***************************************************************************/
2385
-
2386
- var cache = {};
2387
-
2388
- /**
2389
- * Buffer a sound from URL, Data URI or cache and decode to audio source (Web Audio API).
2390
- * @param {Howl} self
2391
- */
2392
- var loadBuffer = function(self) {
2393
- var url = self._src;
2394
-
2395
- // Check if the buffer has already been cached and use it instead.
2396
- if (cache[url]) {
2397
- // Set the duration from the cache.
2398
- self._duration = cache[url].duration;
2399
-
2400
- // Load the sound into this Howl.
2401
- loadSound(self);
2402
-
2403
- return;
2404
- }
2405
-
2406
- if (/^data:[^;]+;base64,/.test(url)) {
2407
- // Decode the base64 data URI without XHR, since some browsers don't support it.
2408
- var data = atob(url.split(',')[1]);
2409
- var dataView = new Uint8Array(data.length);
2410
- for (var i=0; i<data.length; ++i) {
2411
- dataView[i] = data.charCodeAt(i);
2412
- }
2413
-
2414
- decodeAudioData(dataView.buffer, self);
2415
- } else {
2416
- // Load the buffer from the URL.
2417
- var xhr = new XMLHttpRequest();
2418
- xhr.open(self._xhr.method, url, true);
2419
- xhr.withCredentials = self._xhr.withCredentials;
2420
- xhr.responseType = 'arraybuffer';
2421
-
2422
- // Apply any custom headers to the request.
2423
- if (self._xhr.headers) {
2424
- Object.keys(self._xhr.headers).forEach(function(key) {
2425
- xhr.setRequestHeader(key, self._xhr.headers[key]);
2426
- });
2427
- }
2428
-
2429
- xhr.onload = function() {
2430
- // Make sure we get a successful response back.
2431
- var code = (xhr.status + '')[0];
2432
- if (code !== '0' && code !== '2' && code !== '3') {
2433
- self._emit('loaderror', null, 'Failed loading audio file with status: ' + xhr.status + '.');
2434
- return;
2435
- }
2436
-
2437
- decodeAudioData(xhr.response, self);
2438
- };
2439
- xhr.onerror = function() {
2440
- // If there is an error, switch to HTML5 Audio.
2441
- if (self._webAudio) {
2442
- self._html5 = true;
2443
- self._webAudio = false;
2444
- self._sounds = [];
2445
- delete cache[url];
2446
- self.load();
2447
- }
2448
- };
2449
- safeXhrSend(xhr);
2450
- }
2451
- };
2452
-
2453
- /**
2454
- * Send the XHR request wrapped in a try/catch.
2455
- * @param {Object} xhr XHR to send.
2456
- */
2457
- var safeXhrSend = function(xhr) {
2458
- try {
2459
- xhr.send();
2460
- } catch (e) {
2461
- xhr.onerror();
2462
- }
2463
- };
2464
-
2465
- /**
2466
- * Decode audio data from an array buffer.
2467
- * @param {ArrayBuffer} arraybuffer The audio data.
2468
- * @param {Howl} self
2469
- */
2470
- var decodeAudioData = function(arraybuffer, self) {
2471
- // Fire a load error if something broke.
2472
- var error = function() {
2473
- self._emit('loaderror', null, 'Decoding audio data failed.');
2474
- };
2475
-
2476
- // Load the sound on success.
2477
- var success = function(buffer) {
2478
- if (buffer && self._sounds.length > 0) {
2479
- cache[self._src] = buffer;
2480
- loadSound(self, buffer);
2481
- } else {
2482
- error();
2483
- }
2484
- };
2485
-
2486
- // Decode the buffer into an audio source.
2487
- if (typeof Promise !== 'undefined' && Howler.ctx.decodeAudioData.length === 1) {
2488
- Howler.ctx.decodeAudioData(arraybuffer).then(success).catch(error);
2489
- } else {
2490
- Howler.ctx.decodeAudioData(arraybuffer, success, error);
2491
- }
2492
- };
2493
-
2494
- /**
2495
- * Sound is now loaded, so finish setting everything up and fire the loaded event.
2496
- * @param {Howl} self
2497
- * @param {Object} buffer The decoded buffer sound source.
2498
- */
2499
- var loadSound = function(self, buffer) {
2500
- // Set the duration.
2501
- if (buffer && !self._duration) {
2502
- self._duration = buffer.duration;
2503
- }
2504
-
2505
- // Setup a sprite if none is defined.
2506
- if (Object.keys(self._sprite).length === 0) {
2507
- self._sprite = {__default: [0, self._duration * 1000]};
2508
- }
2509
-
2510
- // Fire the loaded event.
2511
- if (self._state !== 'loaded') {
2512
- self._state = 'loaded';
2513
- self._emit('load');
2514
- self._loadQueue();
2515
- }
2516
- };
2517
-
2518
- /**
2519
- * Setup the audio context when available, or switch to HTML5 Audio mode.
2520
- */
2521
- var setupAudioContext = function() {
2522
- // If we have already detected that Web Audio isn't supported, don't run this step again.
2523
- if (!Howler.usingWebAudio) {
2524
- return;
2525
- }
2526
-
2527
- // Check if we are using Web Audio and setup the AudioContext if we are.
2528
- try {
2529
- if (typeof AudioContext !== 'undefined') {
2530
- Howler.ctx = new AudioContext();
2531
- } else if (typeof webkitAudioContext !== 'undefined') {
2532
- Howler.ctx = new webkitAudioContext();
2533
- } else {
2534
- Howler.usingWebAudio = false;
2535
- }
2536
- } catch(e) {
2537
- Howler.usingWebAudio = false;
2538
- }
2539
-
2540
- // If the audio context creation still failed, set using web audio to false.
2541
- if (!Howler.ctx) {
2542
- Howler.usingWebAudio = false;
2543
- }
2544
-
2545
- // Check if a webview is being used on iOS8 or earlier (rather than the browser).
2546
- // If it is, disable Web Audio as it causes crashing.
2547
- var iOS = (/iP(hone|od|ad)/.test(Howler._navigator && Howler._navigator.platform));
2548
- var appVersion = Howler._navigator && Howler._navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/);
2549
- var version = appVersion ? parseInt(appVersion[1], 10) : null;
2550
- if (iOS && version && version < 9) {
2551
- var safari = /safari/.test(Howler._navigator && Howler._navigator.userAgent.toLowerCase());
2552
- if (Howler._navigator && !safari) {
2553
- Howler.usingWebAudio = false;
2554
- }
2555
- }
2556
-
2557
- // Create and expose the master GainNode when using Web Audio (useful for plugins or advanced usage).
2558
- if (Howler.usingWebAudio) {
2559
- Howler.masterGain = (typeof Howler.ctx.createGain === 'undefined') ? Howler.ctx.createGainNode() : Howler.ctx.createGain();
2560
- Howler.masterGain.gain.setValueAtTime(Howler._muted ? 0 : Howler._volume, Howler.ctx.currentTime);
2561
- Howler.masterGain.connect(Howler.ctx.destination);
2562
- }
2563
-
2564
- // Re-run the setup on Howler.
2565
- Howler._setup();
2566
- };
2567
-
2568
- // Add support for CommonJS libraries such as browserify.
2569
- {
2570
- exports.Howler = Howler;
2571
- exports.Howl = Howl;
2572
- }
2573
-
2574
- // Add to global in Node.js (for testing, etc).
2575
- if (typeof commonjsGlobal !== 'undefined') {
2576
- commonjsGlobal.HowlerGlobal = HowlerGlobal;
2577
- commonjsGlobal.Howler = Howler;
2578
- commonjsGlobal.Howl = Howl;
2579
- commonjsGlobal.Sound = Sound;
2580
- } else if (typeof window !== 'undefined') { // Define globally in case AMD is not available or unused.
2581
- window.HowlerGlobal = HowlerGlobal;
2582
- window.Howler = Howler;
2583
- window.Howl = Howl;
2584
- window.Sound = Sound;
2585
- }
2586
- })();
2587
-
2588
-
2589
- /*!
2590
- * Spatial Plugin - Adds support for stereo and 3D audio where Web Audio is supported.
2591
- *
2592
- * howler.js v2.2.4
2593
- * howlerjs.com
2594
- *
2595
- * (c) 2013-2020, James Simpson of GoldFire Studios
2596
- * goldfirestudios.com
2597
- *
2598
- * MIT License
2599
- */
2600
-
2601
- (function() {
2602
-
2603
- // Setup default properties.
2604
- HowlerGlobal.prototype._pos = [0, 0, 0];
2605
- HowlerGlobal.prototype._orientation = [0, 0, -1, 0, 1, 0];
2606
-
2607
- /** Global Methods **/
2608
- /***************************************************************************/
2609
-
2610
- /**
2611
- * Helper method to update the stereo panning position of all current Howls.
2612
- * Future Howls will not use this value unless explicitly set.
2613
- * @param {Number} pan A value of -1.0 is all the way left and 1.0 is all the way right.
2614
- * @return {Howler/Number} Self or current stereo panning value.
2615
- */
2616
- HowlerGlobal.prototype.stereo = function(pan) {
2617
- var self = this;
2618
-
2619
- // Stop right here if not using Web Audio.
2620
- if (!self.ctx || !self.ctx.listener) {
2621
- return self;
2622
- }
2623
-
2624
- // Loop through all Howls and update their stereo panning.
2625
- for (var i=self._howls.length-1; i>=0; i--) {
2626
- self._howls[i].stereo(pan);
2627
- }
2628
-
2629
- return self;
2630
- };
2631
-
2632
- /**
2633
- * Get/set the position of the listener in 3D cartesian space. Sounds using
2634
- * 3D position will be relative to the listener's position.
2635
- * @param {Number} x The x-position of the listener.
2636
- * @param {Number} y The y-position of the listener.
2637
- * @param {Number} z The z-position of the listener.
2638
- * @return {Howler/Array} Self or current listener position.
2639
- */
2640
- HowlerGlobal.prototype.pos = function(x, y, z) {
2641
- var self = this;
2642
-
2643
- // Stop right here if not using Web Audio.
2644
- if (!self.ctx || !self.ctx.listener) {
2645
- return self;
2646
- }
2647
-
2648
- // Set the defaults for optional 'y' & 'z'.
2649
- y = (typeof y !== 'number') ? self._pos[1] : y;
2650
- z = (typeof z !== 'number') ? self._pos[2] : z;
2651
-
2652
- if (typeof x === 'number') {
2653
- self._pos = [x, y, z];
2654
-
2655
- if (typeof self.ctx.listener.positionX !== 'undefined') {
2656
- self.ctx.listener.positionX.setTargetAtTime(self._pos[0], Howler.ctx.currentTime, 0.1);
2657
- self.ctx.listener.positionY.setTargetAtTime(self._pos[1], Howler.ctx.currentTime, 0.1);
2658
- self.ctx.listener.positionZ.setTargetAtTime(self._pos[2], Howler.ctx.currentTime, 0.1);
2659
- } else {
2660
- self.ctx.listener.setPosition(self._pos[0], self._pos[1], self._pos[2]);
2661
- }
2662
- } else {
2663
- return self._pos;
2664
- }
2665
-
2666
- return self;
2667
- };
2668
-
2669
- /**
2670
- * Get/set the direction the listener is pointing in the 3D cartesian space.
2671
- * A front and up vector must be provided. The front is the direction the
2672
- * face of the listener is pointing, and up is the direction the top of the
2673
- * listener is pointing. Thus, these values are expected to be at right angles
2674
- * from each other.
2675
- * @param {Number} x The x-orientation of the listener.
2676
- * @param {Number} y The y-orientation of the listener.
2677
- * @param {Number} z The z-orientation of the listener.
2678
- * @param {Number} xUp The x-orientation of the top of the listener.
2679
- * @param {Number} yUp The y-orientation of the top of the listener.
2680
- * @param {Number} zUp The z-orientation of the top of the listener.
2681
- * @return {Howler/Array} Returns self or the current orientation vectors.
2682
- */
2683
- HowlerGlobal.prototype.orientation = function(x, y, z, xUp, yUp, zUp) {
2684
- var self = this;
2685
-
2686
- // Stop right here if not using Web Audio.
2687
- if (!self.ctx || !self.ctx.listener) {
2688
- return self;
2689
- }
2690
-
2691
- // Set the defaults for optional 'y' & 'z'.
2692
- var or = self._orientation;
2693
- y = (typeof y !== 'number') ? or[1] : y;
2694
- z = (typeof z !== 'number') ? or[2] : z;
2695
- xUp = (typeof xUp !== 'number') ? or[3] : xUp;
2696
- yUp = (typeof yUp !== 'number') ? or[4] : yUp;
2697
- zUp = (typeof zUp !== 'number') ? or[5] : zUp;
2698
-
2699
- if (typeof x === 'number') {
2700
- self._orientation = [x, y, z, xUp, yUp, zUp];
2701
-
2702
- if (typeof self.ctx.listener.forwardX !== 'undefined') {
2703
- self.ctx.listener.forwardX.setTargetAtTime(x, Howler.ctx.currentTime, 0.1);
2704
- self.ctx.listener.forwardY.setTargetAtTime(y, Howler.ctx.currentTime, 0.1);
2705
- self.ctx.listener.forwardZ.setTargetAtTime(z, Howler.ctx.currentTime, 0.1);
2706
- self.ctx.listener.upX.setTargetAtTime(xUp, Howler.ctx.currentTime, 0.1);
2707
- self.ctx.listener.upY.setTargetAtTime(yUp, Howler.ctx.currentTime, 0.1);
2708
- self.ctx.listener.upZ.setTargetAtTime(zUp, Howler.ctx.currentTime, 0.1);
2709
- } else {
2710
- self.ctx.listener.setOrientation(x, y, z, xUp, yUp, zUp);
2711
- }
2712
- } else {
2713
- return or;
2714
- }
2715
-
2716
- return self;
2717
- };
2718
-
2719
- /** Group Methods **/
2720
- /***************************************************************************/
2721
-
2722
- /**
2723
- * Add new properties to the core init.
2724
- * @param {Function} _super Core init method.
2725
- * @return {Howl}
2726
- */
2727
- Howl.prototype.init = (function(_super) {
2728
- return function(o) {
2729
- var self = this;
2730
-
2731
- // Setup user-defined default properties.
2732
- self._orientation = o.orientation || [1, 0, 0];
2733
- self._stereo = o.stereo || null;
2734
- self._pos = o.pos || null;
2735
- self._pannerAttr = {
2736
- coneInnerAngle: typeof o.coneInnerAngle !== 'undefined' ? o.coneInnerAngle : 360,
2737
- coneOuterAngle: typeof o.coneOuterAngle !== 'undefined' ? o.coneOuterAngle : 360,
2738
- coneOuterGain: typeof o.coneOuterGain !== 'undefined' ? o.coneOuterGain : 0,
2739
- distanceModel: typeof o.distanceModel !== 'undefined' ? o.distanceModel : 'inverse',
2740
- maxDistance: typeof o.maxDistance !== 'undefined' ? o.maxDistance : 10000,
2741
- panningModel: typeof o.panningModel !== 'undefined' ? o.panningModel : 'HRTF',
2742
- refDistance: typeof o.refDistance !== 'undefined' ? o.refDistance : 1,
2743
- rolloffFactor: typeof o.rolloffFactor !== 'undefined' ? o.rolloffFactor : 1
2744
- };
2745
-
2746
- // Setup event listeners.
2747
- self._onstereo = o.onstereo ? [{fn: o.onstereo}] : [];
2748
- self._onpos = o.onpos ? [{fn: o.onpos}] : [];
2749
- self._onorientation = o.onorientation ? [{fn: o.onorientation}] : [];
2750
-
2751
- // Complete initilization with howler.js core's init function.
2752
- return _super.call(this, o);
2753
- };
2754
- })(Howl.prototype.init);
2755
-
2756
- /**
2757
- * Get/set the stereo panning of the audio source for this sound or all in the group.
2758
- * @param {Number} pan A value of -1.0 is all the way left and 1.0 is all the way right.
2759
- * @param {Number} id (optional) The sound ID. If none is passed, all in group will be updated.
2760
- * @return {Howl/Number} Returns self or the current stereo panning value.
2761
- */
2762
- Howl.prototype.stereo = function(pan, id) {
2763
- var self = this;
2764
-
2765
- // Stop right here if not using Web Audio.
2766
- if (!self._webAudio) {
2767
- return self;
2768
- }
2769
-
2770
- // If the sound hasn't loaded, add it to the load queue to change stereo pan when capable.
2771
- if (self._state !== 'loaded') {
2772
- self._queue.push({
2773
- event: 'stereo',
2774
- action: function() {
2775
- self.stereo(pan, id);
2776
- }
2777
- });
2778
-
2779
- return self;
2780
- }
2781
-
2782
- // Check for PannerStereoNode support and fallback to PannerNode if it doesn't exist.
2783
- var pannerType = (typeof Howler.ctx.createStereoPanner === 'undefined') ? 'spatial' : 'stereo';
2784
-
2785
- // Setup the group's stereo panning if no ID is passed.
2786
- if (typeof id === 'undefined') {
2787
- // Return the group's stereo panning if no parameters are passed.
2788
- if (typeof pan === 'number') {
2789
- self._stereo = pan;
2790
- self._pos = [pan, 0, 0];
2791
- } else {
2792
- return self._stereo;
2793
- }
2794
- }
2795
-
2796
- // Change the streo panning of one or all sounds in group.
2797
- var ids = self._getSoundIds(id);
2798
- for (var i=0; i<ids.length; i++) {
2799
- // Get the sound.
2800
- var sound = self._soundById(ids[i]);
2801
-
2802
- if (sound) {
2803
- if (typeof pan === 'number') {
2804
- sound._stereo = pan;
2805
- sound._pos = [pan, 0, 0];
2806
-
2807
- if (sound._node) {
2808
- // If we are falling back, make sure the panningModel is equalpower.
2809
- sound._pannerAttr.panningModel = 'equalpower';
2810
-
2811
- // Check if there is a panner setup and create a new one if not.
2812
- if (!sound._panner || !sound._panner.pan) {
2813
- setupPanner(sound, pannerType);
2814
- }
2815
-
2816
- if (pannerType === 'spatial') {
2817
- if (typeof sound._panner.positionX !== 'undefined') {
2818
- sound._panner.positionX.setValueAtTime(pan, Howler.ctx.currentTime);
2819
- sound._panner.positionY.setValueAtTime(0, Howler.ctx.currentTime);
2820
- sound._panner.positionZ.setValueAtTime(0, Howler.ctx.currentTime);
2821
- } else {
2822
- sound._panner.setPosition(pan, 0, 0);
2823
- }
2824
- } else {
2825
- sound._panner.pan.setValueAtTime(pan, Howler.ctx.currentTime);
2826
- }
2827
- }
2828
-
2829
- self._emit('stereo', sound._id);
2830
- } else {
2831
- return sound._stereo;
2832
- }
2833
- }
2834
- }
2835
-
2836
- return self;
2837
- };
2838
-
2839
- /**
2840
- * Get/set the 3D spatial position of the audio source for this sound or group relative to the global listener.
2841
- * @param {Number} x The x-position of the audio source.
2842
- * @param {Number} y The y-position of the audio source.
2843
- * @param {Number} z The z-position of the audio source.
2844
- * @param {Number} id (optional) The sound ID. If none is passed, all in group will be updated.
2845
- * @return {Howl/Array} Returns self or the current 3D spatial position: [x, y, z].
2846
- */
2847
- Howl.prototype.pos = function(x, y, z, id) {
2848
- var self = this;
2849
-
2850
- // Stop right here if not using Web Audio.
2851
- if (!self._webAudio) {
2852
- return self;
2853
- }
2854
-
2855
- // If the sound hasn't loaded, add it to the load queue to change position when capable.
2856
- if (self._state !== 'loaded') {
2857
- self._queue.push({
2858
- event: 'pos',
2859
- action: function() {
2860
- self.pos(x, y, z, id);
2861
- }
2862
- });
2863
-
2864
- return self;
2865
- }
2866
-
2867
- // Set the defaults for optional 'y' & 'z'.
2868
- y = (typeof y !== 'number') ? 0 : y;
2869
- z = (typeof z !== 'number') ? -0.5 : z;
2870
-
2871
- // Setup the group's spatial position if no ID is passed.
2872
- if (typeof id === 'undefined') {
2873
- // Return the group's spatial position if no parameters are passed.
2874
- if (typeof x === 'number') {
2875
- self._pos = [x, y, z];
2876
- } else {
2877
- return self._pos;
2878
- }
2879
- }
2880
-
2881
- // Change the spatial position of one or all sounds in group.
2882
- var ids = self._getSoundIds(id);
2883
- for (var i=0; i<ids.length; i++) {
2884
- // Get the sound.
2885
- var sound = self._soundById(ids[i]);
2886
-
2887
- if (sound) {
2888
- if (typeof x === 'number') {
2889
- sound._pos = [x, y, z];
2890
-
2891
- if (sound._node) {
2892
- // Check if there is a panner setup and create a new one if not.
2893
- if (!sound._panner || sound._panner.pan) {
2894
- setupPanner(sound, 'spatial');
2895
- }
2896
-
2897
- if (typeof sound._panner.positionX !== 'undefined') {
2898
- sound._panner.positionX.setValueAtTime(x, Howler.ctx.currentTime);
2899
- sound._panner.positionY.setValueAtTime(y, Howler.ctx.currentTime);
2900
- sound._panner.positionZ.setValueAtTime(z, Howler.ctx.currentTime);
2901
- } else {
2902
- sound._panner.setPosition(x, y, z);
2903
- }
2904
- }
2905
-
2906
- self._emit('pos', sound._id);
2907
- } else {
2908
- return sound._pos;
2909
- }
2910
- }
2911
- }
2912
-
2913
- return self;
2914
- };
2915
-
2916
- /**
2917
- * Get/set the direction the audio source is pointing in the 3D cartesian coordinate
2918
- * space. Depending on how direction the sound is, based on the `cone` attributes,
2919
- * a sound pointing away from the listener can be quiet or silent.
2920
- * @param {Number} x The x-orientation of the source.
2921
- * @param {Number} y The y-orientation of the source.
2922
- * @param {Number} z The z-orientation of the source.
2923
- * @param {Number} id (optional) The sound ID. If none is passed, all in group will be updated.
2924
- * @return {Howl/Array} Returns self or the current 3D spatial orientation: [x, y, z].
2925
- */
2926
- Howl.prototype.orientation = function(x, y, z, id) {
2927
- var self = this;
2928
-
2929
- // Stop right here if not using Web Audio.
2930
- if (!self._webAudio) {
2931
- return self;
2932
- }
2933
-
2934
- // If the sound hasn't loaded, add it to the load queue to change orientation when capable.
2935
- if (self._state !== 'loaded') {
2936
- self._queue.push({
2937
- event: 'orientation',
2938
- action: function() {
2939
- self.orientation(x, y, z, id);
2940
- }
2941
- });
2942
-
2943
- return self;
2944
- }
2945
-
2946
- // Set the defaults for optional 'y' & 'z'.
2947
- y = (typeof y !== 'number') ? self._orientation[1] : y;
2948
- z = (typeof z !== 'number') ? self._orientation[2] : z;
2949
-
2950
- // Setup the group's spatial orientation if no ID is passed.
2951
- if (typeof id === 'undefined') {
2952
- // Return the group's spatial orientation if no parameters are passed.
2953
- if (typeof x === 'number') {
2954
- self._orientation = [x, y, z];
2955
- } else {
2956
- return self._orientation;
2957
- }
2958
- }
2959
-
2960
- // Change the spatial orientation of one or all sounds in group.
2961
- var ids = self._getSoundIds(id);
2962
- for (var i=0; i<ids.length; i++) {
2963
- // Get the sound.
2964
- var sound = self._soundById(ids[i]);
2965
-
2966
- if (sound) {
2967
- if (typeof x === 'number') {
2968
- sound._orientation = [x, y, z];
2969
-
2970
- if (sound._node) {
2971
- // Check if there is a panner setup and create a new one if not.
2972
- if (!sound._panner) {
2973
- // Make sure we have a position to setup the node with.
2974
- if (!sound._pos) {
2975
- sound._pos = self._pos || [0, 0, -0.5];
2976
- }
2977
-
2978
- setupPanner(sound, 'spatial');
2979
- }
2980
-
2981
- if (typeof sound._panner.orientationX !== 'undefined') {
2982
- sound._panner.orientationX.setValueAtTime(x, Howler.ctx.currentTime);
2983
- sound._panner.orientationY.setValueAtTime(y, Howler.ctx.currentTime);
2984
- sound._panner.orientationZ.setValueAtTime(z, Howler.ctx.currentTime);
2985
- } else {
2986
- sound._panner.setOrientation(x, y, z);
2987
- }
2988
- }
2989
-
2990
- self._emit('orientation', sound._id);
2991
- } else {
2992
- return sound._orientation;
2993
- }
2994
- }
2995
- }
2996
-
2997
- return self;
2998
- };
2999
-
3000
- /**
3001
- * Get/set the panner node's attributes for a sound or group of sounds.
3002
- * This method can optionall take 0, 1 or 2 arguments.
3003
- * pannerAttr() -> Returns the group's values.
3004
- * pannerAttr(id) -> Returns the sound id's values.
3005
- * pannerAttr(o) -> Set's the values of all sounds in this Howl group.
3006
- * pannerAttr(o, id) -> Set's the values of passed sound id.
3007
- *
3008
- * Attributes:
3009
- * coneInnerAngle - (360 by default) A parameter for directional audio sources, this is an angle, in degrees,
3010
- * inside of which there will be no volume reduction.
3011
- * coneOuterAngle - (360 by default) A parameter for directional audio sources, this is an angle, in degrees,
3012
- * outside of which the volume will be reduced to a constant value of `coneOuterGain`.
3013
- * coneOuterGain - (0 by default) A parameter for directional audio sources, this is the gain outside of the
3014
- * `coneOuterAngle`. It is a linear value in the range `[0, 1]`.
3015
- * distanceModel - ('inverse' by default) Determines algorithm used to reduce volume as audio moves away from
3016
- * listener. Can be `linear`, `inverse` or `exponential.
3017
- * maxDistance - (10000 by default) The maximum distance between source and listener, after which the volume
3018
- * will not be reduced any further.
3019
- * refDistance - (1 by default) A reference distance for reducing volume as source moves further from the listener.
3020
- * This is simply a variable of the distance model and has a different effect depending on which model
3021
- * is used and the scale of your coordinates. Generally, volume will be equal to 1 at this distance.
3022
- * rolloffFactor - (1 by default) How quickly the volume reduces as source moves from listener. This is simply a
3023
- * variable of the distance model and can be in the range of `[0, 1]` with `linear` and `[0, ∞]`
3024
- * with `inverse` and `exponential`.
3025
- * panningModel - ('HRTF' by default) Determines which spatialization algorithm is used to position audio.
3026
- * Can be `HRTF` or `equalpower`.
3027
- *
3028
- * @return {Howl/Object} Returns self or current panner attributes.
3029
- */
3030
- Howl.prototype.pannerAttr = function() {
3031
- var self = this;
3032
- var args = arguments;
3033
- var o, id, sound;
3034
-
3035
- // Stop right here if not using Web Audio.
3036
- if (!self._webAudio) {
3037
- return self;
3038
- }
3039
-
3040
- // Determine the values based on arguments.
3041
- if (args.length === 0) {
3042
- // Return the group's panner attribute values.
3043
- return self._pannerAttr;
3044
- } else if (args.length === 1) {
3045
- if (typeof args[0] === 'object') {
3046
- o = args[0];
3047
-
3048
- // Set the grou's panner attribute values.
3049
- if (typeof id === 'undefined') {
3050
- if (!o.pannerAttr) {
3051
- o.pannerAttr = {
3052
- coneInnerAngle: o.coneInnerAngle,
3053
- coneOuterAngle: o.coneOuterAngle,
3054
- coneOuterGain: o.coneOuterGain,
3055
- distanceModel: o.distanceModel,
3056
- maxDistance: o.maxDistance,
3057
- refDistance: o.refDistance,
3058
- rolloffFactor: o.rolloffFactor,
3059
- panningModel: o.panningModel
3060
- };
3061
- }
3062
-
3063
- self._pannerAttr = {
3064
- coneInnerAngle: typeof o.pannerAttr.coneInnerAngle !== 'undefined' ? o.pannerAttr.coneInnerAngle : self._coneInnerAngle,
3065
- coneOuterAngle: typeof o.pannerAttr.coneOuterAngle !== 'undefined' ? o.pannerAttr.coneOuterAngle : self._coneOuterAngle,
3066
- coneOuterGain: typeof o.pannerAttr.coneOuterGain !== 'undefined' ? o.pannerAttr.coneOuterGain : self._coneOuterGain,
3067
- distanceModel: typeof o.pannerAttr.distanceModel !== 'undefined' ? o.pannerAttr.distanceModel : self._distanceModel,
3068
- maxDistance: typeof o.pannerAttr.maxDistance !== 'undefined' ? o.pannerAttr.maxDistance : self._maxDistance,
3069
- refDistance: typeof o.pannerAttr.refDistance !== 'undefined' ? o.pannerAttr.refDistance : self._refDistance,
3070
- rolloffFactor: typeof o.pannerAttr.rolloffFactor !== 'undefined' ? o.pannerAttr.rolloffFactor : self._rolloffFactor,
3071
- panningModel: typeof o.pannerAttr.panningModel !== 'undefined' ? o.pannerAttr.panningModel : self._panningModel
3072
- };
3073
- }
3074
- } else {
3075
- // Return this sound's panner attribute values.
3076
- sound = self._soundById(parseInt(args[0], 10));
3077
- return sound ? sound._pannerAttr : self._pannerAttr;
3078
- }
3079
- } else if (args.length === 2) {
3080
- o = args[0];
3081
- id = parseInt(args[1], 10);
3082
- }
3083
-
3084
- // Update the values of the specified sounds.
3085
- var ids = self._getSoundIds(id);
3086
- for (var i=0; i<ids.length; i++) {
3087
- sound = self._soundById(ids[i]);
3088
-
3089
- if (sound) {
3090
- // Merge the new values into the sound.
3091
- var pa = sound._pannerAttr;
3092
- pa = {
3093
- coneInnerAngle: typeof o.coneInnerAngle !== 'undefined' ? o.coneInnerAngle : pa.coneInnerAngle,
3094
- coneOuterAngle: typeof o.coneOuterAngle !== 'undefined' ? o.coneOuterAngle : pa.coneOuterAngle,
3095
- coneOuterGain: typeof o.coneOuterGain !== 'undefined' ? o.coneOuterGain : pa.coneOuterGain,
3096
- distanceModel: typeof o.distanceModel !== 'undefined' ? o.distanceModel : pa.distanceModel,
3097
- maxDistance: typeof o.maxDistance !== 'undefined' ? o.maxDistance : pa.maxDistance,
3098
- refDistance: typeof o.refDistance !== 'undefined' ? o.refDistance : pa.refDistance,
3099
- rolloffFactor: typeof o.rolloffFactor !== 'undefined' ? o.rolloffFactor : pa.rolloffFactor,
3100
- panningModel: typeof o.panningModel !== 'undefined' ? o.panningModel : pa.panningModel
3101
- };
3102
-
3103
- // Create a new panner node if one doesn't already exist.
3104
- var panner = sound._panner;
3105
- if (!panner) {
3106
- // Make sure we have a position to setup the node with.
3107
- if (!sound._pos) {
3108
- sound._pos = self._pos || [0, 0, -0.5];
3109
- }
3110
-
3111
- // Create a new panner node.
3112
- setupPanner(sound, 'spatial');
3113
- panner = sound._panner;
3114
- }
3115
-
3116
- // Update the panner values or create a new panner if none exists.
3117
- panner.coneInnerAngle = pa.coneInnerAngle;
3118
- panner.coneOuterAngle = pa.coneOuterAngle;
3119
- panner.coneOuterGain = pa.coneOuterGain;
3120
- panner.distanceModel = pa.distanceModel;
3121
- panner.maxDistance = pa.maxDistance;
3122
- panner.refDistance = pa.refDistance;
3123
- panner.rolloffFactor = pa.rolloffFactor;
3124
- panner.panningModel = pa.panningModel;
3125
- }
3126
- }
3127
-
3128
- return self;
3129
- };
3130
-
3131
- /** Single Sound Methods **/
3132
- /***************************************************************************/
3133
-
3134
- /**
3135
- * Add new properties to the core Sound init.
3136
- * @param {Function} _super Core Sound init method.
3137
- * @return {Sound}
3138
- */
3139
- Sound.prototype.init = (function(_super) {
3140
- return function() {
3141
- var self = this;
3142
- var parent = self._parent;
3143
-
3144
- // Setup user-defined default properties.
3145
- self._orientation = parent._orientation;
3146
- self._stereo = parent._stereo;
3147
- self._pos = parent._pos;
3148
- self._pannerAttr = parent._pannerAttr;
3149
-
3150
- // Complete initilization with howler.js core Sound's init function.
3151
- _super.call(this);
3152
-
3153
- // If a stereo or position was specified, set it up.
3154
- if (self._stereo) {
3155
- parent.stereo(self._stereo);
3156
- } else if (self._pos) {
3157
- parent.pos(self._pos[0], self._pos[1], self._pos[2], self._id);
3158
- }
3159
- };
3160
- })(Sound.prototype.init);
3161
-
3162
- /**
3163
- * Override the Sound.reset method to clean up properties from the spatial plugin.
3164
- * @param {Function} _super Sound reset method.
3165
- * @return {Sound}
3166
- */
3167
- Sound.prototype.reset = (function(_super) {
3168
- return function() {
3169
- var self = this;
3170
- var parent = self._parent;
3171
-
3172
- // Reset all spatial plugin properties on this sound.
3173
- self._orientation = parent._orientation;
3174
- self._stereo = parent._stereo;
3175
- self._pos = parent._pos;
3176
- self._pannerAttr = parent._pannerAttr;
3177
-
3178
- // If a stereo or position was specified, set it up.
3179
- if (self._stereo) {
3180
- parent.stereo(self._stereo);
3181
- } else if (self._pos) {
3182
- parent.pos(self._pos[0], self._pos[1], self._pos[2], self._id);
3183
- } else if (self._panner) {
3184
- // Disconnect the panner.
3185
- self._panner.disconnect(0);
3186
- self._panner = undefined;
3187
- parent._refreshBuffer(self);
3188
- }
3189
-
3190
- // Complete resetting of the sound.
3191
- return _super.call(this);
3192
- };
3193
- })(Sound.prototype.reset);
3194
-
3195
- /** Helper Methods **/
3196
- /***************************************************************************/
3197
-
3198
- /**
3199
- * Create a new panner node and save it on the sound.
3200
- * @param {Sound} sound Specific sound to setup panning on.
3201
- * @param {String} type Type of panner to create: 'stereo' or 'spatial'.
3202
- */
3203
- var setupPanner = function(sound, type) {
3204
- type = type || 'spatial';
3205
-
3206
- // Create the new panner node.
3207
- if (type === 'spatial') {
3208
- sound._panner = Howler.ctx.createPanner();
3209
- sound._panner.coneInnerAngle = sound._pannerAttr.coneInnerAngle;
3210
- sound._panner.coneOuterAngle = sound._pannerAttr.coneOuterAngle;
3211
- sound._panner.coneOuterGain = sound._pannerAttr.coneOuterGain;
3212
- sound._panner.distanceModel = sound._pannerAttr.distanceModel;
3213
- sound._panner.maxDistance = sound._pannerAttr.maxDistance;
3214
- sound._panner.refDistance = sound._pannerAttr.refDistance;
3215
- sound._panner.rolloffFactor = sound._pannerAttr.rolloffFactor;
3216
- sound._panner.panningModel = sound._pannerAttr.panningModel;
3217
-
3218
- if (typeof sound._panner.positionX !== 'undefined') {
3219
- sound._panner.positionX.setValueAtTime(sound._pos[0], Howler.ctx.currentTime);
3220
- sound._panner.positionY.setValueAtTime(sound._pos[1], Howler.ctx.currentTime);
3221
- sound._panner.positionZ.setValueAtTime(sound._pos[2], Howler.ctx.currentTime);
3222
- } else {
3223
- sound._panner.setPosition(sound._pos[0], sound._pos[1], sound._pos[2]);
3224
- }
3225
-
3226
- if (typeof sound._panner.orientationX !== 'undefined') {
3227
- sound._panner.orientationX.setValueAtTime(sound._orientation[0], Howler.ctx.currentTime);
3228
- sound._panner.orientationY.setValueAtTime(sound._orientation[1], Howler.ctx.currentTime);
3229
- sound._panner.orientationZ.setValueAtTime(sound._orientation[2], Howler.ctx.currentTime);
3230
- } else {
3231
- sound._panner.setOrientation(sound._orientation[0], sound._orientation[1], sound._orientation[2]);
3232
- }
3233
- } else {
3234
- sound._panner = Howler.ctx.createStereoPanner();
3235
- sound._panner.pan.setValueAtTime(sound._stereo, Howler.ctx.currentTime);
3236
- }
3237
-
3238
- sound._panner.connect(sound._node);
3239
-
3240
- // Update the connections.
3241
- if (!sound._paused) {
3242
- sound._parent.pause(sound._id, true).play(sound._id, true);
3243
- }
3244
- };
3245
- })();
3246
- } (howler));