AudioFlinger could not create track. status: -12
Asked Answered
M

9

42

I am programming for android 2.2 and am trying to using the SoundPool class to play several sounds simultaneously but at what feel like random times sound will stop coming out of the speakers.

for each sound that would have been played this is printed in the logcat:

AudioFlinger could not create track. status: -12 
Error creating AudioTrack
Audio track delete

No exception is thrown and the program continues to execute without any changes except for the lack of volume. I've had a really hard time tracking down what conditions cause the error or recreating it after it happens. I can't find the error in the documentation anywhere and am pretty much at a loss.

Any help would be greatly appreciated!

Edit: I forgot to mention that I am loading mp3 files, not ogg.

Messinger answered 15/8, 2012 at 5:44 Comment(4)
How many tracks are you creating? AFAIK -12 is NO_MEMORY, which could mean that you've run out of tracks (I think the max number of open tracks used to be 32 - not sure if that is still true).Orelu
Hmmmmm, I am loading a lot of tracks but they are split up among 5 soundpools. each soundpool will have a maximum of ~15 sounds loaded. do you know if the 32 max tracks was system wide or per sound pool?Messinger
It's per mixer thread (of which you've got one per output thread AFAIK). But since many platforms use a single output thread for all non-A2DP playback it essentially becomes a global limit.Orelu
I got this when I called stop but failed to call release on my tracks.Corporeity
G
23

i had almost this exact same problem with some sounds i was attempting to load and play recently.

i even broke it down to loading a single mp3 that was causing this error.

one thing i noted: when i loaded with a loop of -1, it would fail with the "status 12" error, but when i loaded it to loop 0 times, it would succeed. even attempting to load 1 time failed.

the final solution was to open the mp3 in an audio editor and re-edit it with slightly lesser quality so that the file is now smaller, and doesn't seem to take up quite as many resources in the system.

finally, there is this discussion that encourages performing a release on the objects you are using, because there is indeed a hard limit on the resources that can be used, and it is system-wide, so if you use several of the resources, other apps will not be able to use them.

https://groups.google.com/forum/#!topic/android-platform/tyITQ09vV3s/discussion%5B1-25%5D

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), and AudioTrack is used internally beneath SoundPool, ToneGenerator, MediaPlayer, native audio based on OpenSL ES, etc. But the actual AudioTrack limit is < 32; it depends more on soft factors such as memory, CPU load, etc. Also note that the limiter in the Android audio mixer does not currently have dynamic range compression, so it is possible to clip if you have a large number of active sounds and they're all loud.

For video players the limit is much much lower due to the intense load that video puts on the device.

I'll use this as an opportunity to remind media developers: please remember to call release() for media objects when your app is paused. This frees up the underlying resources that other apps will need. Don't rely on the media objects being cleaned up in finalize by the garbage collector, as that has unpredictable timing.

Gavrielle answered 19/8, 2012 at 6:47 Comment(0)
M
3

I had a similar issue where the music tracker within my Android game would drop notes and I got the Audioflinger error (although my status was -22). I got it working however so this might help some people.

The problem occurred when a single sample was being output multiple times simultaneously. So in my case it was a single sample being played on two or more tracks. This seemed to occasionally deadlock or something and one of the two notes would be dropped. The solution was to have two copies of the sample (two actual ogg files - identical but both in the assets). Then on each track even although I was playing the same sample, it was coming from a different file. This totally fixed the issue for me.

Not sure why it works as I cache the samples into memory, but even loading the same file into two different sounds didn't fix it. Only when the samples came out of two different files did the errors go away.

I'm sure this won't help everyone and it's not the prettiest fix but it might help someone.

Mariquilla answered 28/1, 2013 at 0:32 Comment(1)
Thank you very much! This really helped me :) I had the error mentioned in the question when switching to ear speaker on playing voice (with exo player). And the problem was the 'simultaneously' part actually, playing voice immediately just after calling pause without any delay.Inhabitant
S
2

john.k.doe is right. You must reduce the size of your mp3 file. You should keep the size under 100kb per file. I had to reduce my 200kb file to 72kb using a constante bit rate(CBR) of 32kbps instead of the usual 128kbps. That worked for me!

Smutchy answered 9/5, 2013 at 3:38 Comment(0)
A
1

Try

 final ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 50);
 tg.startTone(ToneGenerator.TONE_PROP_BEEP, 200);
 tg.release();

Releasing should keep your resources.

Adrianneadriano answered 27/12, 2012 at 3:53 Comment(0)
Z
1

I was with this problem. In order to solve it i run the method .release() of SoundPool object after finish playing the sound.

Here's my code:

SoundPool pool = new SoundPool(10, AudioManager.STREAM_MUSIC, 50);
final int teste = pool.load(this.ctx,this.soundS,1);
pool.setOnLoadCompleteListener(new OnLoadCompleteListener(){

@Override 
    public void onLoadComplete(SoundPool sound,int sampleId,int status){
        pool.play(teste, 20,20, 1, 0, 1);
        new Thread(new Runnable(){
@Override                       
     public void run(){
         try {
        Thread.sleep(2000);
                pool.release();
         } catch (InterruptedException e) { e.printStackTrace(); }
         }
        }).start();
    }
});

Note that in my case my sounds had length 1-2 seconds max, so i put the value of 2000 miliseconds in Thread.sleep(), in order to only release the resources after the player have had finished.

Z answered 6/11, 2013 at 15:2 Comment(0)
C
1

Like said above, there is a problem with looping: when I set repeat to -1 I get this error, but with 0 everything is working properly. I've noticed that some sounds give this error when I'm trying to play them one by one. For example:

mSoundPool.stop(mStreamID);
mStreamID = mSoundPool.play(mRandID, mVolume, mVolume, 1, -1, 1f);

In such case, first track is played ok, but when I switch sounds, next track gives this error. It seems that using looping, a buffer is somehow overloaded, and mSoundPool.stop cannot release resources immediately.

Solution:

final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
   @Override
   public void run() {
      mStreamID = mSoundPool.play(mRandID, mVolume, mVolume, 1, -1, 1f);
}, 350);

And it's working, but delay is different for different devices.

Carey answered 1/7, 2015 at 15:50 Comment(0)
F
1

In my case, reducing the quality and thereby the file sizes of the MP3's to under 100kb wasn't sufficient, as some 51kb files worked while some longer duration 41kb files still did not.

What helped us was reducing the sample rate from 44100 to 22050 or shortening the duration to less than 5 seconds.

Fiducial answered 3/9, 2015 at 21:6 Comment(0)
D
1

I see too many overcomplicated answer. Error -12 means that you did not release the variables. I had the same problem after I played an OGG audio file 8 times. This worked for me:

SoundPoolPlayer onBeep; //Global variable 

    if(onBeep!=null){
       onBeep.release();
    }
    onBeep = SoundPoolPlayer.create(getContext(), R.raw.micon);
    onBeep.setOnCompletionListener(
       new MediaPlayer.OnCompletionListener() {
          @Override
          public void onCompletion(MediaPlayer mp) {    //mp will be null here
             loge("ON Beep! END");
             startGoogleASR_API_inner();
             }
                        }
          );
    onBeep.play();

Releasing the variable right after .play() would mess things up, and it is not possible to release the variable inside onCompletion, so notice how I release the variable before using it(and checking for null to avoid nullpointer exceptions).

It works like charm!

Dafna answered 30/10, 2017 at 9:50 Comment(0)
M
0

A single soundPool has an internal memory limitation of 1 (one) Mb. You might be hitting this if your sound is very high quality. If you have many sounds and are hitting this limit, just create more soundpools, and distribute your sounds across them.

You may not even be able to reach the hard track limit if you are running out of memory before you get there.

That error not only appears when the stream or track limit has been reached, but also the memory limit. Soundpool will stop playing old and/or de-prioritized sounds in order to play a new sound.

Mariammarian answered 8/10, 2013 at 0:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.