web-dev-qa-db-fra.com

Android: API sonore (déterministe, faible latence)

J'examine toutes sortes d'API sonores Android et j'aimerais savoir laquelle utiliser. Mon objectif est d'obtenir un son à faible latence ou, au moins, un comportement déterministe en ce qui concerne le délai de lecture.

Nous avons eu beaucoup de problèmes et il semble que l'API de son Android est une merde, alors j'explore les possibilités.

Le problème que nous avons est qu'il y a un délai important entre sound_out.write(sound_samples); et le son réel joué par les haut-parleurs. Habituellement, c'est environ 300 ms. Le problème est que sur tous les appareils, c'est différent; certains n'ont pas ce problème, mais la plupart sont paralysés (cependant, l'appel CS n'a pas de latence). Le plus gros problème de ce délai ridicule est que, sur certains appareils, ce délai semble être une valeur aléatoire (c’est-à-dire que ce n’est pas toujours 300 ms).

Je suis en train de lire sur OpenSL ES et j'aimerais savoir si quelqu'un en a déjà fait l'expérience, ou si c'est la même merde mais emballée dans un paquet différent?

Je préfère avoir un accès natif, mais je ne crains pas l'indirection de la couche Java tant que je peux obtenir un comportement déterministe: soit le délai doit être constant (pour un périphérique donné), soit je souhaite accéder à la lecture actuelle. position au lieu de le deviner avec une plage d'erreur de ± 300 ms ...

MODIFIER:
1,5 ans plus tard, j'ai essayé plusieurs téléphones Android pour voir comment obtenir la meilleure latence possible pour une communication vocale en temps réel. À l’aide d’outils spécialisés, j’ai mesuré le retard du trajet de sortie d’onde. Les meilleurs résultats ont été supérieurs à 100 ms, la plupart des téléphones se situant dans une plage de 180 ms. Quelqu'un a des idées?

34
Pavel

SoundPool est l'interface sur la plus faible latence sur la plupart des périphériques, car le pool est stocké dans le processus audio. Tous les autres chemins audio nécessitent une communication inter-processus. OpenSL est le meilleur choix si SoundPool ne répond pas à vos besoins.

Pourquoi OpenSL? AudioTrack et OpenSL ont des latences similaires, avec une différence importante: les rappels de mémoire tampon AudioTrack sont traités dans Dalvik, tandis que les rappels OpenSL sont gérés dans des threads natifs. L'implémentation actuelle de Dalvik n'est pas capable de gérer les rappels à des latences extrêmement basses, car il n'y a aucun moyen de suspendre la récupération de place lors des rappels audio. Cela signifie que la taille minimale des tampons AudioTrack doit être supérieure à celle des tampons OpenSL afin de permettre une lecture sans problèmes.

Sur la plupart des versions Android, cette différence entre AudioTrack et OpenSL ne fait aucune différence. Mais avec Jellybean, Android dispose désormais d’un chemin audio à faible latence. La latence réelle dépend toujours du périphérique, mais elle peut être considérablement plus basse que précédemment. Par exemple, http://code.google.com/p/music-synthesizer-for-Android/ utilise des tampons de 384 images sur le Galaxy Nexus pour une latence de sortie totale inférieure à 30 ms. Cela nécessite que le fil audio gère les mémoires tampons environ une fois toutes les 8 ms, ce qui était impossible dans les versions précédentes d'Android. Ce n'est toujours pas faisable dans un fil Dalvik.

Cette explication suppose deux choses: premièrement, vous demandez à OpenSL les tampons les plus petits possibles et vous effectuez le traitement dans le rappel de mémoire tampon plutôt que dans une file d'attente de mémoire tampon. Deuxièmement, votre appareil prend en charge le chemin d'accès à faible latence. Sur la plupart des appareils actuels, vous ne verrez pas beaucoup de différence entre AudioTrack et OpenSL ES. Toutefois, sur les appareils prenant en charge Jellybean + et l’audio à faible temps de latence, OpenSL ES vous fournira le chemin le plus lent.

26
Ian Ni-Lewis

IIRC, OpenSL passe par la même interface qu'AudioTrack, donc, au mieux, il correspond à AudioTrack. (FWIW, j'utilise actuellement OpenSL pour une sortie "faible latence")

La triste vérité est qu’il n’existe pas d’audio à faible latence sur Android. Il n'existe même pas de méthode appropriée pour marquer et/ou filtrer les périphériques en fonction de la latence audio.

L’interface que vous voudrez utiliser pour réduire la latence dépendra de ce que vous essayez de faire. Si vous voulez avoir un flux audio, vous allez regarder OpenSL ou AudioTrack.

Si vous souhaitez déclencher des onehots statiques, vous pouvez utiliser SoundPool. Pour les onehots statiques, SoundPool aura une faible latence car les échantillons sont préchargés sur le matériel. Je pense qu'il est également possible de précharger des photos avec OpenSL, mais je n'ai pas essayé.

2
Drakonite

La latence la plus basse que vous puissiez obtenir provient de SoundPool. Vous pouvez jouer de cette façon une limite de la taille du son, mais si vous êtes sous la limite (1 Mo, IIRC), le temps de latence est assez faible. Même ce n'est probablement pas 40ms, cependant.

Mais c'est plus rapide que ce que vous pouvez obtenir en streaming, du moins d'après mon expérience.

Avertissement: il est possible que vous rencontriez des pannes occasionnelles dans SoundPool sur des appareils Samsung. Je suppose que cela ne se produit que lorsque vous accédez au SoundPool à partir de plusieurs threads, mais je n'ai pas vérifié cela.

EDIT: OpenSL ES a apparemment une latence extrêmement ÉLEVÉE sur Kindle Fire, alors que SoundPool est bien meilleur, mais l’inverse peut être vrai sur d’autres plateformes.

1
SomeCallMeTim

À propos du problème de la latence déterministe/constante, vous trouverez ici un article intéressant:

APPROCHES POUR UNE LATENCE AUDIO CONSTANTE SOUS Android

Le cœur de leurs recherches est le suivant: Etant donné que Audio HAL, qui est l’un des niveaux les plus profonds d’audiopath et responsable du minutage des événements de rappel audio, est mis en œuvre par le fournisseur, les latences relatives peuvent varier, en particulier dans le matériel peu coûteux. Ils suggèrent donc deux approches pour réduire la variance de la latence. L'une consiste à gérer le temps de rappel en insérant l'audio à intervalles fixes, l'autre à filtrer les temps de rappel pour estimer le moment auquel un rappel à latence constante aurait dû se produire en appliquant un filtre de lissage. Avec ces deux approches, le pourrait considérablement réduire la variance de la latence.

Il convient également de mentionner qu’il existe une nouvelle API audio native pour Android, AAudio.

API AAudio

Il est disponible/stable à partir d'Android Oreo 8.1 (API niveau 27). Il existe également un wrapper, qui choisit dynamiquement entre OpenSL ES et AAudio et qui est beaucoup plus facile à coder pour OpenSL ES. Il est toujours dans l'aperçu du développeur.

Bibliothèque Audio Hautbois

0
Niklas D

Le meilleur moyen d’obtenir une latence faible pour le code natif sur Android est d’utiliser Oboe.

https://github.com/google/oboe

Oboe encapsule AAudio sur les nouveaux périphériques. AAudio offre les chemins de latence les plus bas possibles. Si AAudio n'est pas disponible, Oboe appelle OpenSL ES. Le hautbois est beaucoup plus facile à utiliser que OpenSL ES.

AAudio appelle via AudioTrack ou via un nouveau chemin de données MMAP. AAudio facilite l’obtention d’une piste FAST, car vous pouvez laisser certains paramètres non spécifiés. AAudio choisira ensuite les bons paramètres nécessaires pour une piste FAST.

0
philburk