AudioRecord y AudioTrack latency
Estoy tratando de desarrollar una aplicación como iRig para Android, por lo que el primer paso es capturar la entrada de micrófono y jugar al mismo tiempo.
Lo tengo, pero el problema es que tengo alguna latencia que hace que esto sea inutilizable, y si empiezo a procesar el búfer, me temo que será totalmente inutilizable.
- AudioRecord: registros de "Overrun user" - ¿qué significan?
- ¿Cómo ajustar la frecuencia de muestreo de audio superior a 44.1kHz en la plataforma linux / android?
- AudioRecord: inicio () estado -38
- La inicialización de Android AudioRecord falla cada vez
- Cancelación de ruido activo de Android
Yo uso audiorecord y audiotrack como este:
new Thread(new Runnable() { public void run() { while(mRunning){ mRecorder.read(mBuffer, 0, mBufferSize); //Todo: Apply filters here into the buffer and then play it modified mPlayer.write(mBuffer, 0, mBufferSize); //Log.v("MY AMP","ARA"); }
Y la inicialización de esta manera:
// ==================== INITIALIZE ========================= // public void initialize(){ mBufferSize = AudioRecord.getMinBufferSize(mHz, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); mBufferSize2 = AudioTrack.getMinBufferSize(mHz, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); mBuffer = new byte[mBufferSize]; Log.v("MY AMP","Buffer size:" + mBufferSize); mRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, mHz, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, mBufferSize); mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, mHz, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, mBufferSize2, AudioTrack.MODE_STREAM); }
¿Sabes cómo obtener una respuesta más rápida? ¡Gracias!
- Grabación de audio en vivo y reproducción en Android y manejo de subprocesos y devolución de llamada
- Escritura de datos grabados PCM en un archivo .wav (java android)
- Grabar con AudioRecord en Android acelera el audio?
- Android AudioRecord y MediaRecorder
- Android AudioRecord ejemplo
- Emitir codificación y decodificación de una grabación de audio al formato G711 (PCMU - uLaw)
- AudioFlinger no pudo crear pista de grabación, estado: -1, Necesita ayuda para ifx
- AudioRecord - archivo PCM de escritura
Las clases AudioTrack \ AudioRecord de Android tienen una alta latencia debido a tamaños de búfer mínimos. La razón de esos tamaños de búfer es minimizar las gotas cuando los GC ocurren de acuerdo con Google (que es una decisión equivocada en mi opinión, puede optimizar su propia gestión de memoria).
Lo que quieres hacer es usar OpenSL, que está disponible desde 2.3. Contiene APIs nativas para el streaming de audio. Aquí hay algunos documentos: http://mobilepearls.com/labs/native-android-api/opensles/index.html
Sólo un pensamiento, pero no debería estar leyendo <mBufferSize
Mi primera instict fue sugerir la entrada de AudioTrack en modo estático en lugar de modo de streaming, ya que el modo estático tiene notablemente menor latencia. Sin embargo, el modo estático es más apropiado para sonidos cortos que encajan completamente en la memoria en lugar de un sonido que está captando desde otro lugar. Pero apenas como una conjetura salvaje, qué si usted fija AudioTrack al modo estático y lo alimenta pedazos discretos de su audio de la entrada?
Si quieres un control más estricto sobre el audio, te recomiendo que eches un vistazo a OpenSL ES para Android. La curva de aprendizaje será un poco más pronunciada, pero obtendrá mucho más control de grano fino y menor latencia.
Como mSparks señaló, la transmisión debe hacerse utilizando un tamaño de lectura más pequeño: no es necesario leer el búfer completo para transmitir datos!
int read = mRecorder.read(mBuffer, 0, 256); /* Or any other magic number */ if (read>0) { mPlayer.write(mBuffer, 0, read); }
Esto reducirá drásticamente su latencia. Si mHz es 44100 y su está en la configuración de MONO con 256 su latencia no será menor que 1000 * 256/44100 milisegundos = ~ 5.8 ms. 256/44100 es la conversión de muestras en segundos, por lo que multiplicar por 1000 le da milisegundos. Los problemas son la implementación interna del jugador. No tienes control sobre eso desde java. Espero que esto ayude a alguien 🙂
- ¿Cómo utilizar genéricos personalizados en la clase GSON TypeToken?
- Por qué, los recursos en android se convierten en HEXA-DECIMAL dentro de R.java