diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 9d4ed7af..73bcbc0a 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,10 +1,10 @@
-### Issue/Feature
+# Issue/Feature
-### Related Issues
+## Related Issues
### Solution
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..04c01ba7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+node_modules/
+dist/
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b71f5c6a..c3bcf761 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,12 +1,86 @@
+# 3.0.0
+
+This is the first alpha release of Howler.js v3.0, a major rewrite that migrates the library to TypeScript and introduces a modern plugin architecture.
+
+## Breaking Changes
+
+- **ES Modules Only**: Howler.js v3.0+ is distributed exclusively as ES Modules. For CommonJS/UMD support, use v2.x.
+- **TypeScript**: The library is now written in TypeScript with full type definitions included.
+- **Spatial Plugin**: The spatial audio functionality has been moved to a plugin that must be explicitly registered.
+- **Browser Support**: Requires modern browsers with ES Module support (Chrome 61+, Firefox 67+, Safari 11.1+, Edge 79+).
+
+### New Features
+
+- `ADDED` Complete TypeScript rewrite with full type definitions
+- `ADDED` Modern plugin system with hook-based architecture (`HowlerPlugin`, `PluginManager`)
+- `ADDED` Spatial audio plugin refactored to use the new plugin system
+- `ADDED` Lightweight UA parser for consistent browser/device detection
+- `ADDED` TypeScript types exported: `SpatialHowler`, `SpatialHowl`, `SpatialHowlOptions`
+- `ADDED` Plugin lifecycle hooks: `onHowlerInit`, `onHowlCreate`, `onSoundCreate`, `onHowlLoad`, `onHowlDestroy`, `onUnregister`
+- `ADDED` `Howler.addPlugin()` and `Howler.removePlugin()` methods for plugin management
+- `ADDED` `Howler.hasPlugin()` method to check if a plugin is registered
+- `ADDED` Import map examples in documentation for cleaner CDN usage
+- `ADDED` Comprehensive TypeScript examples throughout documentation
+
+### Improvements
+
+- `CHANGED` All user agent detection now uses centralized `light-ua-parser` functions
+- `CHANGED` Spatial plugin properly cleans up state when unregistered
+- `CHANGED` Plugin hooks execute correctly for both HTML5 and WebAudio backends
+- `CHANGED` Improved error handling in plugin system
+- `CHANGED` Better separation of concerns with modular architecture
+- `CHANGED` All code examples migrated to TypeScript with proper types
+
+### Migration Guide
+
+**From v2.x to v3.0:**
+
+1. **Update imports to ES Modules:**
+
+ ```typescript
+ // v2.x (CommonJS)
+ const { Howl, Howler } = require('howler');
+
+ // v3.0 (ES Modules)
+ import { Howl, Howler } from 'howler';
+ ```
+
+2. **Register spatial plugin if needed:**
+
+ ```typescript
+ // v3.0 - Spatial audio is now a plugin
+ import { SpatialAudioPlugin } from 'howler/plugins/spatial';
+ const plugin = new SpatialAudioPlugin()
+ Howler.addPlugin(plugin);
+ ```
+
+3. **Use TypeScript types for better IDE support:**
+
+ ```typescript
+ import type { SpatialHowler, SpatialHowl } from 'howler/plugins/spatial';
+ const howler: SpatialHowler = Howler as SpatialHowler;
+ const sound: SpatialHowl = new Howl({...}) as SpatialHowl;
+ ```
+
+### Documentation
+
+- Updated all code examples to TypeScript
+- Added import map examples for CDN and local builds
+- Comprehensive plugin system documentation
+- TypeScript type usage examples throughout
+
## 2.2.3 (September 20, 2023)
+
- `FIXED` Invalid regex detection of Opera versions 100+ ([#1676](https://github.com/goldfire/howler.js/pull/1676)).
- `FIXED` The `pannerAttr` method wouldn't set the values the first time it was called ([#1497](https://github.com/goldfire/howler.js/issues/1497)).
- `FIXED` Error when refreshing the buffer on a sound that has already been unloaded ([#1508](https://github.com/goldfire/howler.js/issues/1508)).
## 2.2.3 (June 30, 2021)
+
- `FIXED` Fatal error in Chrome for iOS ([#1491](https://github.com/goldfire/howler.js/issues/1491)).
## 2.2.2 (June 27, 2021)
+
The README has been updated with more examples and various clarifications. PRs/issues with suggestions for further improvements are appreciated.
- `CHANGED` Include `keydown` event when unlocking audio ([#1417](https://github.com/goldfire/howler.js/pull/1417)).
@@ -17,12 +91,14 @@ The README has been updated with more examples and various clarifications. PRs/i
- `FIXED` Before a sound had loaded, calling `pause()` after `seek()` didn't have the intended behavior ([#1439](https://github.com/goldfire/howler.js/issues/1439)).
## 2.2.1 (Oct 25, 2020)
+
- `FIXED` The latest Safari 14 changed how WAV support was detected ([#1415](https://github.com/goldfire/howler.js/pull/1415)).
- `FIXED` Edge case that could cause an infinite loop while fading ([#1369](https://github.com/goldfire/howler.js/pull/1369)).
- `FIXED` Calling `seek` without a seek value while a file was still loading no longer adds it to the queue and correctly returns `0` ([#1189](https://github.com/goldfire/howler.js/issues/1189)).
- `FIXED` Correctly handle finite audio files that return `Infinity` duration in Safari ([#658](https://github.com/goldfire/howler.js/pull/658)).
## 2.2.0 (May 17, 2020)
+
- `ADDED` New `xhr` property that allows setting custom headers (such as for auth), changing the `withCredentials` setting and specifying the HTTP method for the request. These only apply to Web Audio ([#997](https://github.com/goldfire/howler.js/pull/997)).
- `ADDED` New `Howler.stop()` global stop method to stop all sounds at once ([#1308](https://github.com/goldfire/howler.js/issues/1308)).
- `ADDED` Support for `m4b` audio format ([#1170](https://github.com/goldfire/howler.js/pull/1170)).
@@ -33,24 +109,29 @@ The README has been updated with more examples and various clarifications. PRs/i
- `FIXED` Memory leak in Safari when an audio context can't be unlocked ([#1338](https://github.com/goldfire/howler.js/pull/1338)).
### Breaking Changes
-* The `xhrWithCredentials` property is now included in the `xhr` property object with key `withCredentials`.
+
+- The `xhrWithCredentials` property is now included in the `xhr` property object with key `withCredentials`.
## 2.1.3 (December 24, 2019)
+
- `FIXED` Don't try to obtain HTML5 audio if there is no audio support ([#1191](https://github.com/goldfire/howler.js/issues/1191)).
- `FIXED` The x/y/z orientations for the top of the listener weren't being set properly ([#1221](https://github.com/goldfire/howler.js/pull/1221)).
- `FIXED` Race condition that could prevent looping audio from always looping ([#1225](https://github.com/goldfire/howler.js/pull/1225)).
- `FIXED` Race condition that could cause the main volume to be reset to 1 if called before `unlockAudio` ([#1210](https://github.com/goldfire/howler.js/pull/1210)).
## 2.1.2 (April 19, 2019)
+
- `FIXED` Removed browser check for auto play unlock since all major browsers now implement this.
- `FIXED` Live streams now stop downloading when they are stopped, also fixing issue in Chrome with stopping twice ([#1129](https://github.com/goldfire/howler.js/issues/1129)).
- `FIXED` Prevent error in Edge when `Audio` isn't supported ([#1147](https://github.com/goldfire/howler.js/issues/1147)).
## 2.1.1 (December 21, 2018)
+
- `FIXED` Regression that broke simple play/pause usage in certain edge cases ([#1101](https://github.com/goldfire/howler.js/issues/1101)).
- `FIXED` Loading and unloading multiple Howls with the same src could cause them all to unload ([#1103](https://github.com/goldfire/howler.js/issues/1103)).
## 2.1.0 (December 12, 2018)
+
- `ADDED` Howler now maintains a general pool of HTML5 Audio nodes that are unlocked on first user input, which fixes issues with subsequent HTML5 Audio plays not working ([#1008](https://github.com/goldfire/howler.js/pull/1008)).
- `ADDED` New global `html5PoolSize` option that allows setting the default size of the HTML5 Audio object pool ([#1008](https://github.com/goldfire/howler.js/pull/1008)).
- `CHANGED` Since locking of audio is no longer mobile-only, `mobileAutoEnable` has been renamed to `autoUnlock`.
@@ -64,15 +145,19 @@ The README has been updated with more examples and various clarifications. PRs/i
- `FIXED` Calling `play` twice before a sound had loaded could lead to both sounds having the same `ID` ([#1060](https://github.com/goldfire/howler.js/issues/1060)).
### Breaking Changes
-* If you are directly setting `Howler.mobileAutoEnable` (it defaults to true), then you should change this to `Howler.autoUnlock`.
-* The new HTML5 Audio object pool shouldn't change anything for 99% of use-cases, but if for whatever reason you don't want to use the pool, you can set `html5PoolSize` to 0 to bypass using the pool.
+
+- If you are directly setting `Howler.mobileAutoEnable` (it defaults to true), then you should change this to `Howler.autoUnlock`.
+
+- The new HTML5 Audio object pool shouldn't change anything for 99% of use-cases, but if for whatever reason you don't want to use the pool, you can set `html5PoolSize` to 0 to bypass using the pool.
## 2.0.15 (August 24, 2018)
+
- `FIXED` Errors with touch events and blocked click events in Chrome ([#1003](https://github.com/goldfire/howler.js/issues/1003) [#1011](https://github.com/goldfire/howler.js/issues/1011) [#1025](https://github.com/goldfire/howler.js/issues/1025) [#1026](https://github.com/goldfire/howler.js/issues/1026)).
- `FIXED` Audio decoding error wasn't always handled correctly ([#1019](https://github.com/goldfire/howler.js/pull/1019)).
- `FIXED` Potential error during playback in Internet Explorer 11 ([#1016](https://github.com/goldfire/howler.js/pull/1016)).
## 2.0.14 (July 12, 2018)
+
- `CHANGED` Auto unlocking of audio now runs on Chrome to fix issue with HTML5 Audio needing user interaction.
- `CHANGED` Added a new `unlock` event that is fired when the auto unlock happens.
- `CHANGED` A `playerror` now gets fired when HTML5 Audio fails to play due to lack of user interaction.
@@ -83,35 +168,42 @@ The README has been updated with more examples and various clarifications. PRs/i
- `FIXED` Another issue in Safari where spatial orientation was throwing an error.
## 2.0.13 (June 22, 2018)
+
- `FIXED` Prevent `stop` event from firing alongside `end` when using HTML5 Audio ([#974](https://github.com/goldfire/howler.js/issues/074)).
- `FIXED` Correctly reset a `Sound` after using spatial audio ([#962](https://github.com/goldfire/howler.js/issues/962)).
- `FIXED` Remove a `Howl` from cache when unloaded after failing to load ([#978](https://github.com/goldfire/howler.js/issues/978)).
- `FIXED` Race condition could lead to error when cleaning the buffer.
## 2.0.12 (May 9, 2018)
+
- `FIXED` The previous Chrome deprecation fixes broke spatial positioning in Safari.
## 2.0.10 (May 5, 2018)
+
- `FIXED` Fixed another Chrome deprecation warning when using panning methods ([#923](https://github.com/goldfire/howler.js/issues/923)).
- `FIXED` Playback rate wasn't working correctly in Internet Explorer when defined in the `Howl` constructor ([#936](https://github.com/goldfire/howler.js/issues/936)).
- `FIXED` Looped audio would only play twice in Internet Explorer ([#921](https://github.com/goldfire/howler.js/issues/921)).
## 2.0.9 (February 10, 2018)
+
- `FIXED` More accurate HTML5 Audio `end` timer and fix for Firefox streams ending early ([#883](https://github.com/goldfire/howler.js/issues/883)).
- `FIXED` Prevent `play` events from duplicating in certain instances ([#899](https://github.com/goldfire/howler.js/issues/899)).
- `FIXED` Add second parameter to HTML5 Audio playback promise to fix Safari error ([#896](https://github.com/goldfire/howler.js/pull/896)).
- `FIXED` Refactored the internal queue system to fix various edge cases.
## 2.0.8 (January 19, 2018)
+
- `CHANGED` Fades now use elapsed time to be more accurate when intervals are inconsistent ([#885](https://github.com/goldfire/howler.js/issues/885)).
- `CHANGED` Improve timing of short fades ([#884](https://github.com/goldfire/howler.js/issues/884)).
- `FIXED` Fixed another Chrome deprecation when setting playback rate.
- `FIXED` Prevent `onplay` from firing when first setting `stereo` value ([#843](https://github.com/goldfire/howler.js/issues/843)).
## 2.0.7 (December 18, 2017)
+
- `FIXED` Accidental `const` was included in the previous version.
## 2.0.6 (December 15, 2017)
+
- `FIXED` Replaced deprecated `gain.value` and `gain.pan.value` with `setValueAtTime` ([#856](https://github.com/goldfire/howler.js/issues/856)).
- `FIXED` Audio sprites weren't ending correctly in Internet Explorer 11 ([#841](https://github.com/goldfire/howler.js/issues/841)).
- `FIXED` Correctly set group volume when fading ([#539](https://github.com/goldfire/howler.js/issues/539)).
@@ -120,6 +212,7 @@ The README has been updated with more examples and various clarifications. PRs/i
- `FIXED` Incorrect reference to global `_scratchBuffer` ([#834](https://github.com/goldfire/howler.js/pull/834)).
## 2.0.5 (October 6, 2017)
+
- `ADDED` Add support for `withCredentials` to Web Audio XHR requests ([#610](https://github.com/goldfire/howler.js/pull/610)).
- `ADDED` Add `playerror` event for when mobile HTML5 audio is unable to play ([#774](https://github.com/goldfire/howler.js/issues/774)).
- `FIXED` Refactor fade method to eliminate bind memory allocations (no change to API).
@@ -130,6 +223,7 @@ The README has been updated with more examples and various clarifications. PRs/i
- `FIXED` Various corrections and improvements to the spatial audio documentation.
## 2.0.4 (June 9, 2017)
+
- `CHANGED` Removed the `resuming` state, which wasn't actually being used and was leading to a bug on Android ([#679](https://github.com/goldfire/howler.js/pull/679)).
- `CHANGED` Any playback initiated before the sound has loaded will now go into the queue to fix various race conditions ([#714](https://github.com/goldfire/howler.js/pull/714)).
- `FIXED` Correctly initialize an AudioContext with the global mute status ([#714](https://github.com/goldfire/howler.js/pull/714)).
@@ -143,6 +237,7 @@ The README has been updated with more examples and various clarifications. PRs/i
- `FIXED` `npm` warning caused by invalid license definition ([#763](https://github.com/goldfire/howler.js/pull/763)).
## 2.0.3 (March 11, 2017)
+
- `CHANGED` Unloading a sound no longer fires the `end` event ([#675](https://github.com/goldfire/howler.js/pull/675)).
- `FIXED` Remove `setTimeout` wrapper on HTML5 `play` call to fix issues on mobile browsers ([#694](https://github.com/goldfire/howler.js/pull/694)).
- `FIXED` Remove rare possibility of duplicate sound ID's by using global counter ([#709](https://github.com/goldfire/howler.js/issues/709)).
@@ -152,6 +247,7 @@ The README has been updated with more examples and various clarifications. PRs/i
- `FIXED` Regression in Firefox relating to spatial audio ([#664](https://github.com/goldfire/howler.js/issues/664)).
## 2.0.2 (December 4, 2016)
+
- `FIXED` Wait to begin playback until AudioContext has resumed ([#643](https://github.com/goldfire/howler.js/issues/643)).
- `FIXED` Run `noAudio` check on initial setup instead of waiting for first `Howl` ([#619](https://github.com/goldfire/howler.js/issues/619)).
- `FIXED` Add `play` event to start of queue when `autoplay` is used ([#659](https://github.com/goldfire/howler.js/issues/659)).
@@ -161,6 +257,7 @@ The README has been updated with more examples and various clarifications. PRs/i
- `FIXED` Always fire pause event even if sound is already paused ([#639](https://github.com/goldfire/howler.js/issues/639)).
## 2.0.1 (October 14, 2016)
+
- `ADDED` Support for FLAC audio files.
- `FIXED` Improve fading performance when short fade times are used ([#621](https://github.com/goldfire/howler.js/issues/621)).
- `FIXED` Correctly handle fades from 0 to 0 volume ([#575](https://github.com/goldfire/howler.js/issues/575)).
@@ -172,6 +269,7 @@ The README has been updated with more examples and various clarifications. PRs/i
- `FIXED` Set correct loop start/end when calling `loop` on a sprite ([#604](https://github.com/goldfire/howler.js/issues/604)).
## 2.0.0 (July 19, 2016)
+
This major release contains just a few breaking changes outlined below. Howler.js has been rewritten from the ground up using the knowledge and work since the initial release. There's a long list of additions and improvements, which I urge you to read through as the library has evolved quite a bit over this time.
The biggest change is how you should think about your audio when using howler.js. There is now the concept of global (`Howler`), group (`Howl`) and single sound (`Sound`). Each sound that is played gets its own `Sound` object that can be manipulated, giving much greater control over playback, whether using sprites or not. `Howl` method calls can then apply to one sound or all in the group.
@@ -187,6 +285,7 @@ Howler.js now also has the concept of plugins. The core represents 100% compatib
Read more about the update [in this blog post](http://goldfirestudios.com/blog/143/howler.js-v2.0-Released).
### Breaking Changes
+
- The `buffer` option is now named `html5`. Use this to force HTML5 Audio usage.
- The `urls` option is now named `src` to specify the audio file(s) to play.
- The `pos` method has been renamed to `seek`.
@@ -231,6 +330,7 @@ sound.once('fade', function(){
```
### New Features
+
- Lots of general code cleanup, simplification and reorganization.
- Howler.js is now modularized. The core represents the initial goal for howler.js with 100% compatibility across HTML5 Audio and Web Audio. The spatial plugin adds spatial and stereo support through Web Audio API.
- The new structure allows for full control of sprite playback (this was buggy or didn't work at all before).
@@ -255,6 +355,7 @@ sound.once('fade', function(){
- Web Audio AudioContext now automatically suspends and resumes to lower processing and power usage.
### Bug Fixes
+
- Improved the `ext` option and made it especially usefully for playing streams (for example, SoundCloud).
- The `fade` method now uses native Web Audio fading when in that mode.
- Fades are now automatically stopped when a new one is started, volume is changed or the sound is paused/stopped.
@@ -284,25 +385,31 @@ sound.once('fade', function(){
- Only setup AudioContext after first `Howl` is setup so that background audio on mobile devices behaves as expected.
## 1.1.29 (January 22, 2016)
+
- `ADDED` Error messages added onto each `loaderror` event (thanks Philip Silva).
- `FIXED` Various edge-case bugs by no longer comparing functions by string in `.off()` (thanks richard-livingston).
- `FIXED` Edge case where multiple overlapping instances of the same sound won't all fire `end` (thanks richard-livingston).
- `FIXED` `end` event now fires correctly when changing the `rate` of a sound.
## 1.1.28 (October 22, 2015)
+
- `FIXED` Typo with iOS enabler that was preventing it from working.
## 1.1.27 (October 2, 2015)
+
- `FIXED` Automatic audio unlocking on iOS 9 by switching to `touchend` from `touchstart`.
## 1.1.26 (April 21, 2015)
+
- `FIXED` Looping in Chrome due to a change in the Web Audio spec implemented in Chrome 42.
## 1.1.25 (July 29, 2014)
+
- `ADDED` The `AudioContext` is now available on the global `Howler` object (thanks Matt DesLauriers).
- `FIXED` When falling back to HTML5 Audio due to XHR error, delete cache for source file to prevent multi-playback issues.
## 1.1.24 (July 20, 2014)
+
- `FIXED` Improved performance of loading files using data URIs (thanks Rob Wu).
- `FIXED` Data URIs now work with Web Audio API (thanks Rob Wu).
- `FIXED` Omitting the second parameter of the `off` method now correctly clears all events by that name (thanks Gabriel Munteanu).
@@ -310,37 +417,44 @@ sound.once('fade', function(){
- `FIXED` Small error fix in iOS check.
## 1.1.23 (July 2, 2014)
+
- `FIXED` Playing multiple sprites rapidly with HTML5 Audio cause the sprite to break due to a v1.1.22 update.
- `FIXED` Don't run the iOS test if there is no audio context, which prevents a breaking error.
## 1.1.22 (June 28, 2014)
+
- `ADDED` Howler will now automatically attempt to unlock audio on iOS (thanks Federico Brigante).
- `ADDED` New `codecs` global Howler method to check for codec support in the current browser (thanks Jay Oster).
- `FIXED` End timers are now correctly cleaned up when a sound naturally completes rather than being forced to stop.
## 1.1.21 (May 28, 2014)
+
- `ADDED` Support for npm and bower (thanks Morantron).
- `ADDED` Support for audio/aac, audio/m4a and audio/mp4 mime types (thanks Federico Brigante).
- `FIXED` Calculation of duration after pausing a sprite that was sometimes causing unexpected behavior.
- `FIXED` Clear the event listener when creating a new HTML5 Audio node.
## 1.1.20 (April 18, 2014)
+
- `ADDED` When using Web Audio API, the panningModel now defaults to 'equalpower' to give higher quality sound. It then automatically switches to 'HRTF' when using 3D sound. This can also be overridden with the new `model` property.
- `FIXED` Another bug causing issues in CocoonJS (thanks Olivier Biot).
- `FIXED` Issue that could have caused invalid state errors and a memory leak when unloading in Internet Explorer.
- `FIXED` The documentation has been updated to include the `rate` property.
## 1.1.19 (April 14, 2014)
+
- `ADDED` Added CocoonJS support (thanks Olivier Biot).
- `FIXED` Several issues with pausing sprite instances by overhauling how end timers are tracked and cleared internally.
- `FIXED` Prevent error when using a server-side require where window is absent (thanks AlexMost).
## 1.1.18 (March 23, 2014)
+
- `FIXED` Muting a looping sound now correctly keeps the sound muted when using HTML5 Audio.
- `FIXED` Wrap AudioContext creation in try/catch to gracefully handle browser bugs: [Chromium issue](https://code.google.com/p/chromium/issues/detail?id=308784) (thanks Chris Buckley).
- `FIXED` Listen for HTML5 Audio errors and fire `loaderror` if any are encountered (thanks digitaltonic).
## 1.1.17 (February 5, 2014)
+
- `FIXED` Another bug in Chrome that would throw an error when pausing/stopping when a source is already stopped.
- `ADDED` CommonJS support for things like Browserify (thanks Michal Kuklis).
- `ADDED` Support for playback mp4 files.
@@ -349,10 +463,12 @@ sound.once('fade', function(){
- `FIXED` The `onend` callback now correctly fires when changing the pos of a sound after it has started playing and when it is using HTML5 Audio.
## 1.1.16 (January 8, 2014)
+
- `FIXED` Prevent InvalidStateError when unloading a sound that has already been stopped.
- `FIXED` Bug in unload method that prevented the first sound from being unloaded.
## 1.1.15 (December 28, 2013)
+
- `FIXED` Bug that prevented master volume from being set to 0.
- `FIXED` Bug that prevented initial volume from being set to 0.
- `FIXED` Update the README to accurately show `autoplay` as defaulting to `false`.
@@ -361,45 +477,55 @@ sound.once('fade', function(){
- `FIXED` An issue with looping after resuming playback when in WebAudio playback (thanks anzev).
## 1.1.14 (October 18, 2013)
+
- `FIXED` Critical bug fix that was breaking support on some browsers and some codecs.
## 1.1.13 (October 17, 2013)
+
- `FIXED` Code cleanup by removing redundant `canPlay` object (thanks Fabien).
- `FIXED` File extensions are now detected correctly if there is a query string with dots in the filename (thanks theshock).
- `FIXED` Fire `onloaderror` if a bad filename is passed with the `urls` property.
## 1.1.12 (September 12, 2013)
+
- `UPDATED` Changed AMD definition to anonymous module and define it as global always (thanks Fabien).
- `ADDED` Added the `rate` property to `Howl` object creation, allowing you to specify the playback rate. This only works when using Web Audio (thanks Qqwy).
- `FIXED` Prevent some instances of IE9 from throwing "Not Implemented" error (thanks Tero Tilus).
## 1.1.11 (July 28, 2013)
+
- `FIXED` Bug caused by trying to disconnect audio node when using HTML5 Audio.
- `FIXED` Correctly return the sound's position when it is paused.
- `FIXED` Another bug that caused looping sounds to not always correctly resume after a pause.
## 1.1.10 (July 26, 2013)
+
- `ADDED` New `unload` method to destroy a Howl object. This will stop all associated sounds instantly and remove the sound from the cache.
- `FIXED` When using Web Audio, loop from the correct position after pausing the sound halfway through.
- `FIXED` Always return a number when getting a sound's position with the `pos` method, and always return the reference to the sound when setting a sound that hasn't loaded.
## 1.1.9 (July 11, 2013)
+
- `FIXED` Issue where calling the `volume` method before a sound had loaded prevented the volume from being changed.
## 1.1.8 (July 10, 2013)
+
- `FIXED` `urls` method now works again, and can take a string rather than an array if only one url is being passed.
- `FIXED` Make `node.play` async when not using webAudio (thanks Alex Dong).
## 1.1.7 (May 30, 2013)
+
- `FIXED` Hotfix for a missing parameter that somehow missed the 1.1.6 commit in global muting.
## 1.1.6 (May 30, 2013)
+
- `ADDED` A general `fade` method that allows a playing sound to be faded from one volume to another.
- `DEPRECATED` The `fadeIn` and `fadeOut` methods should no longer be used and have been deprecated. These will be removed in a future major release.
- `FIXED` No longer require the sprite parameter to be passed into the `play` method when just passing a callback function.
- `FIXED` Cleaned up global muting code. (thanks arnorhs).
## 1.1.5 (May 3, 2013)
+
- `ADDED` Support for the Ogg Opus codec (thanks Andrew Carpenter).
- `ADDED` Semver tags for easy package management (thanks Martin Reurings).
- `ADDED` Improve style/readability of code that discovers which audio file extension to use (thanks Fabien).
@@ -407,23 +533,28 @@ sound.once('fade', function(){
- `FIXED` A few small typos in the comments. (thanks VAS).
## 1.1.4 (April 28, 2013)
+
- `FIXED` A few small bugs that broke global mute and unmute when using HTML5 Audio.
## 1.1.3 (April 27, 2013)
+
- `FIXED` Bug that prevented global mute from working 100% of the time when using HTML5 Audio.
## 1.1.2 (April 24, 2013)
+
- `FIXED` Calling `volume` before `play` now works as expected.
- `FIXED` Edge case issue with cache cleaning.
- `FIXED` Load event didn't fire when new URLs were loaded after the initial load.
## 1.1.1 (April 17, 2013)
+
- `ADDED` `onloaderror` event fired when sound fails to load (thanks Thiago de Barros Laceda).
- `ADDED` `format` property that overrides the URL extraction of the file format (thanks Kenan Shifflett).
- `FIXED` AMD implementation now only defines one module and removes global scope (thanks Kenan Shifflett).
- `FIXED` Broken chaining with `play` method.
## 1.1.0 (April 11, 2013)
+
- `ADDED` New `pos3d` method that allows for positional audio (Web Audio API only).
- `ADDED` Multi-playback control system that allows for control of specific play instances when sprites are used. A callback has been added to the `play` method that returns the `soundId` for the playback instance. This can then be passed as the optional last parameter to other methods to control that specific playback instead of the whole sound object.
- `ADDED` Pass the `Howl` object reference as the first parameter in the custom event callbacks.
@@ -437,23 +568,29 @@ sound.once('fade', function(){
- `FIXED` Various code cleanup and optimizations.
## 1.0.13 (March 20, 2013)
+
- `ADDED` Support for AMD loading as a module (thanks @mostlygeek).
## 1.0.12 (March 28, 2013)
+
- `ADDED` Automatically switch to HTML5 Audio if there is an error due to CORS.
- `FIXED` Check that only numbers get passed into volume methods.
## 1.0.11 (March 8, 2013)
+
- `ADDED` Exposed `usingWebAudio` value through the global `Howler` object.
- `FIXED` Issue with non-sprite HTML5 Audio clips becoming unplayable (thanks Paul Morris).
## 1.0.10 (March 1, 2013)
+
- `FIXED` Issue that caused simultaneous playback of audio sprites to break while using HTML5 Audio.
## 1.0.9 (March 1, 2013)
+
- `ADDED` Spec-implementation detection to cover new and deprecated Web Audio API methods (thanks @canuckistani).
## 1.0.8 (February 25, 2013)
+
- `ADDED` New `onplay` event.
- `ADDED` Support for playing audio from base64 encoded strings.
- `FIXED` Issue with soundId not being unique when multiple sounds were played simultaneously.
@@ -461,35 +598,43 @@ sound.once('fade', function(){
- `FIXED` Issue with `onend` timer not getting cleared all the time.
## 1.0.7 (February 18, 2013)
+
- `FIXED` Cancel the correct timer when multiple HTML5 Audio sounds are played at the same time.
- `FIXED` Make sure howler.js is future-compatible with UglifyJS 2.
- `FIXED` Duration now gets set correctly when pulled from cache.
- `FIXED` Tiny typo in README.md (thanks @johnfn).
## 1.0.6 (February 8, 2013)
+
- `FIXED` Issue with global mute calls happening before an HTML5 Audio element is loaded.
## 1.0.5 (February 7, 2013)
+
- `FIXED` Global mute now also mutes all future sounds that are played until `unmute` is called.
## 1.0.4 (February 6, 2013)
+
- `ADDED` Support for WebM audio.
- `FIXED` Issue with volume changes when on HTML5 Audio.
- `FIXED` Round volume values to fix inconsistencies in fade in/out methods.
## 1.0.3 (February 2, 2013)
-- `FIXED` Make sure `self` is always defined before returning it.
+
+- `FIXED` Make sure `self` is always defined before returning it.
## 1.0.2 (February 1, 2013)
+
- `ADDED` New `off` method that allows for the removal of custom events.
- `FIXED` Issue with chaining the `on` method.
- `FIXED` Small typo in documentation.
## 1.0.1 (January 30, 2013)
+
- `ADDED` New `buffer` property that allows you to force the use of HTML5 on specific sounds to allow streaming of large audio files.
- `ADDED` Support for multiple events per event type.
- `FIXED` Issue with method chaining before a sound was ready to play.
- `FIXED` Use `self` everywhere instead of `this` to maintain consistency.
## 1.0.0 (January 28, 2013)
+
- First commit
diff --git a/README.md b/README.md
index 4a4766f0..c9e0d099 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
[](https://howlerjs.com)
# Description
+
[howler.js](https://howlerjs.com) is an audio library for the modern web. It defaults to [Web Audio API](http://webaudio.github.io/web-audio-api/) and falls back to [HTML5 Audio](https://html.spec.whatwg.org/multipage/embedded-content.html#the-audio-element). This makes working with audio in JavaScript easy and reliable across all platforms.
Additional information, live demos and a user showcase are available at [howlerjs.com](https://howlerjs.com).
@@ -8,6 +9,7 @@ Additional information, live demos and a user showcase are available at [howlerj
Follow on Twitter for howler.js and development-related discussion: [@GoldFireStudios](https://twitter.com/goldfirestudios).
### Features
+
* Single API for all audio needs
* Defaults to Web Audio API and falls back to HTML5 Audio
* Handles edge cases and bugs across environments
@@ -23,16 +25,21 @@ Follow on Twitter for howler.js and development-related discussion: [@GoldFireSt
* As light as 7kb gzipped
### Browser Compatibility
-Tested in the following browsers/versions:
-* Google Chrome 7.0+
-* Internet Explorer 9.0+
-* Firefox 4.0+
-* Safari 5.1.4+
-* Mobile Safari 6.0+ (after user input)
-* Opera 12.0+
-* Microsoft Edge
+
+Howler.js v3.0+ requires ES Module support. The library works in all modern browsers that support ES modules:
+
+* Google Chrome 61.0+
+* Firefox 67.0+
+* Safari 11.1+
+* Edge 79.0+
+* Opera 48.0+
+* Mobile Safari 11.0+
+* Android Chrome 61.0+
+
+**Legacy Browser Support**: For older browsers without native ES module support, use the provided `es-module-shims` polyfill. All test and example files include this polyfill for maximum compatibility. For even older browser support (IE9+), use Howler.js v2.x which uses CommonJS/UMD format.
### Live Demos
+
* [Audio Player](https://howlerjs.com/#player)
* [Radio](https://howlerjs.com/#radio)
* [Spatial Audio](https://howlerjs.com/#spatial)
@@ -41,6 +48,7 @@ Tested in the following browsers/versions:
# Documentation
### Contents
+
* [Quick Start](#quick-start)
* [Examples](#examples)
* [Core](#core)
@@ -69,48 +77,280 @@ Several options to get up and running:
* Install with [Bower](http://bower.io/): `bower install howler`
* Hosted CDN: [`cdnjs`](https://cdnjs.com/libraries/howler) [`jsDelivr`](https://www.jsdelivr.com/projects/howler.js)
-In the browser:
+As an ES Module (ESM):
+
+```typescript
+import { Howl, Howler } from 'howler';
+import { SpatialAudioPlugin } from 'howler/plugins/spatial';
+```
+
+Howler.js v3.0+ is distributed exclusively as ES Modules. For CommonJS support, use v2.x.
+
+Distribution files:
+
+* **Main entry point** (`howler`): Core Howler.js library
+ * `dist/index.js` - Main entry point with Howler, Howl, Sound classes
+ * `dist/howler.core.js` - Core audio implementation
+ * `dist/index.d.ts` - TypeScript type definitions
+* **Spatial plugin entry point** (`howler/plugins/spatial`): Spatial audio plugin
+ * `dist/plugins/spatial.js` - Spatial audio plugin with 3D positioning support
+ * `dist/plugins/spatial-plugin.js` - SpatialAudioPlugin implementation
+ * `dist/plugins/spatial.d.ts` - Spatial plugin type definitions
+* **Plugin System** (`howler`): Hook-based plugin architecture
+ * `dist/plugins/plugin.js` - PluginManager and HowlerPlugin base class
+
+**Note**: Howler.js v3.0+ is built entirely in TypeScript and distributed as ES Modules only, enabling better tree-shaking and code splitting. The plugin system allows safe extension without prototype mutation.
+
+### Plugin System
+
+Howler.js v3.0+ includes a modern, hook-based plugin architecture that allows you to extend functionality safely and composably.
+
+#### Architecture Overview
+
+The plugin system is built around:
+
+* **HowlerPlugin**: Base class for creating plugins
+* **PluginManager**: Manages plugin registration and lifecycle
+* **Plugin Hooks**: Well-defined lifecycle events for plugins to hook into
+
+#### Creating a Plugin
+
+Plugins extend `HowlerPlugin` and implement hooks:
+
+```typescript
+import { HowlerPlugin, type PluginHooks } from 'howler';
+import type { HowlerGlobal, Howl } from 'howler';
+
+export class MyPlugin extends HowlerPlugin {
+ readonly name = 'my-plugin';
+
+ getHooks(): PluginHooks {
+ return {
+ onHowlerInit: (howler: HowlerGlobal) => {
+ console.log('Howler initialized');
+ },
+ onHowlCreate: (howl: Howl, options) => {
+ console.log('Howl instance created', howl);
+ },
+ };
+ }
+}
+```
+
+#### Using Plugins
+
+Register plugins directly with Howler:
+
+**TypeScript/ES Modules:**
+
+```typescript
+import { Howler, Howl } from 'howler';
+import { SpatialAudioPlugin, type SpatialHowler, type SpatialHowl } from 'howler/plugins/spatial';
+
+// Register the spatial audio plugin
+Howler.addPlugin(new SpatialAudioPlugin());
+
+// Type annotations for TypeScript support
+import type { SpatialHowlOptions } from 'howler/plugins/spatial';
+
+const listener: SpatialHowler = Howler as SpatialHowler;
+const sound: SpatialHowl = new Howl({
+ src: ['audio.mp3'],
+ pos: [0, 0, 0], // Spatial audio options available
+} as SpatialHowlOptions) as SpatialHowl;
+
+// Use spatial methods with full type support
+sound.pos(10, 5, 0);
+listener.stereo(0.5);
+listener.orientation(1, 0, 0, 0, 1, 0);
+```
+
+**HTML with Script Type Module:**
```html
-
-
+
+
+
+ // Set listener position (where the "ear" is)
+ Howler.pos(0, 0, 0);
+
+ // Set listener orientation (which way they're facing)
+ Howler.orientation(0, 0, -1, 0, 1, 0);
+
+ // Set sound position (where the sound is in 3D space)
+ sound.pos(10, 5, 0);
+
+ // Apply stereo panning
+ sound.stereo(0.5);
+
+ // Play the sound
+ sound.play();
+
+