41 votes

Lecture audio à faible latence sur Android

J'essaie actuellement de minimiser la latence audio pour une application simple :

J'ai une vidéo sur un PC, et je transmets l'audio de la vidéo par RTP à un client mobile. Avec un algorithme de mise en mémoire tampon très similaire, je peux obtenir une latence de 90 ms sur iOS, mais une latence terrible de ± 180 ms sur Android.

Je suppose que la différence vient du fait que bien connu latence questions sur Android.

Cependant, après avoir lu un peu, Je suis tombé sur cet article qui stipule que :

  1. L'audio à faible latence est disponible depuis Android 4.1/4.2 sur certains appareils.

  2. L'audio à faible latence peut être obtenu en utilisant libpd, qui est la bibliothèque Pure Data pour Android .

J'ai deux questions, directement liées à ces deux déclarations :

  1. Où puis-je trouver plus d'informations sur le nouveau système audio à faible latence de Jellybean ? C'est tout ce que j'ai pu trouver, mais il manque cruellement d'informations spécifiques. . Les changements doivent-ils être transparents pour moi, ou dois-je implémenter une nouvelle classe/des appels à l'API pour que je remarque des changements dans mon application ? J'utilise l'API AudioTrack et je ne suis même pas sûr qu'elle puisse bénéficier de cette amélioration ou que je doive me tourner vers un autre mécanisme de lecture audio.

  2. Devrais-je envisager d'utiliser libpd ? Il me semble que c'est la seule chance que j'ai d'obtenir des latences plus faibles, mais puisque j'ai toujours considéré PD comme un utilitaire de synthèse audio, est-il vraiment adapté à un projet qui ne fait que saisir des images d'un flux réseau et les lire ? Je ne fais pas vraiment de synthèse. Est-ce que je suis la mauvaise piste ?

En outre, avant que quelqu'un ne mentionne OpenSL ES, Cet article indique clairement qu'il ne faut pas s'attendre à une amélioration de la latence en l'utilisant. :

"Comme OpenSL ES est une API C native, les threads d'applications non-Dalvik qui appellent OpenSL ES n'ont pas de surcharge liée à Dalvik, comme le garbage par exemple. appellent OpenSL ES n'ont pas de surcharge liée à Dalvik comme les pauses de la les pauses de collecte de déchets. Cependant, il n'y a pas d'avantage de performance supplémentaire à l'utilisation d'OpenSL ES que cela. En particulier, l'utilisation d'OpenSL ES ne se traduit pas par une latence audio plus faible, une priorité d'ordonnancement plus élevée, etc. que ce que la plate-forme fournit généralement."

13 votes

Je suis membre de l'équipe Android et je travaille en étroite collaboration avec les auteurs de l'article que vous citez. Le passage que vous citez n'est plus strictement vrai. Lorsque l'article a été écrit, les plus petits tampons disponibles pour OpenSL étaient encore assez grands. Maintenant que la taille des tampons a été réduite dans Jellybean, la latence a chuté à un point tel que "les frais généraux liés à Dalvik tels que les pauses de collecte des déchets" sont une considération très importante. La seule façon de profiter de manière fiable des tampons plus petits de Jellybean est d'utiliser OpenSL.

69voto

Ian Ni-Lewis Points 1219

Pour obtenir la latence la plus faible sur Android à partir de la version 4.2.2, vous devez effectuer les opérations suivantes, classées du moins évident au plus évident :

  1. Choisissez un appareil qui prend en charge FEATURE_AUDIO_PRO si possible, ou FEATURE_AUDIO_LOW_LATENCY sinon. ("Faible latence" correspond à 50 ms en aller simple ; pro correspond à <20 ms en aller-retour).

  2. Utilisez OpenSL. Le GC Dalvik a un coût amorti faible, mais lorsqu'il fonctionne, il prend plus de temps qu'un thread audio à faible latence ne peut le permettre.

  3. Traiter l'audio dans un callback de file d'attente tampon. Le système exécute les callbacks de la file d'attente tampon dans un thread dont l'ordonnancement est plus favorable que celui des threads normaux du mode utilisateur.

  4. Faites en sorte que la taille de votre tampon soit un multiple de AudioManager.getProperty(PROPERTY_OUTPUT_FRAMES_PER_BUFFER). Sinon, votre callback recevra occasionnellement deux appels par timeslice au lieu d'un. À moins que l'utilisation de votre CPU soit très faible, cela finira probablement par provoquer des problèmes. (Sur Android M, il est très important d'utiliser EXACTEMENT la taille de la mémoire tampon du système, en raison d'un bogue dans le code de gestion de la mémoire tampon).

  5. Utilisez la fréquence d'échantillonnage fournie par AudioManager.getProperty(PROPERTY_OUTPUT_SAMPLE_RATE). Sinon, vos tampons feront un détour par le rééchantillonneur du système.

  6. Ne jamais faire un syscall ou verrouiller un objet de synchronisation à l'intérieur du callback du tampon. Si vous devez synchroniser, utilisez une structure sans verrou. Pour de meilleurs résultats, utilisez une structure complètement sans attente, comme un tampon en anneau à lecture unique et à écriture unique. Un grand nombre de développeurs se trompent et se retrouvent avec des problèmes imprévisibles et difficiles à déboguer.

  7. Utilisez des instructions vectorielles telles que NEON, SSE, ou tout autre jeu d'instructions équivalent sur votre processeur cible.

  8. Testez et mesurez votre code. Notez le temps d'exécution - et n'oubliez pas que vous devez connaître la performance la plus défavorable, et non la moyenne, car c'est le cas le plus défavorable qui provoque les problèmes. Et soyez prudent. Vous savez déjà que s'il faut plus de temps pour traiter votre audio que pour le lire, vous n'obtiendrez jamais une faible latence. Mais sur Android, c'est encore plus important, car la fréquence du processeur fluctue énormément. Vous pouvez utiliser 60 à 70 % de l'unité centrale pour l'audio, mais n'oubliez pas que ce pourcentage variera en fonction de la température de l'appareil, du démarrage et de l'arrêt des radios wifi ou LTE, etc.

L'audio à faible latence n'est plus une nouvelle fonctionnalité pour Android, mais elle nécessite toujours des modifications spécifiques au matériel, aux pilotes, au noyau et au framework pour être mise en œuvre. Cela signifie qu'il y a beaucoup de variations dans la latence que vous pouvez attendre de différents appareils, et étant donné le nombre de prix différents auxquels les téléphones Android sont vendus, il y aura probablement toujours des différences. Recherchez FEATURE_AUDIO_PRO ou FEATURE_AUDIO_LOW_LATENCY pour identifier les appareils qui répondent aux critères de latence requis par votre application.

0 votes

Re point 5. Si l'audio source est enregistré à 44100, par exemple, mais que PROPERTY_OUTPUT_SAMPLE_RATE est de 48000, l'audio sera lu trop rapidement. Quelle est la meilleure façon de contourner ce problème ?

0 votes

Ian, je crois que PROPERTY_OUTPUT_SAMPLE_RATE (POSR) fait référence au taux d'échantillonnage audio natif du processeur sonore de votre appareil. Cela signifie que si vous lui fournissez de l'audio échantillonné à 48kHz et que le POSR de votre appareil est de 48kHz, le système n'aura pas à faire de "travail supplémentaire" et pourra donc être lu sans latence supplémentaire.

0 votes

Le fait de donner un signal audio échantillonné à 44,1 kHz ne signifie pas qu'il sera lu à une vitesse différente, mais vous demandez au système d'exploitation ou à l'appareil d'effectuer une étape supplémentaire de rééchantillonnage pour traiter le signal audio à 48 kHz, ce qui ajoute de la latence.

6voto

Michael Points 18419

Lorsque vous utilisez OpenSL ES, vous devez remplir les conditions suivantes pour obtenir une sortie à faible latence sur Jellybean et les versions ultérieures d'Android :

  • L'audio doit être mono ou stéréo, PCM linéaire.

  • La fréquence d'échantillonnage audio doit être la même que la fréquence d'échantillonnage native de la sortie (cela peut ne pas être nécessaire sur certains appareils, car l'option FastMixer est capable de rééchantillonner si le fournisseur le configure pour le faire. Mais lors de mes tests, j'ai obtenu des artefacts très perceptibles lors du suréchantillonnage de 44,1 à 48 kHz dans le format FastMixer ).

  • Votre BufferQueue doit avoir au moins 2 tampons. (Cette exigence a depuis été assouplie. Voir cet engagement par Glenn Kasten. Je ne suis pas sûr de la version d'Android dans laquelle il est apparu pour la première fois, mais je dirais 4.4).

  • Vous ne pouvez pas utiliser certains effets (par exemple, la réverbération, l'amplification des basses, l'égalisation, la virtualisation, ...).

El SoundPool La classe essaiera également d'utiliser des AudioTrack en interne lorsque cela est possible (les mêmes critères que ci-dessus s'appliquent, à l'exception de l'élément BufferQueue partie).

5voto

AndrewBloom Points 71

Du lien au point 1 :

"Audio à faible latence

Android 4.2 améliore la prise en charge de la lecture audio à faible latence, à partir de à partir des améliorations apportées dans la version Android 4.1 pour la latence de sortie audio à l'aide des API OpenSL ES, Soundpool et générateur de sons. Ces Ces améliorations dépendent de la prise en charge matérielle. fonctionnalités audio à faible latence peuvent annoncer leur prise en charge aux applications par le biais d'une constante de fonctionnalité matérielle. une constante de fonctionnalité matérielle".

Votre citation dans sa forme complète :

"Performance

Comme OpenSL ES est une API C native, les threads d'applications non-Dalvik qui appellent OpenSL ES n'ont pas d'interface Dalvik. qui appellent OpenSL ES n'ont pas de surcharge liée à Dalvik comme les pauses les pauses de collecte de déchets. Cependant, il n'y a pas d'avantage supplémentaire de performance à l'utilisation d'OpenSL ES que cela. En particulier, l'utilisation d'OpenSL ES n'entraîne pas une latence audio plus faible, une priorité d'ordonnancement plus élevée, etc. que ce que la plate-forme fournit généralement. D'autre part, comme la plateforme Android et les implémentations spécifiques des appareils continuent à continue d'évoluer, une application OpenSL ES peut s'attendre à bénéficier de toutes les améliorations futures des performances du système."

Ainsi, l'api pour communiquer avec les pilotes et ensuite avec l'ordinateur est OpenSl (de la même manière qu'Opengl le fait avec les graphiques). Les versions précédentes d'Android ont une mauvaise conception des pilotes et/ou de l'hw, cependant. Ces problèmes ont été abordés et corrigés avec les versions 4.1 et 4.2, donc si le hd a la puissance nécessaire, vous obtenez une faible latence en utilisant OpenSL.

Encore une fois, d'après cette note du site web de la bibliothèque puredata, il est évident que la bibliothèque utilise OpenSL elle-même pour obtenir une faible latence :

Prise en charge de la faible latence pour les dispositifs conformes La dernière version de Pd pour Android (à partir du 28/12/2012) prend en charge l'audio à faible latence pour les dispositifs appareils Android conformes. Lorsque vous mettez à jour votre copie, assurez-vous de tirer la dernière version de version de pd-for-Android et du sous-module libpd depuis GitHub.

Au moment où nous écrivons ces lignes, les Galaxy Nexus, Nexus 4 et Nexus 10 fournissent une piste à faible latence pour les fichiers audio. piste à faible latence pour la sortie audio. Afin d'atteindre la piste à faible latence faible latence, une application doit utiliser OpenSL, et doit fonctionner à la bonne taux d'échantillonnage et la taille de la mémoire tampon. Ces paramètres dépendent de l'appareil (Galaxy Nexus et Nexus 10 fonctionnent à 44100Hz, tandis que Nexus 4 fonctionne à 48000Hz). à 48000Hz ; la taille de la mémoire tampon est différente pour chaque appareil).

Comme à son habitude, Pd pour Android passe outre toutes ces complexités, autant que possible, en fournissant un accès à l'ensemble des fonctions. possible, en fournissant l'accès aux nouvelles fonctionnalités à faible latence quand elles sont disponibles, tout en restant rétro-compatible avec les versions versions antérieures d'Android. Sous le capot, les composants audio de Pd for Android utiliseront OpenSL à partir de la version 2.3 d'Android. sur l'ancienne API AudioTrack/AudioRecord en Java sur Android 2.2 et antérieures.

3voto

Ceux d'entre vous qui sont plus intéressés par le problème des 10 millisecondes d'Android, c'est-à-dire l'audio à faible latence sur Android. Chez Superpowered, nous avons créé le Android Audio Path Latency Explainer. Voir ici :

http://superpowered.com/androidaudiopathlatency/#axzz3fDHsEe56

2voto

Une autre base de données des latences audio et des tailles de tampon utilisées :

http://superpowered.com/latency/#table

Code source :

https://github.com/superpoweredSDK/SuperpoweredLatency

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X