Audio delay on android

Hi,

I’m working game which is heavily relying on audio at certain events. So the current audio delay when using audio.play() on Android is a real show stopper for me.

Any possiblity that you guys can fix this soon?
[import]uid: 11219 topic_id: 6861 reply_id: 306861[/import]

This also has an effect on performance / framerate. Each time audio.play() is called, my game hangs for a moment / the framerate drops.

I tried to use the old sound API (media.playEventSound, media.playSound) instead, but I need to play a background music track while playing event sounds, which isn’t possible as far as I know? [import]uid: 11219 topic_id: 6861 reply_id: 23927[/import]

It is possible.

I’m using media.playEventSound and media.playSound in my game and it works fine:

YouTube Video: (Walkabout Demo in the market now)
https://www.youtube.com/watch?v=ghuDnAZFPp4

I believe they use one channel each, and so both can play at the same time, but you can’t play more than 1 event sound at a time, or more than one playsound at a time.

In my game I just fade out the music to play the end level sound. There’s no fade with media. but you can do it using a timer and

if getvolume > 0.1 then
setvolume(getvolume - 0.1)
else
kill timer
setvolume(0)
end

^^ psudo-ish code because its late and I’m lazy to look up the exact api calls :slight_smile: [import]uid: 8872 topic_id: 6861 reply_id: 23968[/import]

Hi kam and thanks for your detailed response.
I tried out media.playSound and media.playEventSound before and it didn’t work (event sounds weren’t played if media.playSound was playing) but I’ll try it again.
[import]uid: 11219 topic_id: 6861 reply_id: 24002[/import]

Ok this seems to work, thanks. But I’ll have to make separate sound files for iOS devices in aif format…I was hoping that the daily builds would make this obsolete by using mp3 files for both iOS and Android with the new audio API…hopefully this will work, soon.

To avoid making 2 versions of each sound file, I built myself a little “audio bridge” for the time audio.play doesn’t work correctly on Android:

[code]
local is_android = (system.getInfo(“platformName”) == “Android”)

function audio_bridge:playEventSound(soundpath)
if(is_android) then
local soundID = media.newEventSound(soundpath)
timer.performWithDelay(50,
function(event)
media.playEventSound(soundID)
end
)
else
audio_bridge:playSound(soundpath)
end
end

function audio_bridge:playSound(soundpath)
if(is_android) then
media.playSound(soundpath)
else
local audioChannel = audio.findFreeChannel()
local soundID = audio.loadSound(soundpath)
audio.play(soundID, {channel = audioChannel})
end
end
[/code] [import]uid: 11219 topic_id: 6861 reply_id: 24007[/import]

I would also like to see the delay when using audio.play() fixed on Android devices. Yet another disappointment for me using Corona on Android. When I tap a screen that plays a sound, there is about a half-second delay before the sound plays. It’s instant on iOS devices.

I will also try the above workaround to see if I can get the eventsound stuff to work. All of my sounds are in wav files, so I’m hoping I don’t need to convert them.

Thanks for making this post to help us out until Corona can be fixed. [import]uid: 12529 topic_id: 6861 reply_id: 24994[/import]

Hi Mr Potter,

if you’re event sounds are all in WAV, you should simply use media.newEventSound and media.playEventSound. And you should preload all event sounds on startup of your level.

The code above was only posted for using mp3 files on both iOS and Android, but from my tests the code doesn’t work totally well on Android and causes crashes. The best way from my current experience is to preload all(!) event sounds before you playback any sound. But if you preload all sounds, you have to differentiate between iOS and Android before loading them, so you have to do it like this:

local soundEvent1  
local soundEvent2  
  
if(is\_android) then  
 soundEvent1 = media.newEventSound("file1.mp3")  
 soundEvent2 = media.newEventSound("file2.mp3")  
else  
 soundEvent1 = audio.loadSound("file1.mp3")  
......  
end  

And if you already differentiate between iOS and Android on startup, you can also do the same for playing back the sound, making the above “audio_bridge” code redundant.

if(is\_android) then media.playEventSound(soundEvent1) else local audioChannel = audio.findFreeChannel() audio.play(soundEvent1, {channel = audioChannel}) end [import]uid: 11219 topic_id: 6861 reply_id: 25057[/import]

I couldn’t get playEventSound to work at all for WAV files on Android. I converted all of my WAV files to OGG files and then the playEventSound worked on Android. I haven’t seen any crashes on my device yet for this, but I will keep your advice in mind about pre-loading sounds.

Actually, what I modified your code to do is to cache the SoundID values, so they are only created once when first needed, and then the subsequent times the same sound is played it used the already cached SoundID. So that is similar to pre-loading, but is more of a “load on demand and cache” logic.

Still, thanks for the idea of using playEventSound for Android but still using audio.play for iOS. That was the key I needed to get this all working. [import]uid: 12529 topic_id: 6861 reply_id: 25138[/import]

Are you supposed to preload audio by setting a volume of 0, and then calling audio.play() for each sound used during initialization? [import]uid: 4596 topic_id: 6861 reply_id: 25165[/import]

Hmm there must be a better way. Otherwise you’re using audio resources for no reason while the volume is 0 [import]uid: 8872 topic_id: 6861 reply_id: 25173[/import]

Hey Mr Potter,

I use MP3 files, they work for media.playEventSound and audio.play.
And they are smaller…:slight_smile:

@sing: Setting the volume isn’t necessary from my experience. [import]uid: 11219 topic_id: 6861 reply_id: 25174[/import]

We are working on this, but Android audio is a really hard problem. Android audio is currently just terrible so we don’t have much to work with. You just need to Google it to see for yourself.

http://code.google.com/p/android/issues/detail?id=3434
http://kile.stravaganza.org/blog/post/android-audio-api-sucks
http://www.badlogicgames.com/wordpress/?p=1315
http://groups.google.com/group/android-ndk/browse_thread/thread/29f88a99dc954c71
http://mindtherobot.com/blog/555/android-audio-problems-hidden-limitations-and-opensl-es/
http://music.columbia.edu/pipermail/portaudio/2010-December/011146.html

That said, I just pushed some new changes to the Android OpenAL backend today that try to improve the latency. This needs to be tested by all of you to make sure it doesn’t break things in other ways.

We are investigating OpenSL ES as a new backend to OpenAL, but it requires Android 2.3+. But early word on the internet is that the performance is still terrible. I suspect that we will need to wait for hardware makers to get their act together as well to take advantage of OpenSL ES.

[import]uid: 7563 topic_id: 6861 reply_id: 25205[/import]

I fast tracked the daily build. #306 with the latency change is up now.

[import]uid: 7563 topic_id: 6861 reply_id: 25213[/import]

Thanks for your quick fix. The delay’s definitely better, but using the new audio API I still get worse performance on Android than using the old media API. From my spectations the loading of sounds with audio.loadSound takes longer and audio.play also has a negative impact on the game’s performance.
At the beginning of my screen I load all my event sounds:

local sound1 = audio.loadSound(…)

And if I use the new audio API it takes longer to open the level. Using media.newEventSound I have no loading delay, at all.
In my level, I show an image on screen and play back a sound if a certain event happens. Simple thing.

media.playEventSound(mySound)  
image1.alpha = 1  

or

audio.play(mySound)  
image1.alpha = 1  

With media.playEventSound the sound is played back and the image appears instantly. With audio.play and build 306 the audio is played back with a shorter delay than before, but the image appears delayed in comparison to media.playEventSound. As if the internal corona audio call would work like this:

function audio.play(soundfile)  
 system.playback(soundfile)  
 timer.performWithDelay(500,   
 function(event)  
 --go on with the stuff that follows after the audio call  
 return  
 end  
 )  
end  

So using the new audio API is still relatively unreliable for me on Android (tested with 2.2 and 2.3) and the old API works pretty perfectly. [import]uid: 11219 topic_id: 6861 reply_id: 25249[/import]

Maybe audio.loadSound() is pre-caching the audio so it’s ready on audio.play(), whereas media.playSoundEvent() only caches on first playback, which could explain why audio.loudSound increases the time for your app to load.

image1.alpha = 1 audio.play( mySound ) [import]uid: 4596 topic_id: 6861 reply_id: 25810[/import]


Maybe audio.loadSound() is pre-caching the audio so it’s ready on audio.play(), whereas media.playSoundEvent() only caches on first playback, which could explain why audio.loudSound increases the time for your app to load.

It is doing exactly that. [import]uid: 7563 topic_id: 6861 reply_id: 38306[/import]