ndk - como quitar la latencia en android
Android: sonido API(determinista, baja latencia) (4)
IIRC, OpenSL pasa a través de la misma interfaz que AudioTrack, por lo que en el mejor de los casos coincidirá con AudioTrack. (FWIW, actualmente estoy usando OpenSL para una salida de "baja latencia")
La triste realidad es que no existe el audio de baja latencia en Android. Ni siquiera hay una forma adecuada de marcar y / o filtrar dispositivos en función de la latencia de audio.
La interfaz que querrás usar para minimizar la latencia dependerá de lo que trates de hacer. Si quieres tener una transmisión de audio, estarás viendo OpenSL o AudioTrack.
Si desea activar algunas fotos estáticas, puede usar SoundPool. Para fotos estáticas, SoundPool tendrá baja latencia ya que las muestras están precargadas en el hardware. Creo que es posible precargar algunas fotos usando OpenSL también, pero no lo he intentado.
Estoy revisando todo tipo de API de sonido de Android y me gustaría saber cuál debo usar. Mi objetivo es obtener un audio de baja latencia o, al menos, un comportamiento determinista con respecto a la demora de la reproducción.
Hemos tenido muchos problemas y parece que la API de sonido de Android es una mierda, así que estoy explorando posibilidades.
El problema que tenemos es que hay un retraso significativo entre sound_out.write(sound_samples);
y el sonido real reproducido por los altavoces. Por lo general, es alrededor de 300 ms. El problema es que en todos los dispositivos es diferente; algunos no tienen ese problema, pero la mayoría están lisiados (sin embargo, la llamada CS tiene latencia cero). El mayor problema con este retraso ridículo es que en algunos dispositivos este retraso parece ser un valor aleatorio (es decir, no siempre es de 300ms).
Estoy leyendo sobre OpenSL ES y me gustaría saber si alguien tuvo experiencia con él, o es la misma mierda pero está empaquetado en un paquete diferente.
Prefiero tener acceso nativo, pero no me importa la indirección de la capa Java siempre que pueda obtener un comportamiento determinista: o el retraso debe ser constante (para un dispositivo determinado) o me gustaría tener acceso a la reproducción actual. posición en lugar de adivinarlo con un rango de error de ± 300 ms ...
EDITAR:
1.5 años después, probé con varios teléfonos Android para ver cómo puedo obtener la mejor latencia posible para una comunicación de voz en tiempo real. Utilizando herramientas especializadas, medí la demora de la ruta de onda. Los mejores resultados fueron más de 100 ms, la mayoría de los teléfonos estaban en el rango de 180ms. ¿Alguien tiene ideas?
La latencia más baja que puede obtener es de SoundPool. Hay un límite en la cantidad de sonido que puedes tocar de esa manera, pero si estás por debajo del límite (1Mb, IIRC) la latencia es bastante baja. Incluso eso probablemente no sea 40ms, sin embargo.
Pero es más rápido de lo que se puede obtener al transmitir, al menos en mi experiencia.
Advertencia: Es posible que vea bloqueos ocasionales en SoundPool en dispositivos Samsung. Tengo una teoría que dice que solo ocurre cuando accedes al SoundPool desde varios hilos, pero no he verificado esto.
EDITAR: OpenSL ES aparentemente tiene una latencia extremadamente alta en Kindle Fire, mientras que SoundPool es mucho mejor, pero lo contrario puede ser cierto en otras plataformas.
Sobre el problema de una latencia determinista / constante, aquí puede encontrar un artículo interesante:
ENFOQUES PARA LA AUDIENCIA CONSTANTE EN ANDROID
El núcleo de sus investigaciones es: Debido a que la HAL de audio, que es uno de los niveles más profundos del trayecto de audio y responsable del tiempo de los eventos de devolución de llamada de audio, está implementada por el proveedor, las latencias relativas pueden variar, especialmente en hardware barato. Por lo tanto, sugieren dos enfoques para reducir la varianza de la latencia. Uno es cuidar el tiempo de devolución de llamada insertando audio en intervalos fijos, el otro es filtrar los tiempos de devolución de llamada para estimar el tiempo en el que debería haberse producido una devolución de llamada de latencia constante aplicando un filtro de suavizado. Con estos dos enfoques, podría reducir significativamente la varianza de la latencia.
También se debe mencionar, que hay una nueva Android-Audio-API nativa, AAudio.
Está disponible / estable desde Android Oreo 8.1 (API nivel 27). También hay un contenedor, que elige dinámicamente entre OpenSL ES y AAudio y es mucho más fácil codificar OpenSL ES. Todavía está en la vista previa del desarrollador.
SoundPool es la interfaz de latencia más baja en la mayoría de los dispositivos, porque el grupo se almacena en el proceso de audio. Todas las otras rutas de audio requieren comunicación entre procesos. OpenSL es la mejor opción si SoundPool no satisface sus necesidades.
Por qué OpenSL? AudioTrack y OpenSL tienen latencias similares, con una diferencia importante: las devoluciones de llamada en el buffer de AudioTrack se atienden en Dalvik, mientras que las devoluciones de llamada OpenSL se atienden en subprocesos nativos. La implementación actual de Dalvik no es capaz de dar servicio a las devoluciones de llamada a latencias extremadamente bajas, porque no hay forma de suspender la recolección de basura durante las devoluciones de llamadas de audio. Esto significa que el tamaño mínimo para las memorias intermedias AudioTrack debe ser mayor que el tamaño mínimo para las memorias intermedias OpenSL para mantener la reproducción sin problemas.
En la mayoría de los lanzamientos de Android, esta diferencia entre AudioTrack y OpenSL no hizo ninguna diferencia. Pero con Jellybean, Android ahora tiene una ruta de audio de baja latencia. La latencia real aún depende del dispositivo, pero puede ser considerablemente menor que anteriormente. Por ejemplo, http://code.google.com/p/music-synthesizer-for-android/ usa búferes de 384 cuadros en el Galaxy Nexus para una latencia de salida total de menos de 30 ms. Esto requiere que el hilo de audio realice el mantenimiento de los búferes aproximadamente una vez cada 8 ms, lo que no era factible en versiones anteriores de Android. Todavía no es factible en un hilo de Dalvik.
Esta explicación asume dos cosas: en primer lugar, que está solicitando los búferes más pequeños posibles de OpenSL y haciendo su procesamiento en la devolución de llamada del búfer en lugar de hacerlo con una cola de búfer. En segundo lugar, su dispositivo admite la ruta de baja latencia. En la mayoría de los dispositivos actuales, no verá mucha diferencia entre AudioTrack y OpenSL ES. Pero en los dispositivos que admiten Jellybean + y audio de baja latencia, OpenSL ES le brindará la ruta de latencia más baja.