# SoundManager 2: Download

## Get SoundManager 2

Get the latest and greatest.

### Download SoundManager 2

Latest changes: IE "Edge" 14 fix, `onError()` and `setPlaybackRate()` for sound objects, `eslint` code modernization (maintaining back-compat to IE 6) and more. See revision history for details.

Download SoundManager 2.97a.20170601 or see on GitHub, or on npm

Performance tip: SM2's code size varies from over 150 KB (commented, debug-enabled) down to 12 KB (optimized) over HTTP; check the pre-optimized builds for details.

Side reading + video talks, slides etc.

- Video, 02/2012: Web Audio: HTML5 + Flash (in a tree) (slides.) Updated HTML5 content, demos and SURVIVOR C64 game demo.
- Video, 12/2011: Adding Sound To HTML (slides.) Overview + updated content from 06/2011 talk.
- Video, 06/2011: The State Of HTML5 Audio
- Article: "Probably, Maybe, No": The State of HTML5 Audio.

## Revision History

Latest changes and archived notes from bug fixes, API updates, feature development etc.

### Revision History

A changelog of sorts.

- ### V2.97a.20170601 - IE "Edge" 14 fix, `onError()` and `setPlaybackRate()` for sound objects, `eslint` code modernization (maintaining back-compat to IE 6) and more. See GitHub commits.

  - Bug fixes

    - Internet Explorer "Edge" 14 fix, `try ... catch` due to `navigator.plugins` access now throwing an exception. See PR #150.

  - API Updates

    - Sound objects finally have an `onError()` event callback for load failures (and network/decode/playback for HTML5.) See SMSound.onError() for details.

    - `setPlaybackRate()` (HTML5-only), accepting values between 0.5 and 4. See SMSound.setPlaybackRate() for details.

  - Bar UI Updates

    - Touch events added for playback / progress track. Touch, drag and release to scrub through time.

    - `whileplaying` callback added to player `on` object. `SMSound` object also now provided to callback.

  - Miscellaneous

    - Large `eslint` modernization, stylistic and formatting updates to SM2 core and most demo JavaScript, whilst maintaining ES5 compatibility back to IE 6.

    - `FLAC` support check added to `audioFormats`. SM2 will always check for MIME/file extension support if not already known, but FLAC support has been added to Chrome 56. See Issue 148.

    - De-cruftication and removal of many legacy `-o-`, `-ms-` and `-webkit-` -specific CSS prefixes.

- ### V2.97a.20150601 - Minor tweaks for mobile and desktop Safari. Package/module (bower/npm) setup, "Bar UI" API update, Turntable UI demo and more. See GitHub commits.

  - Bug fixes

    - At some point (perhaps iOS 7.1?), iOS devices began allowing multiple HTML5 `Audio()` instances to exist and play simultaneously. By default, SM2 will still apply the singleton pattern via `useGlobalHTML5Audio` for iOS because playlist-style behaviour may not work without it. If you aren't concerned with playlist-style behaviour and want to use multiple audio instances, see `ignoreMobileRestrictions`.

    - Added `forceUseGlobalHTML5Audio` setup option, to address desktop Safari breaking playlist-style playback when in a background tab (something with `new Audio()` prevents playback from starting automatically?)

    - Improved RequireJS compatibility, correct `define()` usage and support for `SM2_DEFER`.

  - API Updates

    - API now fires `onstop()` when destroying a sound.

    - New setup option: `ignoreMobileRestrictions`. Enable if you want to avoid the singleton HTML5 object pattern used for mobile devices. iOS WebView purportedly allows use of multiple HTML5 `Audio()` objects.

    - `soundManager.setVolume(33)` now applies to all sounds. (Overloaded form; standard is `soundManager.setVolume('mySound', 33)`.)

  - Bar UI Updates

    - Added `window.sm2BarPlayers` API including data and methods. Players are now scriptable / controllable from JS.

    - `on` object for event callbacks, global and per-instance - e.g., `window.sm2BarPlayers.on = { play: function() { ... }, stop: function() { ... } });` - or, per-instance: `window.sm2BarPlayers[0].on = { ... }`

    - New config option: `stopOtherSounds` (i.e., only one player active at a time)

    - More config: `excludeClass` (default: `sm2-exclude`), prevents SM2 from playing link. Will fall through, download etc.

    - Added support for additional links in playlist: shopping cart ("buy now"), and music note ("download") next to each playlist item.

    - Playlist now scrolls currently-playing item into view by default.

    - Fix timing issue when user switches tracks in error case.

    - Improved playlist open-by-default UI state. Added playlist toggle to demo.

    - Check for `defaultItem`, handle case when starting with an empty playlist.

    - Workaround for non-zero `scrollTop` offset the first time the playlist is opened.

    - Minor UI tweaks for alignment, polish.

  - Miscellaneous

    - New 2015 Turntable UI Demo. Based on the 2011 "Wheels Of Steel" browser-based turntable UI prototype. Basic UI, API and load/play ability with easily customizable slipmats, record and album artwork.

    - Added `bower.json`, `component.json` and npm `package.json` definition files.

    - Improved RequireJS compatibility, correct `define()` usage and support for `SM2_DEFER`.

    - `soundmanager2.js` code style review (mostly for consistency.) Line breaks, quotes on strings, conditions and ternary statements, comment formatting etc.

    - Side note: The prior release's pre-emptive fix for iOS 8 ended up being a non-issue, as the official iOS 8 release did not use "OS 10" in the user-agent string. Nonetheless, SM2 will now correctly identify iOS 10+ vs. incorrectly flagging it as "iOS 1".

- ### V2.97a.20140901 - iOS 8 compatibility fix, "Bar UI" player demo, `durationchange`, buffering, edge case tweaks for HTML5 and RTMP, and browser environment checks. See GitHub commits, or download archived version.

  - Bug fixes

    - Why UA sniffing is generally bad, real-world example #1048577: "That time a missing `/s` on `navigator.userAgent` (based on single-digit UA version assumptions) broke SM2 on iOS 8+ devices."

      The upside: The fix is adding `\s` to a UA `regex` check targeting legacy iOS devices with broken `HTML5 Audio()` support, so that the `"OS 10 "` portion of the UA string does not match the pattern `"OS 1 "`.

      This is a pre-emptive fix for the pending iOS 8 release, which reportedly includes the string `"iPhone OS 10_10 like Mac OS X"`. Due to SM2 checking for `/os ([12|3_0|3_1])/i` which had broken `HTML5 Audio()` support, and not considering the far future possibility of `"iOS 10"` being included in the userAgent string at the time, HTML5 audio is incorrectly disabled on iOS 8 beta 3 and is likely to apply to the final iOS 8 release.

      This is a good example and reminder of why UA checks are generally bad, and dangerous; similar issues hit other libraries doing UA and plugin checks both client and server-side when IE hit 10, and Flash hit version 10, so this iOS pattern change may affect some other libraries targeting iOS as well.

    - HTML5: Listen to `durationchange` event, catch-all for duration update events. May help on mobile if duration is determined late. (Related discussion [Internet Archive].)

    - Explicitly provide buffering status to `onbufferchange()`. Don't set `buffering(0)` when loading, since playback may still be paused.

    - Flash: Fix edge case where `play({ url: xxx, position: 0 });` on existing sound with assigned URL. New URL wouldn't take effect.

  - API Updates

    - SMSound `onwarning` and `onfailure` options for NetStream / RTMP error/exception handling. Removed additional sound param on `onfailure()` callback. Apologies if this breaks anyone's implementation (disclaimer: these options are still experimental, and undocumented. :D) "Unhandled" exceptions are now considered non-fatal, using `onwarning` instead of presuming playback has failed etc.

  - Miscellaneous

    - "Bar UI" player demo added. SVG-based iconography, degrades nicely down to IE 8. See live demo.

    - Retina/hi-dpi updates for 360° canvas, small 360° player buttons and basic button player demo image assets.

    - CommonJS + AMD (requireJS) `module.exports` / `define()` compatibility (see commit for details.)

    - Check `window` && `window.document`, barf if loaded in server-side node environment vs. in a browser. (Even if Node.js etc. support `Audio()` at some point, SM2 was designed for a browser; this check is probably A Good Thing™ to have in place.) If you feel you have a use case that makes sense here, feedback is appreciated.

- ### V2.97a.20131201 - 100% HTML5 mode by default. Duration fix for Adobe FMS/RTMP server-based streaming. HTML5 unload, `multiShot` and `autoPlay` tweaks. See GitHub commits, or Download archived version.

  - Bug fixes

    - Adobe FMS (RTMP Server) fix: Invoke server-side `getStreamLength()` call to determine duration. (Red5 and other free RTMP servers use NetStream `onMetaData()` to pass duration.)

    - Fix `html5Unload()` by loading a tiny base64-encoded data: URI WAVe file where supported. Elsewhere, use `about:blank`. This fixes errors in Chrome where the browser attempts to load the url "null" (a string.)

    - D'oh! Fix HTML5 sprite regression where `_oncanplay()` was not being picked up & fired, sound would not play on first click.

    - HTML5: Fix double-play bug with `autoPlay: true`. Correct edge case where `onposition()` items would sometimes be cleared if called/assigned before `play()`.

    - `ontimeout: function(status) {}` callback parameter corrections. Fix missing error { `type: 'INIT_TIMEOUT'` } for missing/404 SWF case, and `INIT_FLASHBLOCK` for flashblock-specific case.

    - HTML5: Apply volume to cloned sounds in HTML5 `multiShot` case.

    - Fixed issue in `_processOnPosition` where the item in `onPositionItems[i]` can be undefined mid-loop if the callback that is triggered changes the length of the `onPositionItems` array, where `onPositionItems.length` becomes zero and there's an uncaught `TypeError` when trying to access `item.fired` the next time around.

    - Fixed mute in HTML5.

    - Fix `onload` in Firefox 3.6 with no flash (and yes, Firefox 25 is the current release. :D)

    - Correct event removal (cloned HTML5 nodes) - `onended` → `ended`

  - API Updates

    - Use 100% HTML5 mode by default, where available. `preferFlash: false` is now the default setting. Firefox does MP3 on Vista (and newer) via HTML5, and recently (via Firefox Aurora builds) on OS X - the last major hold-out. The vast majority of browsers now support MP3 via HTML5, thus reducing the reliance on Flash.

    - Reboot into 100% HTML5 mode where supported if flash fails after loading, i.e., local/offline/file:// or other edge case.

  - Miscellaneous

    - Fixed `canPlayMIME()` documentation example.

- ### V2.97a.20130512 - multiShot for polyphonic HTML5 clients. `createSound()` no longer requires an `id`. Auto-`reboot()` into 100% HTML5 mode where supported. HTML5 unload tweaks. (Download archived version)

  - Bug fixes

    - Init enhancement: If `preferFlash: true` but `useFlashBlock: false` (the default SM2 config) and flash timeout / blocked case occurs, SM2 will reboot reboot into 100% HTML5 mode if available so init can succeed. If flash block handling is enabled, user interaction will be required to whitelist the flash movie and init will be delayed until the SWF loads.

    - Correct `reboot()` to allow 100% HTML5 mode when Flash was previously required due to `preferFlash: true`. Previously, `soundManager.audioFormats.mp3.required = false; soundManager.reboot()` did not result in 100% HTML5 mode under Firefox. Now works as expected.

    - HTML5 unloading: Firefox was supposed to like assigning `''` to `Audio().url` for canceling requests, unloading and destroying the decoder (perhaps only on `<audio>`, in retrospect?) - similarly, `.src = null` did not seem to work, possible request to `./` - undesirable.

      Now using more-conservative `null` URL for unload / destruct on webkit, iOS and others, and `emptyURL` for Firefox (user-customizable, `'about:blank'` by default.)

    - More HTML5 safety checks so that `buffered` can't go beyond 100%.

    - Improve Flash 9 `load()` -> `onload()` failure case, when loading a non-404 (eg., HTTP 301 -> 200) with non-audio content. Improved messaging for Flash 8, Flash 9 + HTML5 with zero-duration (invalid / unsupported sound) case.

    - Fix flash-only (no HTML5 / `useHTML5Audio: false`) init case, e.g., running under IE 8.

    - HTML5: Fix legacy "overloaded" case when `soundManager.play('someID', 'some.mp3');` is called twice, second call would fail. This shortcut method is deprecated, and not recommended for use other than a conveience when in development / testing.

  - API Updates

    - `createSound()` no longer requires an `id` property. If omitted, a unique `id` will automatically be generated for the new sound object with a prefix based on the SM2 setup option `idPrefix`.

      Specifying an `id` is useful if you want to look up the sound via `getSoundById()` - otherwise, you can simply use the object returned by the `createSound()` call.

    - `multiShot` + `multiShotEvents` for HTML5 `Audio()`-based sounds, allowing layered / "chorused" playback if `play()` is called and `multiShot: true` has been specified to either `createSound()` or `play()`. Behaviour should mimic that of Flash 9. If `multiShotEvents: true` is specified, `onfinish()` will fire for each instance. Does not apply to mobile clients (e.g., iOS and Android) which only allow one sound to be played at a time.

      Implementation summary: A `new Audio(src)` instance is created with an `onfinish` listener, and played immediately. It is unloaded and destroyed when playback finishes.

      Caveat #1: If a position argument is provided eg., `play({ position: 1000 })`, the cloned `Audio()` instance must wait for a HTML5 `canplay` event before a seek and playback can begin. This may mean playback *could* have a slight delay vs. playing without the position offset.

      Caveat #2: The from/to parameters used for "sound sprites", e.g., `{ from: 500, to: 1500 }`, are not presently supported under multiShot.

      Caveat #3: multiShot is not supported where only a single audio instance can be playing at once, e.g., iOS (iPhone/iPad) and some Android devices.

      Secondary instances are "fire-and-forget", similar to the Flash 9 implementation, and fire no events other than `onfinish()`. They do not respond to position, volume etc. after playback has begun.

  - Miscellaneous

    - Remove debug-related `complain()` calls from -nodebug and minified script builds

    - Force data: URLs over to HTML5. Catch unsupported case under 100% HTML5 mode, preventing attempt to use Flash fallback.

    - Edge case: Fix error case if `setup()` called without arguments inline, before DOMReady / init etc.

    - Tweak `soundManager.getSoundById()` to not throw error if ID omitted. Improve language on "not found" messaging.

    - Warn on possible 32-sound channel Flash ceiling/limit, which can occur when Flash tries to begin playback and fails to start.

    - Documentation updates: How Clients Download Audio (Flash/HTML5 progressive download vs. byte streaming)

    - Improved API Examples page design, two-column layout with navigation

- ### V2.97a.20130324 - Fix for playlist/event chaining when using `flashVersion = 8` with Flash Player 11.6.602.171. HTML5 iOS `load()` fix. Added Opus to audio formats. (Download archived version)

  - Bug fixes

    - Flash Player 11.6.602.171, released by Adobe on 02/26/2013, introduced an issue with SM2's default Flash 8 (`flashVersion: 8`) API-based JS/Flash interaction, where SM2 methods called from callbacks such as `onfinish()` would not work. This primarily broke methods used for playing sounds in sequence, serially loading a series of sounds and so on. (See discussion (Internet Archive) for more.)

      Note that this does not affect cases where `soundManager.setup({ flashVersion: 9})` is being used; however, SM2 does use `flashVersion: 8` by default.

      Specifically, Flash-initiated events (such as a sound finishing) make Flash -> JS calls to the SM2 API, which subsequently call user-specified event handlers. If the user-specified SM2 `onfinish()` handler immediately calls a SM2 method like `play()` that makes a JS -> Flash call, this call either silently fails or is blocked. Other JS + Flash libraries that use similar callback patterns may also be affected, if their SWF is built targeting the Flash 8 API.

      Suspecting a timing or recursion/stack issue, it was found that introducing a `setTimeout(callback, 0)` to user-specified SM2 callbacks like `onfinish()` restored sequential/playlist functionality.

      Flash Player 11.6.602.180, relased by Adobe on 3/12/2013, exhibits the same behaviour. To avoid additional hacks, SM2 applies this to all Flash 8-based API callbacks regardless of what version of Flash Player is installed. No regressions are anticipated as a result of this change.

      Alternately, this issue can be avoided by using `soundManager.setup({ flashVersion: 9 })` as the Flash 9-based API does not appear to have this problem.

    - HTML5: Fix for iOS `load()` case when using an auto-load and looping pattern (related discussion [Internet Archive, may not work, sorry.])

  - API Updates

    - HTML5: Added check for Opus (OGG-based audio codec, `audio/opus`).

  - Miscellaneous

    - Added documentation for Serving To Clients, and Mobile Device Limitations.

    - Minor SM2 homepage + documentation CSS tweaks (design)

    - This SM2 release is tagged "Mahalo Edition" to say thank-you, and because some SM2 work was done while on vacation in Hawai'i. Also, some new demo sound recordings from the beach on Kaua'i were added.

- ### V2.97a.20130101 - Strict Mode. Android 2.3 HTML5 fixes, cleaner debug output, improved default flashblock handling. Confirmed compatibility with Firefox WMF-based HTML5 MP3 support. New `reset()` method, `reboot()` tweaks (Download archived version)

  - Bug fixes

    - HTML5: Reset last URL and load state for "singleton" (global HTML5 audio) case, on iOS + Android <= 2.3 for specific use case - `createSound()` -> `play()` -> `destruct()` -> `createSound()` -> `play()` with same URL/parameters.

    - HTML5: Fix for Android 2.3 / Nexus 7 - they work better with the singleton HTML5 `audio()` instance as well, same as iOS, for chained (i.e., playlist-style) playback cases.

    - `soundManager.setup()` now allows `html5Test` (regular expression, eg. `/probably|maybe/i`) to be passed. Was previously unrecognized/rejected.

  - API Updates

    - The SoundManager 2 core API (soundmanager2.js) now runs in Strict Mode, via `"use strict";`. This is scoped to a closure within soundmanager2.js, and should not cause issues when combined (rolled-up and/or minified) with other JavaScript code.

    - New `soundManager.reset()` method. Similar to `reboot()`, but also nukes any registered `onready()` and related callbacks. Based on pull request from Github user jabr. Chaining is now possible too, e.g., `soundManager.reset().setup({onready:function(){console.log('reset() complete, reboot OK')}});`. Call `soundManager.beginDelayedInit()` to re-init after a `reset()`.

    - `soundManager.setup({url:...})` + lazy-loading (dynamically-loaded JS) case: If `setup()` given a `url` parameter after `DOMContentLoaded` has fired, assume we should start right away. (Helps reduce need for `beginDelayedInit()` + "just works" for most users).

    - Don't init inline after `document.readyState === 'complete'` (improve lazy-loading case, wait for `setup()` with `url` instead).

  - Miscellaneous

    - Prerelease Firefox builds can play MP3 audio via HTML5 in some cases, as part of a move to support H.264 video (see Bugzilla #799318 for details). Firefox 20 (nightlies, and Aurora channel builds in January 2013) can get native MP3 support via Windows Media Foundation (OS-level codec support) components on Windows 8, Windows 7, and soon, Windows Vista. As of 12/2012, OS X support is planned, and Windows XP support is not. (Disclaimer: Vista, OS X and XP notes sourced from comments on Hacker News; see links).

      When enabled with `media.windows-media-foundation.enabled = true` under `about:config`, Firefox may be able to play MP3s via HTML5 and thus get "100% HTML5 mode" when `soundManager.setup({preferFlash: false})` is used.

      At time of writing (12/30/2012), Firefox 20 (nightly) returns `""` for `canPlayType('audio/mpeg; codecs="mp3"')`, a test commonly used to query for MP3 support under HTML5 and one which works in other modern browsers. Firefox's behaviour differs because it is trying to follow the MPEG spec, which does not include an explicit MP3 MIME type. Instead, `canPlayType('audio/mpeg')`, which is in-spec, presently returns a "maybe" when MP3 is supported under Firefox.

    - Improved SM2 `console.log()` debug output, aiming to be less "noisy". Core setup options are shown better at start-up, eg. "SoundManager V2.97a.20130101 (AS3/Flash 9) + HTML5 audio + preferFlash + html5PollingInterval (50ms) + flashBlock".

    - Christmas light demo: Tweaks for iOS + Android touch devices.

    - MP3 Player Button demo: Include HTML `type` (MIME hint) attribute, if specified.

- ### V2.97a.20121104 - HTML5 + iOS load fixes, Windows 8 App Store compatibility tweak, code pattern improvements (Download archived version)

  - Bug fixes

    - Fix HTML5 `unload()` -> `play()` case (re-use of same object without assigning new URL).

    - More global (iOS) HTML5 object `unload()` / `play()` re-use tweaks, improved handling of re-use and empty / `load()` cases

    - HTML5: Ensure `instanceOptions` are set after `play()` call results in `load()`. Noted `instanceOptions` not being set from within `whileplaying()`.

    - Fix call signature for Flash 8 load method, was tying `usePolicyFile` (enables remote crossdomain.xml request for ID3/waveform data on 3rd-party domains) to precence of `whileloading()` due to driver error. Derp. :D

    - Windows 8 Store Apps (IE 10/"MSAppHost" in UA) don't support Flash or ActiveX, except for (at time of writing), three special ActiveX controls. Thus, `new window.ActiveXObject('ShockwaveFlash.ShockwaveFlash')` seems to work without error. However, an error is thrown if an `<object>` with a Flash ActiveX CLSID is appended to the DOM. http://msdn.microsoft.com/en-us/library/windows/apps/hh465143.aspx

  - Miscellaneous

    - Death to underscores! Removed legacy pattern of `var _foo = ...` for most private internals.

    - Better `typeof x === 'undefined'` -> `x === undefined` pattern per newer jslint rules.

- ### V2.97a.20120916 - Inline, deferred and lazy-load init improvements, HTML5 format / detection improvements, "re-use" load/play URL fix. (Download archived version)

  - API Updates

    - Init improvement: Don't fail if Flash URL is null in normal include + init case. Instead, show note in debug input and wait for `soundManager.setup()` with `url` param, then treat as delayed init case. Improved experience if including `<script>`, then trying to do `setup()` after DOM Ready (common jQuery case).

    - `soundManager.setup({url:...})` + lazy-loading (dynamically-loaded JS) case: If `setup()` given url parameter after DOMContentLoaded has fired, assume we should start right away. (Helps reduce need for `beginDelayedInit()` + "just works" for most users)

    - Don't init inline after `document.readyState === 'complete'` (improve lazy-loading case, wait for setup() with url: instead)

  - Bug fixes

    - Fix `'audio/mpeg'` `canPlay()` checks, was incorrectly returning false due to `audio/mpeg; codecs="mp3"` working and preventing `audio/mpeg` from being checked.

    - More paranoid `Audio()` handling for "bad" Opera (< 10) where `new Audio()` would throw not_enough_arguments (always required URL).

    - Safer HTML5 duration checks - null now assigned instead of undefined.

    - Improve durationEstimate under HTML5 during `whileloading()`.

    - Flash 9/RTMP: Actually provide caption data to `oncaptiondata()`.

    - Fix `SMSound.play({url:...})` "re-use" case where new URL wasn't being assigned + loaded right away, and `SMSound.url` property was not being updated.

    - Correct `load()` and play() with new URL parameter, so that subsequent `play()` call uses new URL (and not URL assigned with original `createSound()` call).

    - Use seconds for `SMSound.buffered` (time ranges) whether HTML5 or Flash, since SM2 API uses seconds for `setPosition()` etc.

    - Correct `play()` -> `pause()` -> `setPosition(0)` -> `play()` -> `pause()` case where the latter wasn't firing due to invalid state.

  - Miscellaneous

    - New Cassette Tape UI Prototype/demo (experimental).

    - Tweaked documentation layout for legibility. Webfont (deja vu sans mono) from dejavu-fonts.org for code examples.

    - Improved lazy-load / deferred example based on new `setup()` logic

    - Added SMSound.buffered documentation

    - Added m4b extension as an mp4 format

    - Safer initial HTML5 support checks

- ### V2.97a.20120624 - New `soundManager.setup()` method, numerous HTML5 improvements for `createSound()`, `load()`, progress and reuse cases, and minor flash audio bug fixes (Download archived version)

  - API: New sugar-like stuff

    - New `soundManager.setup()` mixin-style method for assigning properties and common start-up callbacks. Collects top-level soundManager configuration properties and object collections - `onready`, `ontimeout`, `defaultOptions`, `flash9Options` and `movieStarOptions` - under a single method call.

      Upgrade / legacy note: This is a modern replacement for the direct property assignment method used in all previous versions - eg., `soundManager.url = '/swfs/'` - the old method continues to work for legacy support, but you should migrate to using the new method as it's much cleaner. All included demos use the new method where applicable.

      New `soundManager.setup()` method example

          soundManager.setup({
            // required
            url: '/path/to/swfs/',
            // optional
            flashVersion: 9,
            // convenience
            onready: function() {
              console.log('Ready to play sound!');
            },
            ontimeout: function() {
              console.log('SM2 start-up failed.');
            },
            // more custom parameters
            defaultOptions: {
              volume: 50
            }
          });

      See soundManager.setup() for details.

  - Bug fixes

    - Improve HTML5 audio load/playback reliability + stability on iOS, and for object reuse cases (`play()` -> `load({url: ...})`. Prior behaviour was making initial HTTP request when object was created (meta/preload, not necessarily loading entire file.) Request now only happens with preload/load/play-related calls.

    - HTML5: Firefox seems to have changed when unloading HTML5 audio, `url = ''` now loads hosting page HTML (boo) instead of `null` / no request. Changed to `about:blank` like everyone else. Also fixed boolean logic on `isMovieStar` assignment.

    - Add `audio/mp3` and related MIME checks for flash, correct edge case where `play({type:'audio/mp3'})` would use HTML5 when `preferFlash = true`, due to seeming lack of Flash support for the MIME type.

    - Fixed old Flash 8 `onload()` edge case where loading from cache might return incorrect `didLoad: false` result - corrected by checking for a non-zero sound duration.

    - Properly reset `SMSound.id3 = {}` with internal resetProperty and public methods like `load()`.

    - Edge case fix: Don't attempt to remove flash unless reference exists (prevent false warning when `reboot()` called in 100% HTML5 mode.)

    - Correct empty options JS error on internal `_setup_html5()` when reusing HTML5 audio object per V2.97a.20120527 bug report (Internet Archive)

    - Fix minor false positive (undocumented error handler case) with HTML5 `play()` falsely reporting 32-sound ceiling edge case and calling `SMSound.onplayerror()` (if assigned) when using flashVersion = 9. Should only apply when flash 9 is being used for playback, and ceiling hit.

  - Miscellaneous

    - Finally assign + use `SMSound.id` (instead of sID), matching `createSound({id: 'foo'})` pattern; maintain legacy sID property (ancient behaviour, originally intended to avoid potential namespace conflicts many years ago - now silly and not a concern.)

    - Improved handling of `whileloading()` vs. HTML5 `onload` (when using HTTP range/partial requests).

      HTML5 `onload()` (now triggered via native `canplaythrough` event) may fire early, followed by numerous HTML5 `progress` requests during playback as the audio object requests and buffers more audio ranges (eg., 0-10 seconds), eventually matching the total sound duration.

      Bytes loaded / total are not available, so bytesLoaded instead reflects a fraction of "duration loaded", between 0 and 1 as data is buffered in. Previously, `whileloading` events would not fire once `onload` had fired under HTML5.

    - New (undocumented, for now) `buffered` array on SMSound objects; list of objects following the pattern `SMSound.buffered = [{ start: 0, end: 706 }]` representing loaded time ranges (somewhat similar to HTML5 TimeRanges spec, but using static properties instead of method calls with an index parameter.) Array will initially be empty, zero-length. This can be looped through to show overlays of "loaded" time fragments on progress bars, for example.

      SMSound `buffered` is updated during `whileloading()` calls, where values are provided by the browser. For flash, will always be one item with `{ start: 0, end: SMSound.duration }` assigned. Also stopped sending 1/1 values to `whileplaying()` at `onload()`, since HTML5 can fire `onload()` (via `canplaythrough`) very early followed by many progress (`whileloading()`) events.

      Support note: Not all browsers (eg., Safari 5.1.7) appear to provide buffer / TimeRanges data for HTML5 audio objects. At time of writing (06/2012), Firefox, Chrome Canary, IE 9 and Opera provide TimeRanges alongside progress events.

    - Upgraded demos to use to `soundManager.setup({...})` for most configuration cases (vs. setting `soundManager.url`, `soundManager.defaultOptions.autoLoad` directly etc.)

    - Warn if `soundManager.setup()` called with `url` or `flashVersion`, and init has already fired (ie., flash options already set + movie already loaded) where changes will not take effect until `soundManager.reboot()`.

    - Assign top-level soundManager properties (eg. `soundManager.url`) from `soundManager.setupOptions` at `DOMReady` time; this allows legacy `soundManager.url = ...` assignment to work, and helps to ensure legacy-style, directly-assigned top-level property values get written back to `soundManager.setupOptions`.

- ### V2.97a.20120527 - Fix for `ontimeout()` regression. GWT/JSNI compatibility, slow connection and Safari "background tab" SWF load handling improvements (Download archived version)

  - Bug fixes

    - Fix for `ontimeout()` regression seen when using lazy-loading / SM2_DEFER introduced with V2.97a.20120513; bug introduced when making edits to pass newer jslint rules regarding `return` within `if...else` blocks.

    - Replaced `instanceof Function` with "safer" `typeof x === 'function'` for `onready()`, `ontimeout()` and related callback argument checks as GWT + JSNI was passing arguments that failed the `instanceof` check. (Related bug report.)

    - Corrected another small regression for the `ontimeout()` -> `onready()` "recovery" edge case, ensuring "ready" does not fire after a timeout when init was unsuccessful.

  - Miscellaneous

    - Improved handling for special Safari page load case: When a new tab is opened that does not have focus, the Flash SWF does not load/init until the tab is brought to the foreground. SM2 now recognizes this special case and waits until `window.onfocus()` before attempting to do the JS/Flash part of init. Previously, it would fail with a timeout.

      Code written to originally handle Safari 3.1, which did not support `document.hasFocus()`, was modified and updated for this purpose. The Safari 3.1 logic previously deferred SM2's start-up in a similar fashion. (The old Safari 3.1 `mousemove()` focus-detection hack has been removed as Safari 4 has been out since mid-2009, and Safari 5 since mid-2010.)

    - SM2 init process will now delay and retry if no Flash response, and SWF has loaded > 0 and < 100%. Timeout will now happen only after delay and when SWF has loaded 100%. Should help prevent first-visit (non-cached) failure on very slow or laggy connections.

    - Added note about potential Firefox regression: Offline JS/Flash start-up (viewing HTML pages via `file://` and/or `c:/` and so forth), possibly not working as of Firefox 9 and newer (at time of writing, also up to and including Firefox 12), even despite special security whitelisting under Flash Player "trusted locations" preferences / control panel.

      After successful Flash -> JS call, SM2's "return" JS -> Flash call fails with unusual JS/Flash exception, "Error in ActionScript" error with no further detail. Offline viewing still works in other browsers.

- ### V2.97a.20120513 - Fixes for Android 2.3 playback, `onPosition()` in HTML5, Flash 9 double-play edge case. Minor new Flash 9-specific features (Download archived version)

  - Bug fixes

    - Android 2.3 playback fix (some sounds started only after 2+ play attempts due to Android not liking `load()` immediately followed by `play()`?)

    - `onPosition()` fix for HTML5 playback, items were mistakenly being removed.

    - Fix RTMP stream duration reporting via `onmetadata()` (wrong value was being returned, previously.)

    - Fix for Flash 9 double-play edge case (Internet Archive) found with `pause()` + `setPosition()` calls.

    - JSLINT validation per 04-15-2012 edition rules, mostly removal of multiple return statements within `if ... else` blocks and inverted loop tricks.

  - API updates

    - Enabled waveform/eq/spectrum data features for MovieStar (H.264/NetStream content.)

    - Added `oncaptiondata()` callback for caption data from Flash 9 (NetStream/RTMP-only, similar to `onmetadata()`. Contributor: GitHub user karma.)

    - Added `SMSound.onplayerror()`, presently for Flash 9 (non-MovieStar/NetStream) which can detect lack of available sound hardware or 32-channel ceiling as reasons for playback failure.

    - Added `oncaptiondata()` callback for caption data from Flash 9 (NetStream/RTMP-only, similar to `onmetadata()`.)

  - Miscellaneous

    - Scaling added to 360 UI (via GitHub user tomasdev)

- ### V2.97a.20120318 - Minor updates. `from` / `to` and `onplay()` bug fixes, `canPlayMIME()` and `canPlayLink()` Flash-specific corrections. (Download archived version)

  - Bug fixes

    - Fix silly `undefined"soundID"` debug output message shown at `SMSound.onload` (now says `SMSound._onload()` as previously.)

    - `soundManager.sounds = {}` instead of `[]` on reboot (per bug report [Internet Archive])

    - Fix logic for calling `onplay()`, was always non-truthy. D'oh!

    - Add missing `typeof` to fix html5 MIME check for playability tests

    - Don't apply `width:auto` to SWF (invalid per HTML5, allegedly: Related patch.)

    - Make `soundManager.canPlayMIME()` and `canPlayLink()` check flash support before returning (check after `ontimeout()` was returning truthy when flash required under Firefox, for example, for `'audio/mp3'`)

    - Fix `play()` "`from`" + "`to`" sound sprite playback issue: In some cases, previously-fired "to" events were re-firing due to not being removed, because an equality check was comparing against a potential "to" value of a string rather than a number. (eg., 0-700 followed by 1500-2000; playback would stop in second case, saying 700 had been reached. (Related bug report [Internet Archive].)

    - Re-appeased the jslint gods, removed unused variables and two-statement reverse loop `(for i=x; i--;) { }` trickery.

  - Miscellaneous

    - The SoundManager project turned 10 years old, having originally launched in late 2001. Thanks for using it!

- ### Older Release Info

  For release and changelog history going back to 2010, see the archive page.

## Discussion / Support

For bug reports and technical support, see GitHub Issues.