Comment jouer des sons à des périodes précises sur différents appareils dans Android

Je développe un jeu dans Android et j'ai rencontré un bug très ennuyeux et difficile à trouver. Le problème est que lorsque vous utilisez SoundPool pour jouer vos sons, vous pouvez effectivement boucler tout son que vous jouez. Dans ce cas, le problème est le son des "étapes en cours d'exécution"; Ce son est exécuté assez rapidement et continuellement (environ 400ms ) lorsque le personnage principal est en cours d'exécution.

Maintenant, lorsque vous lisez le son sur un périphérique régulier (pas si puissant), par exemple, Samsung SII, le son est joué tous les 500ms – mais si je lance le même code sur un autre appareil (disons Samsung SIV, Samsung SIII), le son Joue deux fois ou même trois fois plus vite.

Il semble que plus les spécifications matérielles du périphérique sont puissantes, plus vite il joue. Sur certains appareils, il joue si vite que vous entendez presque un solide son continu. J'ai cherché des techniques pour définir un ratio spécifique sur la période entre les sons, mais cela ne fonctionne pas correctement et le problème persiste. Est-ce que quelqu'un sait comment le réparer, soit en utilisant SoundPool , SoundPool , ou toute autre API de contrôle du son sur Android?

  • Soundpool ne boucle pas l'Android 4.3
  • AudioFlinger n'a pas pu créer de piste. Statut: -12
  • Android SoundPool: soyez informé à la fin de la lecture
  • Android MediaPlayer setNextMediaPlayer () alternative
  • L'échantillon de Soundpool n'est pas prêt
  • Uncaught exception lancé par le finalisateur java.lang.IllegalStateException: Binder a été finalisé
  • Soundpool ne joue que les 5 premières secondes du fichier. Pourquoi?
  • Comment puis-je savoir si un son a terminé de jouer dans Android?
  • 5 Solutions collect form web for “Comment jouer des sons à des périodes précises sur différents appareils dans Android”

    Le problème avec la simple mise en boucle ou l'utilisation d'un intervalle régulier pour des étapes comme les étapes est que vous avez un découplage possible du son et des visuels. Si votre son reçoit des retards ou une accélération, ou que vos effets visuels sont retardés ou accélérés, vous devriez régler ce délai de manière dynamique et automatique. Vous avez déjà cette question ici

    Une meilleure solution serait de placer un déclencheur sur l'événement exact qui devrait déclencher le son (dans ce cas, le pied étant placé vers le bas), qui joue ensuite le son. Cela signifie également que si vous avez plusieurs sources du son (comme des pas multiples), vous ne devez pas démarrer manuellement le son avec le bon intervalle.

    Vous pouvez utiliser un AudioTrack pour lire un flux continu de données PCM, car vous passerez un flux, vous pourriez être sûr de l'intervalle entre les sons. L'inconvénient pourrait être un peu de retard lors du premier démarrage du son, mais cela dépend de la taille minimale du tampon, et cela dépend, je pense, de la version Android et de l'appareil. Sur mon Galaxy s2 Android 4.1, il s'agissait d'environ 20 ms.
    Si vous pensez que cela pourrait être une option, je peux publier un code

    Je ne peux pas sembler reproduire le problème sur Galaxy Nexus et Nexus S, cela veut-il dire que je l'ai réparé? Ou peut-être que vous pourriez montrer ce que vous faites différemment de ceci:

     SoundPool soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100); Integer sound1 = soundPool.load(this, R.raw.file1, 1); Integer sound2 = soundPool.load(this, R.raw.file2, 1); playSound(sound1); public void playSound(int sound) { AudioManager mgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE); float volume = mgr.getStreamVolume(AudioManager.STREAM_MUSIC) / mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC); soundPool.play(sound, volume, volume, 1, -1, 1.0f); } 

    Si le problème est que vous souhaitez contrôler l'intervalle entre les sons discrets, la manière la plus simple de le faire est avec un gestionnaire.

    Fondamentalement, vous démarrez un jeu sonore qui est un processus asynchrone. Ensuite, vous utilisez un gestionnaire pour programmer un message pour lire le prochain son à l'avenir. Il faudra des essais et des erreurs pour le faire correctement, mais vous serez garanti que le son commencera au même intervalle après le son précédent sur chaque périphérique.

    Voici un code pour illustrer ce dont je parle.

    Voici une implémentation de gestionnaire que vous pouvez utiliser:

      handler = new Handler() { /* (non-Javadoc) * @see android.os.Handler#handleMessage(android.os.Message) */ @Override public void handleMessage(Message msg) { if (msg.what == NEXT_ITEM_MSG) { playNextSound(); } else if (msg.what == SEQUENCE_COMPLETE_MSG) { // notify a listener listener.onSoundComplete() } } }; 

    Ensuite, vous pouvez écrire playNextSound comme ceci:

     private void playNextSound() { if (mRunning) { // Get the first item SoundSequenceItem item = currentSequence.getNextSequenceItem(); if (item == null) { Message msg = handler.obtainMessage(SEQUENCE_COMPLETE_MSG); handler.sendMessage(msg); return; } // Play the sound int iSoundResId = item.getSoundResId(); if (iSoundResId != -1) { player.playSoundNow(soundResId); } // schedule a message to advance to next item after duration Message msg = handler.obtainMessage(NEXT_ITEM_MSG); handler.sendMessageDelayed(msg, item.getDuration()); } } 

    Et votre SoundSequenceItem pourrait être une classe simple qui possède un identifiant de ressource de fichier son et une durée. Si vous souhaitez continuer à jouer le son pendant que vous déplacez le personnage, vous pouvez faire quelque chose comme ça:

     public void onSoundComplete() { if (character.isRunning()) { currentSequence.addSequenceItem(new SoundSequenceItem(R.id.footsteps,500); playNextSound(); } } 

    Ou vous pouvez modifier playNextSound pour lire continuellement le même son. Le mien est écrit de cette façon pour pouvoir jouer différents sons dans l'ordre.

    J'ai eu beaucoup de problèmes pour développer des applications qui utilisaient des sons et des choses comme ça. Je ne vous suggère pas d'utiliser SoundPool car il est affecté par un bogue, et soyez conscient que les sons en boucle avec SoundPool ne fonctionneront pas sur des périphériques de 4,3 et plus, voir ce problème ouvert, chez AOSP – Issue tracker . Je pense que la solution est d'être native et d'utiliser OpenSL ES o des bibliothèques similaires.

    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.