I'm having troubles with the soundpool class. Here it goes:
In my game app (music app btw) I need to reproduce at least 32 short sounds at the same time, so I declare my soundpool like that:
private SoundPool sp;
sp = new SoundPool(128, AudioManager.STREAM_MUSIC, 0);
After that I load all the MP3 sounds needed, about 80 sound of 55KB each. I have no troubles loading all the sounds, but its slow! Well it's no the problem. The real trouble is when I play about 20 sounds at the same time, there's an error in my log:
ERROR/AudioFlinger(59): no more track names available
ERROR/AudioTrack(26349): AudioFlinger could not create track, status: -12
ERROR/SoundPool(26349): Error creating AudioTrack
After that every sound that i try to play throws the same error, and no sound can be played. Not even sounds of another Activity / soundpool. I have no clue of what's going or how to fix it! Should I change the format of the sound files? Should I free memory or something after playing a sound?
(I'm testing on a Samsung Galaxy S I9000, 2.3.3 OS system. The app is 2.1)
see this (in android group)
For audio, there's a hard limit of 32 active AudioTrack objects per device (not per app:
you need to share those 32 with rest of the system),
A couple of thoughts here. One: the first parameter to the SoundPool constructor is not the number of sounds you want to load into it, it's the maximum number of simultaneous streams that you'll be playing. Second, SoundPool has limited memory for sounds, about 1MB. So I wouldn't be at all surprised if you hit some undocumented limit to the number of tracks you can load in at one time. Notice that 80 sounds times 55k per sound is definitely over 1MB. And that limit is for after the mp3s have been uncompressed into audio data inside SoundPool.
Related
I have started a android.media.MediaPlayer file with:
mp1.start()
and then trying the looping with:
setLooping(true);
but this is ending up with a delay in playing the file again.
I am trying to run an mp3 file containing a rhythm with a set tempo. Is there any better way of looping it in such a manner that the tempo timing does not get disturbed and the rhythm plays seamlessly without any stutter/delay?
Should I use SoundPool instead?
Most of best practices for this particular case recommend using .ogg format. You can convert you file easily using VNC media player.
Wiki for .ogg file format - http://en.wikipedia.org/wiki/.ogg
Another solution is the SoundPool and the third one - is to use Audacity and cut the quiet/“blanksound” from you audio file.
If your audio is not long, then use SoundPool for low-latency media playback, instead of MediaPlayer. Also convert it to ogg, as others have already pointed it out.
Edit: if it is just a tempo, and not a continous sound, then maybe you can also measure the latency and seek your audio based on that, but I am not sure you will get better results this way.
Mediaplayer solutions:
If you insist on using MediaPlayer, then you can:
either crop the sound at the end of your audio files, so there's no sound gap between two playback loops
or create a custom solution yourself as the one described here.
Soundpool alternative:
Now, from my personal experience, if you want to loop files small in size and duration, not more than 1MB, then Soundpool is more convenient and it seems that not any relevant problems are reported in contrary to the MediaPlayer. There have been many complaints when trying to loop sounds using MediaPlayer, so generally Soundpool is usually preferred for looping.
Soundpool size limit:
If you are concerned about Sounpool's size limit, keep in mind that it has 1Mb buffer size limit per track. But this limit applies not to file size but to decompressed raw PCM data. SoundPool is going to decompress the loaded audio to PCM data so it is ready to play instantly without the latency of decoding. If the audio you are loading is compressed heavily, such as MP3, then that can get blown up quite a bit.
Improve performance:
Also, as suggested in another answer, files of type ".ogg" according to many sources appear to perform better than ".mp3" in general. So, you should try to convert your files for better performance, but I don't think you will see an improvement concerning looping.
To convert your files you can use an online tool such as this. If you convert your files remember to also make these changes:
Change your sound file's sampling rate to 16000 Hz
Change your audio channel to mono, instead of stereo.
Make sure your file after these processes is smaller than 1 mb in size.
Please try to do it this way.
audio = MediaPlayer.create(this, R.raw.pl);
audio.setLooping(true);
audio.start();
I'm building an app that plays multiple short sound effects in one activity.
There are over 80 buttons with each buttons that plays a specific sound effect.
I've searched about SoundPool and MediaPlayer and found out SoundPool is more efficient for short sound files.
Here's my question, if I should load over 80 sound effects in one activity, would SoundPool still be the better option? I ask because SoundPool loads the sound at once and reuses it, I think it's a bit heavy to load 80 sounds in one activity (Maybe I'm wrong.) Would like to hear the experts here for a better way or any advice!
Thanks in advance
It does not depend by the number of sounds, but from their size in terms of bytes. Every sound is loaded into memory and if they are too big, you could not have enough memory to load them all.
I would consider using AudioTrack. You instantiate it and when you have to play a sound you can read it from file system or assets or resources and add it to the play queue. It works only with PCM.
Since my last question hasnt been answered where I used simple medaiplayer (Sound sometimes remains silent when playing more sounds in a row, why?) and tried to create the whole thing using SoundPool. But guess what, almost same thing happens but with an error
AudioFlinger could not create track, status: -12
Error creating AudioTrack
I read about that at most 32 sound can be stored in the memory of soundpool then I will get the error. Thats right, after the 32th sound I cannot play any of the sounds since I always get the error. So how could I use more than 32 sounds with SoundPool? I tried to use 3 Soundpools with 20 sounds in each of them, and I always unload all the sound from the other pools with this:
mSoundPoolMapV1.clear(); //clearing HashMap
for(int i=1;i<15;i++){
mSoundPoolV1.unload(i);
}
But same error comes again. (I use 22k sounds instead of 44.1k, I read this could solve it but nothing happened)
Any suggestions appreciated. What the hell is that I cannot play about 50 sounds neither with mediaplayer and nor with soundpool? How is that possible??
With release() :
mSoundPoolMap.clear();
for(int i=1;i<50;i++){
mSoundPool.unload(i);
}
mSoundPool.release();
mSoundPoolMap.put(1, mSoundPool.load(Main.this, R.raw.sound1, 1));
...
mSoundPoolMap.put(50, mSoundPool.load(Main.this, R.raw.sound50, 1));
SO I clear the hashmp, then unload all the sounds, then I release the soundpool. Then I fill the hashmap again, but now It gives me no sound at all. I must miss something, could you tell me what?
There's a limitation in the AudioMixer that only allows 32 AudioTracks at the same time. The SoundPool will try to create an AudioTrack whenever it starts playback of one of the channels (I guess this corresponds to a sample) belonging to the pool. However, the track is not destroyed until you destroy the SoundPool, so the track name will remain allocated even if it has been stopped.
You could try calling release() on your SoundPool. That should cause the native SoundPool object to be destroyed, thereby destroying all AudioTracks it has created and deallocating their names in the AudioMixer.
Underlying audio hardware is not unlimited. You can only hold so many sounds in memory at a time. When I made a 3D audio library for desktops the limit was variable so I had to query the limit from the hardware before starting or it would lead to seemingly random failures. You should have a single SoundPool and just load and unload sounds into as you need them. Then you need to set up some kind of a priority for the sounds that should be playing so you can make sure that the sounds you really need don't get unloaded to play an optional background noise.
The SoundPool Documentation actually has a really nice description of a typical use-case.
I have a game in which a "ding" sound is made for each point scored in a game. Sometimes you can score points in very quick succession. In this case I do not allow overlapping sounds so I wait for the mediaplayer's isPlaying() function to go to false before playing the next sound.
On every phone I've tried so far (admittedly all 2.2 or 2.3) the result is a pleasing rapid-fire succession of sounds.
But just now I've tried Samsung galaxy S II with 4.0.3. On this machine each "ding" is separated by a long gap. The isPlaying() state seems to last twice as long as the sound itself. According to Audacity the sound should last about 0.1 seconds, but isPlaying() is remaining true for .28 seconds.
The sound is saved from Audacity into Ogg Vorbis format.
Any idea what's gone wrong?
It's better to use SoundPool for playing rapid-fire samples in games as they're uncompressed once and kept in memory. MediaPlayer may be decoding on the fly, causing a delay as it gets ready. Not sure why there's such a difference between devices, but I'd give SoundPool a try and see if it improves things.
I have 3 sounds that I would like to play sequentially in Android. I have created a SoundPool and set the "maxStreams" to "1" thinking that in the for loop the sounds would play "one at a time" not all at once. This, unfortunately, is wrong. How do I play the sounds sequentially and NOT all at once using soundPool. Thanks.
The SoundPool has no queue feature. It will just stop previous sounds when a stream is needed.
If the maximum number of streams is exceeded, SoundPool will
automatically stop a previously playing stream based first on priority
and then by age within that priority.
SoundPool documentation