GithubHelp home page GithubHelp logo

goldfire / howler.js Goto Github PK

View Code? Open in Web Editor NEW
23.0K 360.0 2.2K 31.46 MB

Javascript audio library for the modern web.

Home Page: https://howlerjs.com

License: MIT License

JavaScript 91.68% HTML 1.60% CSS 6.72%
javascript audio html5-audio playback volume web-audio audio-library howler

howler.js's Introduction

howler.js

Description

howler.js is an audio library for the modern web. It defaults to Web Audio API and falls back to HTML5 Audio. 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.

Follow on Twitter for howler.js and development-related discussion: @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
  • Supports all codecs for full cross-browser support
  • Automatic caching for improved performance
  • Control sounds individually, in groups or globally
  • Playback of multiple sounds at once
  • Easy sound sprite definition and playback
  • Full control for fading, rate, seek, volume, etc.
  • Easily add 3D spatial sound or stereo panning
  • Modular - use what you want and easy to extend
  • No outside dependencies, just pure JavaScript
  • 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

Live Demos

Documentation

Contents

Quick Start

Several options to get up and running:

  • Clone the repo: git clone https://github.com/goldfire/howler.js.git
  • Install with npm: npm install howler
  • Install with Yarn: yarn add howler
  • Install with Bower: bower install howler
  • Hosted CDN: cdnjs jsDelivr

In the browser:

<script src="/path/to/howler.js"></script>
<script>
    var sound = new Howl({
      src: ['sound.webm', 'sound.mp3']
    });
</script>

As a dependency:

import {Howl, Howler} from 'howler';
const {Howl, Howler} = require('howler');

Included distribution files:

  • howler: This is the default and fully bundled source that includes howler.core and howler.spatial. It includes all functionality that howler comes with.
  • howler.core: This includes only the core functionality that aims to create parity between Web Audio and HTML5 Audio. It doesn't include any of the spatial/stereo audio functionality.
  • howler.spatial: This is a plugin that adds spatial/stereo audio functionality. It requires howler.core to operate as it is simply an add-on to the core.

Examples

Most basic, play an MP3:
var sound = new Howl({
  src: ['sound.mp3']
});

sound.play();
Streaming audio (for live audio or large files):
var sound = new Howl({
  src: ['stream.mp3'],
  html5: true
});

sound.play();
More playback options:
var sound = new Howl({
  src: ['sound.webm', 'sound.mp3', 'sound.wav'],
  autoplay: true,
  loop: true,
  volume: 0.5,
  onend: function() {
    console.log('Finished!');
  }
});
Define and play a sound sprite:
var sound = new Howl({
  src: ['sounds.webm', 'sounds.mp3'],
  sprite: {
    blast: [0, 3000],
    laser: [4000, 1000],
    winner: [6000, 5000]
  }
});

// Shoot the laser!
sound.play('laser');
Listen for events:
var sound = new Howl({
  src: ['sound.webm', 'sound.mp3']
});

// Clear listener after first call.
sound.once('load', function(){
  sound.play();
});

// Fires when the sound finishes playing.
sound.on('end', function(){
  console.log('Finished!');
});
Control multiple sounds:
var sound = new Howl({
  src: ['sound.webm', 'sound.mp3']
});

// Play returns a unique Sound ID that can be passed
// into any method on Howl to control that specific sound.
var id1 = sound.play();
var id2 = sound.play();

// Fade out the first sound and speed up the second.
sound.fade(1, 0, 1000, id1);
sound.rate(1.5, id2);
ES6:
import {Howl, Howler} from 'howler';

// Setup the new Howl.
const sound = new Howl({
  src: ['sound.webm', 'sound.mp3']
});

// Play the sound.
sound.play();

// Change global volume.
Howler.volume(0.5);

More in-depth examples (with accompanying live demos) can be found in the examples directory.

Core

Options

src Array/String [] required

The sources to the track(s) to be loaded for the sound (URLs or base64 data URIs). These should be in order of preference, howler.js will automatically load the first one that is compatible with the current browser. If your files have no extensions, you will need to explicitly specify the extension using the format property.

volume Number 1.0

The volume of the specific track, from 0.0 to 1.0.

html5 Boolean false

Set to true to force HTML5 Audio. This should be used for large audio files so that you don't have to wait for the full file to be downloaded and decoded before playing.

loop Boolean false

Set to true to automatically loop the sound forever.

preload Boolean|String true

Automatically begin downloading the audio file when the Howl is defined. If using HTML5 Audio, you can set this to 'metadata' to only preload the file's metadata (to get its duration without download the entire file, for example).

autoplay Boolean false

Set to true to automatically start playback when sound is loaded.

mute Boolean false

Set to true to load the audio muted.

sprite Object {}

Define a sound sprite for the sound. The offset and duration are defined in milliseconds. A third (optional) parameter is available to set a sprite as looping. An easy way to generate compatible sound sprites is with audiosprite.

new Howl({
  sprite: {
    key1: [offset, duration, (loop)]
  },
});

rate Number 1.0

The rate of playback. 0.5 to 4.0, with 1.0 being normal speed.

pool Number 5

The size of the inactive sounds pool. Once sounds are stopped or finish playing, they are marked as ended and ready for cleanup. We keep a pool of these to recycle for improved performance. Generally this doesn't need to be changed. It is important to keep in mind that when a sound is paused, it won't be removed from the pool and will still be considered active so that it can be resumed later.

format Array []

howler.js automatically detects your file format from the extension, but you may also specify a format in situations where extraction won't work (such as with a SoundCloud stream).

xhr Object null

When using Web Audio, howler.js uses an XHR request to load the audio files. If you need to send custom headers, set the HTTP method or enable withCredentials (see reference), include them with this parameter. Each is optional (method defaults to GET, headers default to null and withCredentials defaults to false). For example:

// Using each of the properties.
new Howl({
  xhr: {
    method: 'POST',
    headers: {
      Authorization: 'Bearer:' + token,
    },
    withCredentials: true,
  }
});

// Only changing the method.
new Howl({
  xhr: {
    method: 'POST',
  }
});

onload Function

Fires when the sound is loaded.

onloaderror Function

Fires when the sound is unable to load. The first parameter is the ID of the sound (if it exists) and the second is the error message/code.

The load error codes are defined in the spec:

  • 1 - The fetching process for the media resource was aborted by the user agent at the user's request.
  • 2 - A network error of some description caused the user agent to stop fetching the media resource, after the resource was established to be usable.
  • 3 - An error of some description occurred while decoding the media resource, after the resource was established to be usable.
  • 4 - The media resource indicated by the src attribute or assigned media provider object was not suitable.

onplayerror Function

Fires when the sound is unable to play. The first parameter is the ID of the sound and the second is the error message/code.

onplay Function

Fires when the sound begins playing. The first parameter is the ID of the sound.

onend Function

Fires when the sound finishes playing (if it is looping, it'll fire at the end of each loop). The first parameter is the ID of the sound.

onpause Function

Fires when the sound has been paused. The first parameter is the ID of the sound.

onstop Function

Fires when the sound has been stopped. The first parameter is the ID of the sound.

onmute Function

Fires when the sound has been muted/unmuted. The first parameter is the ID of the sound.

onvolume Function

Fires when the sound's volume has changed. The first parameter is the ID of the sound.

onrate Function

Fires when the sound's playback rate has changed. The first parameter is the ID of the sound.

onseek Function

Fires when the sound has been seeked. The first parameter is the ID of the sound.

onfade Function

Fires when the current sound finishes fading in/out. The first parameter is the ID of the sound.

onunlock Function

Fires when audio has been automatically unlocked through a touch/click event.

Methods

play([sprite/id])

Begins playback of a sound. Returns the sound id to be used with other methods. Only method that can't be chained.

  • sprite/id: String/Number optional Takes one parameter that can either be a sprite or sound ID. If a sprite is passed, a new sound will play based on the sprite's definition. If a sound ID is passed, the previously played sound will be played (for example, after pausing it). However, if an ID of a sound that has been drained from the pool is passed, nothing will play.

pause([id])

Pauses playback of sound or group, saving the seek of playback.

  • id: Number optional The sound ID. If none is passed, all sounds in group are paused.

stop([id])

Stops playback of sound, resetting seek to 0.

  • id: Number optional The sound ID. If none is passed, all sounds in group are stopped.

mute([muted], [id])

Mutes the sound, but doesn't pause the playback.

  • muted: Boolean optional True to mute and false to unmute.
  • id: Number optional The sound ID. If none is passed, all sounds in group are stopped.

volume([volume], [id])

Get/set volume of this sound or the group. This method optionally takes 0, 1 or 2 arguments.

  • volume: Number optional Volume from 0.0 to 1.0.
  • id: Number optional The sound ID. If none is passed, all sounds in group have volume altered relative to their own volume.

fade(from, to, duration, [id])

Fade a currently playing sound between two volumes. Fires the fade event when complete.

  • from: Number Volume to fade from (0.0 to 1.0).
  • to: Number Volume to fade to (0.0 to 1.0).
  • duration: Number Time in milliseconds to fade.
  • id: Number optional The sound ID. If none is passed, all sounds in group will fade.

rate([rate], [id])

Get/set the rate of playback for a sound. This method optionally takes 0, 1 or 2 arguments.

  • rate: Number optional The rate of playback. 0.5 to 4.0, with 1.0 being normal speed.
  • id: Number optional The sound ID. If none is passed, playback rate of all sounds in group will change.

seek([seek], [id])

Get/set the position of playback for a sound. This method optionally takes 0, 1 or 2 arguments.

  • seek: Number optional The position to move current playback to (in seconds).
  • id: Number optional The sound ID. If none is passed, the first sound will seek.

loop([loop], [id])

Get/set whether to loop the sound or group. This method can optionally take 0, 1 or 2 arguments.

  • loop: Boolean optional To loop or not to loop, that is the question.
  • id: Number optional The sound ID. If none is passed, all sounds in group will have their loop property updated.

state()

Check the load status of the Howl, returns a unloaded, loading or loaded.

playing([id])

Check if a sound is currently playing or not, returns a Boolean. If no sound ID is passed, check if any sound in the Howl group is playing.

  • id: Number optional The sound ID to check.

duration([id])

Get the duration of the audio source (in seconds). Will return 0 until after the load event fires.

  • id: Number optional The sound ID to check. Passing an ID will return the duration of the sprite being played on this instance; otherwise, the full source duration is returned.

on(event, function, [id])

Listen for events. Multiple events can be added by calling this multiple times.

  • event: String Name of event to fire/set (load, loaderror, playerror, play, end, pause, stop, mute, volume, rate, seek, fade, unlock).
  • function: Function Define function to fire on event.
  • id: Number optional Only listen to events for this sound id.

once(event, function, [id])

Same as on, but it removes itself after the callback is fired.

  • event: String Name of event to fire/set (load, loaderror, playerror, play, end, pause, stop, mute, volume, rate, seek, fade, unlock).
  • function: Function Define function to fire on event.
  • id: Number optional Only listen to events for this sound id.

off(event, [function], [id])

Remove event listener that you've set. Call without parameters to remove all events.

  • event: String Name of event (load, loaderror, playerror, play, end, pause, stop, mute, volume, rate, seek, fade, unlock).
  • function: Function optional The listener to remove. Omit this to remove all events of type.
  • id: Number optional Only remove events for this sound id.

load()

This is called by default, but if you set preload to false, you must call load before you can play any sounds.

unload()

Unload and destroy a Howl object. This will immediately stop all sounds attached to this sound and remove it from the cache.

Global Options

usingWebAudio Boolean

true if the Web Audio API is available.

noAudio Boolean

true if no audio is available.

autoUnlock Boolean true

Automatically attempts to enable audio on mobile (iOS, Android, etc) devices and desktop Chrome/Safari.

html5PoolSize Number 10

Each HTML5 Audio object must be unlocked individually, so we keep a global pool of unlocked nodes to share between all Howl instances. This pool gets created on the first user interaction and is set to the size of this property.

autoSuspend Boolean true

Automatically suspends the Web Audio AudioContext after 30 seconds of inactivity to decrease processing and energy usage. Automatically resumes upon new playback. Set this property to false to disable this behavior.

ctx Boolean Web Audio Only

Exposes the AudioContext with Web Audio API.

masterGain Boolean Web Audio Only

Exposes the master GainNode with Web Audio API. This can be useful for writing plugins or advanced usage.

Global Methods

The following methods are used to modify all sounds globally, and are called from the Howler object.

mute(muted)

Mute or unmute all sounds.

  • muted: Boolean True to mute and false to unmute.

volume([volume])

Get/set the global volume for all sounds, relative to their own volume.

  • volume: Number optional Volume from 0.0 to 1.0.

stop()

Stop all sounds and reset their seek position to the beginning.

codecs(ext)

Check supported audio codecs. Returns true if the codec is supported in the current browser.

  • ext: String File extension. One of: "mp3", "mpeg", "opus", "ogg", "oga", "wav", "aac", "caf", "m4a", "m4b", "mp4", "weba", "webm", "dolby", "flac".

unload()

Unload and destroy all currently loaded Howl objects. This will immediately stop all sounds and remove them from cache.

Plugin: Spatial

Options

orientation Array [1, 0, 0]

Sets the direction the audio source is pointing in the 3D cartesian coordinate space. Depending on how directional the sound is, based on the cone attributes, a sound pointing away from the listener can be quiet or silent.

stereo Number null

Sets the stereo panning value of the audio source for this sound or group. This makes it easy to setup left/right panning with a value of -1.0 being far left and a value of 1.0 being far right.

pos Array null

Sets the 3D spatial position of the audio source for this sound or group relative to the global listener.

pannerAttr Object

Sets the panner node's attributes for a sound or group of sounds. See the pannerAttr method for all available options.

onstereo Function

Fires when the current sound has the stereo panning changed. The first parameter is the ID of the sound.

onpos Function

Fires when the current sound has the listener position changed. The first parameter is the ID of the sound.

onorientation Function

Fires when the current sound has the direction of the listener changed. The first parameter is the ID of the sound.

Methods

stereo(pan, [id])

Get/set the stereo panning of the audio source for this sound or all in the group.

  • pan: Number A value of -1.0 is all the way left and 1.0 is all the way right.
  • id: Number optional The sound ID. If none is passed, all in group will be updated.

pos(x, y, z, [id])

Get/set the 3D spatial position of the audio source for this sound or group relative to the global listener.

  • x: Number The x-position of the audio source.
  • y: Number The y-position of the audio source.
  • z: Number The z-position of the audio source.
  • id: Number optional The sound ID. If none is passed, all in group will be updated.

orientation(x, y, z, [id])

Get/set the direction the audio source is pointing in the 3D cartesian coordinate space. Depending on how directional the sound is, based on the cone attributes, a sound pointing away from the listener can be quiet or silent.

  • x: Number The x-orientation of the source.
  • y: Number The y-orientation of the source.
  • z: Number The z-orientation of the source.
  • id: Number optional The sound ID. If none is passed, all in group will be updated.

pannerAttr(o, [id])

Get/set the panner node's attributes for a sound or group of sounds.

  • o: Object All values to update.
    • coneInnerAngle 360 A parameter for directional audio sources, this is an angle, in degrees, inside of which there will be no volume reduction.
    • coneOuterAngle 360 A parameter for directional audio sources, this is an angle, in degrees, outside of which the volume will be reduced to a constant value of coneOuterGain.
    • coneOuterGain 0 A parameter for directional audio sources, this is the gain outside of the coneOuterAngle. It is a linear value in the range [0, 1].
    • distanceModel inverse Determines algorithm used to reduce volume as audio moves away from listener. Can be linear, inverse or exponential. You can find the implementations of each in the spec.
    • maxDistance 10000 The maximum distance between source and listener, after which the volume will not be reduced any further.
    • refDistance 1 A reference distance for reducing volume as source moves further from the listener. This is simply a variable of the distance model and has a different effect depending on which model is used and the scale of your coordinates. Generally, volume will be equal to 1 at this distance.
    • rolloffFactor 1 How quickly the volume reduces as source moves from listener. This is simply a variable of the distance model and can be in the range of [0, 1] with linear and [0, โˆž] with inverse and exponential.
    • panningModel HRTF Determines which spatialization algorithm is used to position audio. Can be HRTF or equalpower.
  • id: Number optional The sound ID. If none is passed, all in group will be updated.

Global Methods

stereo(pan)

Helper method to update the stereo panning position of all current Howls. Future Howls will not use this value unless explicitly set.

  • pan: Number A value of -1.0 is all the way left and 1.0 is all the way right.

pos(x, y, z)

Get/set the position of the listener in 3D cartesian space. Sounds using 3D position will be relative to the listener's position.

  • x: Number The x-position of the listener.
  • y: Number The y-position of the listener.
  • z: Number The z-position of the listener.

orientation(x, y, z, xUp, yUp, zUp)

Get/set the direction the listener is pointing in the 3D cartesian space. A front and up vector must be provided. The front is the direction the face of the listener is pointing, and up is the direction the top of the listener is pointing. Thus, these values are expected to be at right angles from each other.

  • x: Number The x-orientation of listener.
  • y: Number The y-orientation of listener.
  • z: Number The z-orientation of listener.
  • xUp: Number The x-orientation of the top of the listener.
  • yUp: Number The y-orientation of the top of the listener.
  • zUp: Number The z-orientation of the top of the listener.

Group Playback

Each new Howl() instance is also a group. You can play multiple sound instances from the Howl and control them individually or as a group (note: each Howl can only contain a single audio file). For example, the following plays two sounds from a sprite, changes their volume together and then pauses both of them at the same time.

var sound = new Howl({
  src: ['sound.webm', 'sound.mp3'],
  sprite: {
    track01: [0, 20000],
    track02: [21000, 41000]
  }
});

// Play each of the track.s
sound.play('track01');
sound.play('track02');

// Change the volume of both tracks.
sound.volume(0.5);

// After a second, pause both sounds in the group.
setTimeout(function() {
  sound.pause();
}, 1000);

Mobile/Chrome Playback

By default, audio on mobile browsers and Chrome/Safari is locked until a sound is played within a user interaction, and then it plays normally the rest of the page session (Apple documentation). The default behavior of howler.js is to attempt to silently unlock audio playback by playing an empty buffer on the first touchend event. This behavior can be disabled by calling:

Howler.autoUnlock = false;

If you try to play audio automatically on page load, you can listen to a playerror event and then wait for the unlock event to try and play the audio again:

var sound = new Howl({
  src: ['sound.webm', 'sound.mp3'],
  onplayerror: function() {
    sound.once('unlock', function() {
      sound.play();
    });
  }
});

sound.play();

Dolby Audio Playback

Full support for playback of the Dolby Audio format (currently support in Edge and Safari) is included. However, you must specify that the file you are loading is dolby since it is in a mp4 container.

var dolbySound = new Howl({
  src: ['sound.mp4', 'sound.webm', 'sound.mp3'],
  format: ['dolby', 'webm', 'mp3']
});

Facebook Instant Games

Howler.js provides audio support for the new Facebook Instant Games platform. If you encounter any issues while developing for Instant Games, open an issue with the tag [IG].

Format Recommendations

Howler.js supports a wide array of audio codecs that have varying browser support ("mp3", "opus", "ogg", "wav", "aac", "m4a", "m4b", "mp4", "webm", ...), but if you want full browser coverage you still need to use at least two of them. If your goal is to have the best balance of small filesize and high quality, based on extensive production testing, your best bet is to default to webm and fallback to mp3. webm has nearly full browser coverage with a great combination of compression and quality. You'll need the mp3 fallback for Internet Explorer.

It is important to remember that howler.js selects the first compatible sound from your array of sources. So if you want webm to be used before mp3, you need to put the sources in that order.

If you want your webm files to be seekable in Firefox, be sure to encode them with the cues element. One way to do this is by using the dash flag in ffmpeg:

ffmpeg -i sound1.wav -dash 1 sound1.webm

Sponsors

Support the ongoing development of howler.js and get your logo on our README with a link to your site [become a sponsor]. You can also become a backer at a lower tier and get your name in the BACKERS list. All support is greatly appreciated!

GoldFire Studios

License

Copyright (c) 2013-2021 James Simpson and GoldFire Studios, Inc.

Released under the MIT License.

howler.js's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

howler.js's Issues

Non-sprite files no longer play after their first playback ends (HTML5 audio)

To work around IE9's inability to play audio sprites well, I am using separate audio files when the browser does not (yet) support the Web Audio API (IE9 and Firefox).

Each file gets its own "Howl" object. Using Firefox/HTML5 audio: at first these files play when you click their button, and if you quickly click again they play again. But 2 seconds after the first time they were played, clicking will no longer play the sound.

Curiously enough, 2 seconds is also the duration of the audio files. So it seems that something is going amiss when the audio clip ends?

Click the keys of the keyboard on this page to see it happen:
<< url removed >>

This happens with each of the following three versions of howler.js: 1.0.10, 1.0.8, and 1.0.7

FF20 not playing mp3?

I implemented howler.js with click on an image. I register the image like this:

$(document.createElement("img")).attr({ src: './goldfire.jpg'})
            .addClass("image")
            .click({param1: audioname}, cool_function)
                .appendTo("#imagecontainer");

and before that:

       function cool_function(event){
        var sound = new Howl({urls: ['./audio/'+event.data.param1]}).play();
}

which works very nicely on Safari on MacBook Air, and on iPod and iPad. Chrome also ok. But FF20 no sound. The audio is a 96kb/s mp3.

Inconsistent behavior with sound.pos() return value

Return value from sound.pos() (without argument, i.e. getter) depends on sound._loaded, which took my by surprise. IMHO sound.pos() should always return number and sound.pos(pos) should always return sound.

I stumbled upon this when debugging random fails with arithmetics involving sound.pos(), which I expected to always return a number.

Feature Request: Panning with Web Audio API

Great Library guys! I would like to request a feature, or method to the sound library. In the Web Audio API, you can create a panning node and set Position (x,y,and z if you need the 3rd dimension). This will pan the sound left and right depending on the listener position and sound source position. Is it possible to add this panning capability to your wonderful library? Thanks!

What events can I bind to?

The documentation for on(event, callback) does not document what events I can bind to. Is there a list anywhere?

Sound unload method

How do you unload/destroy a sound once you're done with it and want to release it? Normally I'd expect to see an API method for the expressed purpose of deprecating media, such as unload() or dispose(), that will stop the sound's playback, loading, and release all references to it.

Lacking a formal cleanup API method, is simply calling stop() and then orphaning a Howl object really memory-safe?

Feature Request: Simple Compression and Filter

Hi James and all,
James I know you have a lot on your plate right now, but with possible reworking of some of the aspects of Howler's positional methods, I wanted to try to throw in a couple of feature requests that would be relatively easier to implement now, during possible re-structuring, rather than later as an afterthought.

Two effects come to mind when having a robust audio engine for games. The first is almost a necessity - compression. If the developer has too many sounds playing at the same time and a possible background track going on, the audio will become distorted due to clipping. May I suggest a howler.compressor object to limit the final output of the app's audio and to help keep in check the overall volume when the gameplay sounds get heavy (like a sudden firefight in a war game).

The second isn't so much a necessity as it is a cool effect that is difficult to hard-code ourselves, or re-record everything with the effect added. This is a Low-Pass Filter. For those of you non-audio buffs out there, it is essentially a muffling effect. It limits all the high parts of the audio spectrum (imagine speaking while cupping your hand over your mouth). The volume remains the same, but only the low parts pass through.

I can think of a couple of situations where a filter would come in handy - one is in a FPS when the player gets knocked by a nearby grenade or something, a muffled-world sound would ensue as well as red-tinted-screen 'damage' effects or whatever the developer wanted. The second case would be people talking or a club-music atmosphere going on in another room. As you approach the room from outside, the voices or music sound muffled, and when you open the door, the developer switches howler.filter to Off and then you can hear the high parts of the sounds again (just like in real-life).

So in summary, howler.compressor(amount) and howler.filter(frequency). The lower the frequency, the more muffled, the higher the frequency the less muffled the sound becomes. We could even use this feature to code a sweep of that frequency parameter and go smoothly from totally muffled to totally bright (as DeadMau5 makes money doing every night - haha).

Implementing these with Web Audio API is trivial. It's probably 4 or 5 lines of code for each effect. It involves creating the filter or compressor and then hooking them up with the .connect() function to the final audio destination (your speakers). As usual the Web Audio API overkills and gives you total control over every possible parameter if you want to design a synthesizer, but we just need a one-size-fits-all function with maybe 1 adjustable parameter to keep things simple and useful for gaming applications.

Please let me know what you all think.

Support for master volume

Master volume that would dictate the maximum volume for all sounds. Example:

Master volume is set to 0.6, that means that sound with volume 0.5 will have an effective volume of 0.3.

And it would be awesome if I could have multiple "master instances", so I could create one for background music sounds, one for sound effects...

This would allow me to create a nicely configurable sounds volume UI you see in almost any game.

Though to do this, howler would need some re-factoring, so no pressure :)

iOS and Chrome issues

Are there known issues with the iPad and audio? I don't seem to be able to get howler.js to play mp3s on the iPad or iPhone. It stays silent. :(

Also, on Chrome when I try to use fadeIn and fadeOut I get no sound at all. :/

TIA for any help!

FF/IE playing too many sounds at once causes the sound sprite to play entirely

Firefox/IE - both Linux and Windows

Not sure what causes it but first thing revised should be timers clearing method and the process beyond pausing actual node.

Try using this code in console to invoke the buggy behaviour (several times if needed):

for(var i = 0; i < 5; i++) someHowl.play("spriteKey")

However maybe it is just me :)

Error when trying to play mp3 sound

When I want to play sound

$this.sound = new Howl({
            urls: ['sound/sound.mp3']
    }).play();

it throws me this error

TypeError: i is undefined
[Break On This Error]   
...Timer[0]);r._onendTimer.splice(0,1)}if(n){if(!r.bufferSource){return r}r._pos+=t...
howler.min.js (line 10)

Duration is NaN on Firefox

I tried the following code:

var h = new Howl({
    urls:["sounds/sound.ogg","sounds/sound.mp3"],
    loop:true
});

When I log h with Firefox, the _duration variable is NaN and playing the sound, besides sounding totally wrong, slows the browser to a crawl until I have to force quit it. This works on Safari and Chrome.

I tried using setting a duration with the object sent in the new Howl, but the resulting duration is also NaN. Is this a known issue? Could I be doing something wrong?

I'm testing on Firefox 20.0 for Mac.

Thanks.

Safari + Windows - Quicktime

Safari supports the HTMLAudioElement only when quicktime is installed.
If quicktime is missing, "new Audio()" throws an exception.

By the way... Awesome library =).

howler.js v1.1.4 no longer works locally

howler.js v1.1.1 and v1.1.2 worked fine where you can use it locally. Pulling up a webpage at file:///c/users/me/index.html would play the sounds through Howler. However, now I get CORS issues with v1.1.4.

Setting global volume fails when passed a parameter of 0

Line 48: if (vol && vol >= 0 && vol <= 1) { This if construct makes the volume() function silently fail when passed a non-number, but testing for vol as a boolean value makes the function also fail when vol is zero.

That line should be if (typeof(vol) === 'number' && vol >= 0 && vol <= 1) {
because your check will pass if the volume() function is passed something like "1", which leads to a string being stored in the _volume variable, which can lead to issues when performing arithmetic on the result of accessing the volume() property. ".5" + .5 becomes ".50.5"

Testing needed for 1.1.0-b1

Thank you to everyone for all the amazing feedback, with your help we are building the best audio library on the web! I'd like to announce that a new branch has been opened (https://github.com/goldfire/howler.js/tree/1.1.0) that contains the current changes for 1.1.0. There have been a lot of behind-the-scenes changes, so I'd like to do more testing than usual for this update to weed out the edge cases before merging into master and declaring stable.

  • 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.
  • ADDED: New optional parameter in sprite defintions to define a sprite as looping rather than the whole track. In the sprite definition array, set the 3rd value to true for looping (spriteName: [pos, duration, loop]).
  • FIXED: Improved implementation of Web Audio API looping.
  • FIXED: Various code cleanup and optimizations.

Please test out the new code and open any new issues tagged with 1.1.0 if you find problems. This is also a good time to submit feedback for other ideas or improvements you think should go in this release.

Support additional positional methods for Web Audio

I'd like to see methods for setting velocity and orientation on howls. I'd also like to see some means of setting a listener position, orientation and velocity.

If there are no plans to do this within the week, I may have time to hammer out a pull request, but in order to reduce friction in having it accepted, it might be nice to discuss implementation here. Specifically:

  • Have "velocity" and "orientation" methods on Howl similar to pos3d, only without the non-Web Audio path. For non-Web Audio they'd simply be no-op, and it'd be up to the developer to present an alert if these advanced features are used and it is felt that they are necessary to the audio experience.
  • Create a listener lode as a local variable on Howl.
  • Add Howl.listenerPosition, Howl.listenerVelocity and Howl.listenerOrientation methods to set the listener's attributes. I assume that there is never more than one global listener in a Howl app. If there is, then perhaps the app needs more sophistication than Howl can offer.

As an aside, it might be a good idea to create a new method for setting position and deprecating pos3d, since this feature would add many additional 3-D attributes to sound. Maybe reserve position() for 3-D sound, add offset() as a synonym for pos, then deprecate pos/pos3d for a future 2.0 release? I won't implement that now (except for maybe the position() synonym if asked) but I'm tossing it out there as a thought.

Can looping be seamless?

This is a browser issue, not a library issue, but it would be a real nice-to-have. Check out this loop: http://jsfiddle.net/qyXtT/1/

There's a slight gap between end and start on loop. Is there any way to fix that? It's especially bad for the more ambient sounds, like this rain file, or ambient music. Cross fade?

To add to the note about it being a browser issue, I searched the Chromium dev for an issue, couldn't find one. I might open one; looping should be seamless (same for video). But browsers do a slight pause-gap. Tsk, tsk.

cannot play http music in ios6 by using howler.js v.1.1.4

Hi,

here is my test code:

var sound = new Howl({
urls: ['http://a1704.phobos.apple.com/us/r1000/086/Music/ec/12/fc/mzm.ayuevuim.aac.p.m4a'],
buffer:false,
onload: function(){console.log('onload')},
}).play();

and it will work when I use buffer:true.
please help, thanks.

Issue with loop after resuming

Hi,
Thanks for the great library.
I have a problem when resuming a music which must loop: only a small portion of the sound loops, it doesn't restart from the beginning. I guess that the current position ("pos") is somehow corrupted.
Here is how to reproduce it:
1/ Load some sounds (I do it in a class)

// sound
sound: false,
soundFX1: new Howl({urls:["SFX1.mp3","SFX1.ogg"]}),
soundFX2: new Howl({urls:["SFX2.mp3","SFX2.ogg"]}),
soundFX3: new Howl({urls:["SFX3.mp3","SFX3.ogg"]}),
music: new Howl({urls:["music.mp3","music.ogg"], volume:0.5, loop:true}),

2/ Start the music on a click event:

toggleSound: function () {
        if(this.sound) this.music.pause();
        else this.music.play();
        this.sound = !this.sound;
}

3/ Play some sounds:

playSoundEffect: function () {
if (this.sound){
        var playablesounds = [this.soundFX1, this.soundFX2, this.soundFX3];
        var soundtoplay = playablesounds[getRandomInt(0,2)];
        soundtoplay.play();
    }
}

For information: function getRandomInt (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}

4/ Toggle sound near the end of the music by calling toggleSound() : only a small portion of the sound will loop. I could not determined exactly how or when it happens...

For now I decided to replace "this.music.pause();" by "this.music.stop();". It is not the behaviour I want, but it works.

Recording

Is it possible (or are you planning to add support) to record?

Thanks!

Playing two audio sprites at once can cause the whole audio file to play

Trying to play two audio sprites from the same audio file immediately after each other, like so:

myAudio.play( 'soundA' );
myAudio.play( 'soundB' );

Resulted in a glitch with Firefox / HTML5 Audio. Often the whole audio file would play, and not just a single sprite. (It worked fine in Chrome / Web Audio API.)

I found a hack / work-around that seems to prevent the problem:

myAudio.play( 'soundA' );
setTimeout( function(){ myAudio.play( 'soundB' )} , 1 );

Sound starts repeating in ios but works fine on windows.!!!

 var AllSounds = new Howl({
          urls: ['sounds/all2000.mp3'],
          sprite: {
            Excellent_howler: [0, 1000],
            GoodJOb_howler: [2000, 3000],
            GreateJob_howler: [4000, 5000],
            wellDone_howler:[6000,7000],
            num_howler1:[8000,9000],
            num_howler2:[10000,1100],
            num_howler3:[12000,13000],
            num_howler4:[14000,15000],
            num_howler5:[16000,17000],
            num_howler6:[18000,18950],
            num_howler7:[20000,20950],
            num_howler8:[22000,22950],
            num_howler9:[24000,24950],
            num_howler10:[26400,27100]  
        }

        });

And here is the function from which i am calling howler sounds.

Since the whole sprite sheet was playing ,therefor used Allsounds.stop after every second .

function countingTimer(totalNumber,displaynumber){
        if(displaynumber>1){
             console.log('inside clear timer');
             clearTimeout(timer);
             AllSounds.stop();
           }
        if(onmain_screen==false){  
          console.log('totalNumber:'+totalNumber+'displaynumber'+displaynumber);

           if(displaynumber<=totalNumber){         
              stage.update();
              //playing sound
              //createjs.Sound.play("num_sound"+displaynumber)
              AllSounds.play('num_howler'+displaynumber);
              //soundManager.resume('sound_'+displaynumber);
              //soundManager.play('sound_'+displaynumber);
              //soundManager.pause('sound_'+displaynumber);
              countingText.text=""+displaynumber;

              countingText.x=countingTextCordinates[randomArray[0]][displaynumber][0];
              countingText.y=countingTextCordinates[randomArray[0]][displaynumber][1];        
               console.log(countingTextCordinates[randomArray[0]][displaynumber][0]+":"+countingTextCordinates[randomArray[0]][displaynumber][1]);
               if(displaynumber==1){
                stage.addChild(countingText);
               }else{
               }

                stage.update();
                displaynumber++;
                var t=totalNumber;
                //var f = countingTimer;  //use 'this' if called from class
                //f.parameter1 = totalNumber;
                //f.parameter2 = displaynumber;
                console.log('timer is started');
                 timer=setInterval(function() { countingTimer(t,displaynumber); },1500);

                //setInterval("countingTimer(totalNumber,displaynumber)",3000);    
            }else{
              if(givenanswer){
                viewTrueAnswer();
              }else{
                viewWrongAnswer();
              }
            }        
          }
        }

Self is not defined.

On line 92, self is not defined. I'm not sure if you meant to return this or undefined. I assume you meant to return this seeing as the doc-string says "return {Object}". I'm not entirely sure if this has any implications, I'm literally just reading code that is used by a lot of people trying to pick up some tips, etc.

Strange pitched sounds on iOS

Hi!

This is my problem:

  1. I use this code to preload sounds. It works fine on all desktop browsers:
var sound = new Howl({
    urls: files,
    onload: function() {
        ++self.soundsLoaded;
    }
});
  1. I clear cache on my iPad and close the Browser.

  2. I load the website, and the sounds are totally weird. Like they were in slow motion.

  3. I reload the website... and everything goes right and the sounds can be hear perfectly well.

You can check the problem here:

http://www.edshark.com/ocean-of-words/

It happens with iOS Safari and specially on iOS Chrome. What can I do?

Thanks!

What functionality is implemented for sprites, and what is planned for future implementation.

I have been looking into options for my game, and came across howler, it looks great! Thankyou for all the hard work you guys have put into it, and I hope you get lots out of making it open source!

Anyway. I want to use sprites, but I want to have the ability to start, stop, pause, fade (in/out) and loop, but on individual sprites (not the whole sound). Looking into the API it looks as though all this functionality is only implemented for the sound as a whole. For example it would be nice to make one sprite item fade in and play once, while a second sprite item starts without fade and loops. Am i missing this ability in the API? (If so could you provide an example of how to do the above) or is this possibly planned for future release?

Demo Failure with Chromium in Ubuntu

Using Chromium (Version 28.0.1500.52 Ubuntu 12.10), the howler.js demo silently fails without any thrown exceptions or warnings in the console.

Silently, i.e. none of the sounds play but the XHR that loads them appears to be completing without any issues.

Let me know if there's anything more specific I could do to help pinpoint the issue.

IE9 non-sprite audio stops playing (howler.js 1.0 and 1.1)

With both howler.js 1.0.11 and 1.1, in IE9, using non-sprite HTML5 audio, the audio clips will play at first, a few times (5?) and then will stop responding when you click to play them. At that point different audio clips will play once each but not again. This happens both with 1.0.11 and the most recent 1.1 branch.

I thought it might be a problem with the playback position not getting reset to 0, but it appears to be a problem with not finding an inactive node to use. I traced it back as far this function (around line 790 in 1.0.11):

/**
 * Get the first inactive audio node (HTML5 audio use only).
 * If there is none, create a new one and add it to the pool.
 * @param  {Function} callback Function to call when the audio node is ready.
 */
_inactiveNode: function(callback) {
  var self = this,
    node = null;

  // find first inactive node to recycle
  for (var i=0; i<self._audioNode.length; i++) {
    if (self._audioNode[i].paused && self._audioNode[i].readyState === 4) {
      callback(self._audioNode[i]);
      node = true;
      break;
    }
  }

The if clause stops resolving to true and so the callback to play the audio stops getting called. I haven't had time to test any further with it yet. (I have to go to a library to test with IE9, which is why I didn't catch this before.)

This might have been caused by my fix for issue #15. Before that fix non-sprite audio would also be paused on completion. After that fix it is not paused (so that the playback position can return to zero, and not get paused/stuck at the end of the track). So, if IE9 does not automatically set an audio clip to "paused" when it finishes playing, then that would cause this problem.

If that's the case, here are 2 possible fixes:

  1. figure out what state IE9 audio ends up in when it finishes playing, and have this if clause also check for that, in order to identify those inactive nodes.
  2. revert the fix for issue #15, so that all HTML5 audio is paused upon completion, but then explicitly reset the playback position to zero if the audio is not a sprite.

I should be able to work on this a little more tomorrow.

Loop only 2 times under FF 19

Hello,

When using
var ambient = new Howl({
urls: ['/ambient.mp3', '/ambient.ogg'],
volume: 0.3,
loop: true
});

I have noticed the sound in only played twice under FF. It works under Chrome on the contrary.

Semver tags for easy package management

Currently versioning appears to be managed by named branches, although this is useful for manual installation, most packaging tools don't know how to handle this.
It would be far more friendly to add versions as tags onto the code, this way we can use bower, npm and probably some others, to consume howler.js automatically!

Method urls() is not working properly

I'm trying to change the sound urls with the urls() method, but it doesn't work. When I try to play() after change the urls, nothing happens.
I tried on Chrome 28:

var mySound = new Howl({
  urls: ['sound.mp3'],
  autoplay: false
});
mySound.play(); // It works!

mySound.urls(['another_sound.mp3']);
mySound.play(); // It does nothing.

Problem with duration = Infinity

For some reason, some systems (maybe in a specific network) return "Infinite" as audio duration. This causes the plugin to go crazy when you loop a sound, 'cause it immediately fires the end event when played. I think it's a pretty rare issue, but it happened on some client's machines in firefox only (version 22.0).

Pausing issue in v1.1.1

Hi James,
I opened this issue in relation to the recently closed issue that I had started. I feel this is still a relevant issue. There is a pausing problem while trying to use the new .pos3d() method to pan a sound, then playing a sound once, twice, or repeating the sound rapid-fire (like a machine-gun effect in a game).

I found the problem magically goes away when I make a simple boolean change to your howler.js code:

       // set web audio node to paused at end
        if (self._webAudio && !loop) {
          self._nodeById(data.id).paused = false; //changed to 'false' by erichlof
        }  

This came from the play: function . I'm sorry this is kind of a hack and I don't really understand the inner workings of howler well enough to know why this works, but it does.

Can you safely work it in to the next version so we can use the .pos3d() method with the intended results?

Thanks James. Howler 1.1.1 rocks!

Bug with latest version

My .pos3d demo code works fine with the slightly older "howler110.js" file. However when I try to link to the newest library, either howler.js or minified howler.min.js, the 3D functionality goes away. Also, there seems to be a repeating delay or echo in the sound.

Something is not getting hooked up right, maybe with the panner node or destination node. I'll keep an eye out, although since this is not my library, I don't know how good I will be at finding a typo or bug in the code.

I will try though!

Error when trying to develop locally

I get the following error when trying to use howler.js locally without a webserver:

XMLHttpRequest cannot load file:///C:/Users/Scott/WebstormProjects/guess_the_number/bird.wav. Cross origin requests are only supported for HTTP. howler.min.js:10
Uncaught Error: NETWORK_ERR: XMLHttpRequest Exception 101

I know the issue... that I need to use an http URL isntead of file:///. So that means I need a local webserver to develop on. However, I don't want to do that for several reasons. For one, I don't get the live editing feature that WebStorm provides. I'm also trying to teach kids JavaScript with howler.js. I don't want to teach them about webservers at this point yet. Anyway, is there a way to use howler.js without using a webserver?

I know the HTML5 <audio> element can use file URLs. Can I force howler.js to fallback to this method for local files?

script for generating sprites for howler

howdy!

We're playing around with howler, and it's really sweet.

What we're currently trying to work out however is how to generate an mp3 sprite and timing info most effectively. We have a bunch of small mp3s that we'd like to bunch together, and also probably generate a json or a dictionary to fit in the the new Howl statement.

Any suggestions on external tools (preferably in linux bash / python / ruby environment)?

Variable Volume

Is it possible to play a single Howl at different volumes? In my example: I have an explosion sound that needs to be softer the further a player is away from the event. Do I have to create a new instance of a Howl for this? I was hoping to reuse the existing Howl, something to the effect of:

sound.play({ volume: 0.25 });

Add method to determine if sound is playing

Not sure if I'm not getting some aspect of Howler, but there seems to be no method for determining if a given howl is playing.

I'm using an entity system in which entities can indicate a "presence" sound. If the game is active, then any entities with a presence sound should have that sound played. Unfortunately, if I simply loop through all entities and call play() on their registered howls, I get many instances of the same sound overlaying each other.

I'd like it if I can check if a given howl is playing, then not call play(). Or, better yet, perhaps play() could do this check and not start multiple instances...unless one howl is intended to support multiple sounds, in which case it'd be nice to track playing per instance.

wrong duration in new Howl object with the same file

hi
i have played a little and i used the lib in a wrong way i think, but in this way i found a bug.

if you generate 2 Howl object with the same audio file then the second on has a duration of "0". You can not play this second file.
my proposal
change:

...
var loadBuffer = function(obj, url) {
// check if the buffer has already been cached
if (url in cache) {
loadSound(obj);
} else {
// load the buffer from the URL
var xhr = new XMLHttpRequest();
...

to:
loadSound(obj, cache[url]);

Doesn't seem to work with require.js

to fix it I changed line 11119 from define('Howler', function() { to define([], function() {

I take it the dependency on 'Howler' is a throw back to multiple modules being loaded in the same file. issue #34

Minification. What is you strategy?

Hello,
I would like to submit a pull request for enhancement. With this I would ideally send the request with the minified code. What system, command, options are you using to minify the code?

Thanks,
Ross

Howler crashes Chrome when playing many sounds with buffer:true

There is an issue in Chrome, where many audio tags crash the Chrome renderer process (https://code.google.com/p/chromium/issues/detail?id=156331 , it is marked as fixed, but the crashes still happens, see my comment there).

To reproduce the crash in a somewhat realistic use case:

  setInterval(function() {
    new Howl({ urls: ["http://assets.sauspiel.de/sounds/effects/applaus-61-90Punkte-1.mp3"], buffer:true }).volume(1).play()
  }, 1000);

In Mac OS X's Activity Monitor you can follow the Thread count of the Chrome renderer process going up and never down. At about 400 threads the renderer crashes (without leaving crash reports, of course) after playing about 200 sounds.

In contrast if one uses HTML5 Audio without Howler, e.g.

  setInterval(function() {
    var audio = new Audio("http://assets.sauspiel.de/sounds/effects/applaus-61-90Punkte-1.mp3");
    audio.play();
  }, 1000);

The process' thread count still goes up continually, but get's down again when a garbage collect is triggered (as can be seen in the Web Inspector Timeline), making a crash less likely at least.

HTML5 first as option

Hi, I'd like to assign self._webAudio to false when constructing Howl object.

The reason is that html5 audio is CORS tolerant and I'd like to play sounds from other domains without making an XHR request every time.

Add a "loaded" property

It could be useful to have a loaded property so that we don't try to play the sound before is it set to true

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.