How to play more than 32 sounds using SoundPool? - android

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.

Related

Superpowered SDK popping sounds with multiple players

I get popping sounds when simultaneously playing multiple SuperpoweredAudioPlayers. When one SuperpoweredAudioPlayer is playing a moderately loud sound, a popping sound gets made when I call play() on a second SuperpoweredAudioPlayer, even if there is initial silence in the second player and the process() volume is set to 0. I can't have pops in the output since I'm making a music production app. The output also needs to be generated in real time. Am I doing something wrong or is there a workaround? Would it be fixed by having the players in separate threads?
Separate threads are definitely not the solution, as all your audio processing should happen on the same thread. Two audio players are very low with CPU, you don't have a processing problem.
Perhaps you forgot to handle the return value of the process() function. If it's false, then it means silence, and the buffer is not updated (zeroed) at all.

Can Android Visualizer Class be used on SoundPool object?

When using a SoundPool audio class, it definitely has some advantages over a MediaPlayer when just playing short audio clips. The two I've noticed is SoundPool is a lot faster. MediaPlayer can lag a bit on startup and it's much easier to go from one sound clip to the next, where I don't have to stop,reset,prepare each time.
However, is it possible to use the visualizer to get real time fft data from audio data playing in the SoundPool like it is for MediaPlayer? I couldn't come across any topics that cover that, but by the off chance I thought I would ask because it seems like it should be possible. The documentation says, "The SoundPool library uses the MediaPlayer service to decode the audio into a raw 16-bit PCM mono or stereo stream." So if I could reference the MediaPlayer that SoundPool is using then I think I could just use getAudioSessionId() perhaps?
I already tried setting session ID to 0 to just get the output mix. It didn't work but it's not really the ideal effect that I am looking for anyway. Also one of the first things I did was try using the loaded SoundPool SoundID in place of the visualizers session ID, but that also didn't work.

SoundPool error: no more track names available

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.

Android SounPool not Overlap

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

Android soundpool timing

Is there a reliable way to prevent truncating of sounds in soundpool? I have had some success with the sleep() function between sounds, but they still sometimes miss the last bit of sound before starting another sound. My app plays short sounds in sequence.
Jerry
Although this is an old question, I thought I would post something here since I couldn't find a solution to this problem online but did come up with something of a solution...
I get the duration of each sound (using MediaPlayer) when my app starts up, and store the R.id.sound_name value and the duration together. I can then play the sounds using the SoundPool.
Code to get duration:
private long getSoundDuration(int rawId){
MediaPlayer player = MediaPlayer.create(context, rawId);
int duration = player.getDuration();
return duration;
}
In my sound class, I then play the sound as usual then sleep for the duration. Pretty simple stuff.
Seems to work well. Gives me the advantages of low-latency from SoundPool, plus ability to chain things.
A couple things to note:
Don't get the duration each time, as creating a MediaPlayer has overhead.
Durations are taken from file metadata -- ogg's work great for me, but I can't vouch for anything else.
Make sure you have enough Streams.
in the SoundPool constructor, the first argument is MaxStreams.
Set that to whatever you seem fit. 8 or so should be enough i guess... but you might need more, depending on your sounds.

Categories

Resources