java android audiotrack sample-rate

java - AudioTrack muestra las inconsistencias



android sample-rate (1)

Actualmente, la mayoría de los teléfonos Android en el mercado solo admiten una tasa de muestreo. Creo que ciertos Samsung juegan a 48kHz y casi todos los demás juegan a 44.1kHz. Estos valores son dictados por el hardware, y aunque hay una facilidad para cambiar la velocidad nativa, su función es secundaria a prueba de futuro, pero principalmente a 2. remuestrear TODO el audio en tiempo de ejecución en SOFTWARE. Esta es una tarea costosa, y también algo destructiva. La razón por la que hay un límite rígido a 192 kHz (= 2 * 96 kHz) es probable porque el envío de más del doble de la frecuencia máxima (96 kHz) es un desperdicio masivo de recursos, ya que también puede desechar cada segunda muestra para reducir la muestra de manera efectiva un factor de 2 hasta que estés en ese rango.

Es mejor evitar especificar una tasa de muestreo no nativa. Se remuestreará en software y, en el mejor de los casos, es un desperdicio de recursos y, en el peor, una fuente de retraso.

O escucharlo de un ingeniero de Google

Al utilizar AudioTrack para la reproducción, a veces necesito remuestrear audio que no se ajuste a las frecuencias de muestreo compatibles con AudioTrack. Al hacerlo, debo determinar la frecuencia de muestreo máxima admitida por AudioTrack, en el dispositivo actual, en la configuración de audio actual.

Debido a que las frecuencias de muestreo permitidas para AudioTrack están mal documentadas, decidí curiosear el código fuente de AudioTrack y encontré esta línea asombrosa:

private static final int SAMPLE_RATE_HZ_MAX = 96000;

Parece que la instancia de AudioTrack está aplicando un límite rígido de 96 KHz independientemente de las capacidades de reproducción reales del dispositivo.

Más confuso está en la clase AudioFormat , en la que paso al constructor (API 21) de AudioTrack , que contiene esta línea:

if ((sampleRate <= 0) || (sampleRate > 192000)) {

en su método setSampleRate() Ahora que es un límite duro de 192 KHz . Por lo tanto, pasar> 192 KHz a AudioFormat (o su constructor) resultará en IllegalArgumentException de AudioFormat y pasar un AudioFormat configurado de 192 KHz <x <96 KHz a AudioTrack también lanzará una IllegalArgumentException .

Lo que encontré, de lejos, lo más confuso es el método getNativeOutputSampleRate() en AudioTrack que realmente devuelve la tasa de muestreo de salida correcta (bueno, no es de extrañar, dado que se ejecuta directamente desde la capa nativa, pero es tan inconsistente).

Y para rematar, el método setPlaybackRate() que afirma:

El rango de frecuencia de muestreo válido es de 1 Hz al doble del valor devuelto por getNativeOutputSampleRate (int).

Y de hecho, lo intenté, y funciona? Considere el siguiente fragmento de código:

int nativeRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC); android.util.Log.i("UI", "Native stream rate: " + nativeRate + " Hz"); // Build audio attributes AudioAttributes.Builder attribBuilder = new AudioAttributes.Builder(); attribBuilder.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC); attribBuilder.setUsage(AudioAttributes.USAGE_MEDIA); AudioAttributes attrib = attribBuilder.build(); // Build audio format AudioFormat.Builder afBuilder = new AudioFormat.Builder(); afBuilder.setChannelMask(AudioFormat.CHANNEL_OUT_STEREO); afBuilder.setEncoding(AudioFormat.ENCODING_PCM_16BIT); afBuilder.setSampleRate(nativeRate); try{ AudioTrack trackTest = new AudioTrack(attrib, afBuilder.build(), nativeRate, AudioTrack.MODE_STREAM, 0); android.util.Log.i("UI", "Track created successfully (direct)"); }catch(Exception ex){ android.util.Log.w("UI", "Failed to create AudioTrack at native rate!"); // Use a random supported samplerate to get pass constructor afBuilder.setSampleRate(48000); try{ AudioTrack trackTest = new AudioTrack(attrib, afBuilder.build(), nativeRate, AudioTrack.MODE_STREAM, 0); trackTest.setPlaybackRate(nativeRate); android.util.Log.i("UI", "Track created successfully (indirect)"); }catch(Exception e){ android.util.Log.w("UI", "Failed to create AudioTrack at 48 KHz"); } }

siguiendo el flujo del programa, cuando la tasa de muestreo nativa es <96 KHz , el código se imprime:

Velocidad de transmisión nativa: 48000 Hz
Track creado con éxito (directo)

pero, cuando conecto un DAC externo con capacidades de reproducción de hasta 192 KHz , obtengo:

Velocidad de transmisión nativa: 192000 Hz
Error al crear AudioTrack a velocidad nativa!
Track creado con éxito (indirecto)

¿Qué pasa con estas inconsistencias? ¿Y es, setPlaybackRate() idéntico a la frecuencia de muestreo que se pasa al constructor?