I am aware that SoundPool was intended to handle small fx like sounds and I made sure my 4 sound clips which I want to play one by one in some sequence are small enough.
I used ogg quality 0 and clips are 35kb, 14kb, 21kb and 23kb totaling 92kb of compressed audio. I have no idea how to estimate what the uncompressed size would be, but it should not be a lot, right?
So when I play 4 sounds in sequence, it works well for first 9 times (9 sequences x 4 sounds) but starts to cause memory issues on the nines sequence for one of the sounds. It is always sequence 9 when I start to see error.
What is the best way to handle that? I have a few ideas:
1) compress sounds even more (ogg quality -1 and mono instead of stereo)
2) unload and load sounds constantly using SoundPool.load and SoundPool.unload
3) release and recreate soundPool instance time from time
Is there anything else I can do? It is embarrassing that android api cannot handle so small clips. I wonder how people create games with a lot of sound effects...
Errors look like that:
ERROR/AudioFlinger(35): not enough memory for AudioTrack size=1048640
DEBUG/MemoryDealer(35): AudioTrack (0x25018,size=1048576)
It seems I was able to resolve my issue after:
1) downsampled my sound clips from 44 to 22khz. Uncompressed size was cut in half (I figured how to estimate uncompressed sound size - export your clip to uncompressed wav). I used nice open source tool Audacity
2) trim the sounds more to reduce duration
3) put try/catch around play() just in case (it does catch errors when it try to play the sound but cannot)
That seems odd. SoundPool should be expanding your audio clips into memory when it loads them, and once loaded I wouldn't expect you to run into memory issues later. When I've run into memory issues it was right at the beginning, not later on. You sure you're not loading more sounds later on?
To answer your other question, some games use JET Player and MIDI sounds instead of SoundPool. The JetBoy sample program that comes in the Android SDK is a great example of how to do this type of sound work in an app.
Related
I'm making a really small game for android, and trying to add sounds to the game
I'm using the MediaPlayer class to load the audio file (.ogg or .wav)
I want to use .ogg (or .mp3) to shrink the size of the apk, rather than using .wav files.
I understand why loading (i.e. creating the MediaPlayer from a .ogg would take longer than .wav) (compression)
BUT the problem is that when I put the audio on loop by audio.setLooping(true) each time the audio starts again, it lags the game significantly
Why ? does the audio gets decoded each time it's going to start ? even on a loop ?
Also, on the CPU usage, I see spikes marking the beginning of the audio in the loop. so I'm pretty sure that the loop is really causing the lag..
any explanations/solutions?
(P.s. I'm testing on a really low-end physical phone, but for the game it's fairly enough, the sudden spikes are what's causing the problem not the actual usage)
I'm curious if someone can point me to (or just describe) how, given that an Android application has an extremely limited memory space to play with (I think it's around 20 megs), a video player can load and play videos that are an order of magnitude or more larger in size. Is the app loading the video in some sort of chunks?
I ask because I have an app that has some video assets embedded and the app has grown to be about 80 megs and is just a total monster for compiling and debugging (without the assets the app would only be about 2 megs), and I was thinking that I should just remove the assets and have them download on the side and sit on the sdcard, rather than within the apk, but I'm worried that loading them and playing them at run time will bust through the app's memory allotment, and was hoping someone can shed some light on what my options are.
TIA
They buffer the video in manageable chunks, yes. Even if your videos are GBs in size, you won't hit a memory wall using standard video playing APIs. You can use the standard calls to setVideoURI or setVideoPath to point to the file and it will handle it from there. The same works for MediaPlayer in general if you're not using a VideoView
Downloading the videos outside the apk is still a good idea, though. If I had to download a new 80MB file for each incremental upgrade, I'd probably just uninstall instead. If you don't want to host them yourself, look into the supplemental apk option.
You can take your game into the native layer where you can bypass this limit. Take a look at a blog I wrote http://jnispot.blogspot.com/2012/10/jnindk-arrays-bitmaps-and-games-oh-my.html
I have no idea if this is what video apps do, but you can actually increase the memory beyond the normal limit by using malloc statements in native code. This bypasses the normal max of around 20 MB.
I have only used this for encryption on android devices where AES encryption needs rather karger amounts of memory when dealing with large encrypted files (even around 10MB files).
I am developing a game for Android and the Desktop with LibGDX. I am having a problem with playing sounds. The game is a labyrinth style game, there are balls that roll around on the device using the accelerometer. When balls hit the border, or one another a sound is played. The volume is set based on the linear velocity of the collision. The problem is, when the balls get really close to the border, they bounce many times in a small period of time. This ends up bogging down the main thread, and the UI starts to stutter. In log-cat it says "reducing sample rate" or something like that, because it can't handle the load. Also, when there are a bunch of collisions, the sounds keep playing after there aren't anymore collisions.
I need each of the sounds to be played independently of the other sounds. I was thinking, maybe creating a separate thread for the sounds. Any help would be greatly appreciated.
I working now with the sounds of my game. The last LibGDX version works fine playing a lot of sounds simultaneously. All you need to do is, if you plan to play them on the same time is control the number of maximum sounds played (more sounds requires more resources of the device) and reduce the sample rate and quality of the most played. You can resample your sound with Audacity. Try to save it as a OGG file with less quality and try again. Also, you can create your sound as static and play it many times from the same sound without create a new one.
Hope this helps you.
I was looking at Android's SoundPool as a mechanism to implement sound effects in my generic game development library. It seemed ideal.
But a little bit of research indicates that there all kinds of bugs in SoundPool. Are the bugs in SoundPool still relevant?
Because I'm developing a library, any bugs in SoundPool become bugs in my library, and I want to insulate my users from that.
So my question is basically: what API should I use for audio?
Using AudioTrack and writing my own mixer is not out of the question. But obviously it would be preferable to avoid doing that. And is there any API to provide decoding for me?
I need to be able to play a reasonable number of simultaneous sound effects (at least 16, let's say), and have even more open. Sounds need to start playing with low latency. WAV files need to be supported (MP3/Ogg is unimportant). Sound effects need to support seamless looping and dynamic, individual volume adjustment. The Android app lifecycle needs to be properly supported.
I have heard there is a 1MB limit somewhere for SoundPool, this is probably acceptable for each individual sound effect but not for all buffers/sounds. Can someone tell me exactly what the limit is on?
Finally, I need to be able to play background music as well, in compressed formats, with low CPU load. I assume MediaPlayer is ideal for this. Can it be used in parallel with another API?
I know a few people have been using MediaPlayer to fill in for SoundPool. But does it support the features that I need?
Are there any other audio APIs I've missed?
Just to add some more recent feedback on this issue. I've been using SoundPool for some time in an app with a fairly large user base for key press sounds. Our use case:
Must be played immediately
Up to 3+ sounds in parallel
We make use of the setRate across it's full range [0.5f-2.0f]
I've now experienced two major device specific issue and have decided to cut my losses and switch away from SoundPool
A large number of 4.4 LG devices (mostly the LG G2/G3 line) were having a native crash with their implementation of SoundPool. This was fixed in an update (eventually) but we still have a lot of users with un-upgraded devices
Sony Xperia devices currently have all sorts of issue with SoundPool as reported by others. In my case, I've discovered that if you use setRate with rate > 1.0f the SoundPool with start throwing exceptions until your app quits (and burn through a bunch of battery in the process).
TL;DR; I no longer think it's worth the danger/hassle of debugging SoundPool
Stick with OGG files and SoundPool will do you just fine. It's the nature of the multi-platform beast that is Android that there WILL be hardware configurations that will not work with every significant program, no matter how diligently the programmers try.
If this is a large and well-funded project, add to the funding one of each major phone for testing. It's actually much cheaper than the programmer time spent researching and trying to guess what their performance is.
Sorry. Seems as if this isn't the answer that you were looking for. Good luck!
DISCLAIMER: I have a small amount of experience with MediaPlayer, and no successful experience with the other APIs I mention, and the following information is based on what I've read in the DOCs and what I've read from google searches.
You could use mediaplayer (for the background music) with other audio APIs, since MediaPlayer automatically runs on it's own thread, but I believe it has a high-ish cpu load, and I don't think it would take compressed bits very well, but I'm not too sure.
There's also JetPlayer http://developer.android.com/reference/android/media/JetPlayer.html which seems like a lot of work to use effectively, but it would work very well with playing background music, then playing other sounds as needed in the game. From what I read of the DOCs, it takes a MIDI file (I think?) and you mute and unmute tracks to make it work how you want it to.
I like AudioTrack because it gives you the ability to edit sounds at runtime by changing the frequencies of the sound, and SoundPool can do the same.
Though for your situation, AudioTrack doesn't seem like it would work well, since playing two sounds would require two threads because AudioTrack is blocking (I'm pretty sure).
And with SoundPool, I'm thinking that since you have 16 sounds, maybe take two threads with one SoundPool in each thread and apply 8 sounds to each SoundPool. I don't really know though, as I've never even tried using SoundPool.
And again, my information is not based on experience, just what it appears from what I've read, so I may be completely or maybe just slightly wrong, or heck, who knows.
And I don't really know anything about the SoundPool bugs, since I haven't researched it.
I have been scratching my head for the past week to do this effect on the text. http://www.youtube.com/watch?v=gB2PL33DMFs&feature=related
Would be great if someone can give me some tips or guidance or tutorial on how to do this.
thankz for reading and answering =D
If all you want is to display a movie with video and sound, a MediaPlayer can do that easily.
So I assume that you're actually talking about synchronizing some sort of animated display with a sound file being played separately. We did this using a MediaPlayer and polling getCurrentPosition from within an animation loop. This more or less works, but there are serious problems that need to be overcome. (All this deals with playing mp3 files; we didn't try any other audio formats).
First, your mp3 must be recorded at 44,100 Hz sampling rate. Otherwise the value returned by getCurrentPosition is way off. (We think it's scaled by the ratio of the actual sampling rate to 44,100, but we didn't verify this hypothesis.) A bit rate of 128,000 seems to work best.
Second, and more serious, is that the values returned by getCurrentPosition seem to drift away over time from the sound coming out of the device. After about 45 seconds, this starts to be quite noticeable. What's worse is that this drift is significantly different (but always present) in different OS levels, and perhaps from device to device. (We tested this in 2.1 and 2.2 on both emulators and real devices, and 3.0 on an emulator.) We suspected some sort of buffering problem, but couldn't really diagnose it. Our work-around was to break up longer mp3 files into short segments and chain their playback. Lots of bookkeeping aggravation. This is still under test, but so far it seems to have worked.
Ted Hopp: time drifting on MP3 files is likely caused by those MP3 files being VBR. I've been developing Karaoke apps for a while, and pretty much every toolkit - from Qt Phonon to ffmpeg - had problems reporting correct audio position on variable MP3 files. I assume this is because they all try to calculate the current audio position by using the number of decoded frames, which makes it unreliable for VBR MP3s. I described it in a user-friendly way in the Karaoke Lyrics Editor FAQ
Unfortunately the only solution I found is to recode MP3s to CBR. Another was to ditch the current position completely, and rely only on system clocks. That actually produced a better result for VBR MP3s, but still not as good as recoding them into CBR.