Android usa una amplia variedad de formatos de datos de audio de forma interna y expone un subconjunto de estos en APIs públicas, formatos de archivo y la capa de abstracción de hardware (HAL).
Propiedades
Los formatos de datos de audio se clasifican según sus propiedades:
- Compresión
- Sin comprimir, sin pérdida o con pérdida. PCM es el formato de audio sin comprimir más común. FLAC es un formato comprimido sin pérdidas, mientras que MP3 y AAC son formatos comprimidos con pérdidas.
- Profundidad de bits
- Indica la cantidad de bits significativos por muestra de audio.
- Tamaño del contenedor
- Es la cantidad de bits que se usan para almacenar o transmitir una muestra. Por lo general, es igual que la profundidad de bits, pero, a veces, se asignan bits de padding adicionales para la alineación. Por ejemplo, una muestra de 24 bits podría estar contenida en una palabra de 32 bits.
- Alineación
- Si el tamaño del contenedor es exactamente igual a la profundidad de bits, la representación se denomina compactada. De lo contrario, la representación se desempaqueta. Por lo general, los bits significativos de la muestra se alinean con el bit más a la izquierda (más significativo) o más a la derecha (menos significativo) del contenedor. Es convencional usar los términos empaquetados y desempaquetados solo cuando la profundidad de bits no es una potencia de dos.
- Firma
- Indica si los samples tienen firma o no.
- Representación
- Puede ser de punto fijo o de punto flotante. Consulta a continuación.
Representación de punto fijo
El punto fijo es la representación más común de los datos de audio PCM sin comprimir, especialmente en las interfaces de hardware.
Un número de punto fijo tiene una cantidad fija (constante) de dígitos antes y después del punto de base. Todas nuestras representaciones usan base 2, por lo que reemplazamos bit por dígito y punto binario o simplemente punto por punto de base. Los bits a la izquierda del punto son la parte entera y los bits a la derecha del punto son la parte fraccionaria.
Hablamos de PCM de números enteros, ya que los valores de punto fijo suelen almacenarse y manipularse como valores de números enteros. La interpretación como punto fijo es implícita.
Usamos el complemento a dos para todas las representaciones de punto fijo con signo, por lo que se cumple lo siguiente, donde todos los valores están en unidades de una LSB:
|largest negative value| = |largest positive value| + 1
Notación Q y U
Existen varias notaciones para la representación de punto fijo en un número entero. Usamos la notación Q: Qm.n significa m bits enteros y n bits fraccionarios. El "Q" se cuenta como un bit, aunque el valor se expresa en complemento a dos. La cantidad total de bits es m + n + 1.
Um.n es para números sin signo: m bits de número entero y n bits fraccionarios, y la "U" se cuenta como cero bits. La cantidad total de bits es m + n.
La parte entera se puede usar en el resultado final o puede ser temporal. En el último caso, los bits que conforman la parte entera se denominan bits de protección. Los bits de protección permiten que un cálculo intermedio se desborde, siempre que el valor final esté dentro del rango o se pueda restringir para que esté dentro del rango. Ten en cuenta que los bits de protección de punto fijo se encuentran a la izquierda, mientras que los dígitos de protección de la unidad de punto flotante se usan para reducir el error de redondeo y se encuentran a la derecha.
Representación de punto flotante
El punto flotante es una alternativa al punto fijo, en el que la ubicación del punto puede variar. Estas son algunas de las principales ventajas de los números de punto flotante:
- Mayor margen y rango dinámico; la aritmética de punto flotante tolera el exceso de rangos nominales durante el procesamiento intermedio y solo limita los valores al final
- Compatibilidad con valores especiales, como infinitos y NaN
- Es más fácil de usar en muchos casos.
Históricamente, la aritmética de punto flotante era más lenta que la aritmética de números enteros o de punto fijo, pero ahora es común que la aritmética de punto flotante sea más rápida, siempre y cuando las decisiones del flujo de control no se basen en el valor de un cálculo.
Formatos de audio para Android
En la siguiente tabla, se enumeran los principales formatos de audio de Android:
Propiedad | Q0.15 | Q0.7 1 | Q0.23 | Q0.31 | float | |
---|---|---|---|---|---|---|
Bits de del contenedor |
16 | 8 | 24 o 32 2 | 32 | 32 | |
Bits significativos incluidos los signos |
16 | 8 | 24 | 24 o 32 2 | 25 3 | |
Margen en dB |
0 | 0 | 0 | 0 | 126 4 | |
Rango dinámico en dB |
90 | 42 | 138 | De 138 a 186 | 900 5 |
Todos los formatos de punto fijo anteriores tienen un rango nominal de -1.0 a +1.0 menos un MSB. Hay un valor negativo más que un valor positivo debido a la representación del complemento a dos.
Notas al pie:
-
Todos los formatos anteriores expresan valores de muestra firmados.
El formato de 8 bits se suele llamar “sin signo”, pero en realidad es un valor con signo y un sesgo de
0.10000000
. - Q0.23 se puede empaquetar en 24 bits (tres bytes de 8 bits, formato little-endian) o desempaquetar en 32 bits. Si se descomprimen, los bits significativos se justifican a la derecha hacia el MSB con relleno de extensión de signo hacia el MSB (Q8.23) o se justifican a la izquierda hacia el MSB con relleno de cero hacia el MSB (Q0.31). En teoría, Q0.31 permite hasta 32 bits significativos, pero las interfaces de hardware que aceptan Q0.31 rara vez usan todos los bits.
- El punto flotante de precisión simple tiene 23 bits explícitos más un bit oculto y un bit de signo, lo que da como resultado 25 bits significativos en total. Los números no normales tienen menos bits significativos.
- El punto flotante de precisión simple puede expresar valores de hasta ±1.7e+38, lo que explica el gran margen.
- El rango dinámico que se muestra es para valores no normales hasta el valor máximo nominal de ±1.0. Ten en cuenta que algunas implementaciones de números de punto flotante específicas de la arquitectura, como NEON, no admiten números de punto flotante no normales.
Conversiones
En esta sección, se analizan las conversiones de datos entre varias representaciones.
Conversiones de punto flotante
Para convertir un valor del formato Qm.n a punto flotante, haz lo siguiente:
- Convierte el valor a punto flotante como si fuera un número entero (ignorando el punto).
- Multiplica por 2-n.
Por ejemplo, para convertir un valor interno de Q4.27 a punto flotante, usa lo siguiente:
float = integer * (2 ^ -27)
Las conversiones de punto flotante a punto fijo siguen estas reglas:
- El punto flotante de precisión simple tiene un rango nominal de ±1.0, pero el rango completo para los valores intermedios es de ±1.7e+38. La conversión entre punto flotante y punto fijo para la representación externa (como la salida a dispositivos de audio) solo considerará el rango nominal, con limitación para los valores que superen ese rango. En particular, cuando +1.0 se convierte a un formato de punto fijo, se limita a +1.0 menos un MSB.
- Los números no normales (subnormales) y los valores +/- 0.0 se permiten en la representación, pero se pueden convertir de forma silenciosa a 0.0 durante el procesamiento.
- Los infinitos pasarán por las operaciones o se limitarán de forma silenciosa a +/- 1.0. Por lo general, el último es para la conversión a un formato de punto fijo.
- El comportamiento de NaN no está definido: un NaN puede propagarse como un NaN idéntico, o puede convertirse en un NaN predeterminado, puede limitarse de forma silenciosa a +/- 1.0, o puede convertirse de forma silenciosa en 0.0, o generar un error.
Conversiones de punto fijo
Las conversiones entre diferentes formatos Qm.n siguen estas reglas:
- Cuando se aumenta m, se extiende el signo de la parte entera a la izquierda.
- Cuando disminuye m, se restringe la parte entera.
- Cuando se aumenta n, se extiende a cero la parte fraccionaria a la derecha.
- Cuando se disminuye n, se atenúa, se redondea o se trunca el exceso de bits fraccionarios a la derecha.
Por ejemplo, para convertir un valor de Q4.27 a Q0.15 (sin dithering ni redondeo), desplaza el valor de Q4.27 hacia la derecha en 12 bits y limita los resultados que superen el rango firmado de 16 bits. Esto alinea el punto de la representación de Q.
Para convertir Q7.24 en Q7.23, divide con signo por 2, o bien agrega el bit de signo a la cantidad de número entero Q7.24 y, luego, mueve el signo a la derecha en 1. Ten en cuenta que un desplazamiento a la derecha simple con signo no equivale a una división con signo por 2.
Conversiones con pérdida y sin pérdida
Una conversión es sin pérdidas si es invertible: una conversión de A
a B
a C
da como resultado A = C
.
De lo contrario, la conversión es con pérdida.
Las conversiones sin pérdidas permiten la conversión de formato de ida y vuelta.
Las conversiones de representación de punto fijo con 25 bits significativos o menos a punto flotante no tienen pérdidas. Las conversiones de punto flotante a cualquier representación de punto fijo común son con pérdida.