web-dev-qa-db-fra.com

AudioFlinger n'a pas pu créer de piste. statut: -12

Je suis en train de programmer pour Android 2.2 et j'essaie d'utiliser la classe SoundPool pour jouer plusieurs sons simultanément, mais à des moments aléatoires, le son cesse de sortir des haut-parleurs.

pour chaque son qui aurait été joué, ceci est imprimé dans le logcat:

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

Aucune exception n'est levée et le programme continue de s'exécuter sans aucune modification, à l'exception du manque de volume. J'ai eu beaucoup de difficulté à repérer les conditions à l'origine de l'erreur ou à la recréer ultérieurement. Je ne trouve nulle part l'erreur dans la documentation et je suis à peu près perdue. 

Toute aide serait grandement appréciée!

Edit: J'ai oublié de mentionner que je charge des fichiers mp3, pas des fichiers ogg.

37
user1599837

j'avais presque le même problème avec certains sons que j'essayais de charger et de jouer récemment.

je l'ai même décomposé pour charger un seul mp3 qui causait cette erreur.

une chose que j’ai remarquée: quand j’ai chargé avec une boucle de -1, il échouerait avec l’erreur "status 12", mais quand je l’aurais chargé de boucler 0 fois, il réussirait. même tenter de charger 1 fois a échoué.

la solution finale consistait à ouvrir le mp3 dans un éditeur audio et à le rééditer avec une qualité légèrement inférieure, de sorte que le fichier soit maintenant plus petit et ne semble pas occuper autant de ressources du système.

enfin, il y a cette discussion qui encourage à effectuer une libération sur les objets que vous utilisez, car il existe en effet une limite stricte sur les ressources pouvant être utilisées, et elle est globale au système, donc si vous utilisez plusieurs des ressources, d'autres les applications ne pourront pas les utiliser.

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

Pour l'audio, il existe une limite stricte de 32 objets AudioTrack actifs par device (pas par application: vous devez partager ces 32 avec le reste du système), et AudioTrack est utilisé en interne sous SoundPool, ToneGenerator, MediaPlayer, audio natif basé sur OpenSL ES, etc. Mais la limite AudioTrack réelle est <32; cela dépend plus de facteurs mous tels que la mémoire, la charge du processeur, etc. Notez également que le limiteur dans le fichier Le mixeur audio Android ne dispose pas actuellement de compression de la plage dynamique. il est donc possible de découper si vous avez un grand nombre de sons actifs et ils sont tous bruyants.

Pour les lecteurs vidéo, la limite est beaucoup plus basse en raison de la charge intense cette vidéo met sur l'appareil. 

Je vais en profiter pour rappeler aux développeurs de médias: s'il vous plaît N'oubliez pas d'appeler release () pour les objets multimédias lorsque votre application est suspendue . Cela libère les ressources sous-jacentes dont d'autres applications auront besoin . Ne comptez pas sur les objets multimédias nettoyés lors de la finalisation par le fichier collecteur de déchets, car cela a un timing imprévisible.

20
john.k.doe

john.k.doe a raison. Vous devez réduire la taille de votre fichier mp3. Vous devez conserver une taille inférieure à 100 Ko par fichier. J'ai dû réduire mon fichier de 200 Ko à 72 Ko en utilisant un débit constant (CBR) de 32 Ko au lieu des 128 Ko habituels. Cela a fonctionné pour moi!

2
rotterick

J'ai eu un problème similaire où le tracker de musique dans mon jeu Android laissait tomber des notes et j'ai eu l'erreur Audioflinger (même si mon statut était -22). Je l'ai fait fonctionner cependant alors cela pourrait aider certaines personnes.

Le problème est survenu lorsqu'un seul échantillon était sorti plusieurs fois simultanément. Donc, dans mon cas, il s’agissait d’un seul échantillon joué sur deux pistes ou plus. Cela semblait parfois être une impasse ou quelque chose et une des deux notes serait supprimée. La solution consistait à disposer de deux copies de l'échantillon (deux fichiers ogg réels - identiques mais les deux dans l'actif). Puis, sur chaque piste, même si je jouais le même échantillon, il provenait d’un fichier différent. Cela a totalement résolu le problème pour moi. 

Je ne sais pas pourquoi cela fonctionne car je mets en cache les échantillons dans la mémoire, mais même charger le même fichier dans deux sons différents ne le réglait pas. Ce n'est que lorsque les échantillons sont sortis de deux fichiers différents que les erreurs disparaissent.

Je suis sûr que cela n’aidera pas tout le monde et que ce n’est pas la solution la plus jolie, mais que cela pourrait aider quelqu'un. 

2
user2016617

Dans mon cas, réduire la qualité et par conséquent la taille des fichiers MP3 à moins de 100 Ko n'était pas suffisant, car certains fichiers de 51 ko fonctionnaient alors que d'autres, d'une durée supérieure, de 41 ko, ne fonctionnaient toujours pas.

Ce qui nous a aidé a été de réduire le taux d'échantillonnage de 44100 à 22050 ou de réduire la durée à moins de 5 secondes.

1
Steve Castro

Je vois trop de réponses trop compliquées. Erreur -12 signifie que vous n'avez pas publié les variables . J'ai eu le même problème après avoir lu un fichier audio OGG 8 fois . Cela a fonctionné pour moi:

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();

Libérer la variable juste après .play () gâcherait tout, et il n'est pas possible de libérer la variable à l'intérieur de onCompletion, alors remarquez comment je libère la variable avant de l'utiliser (et vérifiant null pour éviter les exceptions nullpointer).

Cela fonctionne comme un charme!

1
Josh

Comme indiqué ci-dessus, il y a un problème de boucle: lorsque je répète répétition à -1, j'obtiens cette erreur, mais avec 0 tout fonctionne correctement ..__ J'ai remarqué que certains sons donnent cette erreur lorsque j'essaie de jouez les un par un. Par exemple:

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

Dans ce cas, la première piste est jouée correctement, mais lorsque je change de son, la piste suivante donne cette erreur. Il semble qu'en utilisant la mise en boucle, une mémoire tampon soit en quelque sorte surchargée et mSoundPool.stop ne peut pas libérer les ressources immédiatement.

Solution :

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

Et cela fonctionne, mais le délai est différent pour différents appareils.

1
Oleksandr Albul

J'étais avec ce problème. Afin de le résoudre, je lance la méthode .release () de l'objet SoundPool après avoir fini de jouer le son.

Voici mon 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();
    }
});

Notez que dans mon cas mes sons avaient une longueur maximum de 1-2 secondes, donc je mets la valeur de 2000 millisecondes dans Thread.sleep (), afin de ne libérer que les ressources une fois que le joueur a terminé.

0
Afaria

Essayer 

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

La libération devrait garder vos ressources.

0
Cléssio Mendes

Un seul soundPool a une limite de mémoire interne de 1 Mb. Vous pouvez toucher ceci si votre son est de très haute qualité. Si vous avez beaucoup de sons et que vous atteignez cette limite, créez simplement plus de pools de sons et distribuez-les.

Vous ne pourrez peut-être même pas atteindre la limite de la voie difficile si vous manquez de mémoire avant d'y arriver.

Cette erreur apparaît non seulement lorsque la limite de flux ou de piste a été atteinte, mais également la limite de mémoire. Soundpool cessera de jouer des sons anciens et/ou sans priorité afin de reproduire un nouveau son. 

0
Dominic Cerisano