Low Latency & Polyphonic Audio in PhoneGap

UPDATE 10/07/2013: This plugin has been updated to support PhoneGap 3.0 method signatures and command line interface.  You can access the latest at: https://github.com/triceam/LowLatencyAudio


If you have ever tried to develop any kind of application using HTML5 audio that is widely supported, then you have likely pulled all the hair from your head. In its current state, HTML5 Audio is wrought with issues… lack of consistent codec support across browsers & operating systems, no polyphony (a single audio clip can not be played on top of itself), and lack of concurrency (on some of the leading mobile browsers you can only play one audio file at a time, if at all). Even the leading HTML5 games for desktop browsers don’t even use HTML5 audio (they use Flash). Don’t believe me? Just take a look at Angry Birds, Cut the Rope, or Bejeweled in a proxy/resource monitor…

The Problem

You want fast & responsive audio for your mobile applications.   This is especially the case for multimedia intensive and/or gaming applications.

HTML5 audio is not *yet* ready for prime-time. There are some great libraries like SoundManager, which can help you try to use HTML5 audio with a failover to Flash, but you are still limited without polyphony or concurrency. In desktop browsers, Flash fixes these issues, and Flash is still vastly superior to HTML5 for audio programming.

If you are building mobile applications, you can have great audio capabilities by developing apps with AIR. However, what if you aren’t using AIR? In native applications, you can access the underlying audio APIs and have complete control.

If you are developing mobile applications with PhoneGap, you can use the Media class, which works great. If you want polyphony, then you will have to do some work managing audio files for yourself, which can get tricky. You can also write native plugins that integrate with the audio APIs for the native operating systems, which is what i will be covering in this post.

Before continuing further, let’s take a minute to understand what I am talking about when I refer to concurrency, polyphony, and low-latency…

Concurrency

Concurrency in audio programming refers to the ability to play multiple audio resources simultaneously.  HTML5 in most mobile devices does not support this – not in iOS, not in Android.  In fact, HTML5 Audio does not work *at all* in Android 2.x and earlier.  Native APIs do support this, and so does PhoneGap’s Media class, which is based on Android MediaPlayer and iOS AVAudioPlayer.

Polyphony

Producing many sounds simultaneously; many-voiced.

In this case, polyphony is the production of multiple sounds simultaneously (I’m not referring to the concept of polyphany in music theory). In describing concurrency, I refered to the ability to play 2 separate sounds at the same time, where with polyphony I refer to the ability to play the same sound “on top” of itself. There can be multiple “voices” of the same sound. In the most literal of definitions concurrency could be considered a part of polyphony, and polyphony a part of concurrency… Hopefully you get what I’m trying to say. In its current state, HTML5 audio supports neither concurrency or polyphony.  The PhoneGap Media class does not support polyphony, however you can probably manage multiple media instances via javascript to achieve polyphonic behavior – this requires additional work in the JavaScript side of things to juggle resources.

Low Latency

Low latency refers to “human-unnoticeable delays between an input being processed and the corresponding output providing real time characteristics” according to wikipedia.   In this case, I refer to low latency audio, meaning that there is an imperceptible delay between when a sound is triggered, and when it actually plays.   This means that sounds will play when expected, not after a wait.   This means a bouncing ball sound should be heard as you see the ball bouncing on the screen.   Not after it has already bounced.

In HTML5, you can auto-load a sound so that it is ready when you need it, but don’t expect to play more than one at a time.  With the PhoneGap Media class, the audio file isn’t actually requested until you invoke “play”.   This occurs inside “startPlaying” on Android, and “play” on iOS.   What I wanted was a way to preload the audio so that it is immediately ready for use at the time it is needed.

The Solution

PhoneGap makes it really easy to build natively installed applications using a familiar paradim: HTML & JavaScript.   Luckily, PhoneGap also allows you to tie into native code using the native plugin model.   This enables you to write your own native code and expose that code to your PhoneGap application via a JavaScript interface… and that is exactly what I did to enable low-latency, concurrent, and polyphonic audio in a PhoneGap experience.

I created PhoneGap native plugins for Android and iOS that allow you to preload audio, and playback that audio quickly, with a very simple to use API.   I’ll get into details how this works further in the post, but you can get a pretty good idea of what I mean by viewing the following two videos.

The first is a basic “Drum Machine”.  You just tap the pads to play an audio sample.

The second is a simple user interface that allows you to layer lots of complex audio, mimicking scenarios that may occur within a video gaming context.

Assets used in this example from freesound.org.  See README for specific links & attribution.

You may have noticed a slight delay in this second video between the tap and the actual sounds.  This is because I am using “touchStart” events in the first example, and just using a normal <a href=”javascript:foo()”> link in the second.  There is always a delay for “normal” links in all multi-touch devices/environments because there has to be time for the device to detect a gesture event. You can bypass this delay in mobile web browsers by using touch events for all input.

Side Note:  I have also noticed that touch events are slightly slower to be recognized on Android devices than iOS.   My assumption is that this is related to specific device capabilities – this is more noticeable on the Amazon Kindle Fire than the Motorola Atrix.   The delay does not appear to be a delay in the actual audio playback.

How it works

The native plugins expose a very simple API for hooking into native Audio capabilities.   The basic usage is:

  • Preload the audio asset
  • Play the audio asset
  • When done, unload the audio asset to conserve resources

The basic components of a PhoneGap native plugin are:

  • A JavaScript interface
  • Corresponding Native Code classes
You can learn more about getting started with native plugins on the PhoneGap wiki.

Let’s start by examining the native plugin’s JavaScript API.  You can see that it just hands off the JavaScript calls to the native layer via PhoneGap:

var PGLowLatencyAudio = {

preloadFX: function ( id, assetPath, success, fail) {
    return PhoneGap.exec(success, fail, "PGLowLatencyAudio", "preloadFX", [id, assetPath]);
},

preloadAudio: function ( id, assetPath, voices, success, fail) {
    return PhoneGap.exec(success, fail, "PGLowLatencyAudio", "preloadAudio", [id, assetPath, voices]);
},

play: function (id, success, fail) {
    return PhoneGap.exec(success, fail, "PGLowLatencyAudio", "play", [id]);
},

stop: function (id, success, fail) {
    return PhoneGap.exec(success, fail, "PGLowLatencyAudio", "stop", [id]);
},

loop: function (id, success, fail) {
    return PhoneGap.exec(success, fail, "PGLowLatencyAudio", "loop", [id]);
},

unload: function (id, success, fail) {
    return PhoneGap.exec(success, fail, "PGLowLatencyAudio", "unload", [id]);
}
};

You would invoke the native functionality by first preloading the audio files BEFORE you need them:

PGLowLatencyAudio.preloadAudio('background', 'assets/background.mp3', 1);
PGLowLatencyAudio.preloadFX('explosion', 'assets/explosion.mp3');
PGLowLatencyAudio.preloadFX('machinegun', 'assets/machine gun.mp3');
PGLowLatencyAudio.preloadFX('missilestrike', 'assets/missle strike.mp3');
PGLowLatencyAudio.preloadAudio('thunder', 'assets/thunder.mp3', 1);

When you need to play an effect you just call either the play or loop functions, passing in the unique sound ID:

PGLowLatencyAudio.play('background');
PGLowLatencyAudio.play('explosion');
PGLowLatencyAudio.play('machinegun');

Next, let’s examine some intricacies of the plugin…   One thing to keep in mind is that I do not have callbacks to the phonegap app once a media asset is loaded.   If you need “loaded” callbacks, you will need to add those yourself.


preloadFX: function ( id, assetPath, success, fail)
params:

id – string unique ID for the audio file
assetPath – the relative path to the audio asset within the www directory
success – success callback function
fail – error/fail callback function

detail:

The preloadFX function loads an audio file into memory.  These are lower-level audio methods and have minimal overhead. These assets should be short (less than 5 seconds). These assets are fully concurrent and polyphonic.

On Android, assets that are loaded using preloadFX are managed/played using the Android SoundPool class. Sound files longer than 5 seconds may have errors including (not playing, clipped content, not looping) – all will fail silently on the device (debug output will be visible if connected to debugger).

On iOS, assets that are loaded using preloadFX are managed/played using System Sound Services from the AudioToolbox framework. Audio loaded using this function is played using AudioServicesPlaySystemSound. These assets should be short, and are not intended to be looped or stopped.


preloadAudio: function ( id, assetPath, voices, success, fail)
params:

id – string unique ID for the audio file
assetPath – the relative path to the audio asset within the www directory
voicesthe number of polyphonic voices available
success – success callback function
fail – error/fail callback function

detail:

The preloadAudio function loads an audio file into memory.  These have more overhead than assets laoded via preloadFX, and can be looped/stopped. By default, there is a single “voice” – only one instance that will be stopped & restarted when you hit play. If there are multiple voices (number greater than 0), it will cycle through voices to play overlapping audio.  You must specify multiple voices to have polyphonic audio – keep in mind, this takes up more device resources.

On Android, assets that are loaded using preloadAudio are managed/played using the Android MediaPlayer.

On iOS, assets that are loaded using preloadAudio are managed/played using AVAudioPlayer.


play: function (id, success, fail)
params:

id – string unique ID for the audio file
success – success callback function
fail – error/fail callback function

detail:

Plays an audio asset.  You only need to pass the audio ID, and the native plugin will determine the type of asset and play it.


loop: function (id, success, fail)
params:

id – string unique ID for the audio file
success – success callback function
fail – error/fail callback function

detail:

Loops an audio asset infinitely.  On iOS, this only works for assets loaded via preloadAudio.  This works for all asset types for Android, however it is recommended to keep usage consistent between platforms.


stop: function (id, success, fail)
params:

id – string unique ID for the audio file
success – success callback function
fail – error/fail callback function

detail:

Stops an audio file.  On iOS, this only works for assets loaded via preloadAudio.  This works for all asset types for Android, however it is recommended to keep usage consistent between platforms.

unload: function (id, success, fail)
params:

id – string unique ID for the audio file
success – success callback function
fail – error/fail callback function

detail:

Unloads an audio file from memory.   DO NOT FORGET THIS!  Otherwise, you will cause memory leaks.


I’m not just doing this for myself, the audio is completely open source for you to take advantage of as well.  You can download the full code, as well as all examples from github at github:

UPDATE 10/07/2013: This plugin has been updated to support PhoneGap 3.0 method signatures and command line interface.  You can access the latest at: https://github.com/triceam/LowLatencyAudio

Enjoy!

  • http://webdev.vdzr.ru Alexbeep

    Any glue for audio stream playing using this plugin?

  • RedRooster

    Hi,

    I could not get your plugin to make any sound but I came up with a hacky solution that is VERY simple to implement.

    var mediaUrlArray=[];
    var mediaArray=[];

    function addMediaUrl(url) {
    mediaUrlArray.push(url);
    mediaArray.push( new Media(url, onSuccessPlaySound, onErrorPlaySound) );
    var length= mediaArray.length;
    // HACK!!: pressing play already loads it
    mediaArray[length-1].play();
    mediaArray[length-1].stop();
    }

    function playMyAudio(url) {
    var idx=mediaUrlArray.indexOf(url);
    // try non-blocking
    setTimeout(function(){mediaArray[idx].play();},0);
    }

    you just create the media-object, fill it up, press play, press stop, it continues loading and is there for you when you need it. No Callbacks involved and I haven’t tested it with a large number of sounds. But so far it’s super-responsive.

    Thanks for the IOS ‘play()’-hint.

    Cheers

    • http://www.tricedesigns.com Andrew

      Were you getting any error messages? You should just have to add the files, and add the Native Plugin mapping, and it should “just work”. If you don’t add the mapping, it will not work. This plugin is also designed to use local assets. If you are loading a remote asset, it won’t work without modification of the native plugin code.

  • RedRooster

    I didn’t get any error. But my debugginbg skills in xCode and Objective-C are non existent. I tried providing fail and succes. But nothing came back. What i did was:

    created a new xcode project.
    created www by building.
    copied the example files of drum machine demo to www.
    copied the plugin js to www

    copied the h and m files to plugins as group

    edited phonegap.plist as described above to activete the plugin.

    then I had to turn off ARC somewhere in Xcode to get rid of warnings.

    Did I forget sth?

  • http://www.tricedesigns.com Andrew

    Did you also add the PGLowLatencyAudio.js file to the www directory? That’s the only thing i see missing from your steps.

  • http://www.tricedesigns.com Andrew

    Oh wait… read it too fast. You have it there. those are the only steps you need. Were you changing any of the files, or using as-is?

  • RedRooster

    First I tried as is. Then I started fiddeling. I have xCode 4.2 on snow leopard , an iPad2 IOS 5.0.1 and the emulators were set to IOS 5.0 as well.

  • http://www.mariosalvucci.com Muccio

    Great Work!
    Do u think is possible to alter the code to change the volume programmatically from the script?

    • http://www.tricedesigns.com Andrew

      It is possible to adjust sound volume via avauioplayer on iOS and via mediaplayer on Android.

  • frederick

    Hi,

    is it possible to force the audio to play even if the app is sleeping (iphone is sleeping or user has switched to other application) ?

    thanks

    • http://www.tricedesigns.com Andrew

      No, this is not possible on iOS. iOS does not allow background threads (with the exception of location specific events), and those would have to be done in native code, not handled by JS in the web view.

  • frederick

    Thanks Andrew

    Yes, i know that iOS does not allow background threads with JS.
    But is it possible with this plugin. If not, is it easy to modify this plugin to play audio in background ?

    thanks

    • http://www.tricedesigns.com Andrew

      Since this uses AVAudioPlayer, it could use background audio, however it won’t be able to necessarily respond to application events… just play an audio file/stream.

  • Pingback: Andrew Trice » Blog Archive » PhoneGap Native Plugins()

  • http://afriapps.co.za Herman

    I call the PGLowLatencyAudio.play(src, playSuccess, playError); function and the success function gets called but no sound plays. its mp3’s ? and on iPhone

    • http://www.tricedesigns.com Andrew

      Did you use preloadAudio, or preloadAsset to load the mp3 file? Did you get a success callback when preloading the content?

  • http://blog.topheman.com Tophe

    In a game with sound effects (something like “explosion.wav” when dropping bombs), when do you unload the sounds to release memory (because you still need the resource) ?

    • http://www.tricedesigns.com Andrew

      Hi Tophe,
      You unload the sound when you no longer need it. My thinking was that you load all sounds for a stage/level, and once that stage/level is over, you unload them before loading assets for the next level. It is subjective on a case by case basis. You dont need to unload/reload every time you want to play the sound.

  • John

    Hello Andrew,

    Thanks so much for solving this problem.

    I’m doing what amounts to a hello world with PGLowLatencyAudio. I’m using the 1.5 version of PhoneGap/Cordova so had to change some names to get it to compile and run, but it seems to be working well now. However, I can only get it to actually play sounds in the emulator. I can’t get the iPad II to make even so much as a peep. There seem to be no exceptions or obvious user errors involved, so I wonder what might be going wrong. Any ideas?

    Thanks Kindly,

    John

  • John

    Haha.

    Nevermind, it’s working great.

    Did I mention something about no obvious user errors? Just disregard that.

    Anyway, I really appreciate your work. Let me know if you need someone to help maintain it.

    Thanks Again,

    John

  • Dani Go Sa

    Hi Andrew,

    just tried to execute your code in a fresh Cordova 1.5.0 installation. I’m having this Preprocessor error:
    ‘PhoneGap/PGPlugin.h’ file not found.
    I can play files using directly Cordova Media object but not byt using your plugin because it doesn’t compile. I’m sure it’s a Cordova issue because I have this file under PhoneGapLib directory in my Documents, but somehow it’s not linked properly. Any idea?

    Thanks.

  • Dani Go Sa

    Sorry Andrew, about the previous comment it’s not true I got that file under Documents, it was detected by Spotlight from older installations of PhoneGap in my TimeMachine backups… so the question is: is your code compatible with Cordova 1.5.0? I can see that header on new Cordova framework, the one that is automatically included when project’s set up.

    Thanx.

    • http://www.tricedesigns.com Andrew

      Dani,
      In PhoneGap 1.5, the naming conventions changed. The PGPlugin class is now CDVPlugin and PGPluginResult is now CDVPluginResult, and so forth… I have not had a chance to update the plugin code yet, but I know that others have gotten it working (see John’s) comments. You should only need to change the references from the old naming to the new naming (in the native code). I hope to update this to the new naming conventions soon, but I haven’t had a chance yet.

      John,
      Great! Glad you got it working. Feel free to share anything that you build with it! I always like to see what other people are able to create.

  • John

    For the Cordova name change:

    I don’t think I had to change anything in the PGLowLatencyAudioAsset.h or .m files, but the two PGLowLatencyAudio.h and .m files needed a bit of tweaking as well as the .js file.

    In each of the following files, change all instances of the PG or PhoneGap references to their corresponding Cordova ones.

    PGLowLatencyAudio.h
    change #import
    to #import

    PGLowLatencyAudio.m
    change PGPluginResult* pluginResult;
    to CDVPluginResult* pluginResult;

    PGLowLatencyAudio .js
    change PhoneGap.exex
    to Cordova.exec

    Hope that helps.

    John

  • John

    … trying again:

    PGLowLatencyAudio.h
    change
    to

    In the imports.

  • John

    … aye:

    PGLowLatencyAudio.h
    change PhoneGap/PGPlugin.h
    to Cordova/CDVPlugin.h

    • http://www.tricedesigns.com Andrew

      Thanks John!

  • http://sepans.com/sp sepans

    I have added volume control and server side loading to work for LowLatency library for android (I am slow with objective-c but I am going to do iOS as well) . I can integrate it since it was a requested feature in your blog.
    Best,

  • http://exarbor.com Ewoud van den Boom

    Implementation of Cordova (vs PhoneGap) name change: https://github.com/ewoudj/phonegap-plugins/tree/master/iPhone/LowLatencyAudio

    • http://www.tricedesigns.com Andrew

      Thanks Ewoud!

  • mkc

    I hate to be that guy….but can anyone help with this error?

    [INFO] Error in success callback: NetworkStatus0 = ReferenceError: Can’t find variable: Cordova

    My javascript seems simple enough:

    function onDeviceReady()
    {
    PGLowLatencyAudio.preloadAudio(‘home’, ‘sound/home.mp3′, 1, successHandler, errorHandler);
    playingSound();
    run();
    }

    function playingSound(){
    PGLowLatencyAudio.play(‘home’);
    }

    function successHandler (result) {
    alert( result );
    }

    function errorHandler (error) {
    alert( error );
    }

    I was using old phonegap 1.3 I couldn’t get the plugin going, now upgraded to 1.6 and made the changes to the plugin files shown on github for cordova and no luck. Any ideas would be great.

    • http://www.tricedesigns.com Andrew

      In PhoneGap 1.6, the PhoneGap class is now “cordova”. Just update the plugin to reference “cordova.exec”.

  • Edwin

    Hi Andrew,

    I just figured out to get the plugin working with cordova 1.5… But since I’ve upgraded to cordova 1.6 it doesn’t seem to work anymore :(

    Can you or anyone help me please?

    • http://www.tricedesigns.com Andrew

      The “Cordova” class is now named “cordova”. Just switch to a lowercase “c” for “cordova” inside the plugin, and it should work.

  • Weimar

    I’m having trouble with setting the volume of sounds via the volume slider on iPad / iPhone. The sounds play at max volume, no matter what I do. Switching the mute button does work however.

    The volume buttons do work with the Cordova 1.6.0 Media object, but I’d like to use PGLowLatencyAudio as it’s more responsive.

    Any ideas how I can control the volume for PGLowLatencyAudio objects via the volume up/down button on the iPad / iPhone?

    • http://www.tricedesigns.com Andrew

      Use preloadAudio instead of preloadFx. The preloadFx function uses system audio, which has different volume settings on iOS. The preloadAudio function internally uses the same media classes as the PhoneGap Media class, and will behave the same way (and also will allow you to preload and have polyphony).

  • Edwin

    Andrew, thanks for your answer.

    But it doesn’t seem to work for me…
    I think I,ve adjusted all there is to adjust.
    It’s still very silent on this part of the planet.

    Can’t seem to figure it out.

    • http://www.tricedesigns.com Andrew

      Are you able to trap any JavaScript errors using a try/catch block? Or, do you see any other error messages? It should work.

  • John

    Hi,

    I had this working, but I’m now having trouble getting the audio to play in my iOS/Cordova app. I’m just throwing this out there to see if this strange scenario sounds familiar to anyone:

    1. The app is slient when run on iPad hardware via the speakers. No errors. But no sound.

    2. The audio works fine when using headphones. No errors.

    3. The audio works fine when running in the emulator. However, I get these errors:

    Error loading /System/Library/Extensions/AppleHDA.kext/Contents/PlugIns/AppleHDAHALPlugIn.bundle/Contents/MacOS/AppleHDAHALPlugIn: dlopen(/System/Library/Extensions/AppleHDA.kext/Contents/PlugIns/AppleHDAHALPlugIn.bundle/Contents/MacOS/AppleHDAHALPlugIn, 262): Symbol not found: ___CFObjCIsCollectable
    Referenced from: /System/Library/Frameworks/Security.framework/Versions/A/Security
    Expected in: /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk/System/Library/Frameworks

    Anyone know why the speakers would be mute and the headphones work? Or why this would only fail on hardware? Same problem observed on a variety of ipads.

    Thanks!

    John

  • John

    Lesson learned: when things get weird (suddenly no sound for no apparent reason), clean the project, throw out the app on the iPad, rebuild, turn up the volume.

    John

  • http://www.edwinvriens.nl Edwin

    Rebuild the app with cordova 1.6.1…
    Cleaned the whole thing… e voila!
    We’re rocking again.

    Did some trail and error.
    I found out an iFrame was frustrating the whole thing?!
    Made a workaround. And off we go…

    Grts Edwin

  • Siddiq

    Has anyone used this plugin with ‘phonegap build’ i.e. http://build.phonegap.com
    service?

    • http://www.tricedesigns.com Andrew

      I have not… you will likely need to update the syntax for the latest version of PhoneGap. This one still uses the PhoneGap naming conventions, where the latest versions use “Cordova” naming conventions.

  • David Denker

    Hey Andrew,

    I’m trying to get your Plugin working for Cordova 1.5 Android
    When I try to preload a sound oder play a sound. The Plugins outputs “A reference does not exist for the specified audio id.”
    Do you or someone else here know what to do?
    Thank you very much!
    David

    • http://www.tricedesigns.com Andrew

      Does that happen when you try to play a sound, or preload a sound? That sounds like an error that would happen if you tried to play a sound that isn’t loaded.

  • David Denker

    It happes booth times. I’m 100% sure that the Paths und Names are correct. I already tried .ogg instead of .mp3. But I had no success.

    • http://www.tricedesigns.com Andrew

      When you preload the asset, do you get a success callback? Something weird has to be happening. I double checked the code, and you would only get that message if there isn’t a preloaded audio asset for the given ID. Can you double check and make sure the ID is the same as the one that is preloaded? ( They are case sensitive.)

    • http://www.tricedesigns.com Andrew

      Also, what platform? Android or iOS?

  • David Denker

    Is use Android. No, the message appears when I preload the asset and also when ich try to play the asset. The JS Code ist the same like on my iOS Version and iOS ist working perfect.
    PGLowLatencyAudio.preloadAudio(‘bgsound’,’./data/noise.mp3′, successHandler, errorHandler);
    PGLowLatencyAudio.loop(‘bgsound’, successHandler, errorHandler);

    • http://www.tricedesigns.com Andrew

      Ahh, I think its a path issue. Make sure your sound files are within the www folder in the eclipse project. If the file is inside assets/www/data/noise.mp3 folder in Eclipse, then use the the following JS:

      PGLowLatencyAudio.preloadAudio(‘bgsound’,’data/noise.mp3′, successHandler, errorHandler);

      Don’t put the “./” in there. It is expecting the sound files to be a child directory of the “www” folder, and you don’t need the path prefix.

      • http://www.tricedesigns.com Andrew

        Also, make sure your quotes are correct… It looks like wordpress changed the quotes on my last comment.

  • David Denker

    I’m using cordova 1.5 are there some changes I might have missed by using the plugin with cordova instead of the older phonegap version? I remeber in iOS I had to change the classname PGPlugin to CSVPlugin are there similar changes in the android version. Sorry, I’m not very familiar with java

    • http://www.tricedesigns.com Andrew

      It is a file path issue. Take a look at my last comment: Make sure your sound files are within the www folder in the eclipse project. If the file is inside assets/www/data/noise.mp3 folder in Eclipse, then use the the following JS:

      PGLowLatencyAudio.preloadAudio(‘bgsound’,’data/noise.mp3', successHandler, errorHandler);

      Don’t put the “./” in there. It is expecting the sound files to be a child directory of the “www” folder (they have to be a child of “www”), and don’t use the “./” path prefix.

  • David Denker

    Makes sense, but i had no success. The Same ERROR appears. I’m using “./” also for all images and it works.

    The Plugin is located in src.com.cordova

    • http://www.tricedesigns.com Andrew

      The plugin is working correctly, otherwise you wouldn’t get the error message that you have. Do not use the “./”. The plugin does use the browser’s location. It appends the actual file system location in native code so that it can properly reference the media file. Adding “./” will break the file system reference.

      • http://www.tricedesigns.com Andrew

        Meant: “The plugin does NOT user the browser’s location.

  • David

    So the .java files have to be located in the www folder? :-)

    • http://www.tricedesigns.com Andrew

      No. Just the media files.

  • David Denker

    Ahhhhh … got it working.
    The Problem was:
    I had a missing parameter by calling preloadAudio. Aufer the location has to be an integer. I found that in your examples.
    So this ist the correct code:
    PGLowLatencyAudio.preloadAudio(‘bgsound’,’data/noise.mp3′,1, successHandler, errorHandler);

    Andrew, thank you very very much for your help :-)

  • woeiren

    thanks,it is great.
    I’ve use it in my case,But still some problems.
    In esclipse run Adroid class,it connot find PhoneGap.exec at load index.html ,but go back index.html and other page works well . I use cordova 1.6.0,and change “PhoneGap.exec” to “cordova” or “Cordova” didn’t fix the problem.

  • Murray Macdonald

    I got it running with android 4.03 and cordova-1.7.0.js after changing a few paths.

    Heads up, the audio paths get automatically prepended with www/ as you will notice in line 71 of PGLowLatencyAudio.java To keep my www/ folder clean I put my assets in www/audio/ and then pre-loaded them using:

    PGLowLatencyAudio.preloadFX(‘beep’,’audio/beep.mp3′, 3, audioSuccess, audioFailure);

    then played them with:

    PGLowLatencyAudio.play(‘beep’);

    When do you suggest to the use of PGLowLatencyAudio.stop(‘beep’); to unload sounds from memory? If I am going to reuse the sound without latency I want to keep it loaded, right? When exactly should I .stop it to avoid the memory leaks you mentioned? I thought when the app ends the memory is automatically reclaimed, right? Or does my non-looping sound need to be stopped after each use?

    I am also having caching issues. Once a sound is loaded, it appears to get cached. If I replace the MP3 with another using the same name the old one remains cached. Any idea how to convince the ‘browser’ to ignore the sound file it has cached? I tried appending ?=timestamp but it doesn’t work as there is no web server managing the cache. Is there any way to clear the cached sounds?

    Thanks!

    • http://www.tricedesigns.com Andrew

      Make sure to unload it by calling the “unload” method for the specified id. It gets cached in the native layer, so don’t assume that the web view lets go of it.

  • Murray Macdonald

    Correction: There is a mistake in my previous posting…

    To load sounds I used:

    PGLowLatencyAudio.preloadAudio(‘beep’, ‘audio/beep.mp3′, 6, audioSuccess, audioFailure);

    NOT

    PGLowLatencyAudio.preloadFX

  • Murray Macdonald

    I got it running with android 4.03 and cordova-1.7.0.js after changing a few paths.

    Heads up, the audio paths get automatically prepended with www/ as you will notice in line 71 of PGLowLatencyAudio.java To keep my www/ folder clean I put my assets in www/audio/ and then pre-loaded them using:

    PGLowLatencyAudio.preloadAudio(‘beep’, ‘audio/beep.mp3′, 6, audioSuccess, audioFailure);

    then played them with:

    PGLowLatencyAudio.play(‘beep’);

    When do you suggest the use of PGLowLatencyAudio.stop(‘beep’); to unload sounds from memory? If I am going to reuse the sound without latency I want to keep it loaded, right? When exactly should I .stop it to avoid the memory leaks you mentioned? I thought when the app ends the memory is automatically reclaimed, right? Or does my non-looping short sound need to be stopped explicitly after each use?

    I am also having caching issues. Once a sound is loaded, it appears to get cached. If I replace the MP3 with another using the same name the old one remains cached, even if I quit the app and build clean. Any idea how to convince it to ignore the sound file it has cached?

    Thanks!

  • John

    Hi Andrew,
    Compliments for your great sounds library!
    A question: there is a license for the library?
    Can it be used in a commercial software?
    Thank you.
    John

    • http://www.tricedesigns.com Andrew

      Yes, you can use it in commercial software. It uses a modified MIT license, which you can read in the README file at: https://github.com/phonegap/phonegap-plugins/tree/master/iOS/LowLatencyAudio

      • Near Privman

        Hi Andrew,

        First of all thank you for this very useful plugin. It is critical to the user experience in our game.

        However, your modified version of the MIT license doesn’t in fact provide any sort of permission, and specifically doesn’t provide a license for commercial use. In the README file you only include the last paragraph of the original MIT license, which disclaims any warranty, but not the first paragraph which provides the permission to make use of the code.

        Since our lawyers are starting to get into the open source licenses we use, this poses a problem for us. Is there any way you will be willing to consider amending the license in some way to allow commercial use?

        Many many thanks,
        Near

        • http://www.tricedesigns.com Andrew

          Feel free to use it however you want. Email me at atrice@adobe.com if you need something more specific.

  • http://sepans.com sepans

    added volume control and loading sound assets from server to android here:
    https://github.com/sepans/phonegap-plugins/tree/master/Android/LowLatencyAudio

    • Will

      Hi Sepans. Your volume additions is just what I was hoping for! But I’m pretty new to phonegap and I seem to behainvg some newb trouble i tried adding this line in the drum machine demo: PGLowLatencyAudio.volume(‘snare’, 0.5); just before the “play” call, but it doesnt seem to be doing anything different. Am I calling it incorrectly?

      thanks

      • Will

        Oh, also I’ts an android app running 2.2+

  • Carl

    Hi Andrew,
    I made a simple test with Phonegap on an iPad 3 using some .mp3 sounds played simultaneously (polyphony) and the library works correctly. However, if I simply convert the same files in AAC (.m4a), then the sounds are not played, only one is audible.
    Does the library supports AAC? Are there some settings that I can change to support AAC files?
    Thank you.

    • http://www.tricedesigns.com Andrew

      If you are using the preloadAudio function, it uses the CordAudio AVAudioPlayer class, which handles file formats & audio files. As long as it is supported by AVAudioPlayer, it should be fine.

      You might also want to check your file encoding, I found this under “Best Practices for iOS Audio” in the iOS Multimedia programming guide:

      For AAC, MP3, and ALAC (Apple Lossless) audio, decoding can take place using hardware-assisted codecs. While efficient, this is limited to one audio stream at a time. If you need to play multiple sounds simultaneously, store those sounds using the IMA4 (compressed) or linear PCM (uncompressed) format.

  • originalp

    We’ve been trying to use your fantastic tool to get our Cordova-based game to work with simultaneous sound effects like in your demos.
    We’ve tried to make them work but can’t. We have three questions:
    1. We couldn’t find the ARC to set it as NO under de “User-defined” settings group of our project. How can we know for sure it’s been removed to retain/release statements?
    2. Does your tool work when previewing on a regular desktop browser or only running on the simulator?
    3. Does your tool work with the latest Cordova 1.9?

    Thank you for your response, Andrew! :)

    • http://www.tricedesigns.com Andrew

      1) I only tested in a non-ARC XCode project. I don’t believe ARC support for phonegap projects is complete yet, so you can only use it in ARC projects.
      2) No, it uses native Objective C code, so you must use the iOS simulator, or a device.
      3) It should, but will need to be updated to the new namespace/class naming. This uses CordovaPlugin instead of the old PGPlugin class (or something close – I don’t remember the exact naming without looking it up).

  • Sergey

    Hi, andrew. Looks like an amazing job done here.

    Is there a way to find out when play() has finished playing? I thought it should be successcallback, but as it turned out it fires just right after strating playing…

    If that does matter – I have 2-3 seconds files. And I need to implement some logic right after playing. Cordova Media element can do that, but it delays 0.3-0.7 seconds to start playing so I’m looking for solution here.

    thank you in advance for any ideas.

    btw – import directive in java file shold be changed to import org.apache.cordova.api.PluginResult.Status;

    • http://www.tricedesigns.com Andrew

      Currently, there is no monitoring built into the plugin to find out when a sound has finished playing. You would need to add this logic in the native plugin (in native code). If you want a quick fix, you can immediately play, then stop a file with the Cordova Media class, and it should preload the sound for you, for future use.

  • Sergey

    Hi, Andrew. Thank you for clearing out.

    I guess it should be new logic then. It should take some time cause I don’t have much expiriens on writing native code of Android of iOS.
    I don’t think I can start and stop a dozen items at a time. I’ve noticed that I can’t initialize and not release too many instances of Media objects (at least on Android) without risking to run out of allowed number instances and start getting errors. But anyway thank you for answer.

  • http://www.skylightthailand.com Luca

    Hi Andrew, thanks for the plugin it works great! I have just one problem: in the app page I have 5 buttons with the sounds and 3 buttons that are linked to others pages of the application. The sounds buttons works, while the buttons with links have stopped working after I added the links to the plugin in the page. Do you have any solution for this? Thanks

    • http://www.tricedesigns.com Andrew

      Hi Luca, It shouldn’t have any issue at all with other links on the page. Any code you can share?

  • http://www.skylightthailand.com Luca

    Hi Andrew, I solved the previous problem about the links. Can you suggest me a solution for this: the app that I developing consist in 4 pages with different sounds in every page. I read about the unload function: can I add this function to the button that link back to the home page of the app? Or when you exit the page the sounds unload automatically? Thanks

    • http://www.tricedesigns.com Andrew

      Ignore that last comment, I just saw this respond. Once sounds are loaded in memory, they are loaded in memory on the native layer. If you change pages, the sounds will still be in memory in the native code, and you can still play them. They do not automatically unload.

  • Shafi

    HI Andrew,
    Gr8 work
    i need to know is there any way to check an audio with a specific id already playing ..

    Thanks You

    • http://www.tricedesigns.com Andrew

      There is no current way to see if audio with a specific id is already playing. This would need to be added to the native code layer.

  • Shafi

    Hi, Im using multiple mp3 audios simulteneously. but it not seem to be working. Is there anything wrong? Which is the supported format in these cases?

    • http://www.tricedesigns.com Andrew

      The only issue would be file encoding. See this from a previous comment for details:

      You might also want to check your file encoding, I found this under “Best Practices for iOS Audio” in the iOS Multimedia programming guide:
      For AAC, MP3, and ALAC (Apple Lossless) audio, decoding can take place using hardware-assisted codecs. While efficient, this is limited to one audio stream at a time. If you need to play multiple sounds simultaneously, store those sounds using the IMA4 (compressed) or linear PCM (uncompressed) format.

  • Shafi

    Thanks for the update Andrew.. what about android?? Is there any specific encoding format for android. I solved iOS issue using ima4. I need help in android too. Thanks

    • http://www.tricedesigns.com Andrew

      Is it the same sound playing over itself? If so, you need to increase the number of voices when calling preloadAudio. Otherwise, I’m not aware of other Android issues that would prevent multiple files from playing.

    • http://www.tricedesigns.com Andrew

      Is this happing on a particular device/os version, or is it consistent across all distributions?

  • http://www.skylightthailand.com/webdesign Luca

    Thanks Andrew, I solved. If can be useful to others this is how I make the unload button for multiple files:

  • http://none juan

    Hi Andrew.

    I’m following this tutorial for the startup of and android phonegap app.

    http://docs.phonegap.com/en/2.0.0/guide_getting-started_android_index.md.html#Getting%20Started%20with%20Android

    I want to integrate this hello world app with your example drum app, how can i do it?, is it any conflict with your example code and this tutorial?

    any suggestions?

    Thanks!!

    Regards

  • http://none juan

    Thanks for the reply!

    Well i do exactly what you said, but i have a problem. Look at my eclipse

    http://i45.tinypic.com/2eyw4eu.png

    Can you tell me if i have to put com.phonegap classes in my src directory or in my assets/www/com/phonegap folder?

    And im using cordova.js, i have remove the phonegap.js thats is included in you html is this correct?

    well , sorry about my english

    thanks!

  • Shafi

    My game has 4 different videos. One background sound. One explosion, bullet firing and a falling sound. All are different audios in mp3 format. Sound is getting overlapped or sometime not working explosion or other FX sounds in android devices. I tested in Galaxy s and HTC desire. Result is same.

  • http://non AndroidBoy

    Andrew, it will be very helpfull if you or somebody that actually can get this demo example working, post a zip with the full project structure.
    So i can imported in my eclipse and see what i’m doing wrong!

    All the files includes in the project drum machine, is so much to ask??

    THanks!!!!

    • http://www.tricedesigns.com Andrew

      All of the files are available in the Git repository. Back around PhoneGap 1.4 or 1.5, the naming conventions changed, and the plugin code has not been updated. You need to change references from:

      import com.phonegap.api.Plugin;
      import com.phonegap.api.PluginResult;
      import com.phonegap.api.PluginResult.Status;

      To:

      import org.apache.cordova.api.Plugin;
      import org.apache.cordova.api.PluginResult;
      import org.apache.cordova.api.PluginResult.Status;

      Everything should work just fine after that.

  • http://none Nicolas

    Hi Andrew, I spent a lot of money and time for an android project with cordova 2.0.0. Your plugin is crucial for me, whitout it my app is useless :(
    There isn’t nothing similar on the web. Could you just make a simple print page to see the correct structure and the js modifications? You can make happier lots of users. Thanks!

    • http://www.tricedesigns.com Andrew

      Hi Nicolas,
      What is the problem that you are encountering? Is there a specific error message? The Java files go within the src folder (or a child of it), and the JavaScript files go within the www folder (or a child of it). You need to add the JS file to your index.html page, and you also need to make sure you add the entry to the plugins.xml file.

  • http://none Nicolas

    Ok, I have no errors for the moment and this is my structure:

    src/com.phonegap/PGLowLatencyAudio.java
    src/com/phonegap/PGLowLatencyAudioAsset.java
    src/com/phonegap/PGPolyphonicVoice.java

    src/plugins.xml

    assets/www/index.html
    assets/www/PGLowLatencyAudio.js
    assets/www/cordova-2.0.0.js
    assets/www/assets/bongo.mp3 (etc)

    These are my changes in:

    PGLowLatencyAudio.java

    return phonegap.exec for return cordova.exec (6 times)

    PGLowLatencyAudio.js
    import org.apache.cordova.api.Plugin;
    import org.apache.cordova.api.PluginResult;
    import org.apache.cordova.api.PluginResult.Status;

    index.html

    I really need :) and appreciate your help

    • http://www.tricedesigns.com Andrew

      If you aren’t getting any compile-time errors or exceptions from the Java stack, then the error is most likely a JavaScript error, or the native plugin is not being invoked.

      The entry in plugins.xml needs to go in res/xml/plugins.xml. See the “getting started” guide for Native Plugins on Android at: http://docs.phonegap.com/en/2.0.0/guide_plugin-development_android_index.md.html#Developing%20a%20Plugin%20on%20Android

      You can also try to run your app inside of emulate.phonegap.com and use Chrome’s debugging tools to see if you have a JavaScript error – it won’t execute any native code, but will allow you to debug what is happening inside of your application.

  • http://rpmdesignfactory.com John Politowski

    Thank you very much Andrew, I’m really enjoying this plugin. It was able to do a seamless loop, which I could not accomplish with JS or HTML5 audio (there was a fraction of a second gap on each cycle).

    What would it take to continue audio after it goes into the background (my small looped samples)? I saw earlier you said it was possible. I have been pouring over native code for a few days, but I don’t really understand it.

    Cheers,

  • http://rpmdesignfactory.com John Politowski

    Thanks for the fast reply Andrew!

    I have tried that already. I believe there is some native code component as well that has to do with starting the AVAudioPlayer Session but I’m not sure how to implement it. Like this perhaps: http://stackoverflow.com/questions/6948833/avaudiosession-background-mode-problem) . I’m going to keep poking around. If I figure out a solution I’ll post it.

    Thank you so much!

  • Davide Reppucci

    Hi Andrew,

    I think this plugin is really useful.
    The app I’m building uses Cordova 2.0.

    So I’ve added plugin files to my XCode project and then the js file to my HTML.

    Then I try to preload an FX:

    LowLatencyAudio.preloadAudio(‘click’, ‘audio/btn-click.mp3′, 1, successHandler, errorHandler);

    But I have no feedback… the game simply freezes and I don’t know why.

    Can you help me, please?
    I’ll appreciate it!

    Thanks,
    Davide

    • http://www.tricedesigns.com Andrew

      Hi Davide, this sounds more like a JS error than an error with the plugin. Can you try running the code under the emulator at http://emulate.phonegap.com, and use the debugging tools to see if there are any error messages. An error inside of the plugin shouldn’t cause the game to freeze. Either the sound would “not play”, or the entire app would crash and you would get a crash report.

  • http://kubide.es mr_villa

    Hi Andrew, thanks for the great post!

    I have a question regarding to play all of the sounds at the same time, synced so I can mute/unmute some of them to acomplish some kind of “DJ Mixing” effects.
    I think this plugin may not be able to play every sounds at the same time with just a simple call to play(), am I right?

    I’ve accomplished that (not perfectly) in js by doing some async calls to the .play() and starting them to play in a specific moment of the file, can it be done using this plugin?

    Thanks!

    • http://www.tricedesigns.com Andrew

      You should be able to play any of the sounds using the “play()” method. Currently, it just plays from the beginning of each file.

  • Dan

    Hi Andrew,

    You do exactly what I want, but sadly it doesnt work for me. I get two success callbacks both on the preloadFX and on the loop function.

    PGLowLatencyAudio.preloadFX(‘background’, ‘css/sound/chicken_beat.ogg’,function(){console.log(“SUCCESS preloadFX”)},function(err){console.log(“ERROR preLoadFX “+err)});
    PGLowLatencyAudio.loop(‘background’,function(){console.log(“SUCCESS loop”)},function(err){console.log(“ERROR loop “+err)});

    But no sound on the device. And yes, the speakers are turned on :). Somebody has an idea why it`s not working?

  • Dan

    Oh and I forgot to add I also tryed an mp3 file.

  • Dan

    Hey me again,

    looks like I had to use preloadAudio and wait a bit till I can loop it. However, I have a short break after each loop. Please ignore my comments before. Has anyone experienced short delays between loops?

    Thanks a lot for your time.

    • http://www.tricedesigns.com Andrew

      Are you using the “loop” function, or manually calling play again? If you are using loop, there should not be any gaps, instead it might actually be a brief moment of silence in the actual audio file that is only apparent if you loop it. The looping is done using native libraries, so there shouldn’t be any delay.

  • jose

    Hi,

    I really don’t understand the purpose of the “voices” option. If I preload the assets with the number of voices ( http://pastebin.com/QpHdvxLB ) where am I telling them to play all at the same time?

    I pasted some of my code for easy understanding of what I mean…

    Thanks!

    • http://www.tricedesigns.com Andrew

      The voices are used to play a sound on top of itself. If you are just looping a single sound, you just need one voice (per sound file). I do not have any synchronization methods built in there. If have plans to add some simple methods to play several sounds at the same time, but they’re not included yet. You would have to build it yourself for the time being. Are the sounds not all playing, or just not synching as you expect? Currently, the only way is to manually call “play” for each sound, as you have already done.

  • André

    I’m impressed. Really. I have a question a little out of context: How do you connect your iPad in sound system?

    I’m reading your posts more older and are incredible. I’m eager to start using PhoneGap.

    Thank you.

  • James

    This plugin is really helpful for creating a lot of different audio/music apps. The only problem that I have found is that it can’t play two or more sounds exactly at the same time in android 2.3. It can play 2 sounds together but after the first sound is played for about one second, the second sound can be added, but not exactly at the same time (ex. hi hat and snare together). I am using the preloadFX function.

    I also have an android 4 and it works perfectly there, like in the video playing the drum machine, if you play the hi hat and snare or bass drum together, they sound exactly at the same time.

    Is there any way to make this feature to work in android 2? Thanks.

    • http://www.tricedesigns.com Andrew

      It might depend on the device. I have 2 Android 2.x devices that don’t seem to have the issue you are describing. What kind of device are you using?

  • http://www.novamara.com Katharine

    This looks really interesting, thank you. Is there any way – or might there be – to build in dynamic volume/panning of individual sounds? I’m trying to convert a web application made with soundmanager, that uses both extensively on concurrent looped sounds.

    • http://www.tricedesigns.com Andrew

      It could definitely be done, it would just need to be added in the native layer, with a JS interface for the new methods.

  • James

    I have a HTC Glacier android 2.3 and I tried it on an Android 2.2 HTC MyTouch 3G.
    The sounds on the drum machine are played simultaneously only in Android 4 (HTC Amaze).

    Also I was trying to using the plugin on an iphone app, there are 2 plugins, for iPhone and for iOS, I am not sure what the difference is; the PGLowLatencyAudio (for iPhone) didn’t work even by changing Phonegap to Cordova on all the files needed. I am now using LowLatencyAudio plugin (for ios) but the function preloadFX won’t work and there is no an example of this feature.

    It would be great if there’s a code example on how to use the preloadFX in LowLatencyAudio for iOS. Thanks a lot.

    • http://www.tricedesigns.com Andrew

      Use the plugin in the iOS folder. It has been updated for the newer Cordova namespace. Where the old version referenced the “PhoneGap” namespace. There are sample projects that are in the repository that demonstrate how to use it. The latency issue you are talking about may be due to Android handling of touch events (in older versions, it does not always like multiple touch events at the same time).

  • Katharine

    hi Andrew -thanks for replying. I’m trying to make a version (of this: http://www.novamara.window) for iOS (or at least for iPad) – but am working in Xcode with the simulator as I don’t own an iPad. Haven’t tried for Android devices yet.

  • J. Blake Harris

    I’m just realizing I need this plugin – and thanks for the work, btw.

    Will this need any changes for Cordova 2.1.0?

    • http://www.tricedesigns.com Andrew

      If you use the version in the “iOS” folder, it should work without anything special.

  • James

    Thank you for your answer Andrew. I am using the iOS plugin for an iPhone drum app and still can get it to play 2 sounds simultaneously. The drum machine example is only available in the iPhone folder.

    When I use the preloadFX function, for example:
    “…javascript:LowLatencyAudio.preloadFX(‘kick’, ‘assets/kick.mp3′, successHandler, errorHandler…” and I push the instrument/button, a message appears that says:

    “index.html
    content has been requested”

    if I push it again it will say:
    “index.html
    a reference to the audio ID already exists”

    I’m not sure if I am doing something wrong, but I keep trying a lot of different ways with no success. Thank you for your help.

  • Davide Reppucci

    Hi Andrew,

    I finally tried the phonegap emulator.
    Well, when I call:

    LowLatencyAudio.preloadFX(‘click’, ‘audio/btn-click.mp3′, successHandler, errorHandler);

    I have this error:

    Uncaught TypeError: Object # has no method ‘exec’

    And it sounds a bit strange to me, because I have your plugin before my call.
    Here it is the plugin code, copied&pasted as it is:

    var LowLatencyAudio = {
    preloadFX: function ( id, assetPath, success, fail) {
    return cordova.exec(success, fail, “LowLatencyAudio”, “preloadFX”, [id, assetPath]);
    },
    preloadAudio: function ( id, assetPath, voices, success, fail) {
    return cordova.exec(success, fail, “LowLatencyAudio”, “preloadAudio”, [id, assetPath, voices]);
    },
    play: function (id, success, fail) {
    return cordova.exec(success, fail, “LowLatencyAudio”, “play”, [id]);
    },
    stop: function (id, success, fail) {
    return cordova.exec(success, fail, “LowLatencyAudio”, “stop”, [id]);
    },
    loop: function (id, success, fail) {
    return cordova.exec(success, fail, “LowLatencyAudio”, “loop”, [id]);
    },
    unload: function (id, success, fail) {
    return cordova.exec(success, fail, “LowLatencyAudio”, “unload”, [id]);
    }
    };
    function successHandler (result) { alert( result ); }
    function errorHandler (error) { alert( error ); }

    It seems I have some issues with cordova (2.0)…Do you know what’s wrong with all this?

    Thank you very much.
    Davide

  • http://addtimer.net Przemek W

    @Davide Reppucci

    Had the same problem (on Android)

    after few hours of goggling and testing found the solution.

    You need to prelaod sounds when device is ready

    document.addEventListener(“deviceready”, loadSounds, false);

  • Pingback: Andrew Trice » Blog Archive » Halloween Fun with PhoneGap()

  • http://Website Igor S

    Hi Andrew, Thank you for the great article and plugins.

    I am looking for a solution to play an audio file and show images at the same time. The moments for images to show are defined by the current position within the audio file. How can this be done with your plugin?

    -Thank you.

    • http://www.tricedesigns.com Andrew

      Currently, this plugin doesn’t support any kind of playback/progress events. They would have to be added to the plugin to achieve this functionality… It’s totally do-able, but not supported as this time.

  • vikas

    How to check current sound playing complete event. Is their way to check sound oncomplete
    event.so that i can activate another button click events

    • http://www.tricedesigns.com Andrew

      No playback/progress events are included in the plugin. It is possible to add them, but you would need to write the native integration layer to expose this via JavaScript.

  • JohnM

    I just tried to implement the plugin, but when I load audio the ID and Path come back as “undefined” when I try to play, I get a success callback with a blank for the requested ID. Anyone have this issue?

    • http://www.tricedesigns.com Andrew

      Make sure that you are using the JS interface correctly. Please look at the sample files to see how it works. You preload an asset by specifying an id and path, then only reference the assets in the future by referencing the id. You won’t need the path again, once the audio file has been loaded. The ID and path would only be undefined if you have not defined them – they are not generated from the plugin.

  • http://www.skylightthailand.com/webdesign Luca

    Hi Andrew, I have successfully implemented the plug-in in the ios version and works perfect. But I have a problem with the Android version. I installed the latest updates of PGLowLatencyAudio and I use cordova 2.2 , the game starts but when I click on the sound I get “file :/ / / android_asset / www / PGLowLatencyAudio.js: Line 12: ReferenceError: Can not find variable: cordoba”, and I can’t hear any sound. Do you have an idea of what it could be? Thanks

    • http://www.tricedesigns.com Andrew

      Hi Luca, the code that I uploaded should work. That message looks like there is a typo somewhere in your code. It is referencing “cordoba” instead of “cordova”. I just double checked, and on github my code still says “cordova” in the LowLatencyAudio JS files for Android and iOS. Maybe something got changed when including it in your project?

  • Luca

    Hello Andrew. Thank you for your fantastic plugin but I have some problems:
    * I copied and linked the js file in the www directory
    * I created (I use Eclipse with Cordova 1.9) the directories com/phonegap in the SRC directory
    * I put the 3 java classes inside
    * Modified the Plugins.xml file as you suggest
    * I changed, in the file PGLowLatencyAudio.java, 2 rows (75 and 102) (they gave me problems) in this way: AssetManager am = ctx.getResources().getAssets(); –> AssetManager am = cordova.getActivity().getResources().getAssets();

    I think the HTML and JS are ok but the callback function in the loading code PGLowLatencyAudio.preloadAudio give me errors and no sound when I call PGLowLatencyAudio.play.
    Can you help me, please?
    Many thanks!

    Luca

    • http://www.tricedesigns.com Andrew

      Can you post a copy of your code in the PGLowLatencyAudio.js file? It’s really hard to debug without seeing anything. You previous comment showed a typo, where it referenced “cordoba” instead of “cordova” (the “b” instead of “v”).

  • Luca

    Thank you for the reply. Yes it’s a mistake (cordoba –> cordova).
    I didn’t touch the PGLowLatencyAudio.js
    I used and simplified your demo file to understand the problem
    This function (in the script tag of index.html) alert me with “error”
    function onDeviceReady()
    {
    PGLowLatencyAudio.preloadAudio(‘background’, ‘assets/background.mp3′, 1,ok,no);
    }
    function ok() {alert(“ok”);}
    function no(){alert(“ERROR!”);}
    When I click on the link in the console I read play –> istance name correctly but no sound.
    The background.mp3 file in the www directory.
    I think my problem is about where I put the java files (it’s the first time for me I deal with these files) and the modified in the lins 75 e 102.
    Can you confirm I well set the files and modified the files? (read my previous message).
    Thanks and happy new yer :)
    Luca

  • Luca

    Hi Andrew, I’m near to finish my app and the plugin works perfect. I would like to ask you just one more thing: in Android, there’s a way to get rid of the Soundpool 5 seconds limit? ‘Cause I have some audio files that are longer.
    Thanks
    Luca

    • http://www.tricedesigns.com Andrew

      There is no way to bypass the 5 second limit. Try using preloadAudio instead of preloadFx. preloadAudio can play longer sounds, but it takes up more memory.

      • Luca

        Thank you!

  • http://rocksetta.com Jeremy Ellis

    I have searched the web for generic phonegap audio android example. The phonegap Documentation examples do not seem to work running phonegap 2.2.0 on either our emulator or samsung Galaxy s3 .
    Your plugin looks good but I would hope phonegap out of the box would have a bareable working audio solution for files in asset_android phone, sd card and url. Presently we can only get the online url working ONCE but never repeating.

    • http://www.tricedesigns.com Andrew

      IF you are just tyring to play an audio file, the PhoneGap Media class should do it for you – there are many apps the use this. http://docs.phonegap.com/en/2.3.0/cordova_media_media.md.html#Media The plugin that I wrote is looking for files relative to the “www” directory within the PhoneGap project structure. I have not updated it to support other locations. This can be done fairly easily, but I just haven’t had the time to update it.

  • JRS

    with the media class could you not use – “/audio/mywav.wav”
    as the src.

    Are there any benefits from the plugin to the media class.

    Thanks Andrew :)
    also will you be updating the depreciated references for 2.2+

    • http://www.tricedesigns.com Andrew

      You could do that if you want. This plugin has less latency b/c it preloads the audio files before you play them. It’s also supports polyphony (playing the sound over top of itself).

      This version should work fine with 2.2+ https://github.com/triceam/phonegap-plugins/tree/master/iOS/LowLatencyAudio

    • http://www.tricedesigns.com Andrew

      Whoops, totally forgot about the method signature change for plugins. I’ll add that to my ever growing todo list, but it should still work with current versions of phonegap.

  • TheSharingWorlds

    Hi Andrew, :) I have a question, this plugin works well on PhoneGap/Cordova 2.3.0?
    Thank you.

    • http://www.tricedesigns.com Andrew

      It should. I’m not aware of any issues with it. You may need to remove memory management functions now covered by ARC-I guess I should update it when I have time, but there’s no reason it wouldn’t work.

  • TheSharingWorlds

    Ok, thanks for your answer! Have a nice day. :)

  • mark

    I’ve been using this plugin for a while, just tried the phonegap 2.5.0 rc version and it seems to work fine. Thanks.

    Can I just ask one thing… if I have a bg music sound looping and fx sounds are played over that, then the fx sounds are quite low but if there is no bg music then the effects sounds are really (too) loud. I was about to try the possibility of playing a blank sound file when bg music is not needed (if such a thing is possible) in the hope that the fx sound levels stay constant. Do you have any idea why this is or what I can do about it?

    • http://www.tricedesigns.com Andrew

      You could modify the plugin to adjust volume levels. However, it currently does not support this feature. You could also adjust volume levels in the source sound assets using an audio processing program, like Adobe Audition, so that you don’t have to adjust sound levels at runtime.

      • mark

        I just went with the looping a blank sound plan, it ensures every fx sound plays at the same volume whether the bg music is playing or not. Otherwise I would have to manage 2 sets of fx sounds at different volumes for when the bg music is playing and when it is not.

        Thanks for the plugin, it has been very useful.

  • Tjoan Lie

    Hi Andrew,
    This is really great, thank you very much for the post.
    I do have trouble though, I have 4 sound effects and the result is rather intermittent. Sometimes it will work great but other times one or two sounds are silent or they are the same.
    I preload the sound effect ondeviceready function as follow:
    PGLowLatencyAudio.preloadFX(‘boink’, ‘boink.mp3′, audioSuccessHandler, audioErrorHandler);
    PGLowLatencyAudio.preloadFX(‘yeah’, ‘yeah.mp3′, audioSuccessHandler, audioErrorHandler);
    PGLowLatencyAudio.preloadFX(‘ouch’, ‘ouch.mp3′, audioSuccessHandler, audioErrorHandler);
    PGLowLatencyAudio.preloadFX(‘eat’, ‘eat.mp3′, audioSuccessHandler, audioErrorHandler);
    And then I called the play function when I need it before unloading them at the end.
    Have you had similar issue before? Any idea what’s wrong?
    The problem so far happens on low end Android mobile phone, I am yet to try it on my Sony tablet.
    Thanks!

    • http://www.tricedesigns.com Andrew

      Android devices (especially low end ones) seem to run out of memory very frequently. When that happens, the OS disposes of the in-memory assets. I have had this happen too. To get around this, I reduced the quality of my audio assets and limited the # of polyphonic voices, so that overall it takes up less memory.

      • Tjoan

        Hi Andrew,
        Thank you very much for your reply.
        I was suspecting that, however the problem also occurs on my Sony Tablet. I will investigate a bit more as the problem only happens when I run the app after uploading. Subsequent runs seems to be fine. There seems to be another issue that causes my app to hang:

        03-12 18:21:10.399: E/dalvikvm(11335): HeapWorker is wedged: 17391ms spent inside Landroid/media/SoundPool;.finalize()V
        03-12 18:21:20.490: E/dalvikvm(11335): VM aborting

        This happens on my LG android phone.
        Have you seen this before?
        I will also try other mobile devices and will report to you.
        I am using cordova version 1.7.

        Thanks again!
        Tjoan

        • http://www.tricedesigns.com Andrew

          No, I haven’t seen this before. What kind of audio file (codec/encoding) are you using, also are the sound files very large? I just did a Google search for “HeapWorker is wedged” and that seems to be a common issue when the VM assumes a deadlock scenario has occurred.

  • Tjoan

    I am using mp3. They are all very small in the order of 100 kB or less as their duration is only 1 second.
    I use preloadFX. There are 4 different sound effect and all of them might be played simultaneously. Is this bad?

  • True Pro

    Can you help me with this plugin with cordova 2.5.0 on iOS where audio doesn’t works ?

    https://github.com/phonegap/phonegap-plugins/issues/1070

    • http://www.tricedesigns.com Andrew

      In PhoneGap 2.5, the Cordova.plist file has changed. It now references config.xml instead of the mappings in Cordova.plist. Your XML entry is correct. However, did you also add the files to the Xcode project? Right-click, and select “Add Files To (name of your project)”. Then select the files so that they are actually included in the Xcode project (not just located in the directory). You can read more about setting up plugins in the PhoneGap docs: http://docs.phonegap.com/en/2.5.0/guide_plugin-development_ios_index.md.html#Developing%20a%20Plugin%20on%20iOS

      • True Pro

        Hello,

        Thanks for helping, sounds seem to work now!

        But I’ve another issue now which is a major one I think. on iPad 4 when the volume is at 0% there is no sound and it increases as you go till 50%. The volume is highest at 50%. Then when you try to increase volume more past the 50% mark the bar increases but volume /decreases/.

        So after 50% the volume starts decreasing and becomes VERY low at 100% – any idea why this could be happening ?

        Thanks in advance!

        • http://tinyfactory.co Alex Rolek

          I’m experiencing the exact same issue. Any ideas for a work around?

          • http://www.tricedesigns.com Andrew

            I haven’t noticed this issue. Can you share a code snippet of how you are using the plugin, so I can try to recreate the scenario?

  • http://rpmdesignfactory.com John P

    Hi Andrew,

    Thank you for this plugin! i have used it on many projects!

    I’m working on a lopping sampler app right now [IOS], and it seems to be working almost perfect, but I’m having a minor sync error between the looping samples. A drum track, bass track and melody track can be played on top of each other.

    I’m using setInterval() to fire off the LowLatencyAudio.play(); for each of the three samples each time around the loop. It’s just milliseconds off, but it’s noticeable and makes the music sound jumbled.

    Also, do you recommend a particular format for best performance? I’ve been trying mp3, caf, and aif, but I haven’t noticed a significant difference.

    Thank you!

    • http://www.tricedesigns.com Andrew

      I normally use MP3s, but you can use other formats. I think the fastest file format for iOS is .caf (core audio format), and for Android I think .ogg or .mp3 are roughly equivalent. I have also heard of older Android device having some issues with .mp3 files. I wouldn’t try to do precise sequencing and synchronization in JavaScript. The JS timer/interval is not exact, it uses an approximation of the interval instead of an exact interval (like you can do in native code), so looping of multiple synchronized assets could be really tough (if not impossible).

  • Patrick Geiger

    Thanks for the plugin, this is very useful!

    I do have a quick question however. In the repository, there is a “PGLowLatencyAudio” plugin in the “iPhone” folder and a “LowLatencyAudio” in the “iOS” folder. The name of the Android version of the plugin is “PGLowLatencyAudio”. Is there a difference between the “iPhone” version and the “iOS” version? To keep my JS code simple, it would be great to use the “PGLowLatencyAudio” version so the name of the plugin matches the Android version.

    Thanks in advance!
    Patrick

    • http://www.tricedesigns.com Andrew

      The JS API is identical. However, the actual native implementation is very different. Your app will be fine with the exact same JS source code.

  • http://nope Mek

    Hi Andrew,

    It’s a wonderful plugin you made! But there is one question. You say it’s important to implement ‘unload’ which sounds pretty obvious. However, I noticed your examples do not use the ‘unload’. Moreover, it’s not clear where to implement the unload statement for sound you need all the time. Can you clarify this for me please.

    Thanks in advance

    • http://www.tricedesigns.com Andrew

      In my examples I didn’t unload them b/c it is a pretty small use case. However, if you are managing lots of sounds/assets, you will want to unload anything that is not necessary at the current time. For example, if you have a game and you load sounds A, B, and C for level 1. When you are done level 1, you might want to unload sounds A, B and C, to release memory so you can load sounds D, E and F for use in level 2. Hopefully that helps.

  • Xavier

    Hello,
    I try to make this work with cordova 2.5 on android but I have some preloading problem. After tweaking the code :
    – remove @Override
    – Plugin –> CordovaPlugin
    I get no errors in eclipse but when preloading wether throug preloadAudio or preloadFX, I get a fail callback. My directory tree looks like this :
    index.html
    js folder
    sounds folder
    I don’t know if it is a path problem, the PGLowLatencyAudio.js is in the js folder while all audio files are in the sounds folder and I try to preload audio files in index.js in the js folder with :
    PGLowLatencyAudio.preloadFX(‘sound1′, ‘sounds/sound1.mp3′);
    I tried with PGLowLatencyAudio.preloadFX(‘sound1′, ‘../sounds/sound1.mp3′); without success.
    Is there a way to get more details in the fail/error callback to debug ?

    Thank you !

  • copic

    Hi Andrew,
    this plugin is really great. I use it for an iPad-app. But when i test it on the Devide Xcode gives me this Error:
    LOG] Error in error callback: LowLatencyAudio1081708623 = TypeError: ‘undefined’ is not a function.
    I use Phonegap 2.6.0

    U have any Idea?
    Thx a lot!
    copic

    • http://www.tricedesigns.com Andrew

      Can you share your code that is causing the issue? This looks like a JS error (possibly bad reference, or misspelling).

  • Nick Doyle

    Thanks so much Andrew, this is awesome. I updated Android for PG v2.7 and made a pull request, but then noticed there are like 94 outstanding pull requests on the phonegap-extensions repo. I guess whoever is maintaining it doesn’t have the bandwidth to process them all =(
    Anyone who’s interested, my updated fork is here: https://github.com/rdkls/phonegap-plugins

    • http://www.tricedesigns.com Andrew

      Hi Nick, Thanks for sharing!

  • Thang Tran Quyet

    thanks u so much Andrew :). All what i need :)

  • Thang Tran Quyet

    I has one question ? Can i use it to play audio from the Internet ?

    • Nguyen Duc Phuong

      Me too. Would be nice to stream the audio from internet. I use FileTransfer to download the file but then attempt to preloadAudio for downloaded file would result in {“0″:”file not found”} error.

  • Han Zhe

    Hello, Andrew.
    I am going to play several mp3 audio at once and control each volume independently.
    Is this possible to do using low latency plugin and phonegap?
    It seems look like low latency plugin use soundpool class .
    Can you let me know its solution soon?
    Regards

  • Jochen Ulrich

    I just created a pull request on Andrew’s repository which also updates to PG/Cordova > 2.1.x and includes some other, minor improvements:
    https://github.com/triceam/phonegap-plugins/pull/2

  • PerQA

    I guess these plugins won’t work with Phonegap 3.0? I am looking for a “preload” function to use with Phonegap’s Media API. I intend to play large audio files, one at a time, so I’m not sure if the plugins described in this article are the right choice.

  • http://tricedesigns.com/ Andrew Trice

    This plugin has been updated to support PhoneGap 3.0 method signatures and command line tooling. The latest version is available for both iOS and Android at https://github.com/triceam/LowLatencyAudio

    • J. Blake Harris

      Thanks Andrew! I’ve used this plugin successfully on PhoneGap 2.x, but with the new Xcode 5.0 and PhoneGap 3, my app is locking up on preloadFX. Is there any example code anywhere I can look at? I don’t want to take up your time troubleshooting…

    • J. Blake Harris

      From what I can tell, the error has something to do with file paths. I wasn’t getting any errors (just freezes) with your most recent updates, but I managed to trace the error to this line of preloadFX in LowLatencyAudio.m:

      [audioMapping setObject:[NSNumber numberWithInt:soundID] forKey: audioID];

      • http://tricedesigns.com/ Andrew Trice

        What file format are you using for audio? I would double check the format, and the path references for the audio file. Here’s a PG 3 app that uses the new plugin, with source code: http://www.tricedesigns.com/2013/10/07/new-version-of-my-halloween-phonegap-app/

        • J. Blake Harris

          Thanks, I’ll take a look. The files are m4a – they worked without problems in the 2.x version…

          • http://tricedesigns.com/ Andrew Trice

            I’ve never tried a .m4a file with this plugin, so I’m no help on that. I do know that .mp3 definitely works on android… Also, anything here *should* work, but that also includes .m4a: http://developer.android.com/guide/appendix/media-formats.html Is it a huge file? sometimes android pukes on large files that take up a lot of memory.

          • J. Blake Harris

            It’s pretty small… less than 100KB. I’ll keep exploring. Thanks.

          • http://tricedesigns.com/ Andrew Trice

            Now that I think about it… I have seen that some older android devices fail on certain file formats, even though they are supposed to work. I have even seen some mp3 encodings fail. Definitely try playing around with different encoding settings and different file formats.

          • J. Blake Harris

            Is there any chance this plugin has dependencies on any other plugins? File, Device, Events, etc? After exhausting all my options with LowLatencyAudio, I built a new project from scratch (3.1.0), and tried the cordova media plugin, and got the exact same result, with MP3 or AAC files. The error, as with LLA, lacked any console message, but I think it has to do with locating the resource. The app just locks up.

  • Henry Ryalt

    Thanks Andrew!

    Any chance of onAudioEnded support sometime in the future, to know when a file completes playing?

  • Vikram Kumar

    Hi,

    Thanks for the nice plugin. I am new to phonegap and creating an app with phonegap and createjs. CreateJS comes with audiosupport through SoundJS. But it has some problems with looping. Hence I wanted to use some plugins and I found this one.

    I tried to implement this but I got struck at this moment. I am on a PC and I have downloaded the plugin through CLI, And then I have added this line in config.xml

    When I tried to compile the app by uploading it to build.phonegap.. I am getting the following error
    [error] {“error”:”plugin unsupported: com.phonegap.lowlatencyaudio @ 0.1.0″}

    I have searched the comments and it seems to be working for everybody else. Please tell me where I am doing wrong. I could not find proper tutorials to add plugins.

  • Ashish Yadav

    Hey I am planning to create a guitar processing app like jam up pro for android?DO you think it is possible?Should I go native or use phonegap? and the real trouble is it possible to process realtime audio in android..
    Sorry but I’m a newbie.

    Thanks

  • Per Liljeqvist

    Have you looked at the problem with getting low latency, talking in a mic at the server sending the audio to IOS and Android devices connected over a local WiFi network. What is the shortest latency you think you can get doing like that. We don’t need any high quality audio so no big bandwidth. Just to support human talk.

  • atteh

    I’m also interested on playing external sounds with this library. Can you think of any way of accomplishing this..for example downloading the .mp3 files inside the app before playing them..?

    • Ryan Knell

      Just did this with the media plugin using the file api. You wouldn’t have a problem where there are lots of small mp3 files that make up a song by any chance would you? ;)

      • atteh

        Nope :) But I ended up giving Web Audio API a try and it works like a charm..low latency and preloading that works on mobile safari.

  • Shachar

    Hi Andrew.

    I downloaded your Halloween app version 2.1 to my iPad 2 (iOS 7) and the sounds are not playing…

    I used your plugin in my app, and it doesn’t seem to work either.
    I’m using phonegap 3.3 and installed the plugin using the command line interface.
    When first adding the plugin, the project didn’t compile. I had to add reference to AudioToolBox.framework. is this normal?

    Its not playing in the simulator, nor does it play on the iPad.
    Do you have any clue why?

    Thank you!

    • Shachar

      Turns out there was a problem with the iPad. I should have switched from lock rotation to mute and then it started working.

  • Martin

    Hi Andrew!

    This is exactly what I was looking for. I am making a karaoke app – playing background music and simultaneously recording voice. With phonegap I get a delay of approx. 0.4s because the phonegap is loading .amr background file to play.

    So I tried your way, but the preloadAudio() does not fire. Can you tell me why?

  • Svilen Vassilev

    Gents, will this work for playing MIDI files? Anyone tried?

  • Tamer Zorba

    hi their .. i want to make sequencer app so i need to fire sound finish playing event..
    is this plugins support it .. ??

  • fred

    Hello. I need some help to use the plugin. i’ve made many test and nothing works.

    i don’t know what’s wrong

    1. i’ve created a phonegap (3.4.0) project : phonegap create piano com.jiwok.piano piano

    2. add the plugin : phonegap plugin add https://github.com/floatinghotpot/cordova-plugin-lowlatencyaudio.git

    3. add in my config.xml file :

    4. copy the LowLatencyAudio.js file in my www root dir

    5. add in my index.html file :

    now it’s a little bit confuse because i’ve found many example code to call some function as this style :

    * PGLowLatencyAudio.play();
    * LowLatencyAudio.play();
    * window.PGLowLatencyAudio.play();
    * window.plugins.LowLatencyAudio.play();

    * etc ..

    i’ve tried all of them but nothing works ..

    i’ve tried on ios and android emulator as on device : same things.

    anyone can help me please ?

    thanks a lot a lot a lot

    fred

  • http://www.pythoninja.com/ Amyth Singh

    It works for the files within the applications `www` directory, for example `www/audio/123.mp3` but how can I make it work with `cdvfile://localhost/persistent/my_app/123.mp3` ??

  • jono

    Does anyone know whether I can use this plugin on IOS to auto play audio on startup? I am writing a game in PhoneGap and would like the background music to start playing when the game is opened. I am aware that Apple block auto play for HTML5 web sites, but as this is a PhoneGap app with a native audio plugin (Low Latency Audio) they may be more lenient :)
    Many thanks

  • KarimFS

    I have used the Low Latency Audio plugin before without any issues, it works great! However, with the recent release of iOS8 and 8.1 I updated Xcode and build a new phonegap project using this plugin and no sound is playing anymore and I don’t see any errors either. Is there a special setting that I need to use for the latest version of xcode or ios?

    In the mean time, I revert back to using the HTML audio tags with start great but while you keep running the app it will start to become sluggish.Help please.