O Android usa uma grande variedade de formatos de dados de áudio internamente e expõe um subconjunto deles em APIs públicas, formatos de arquivo e a camada de abstração de hardware (HAL).
Propriedades
Os formatos de dados de áudio são classificados pelas propriedades:
- Compressão
- Descompactado, compactado sem perdas ou compactado com perdas. O PCM é o formato de áudio não compactado mais comum. O FLAC é um formato compactado sem perdas, enquanto o MP3 e o AAC são formatos compactados com perdas.
- Profundidade de bits
- Número de bits significativos por amostra de áudio.
- Tamanho do contêiner
- Número de bits usados para armazenar ou transmitir uma amostra. Normalmente, isso é igual à profundidade de bits, mas às vezes outros bits de preenchimento são alocados para alinhamento. Por exemplo, uma amostra de 24 bits pode ser contida em uma palavra de 32 bits.
- Alinhamento
- Se o tamanho do contêiner for exatamente igual à profundidade de bits, a representação será chamada de compactada. Caso contrário, a representação é descompactada. Os bits significativos da amostra geralmente são alinhados com o bit mais à esquerda (mais significativo) ou mais à direita (menos significativo) do contêiner. É convencional usar os termos compactado e descompactado somente quando a profundidade em bits não é um número de dois.
- Assinatura
- Define se os samples são assinados ou não.
- Representação
- Ponto fixo ou flutuante. Consulte abaixo.
Representação de ponto fixo
O ponto fixo é a representação mais comum de dados de áudio PCM não compactados, especialmente em interfaces de hardware.
Um número de ponto fixo tem um número fixo (constante) de dígitos antes e depois do ponto radix. Todas as nossas representações usam base 2, então substituímos bit por dígito, e ponto binário ou simplesmente ponto por ponto radix. Os bits à esquerda do ponto são a parte inteira, e os bits à direita do ponto são a parte fracionária.
Falamos de PCM de número inteiro, porque os valores de ponto fixo geralmente são armazenados e manipulados como valores inteiros. A interpretação como ponto fixo é implícita.
Usamos o complemento de dois para todas as representações de ponto fixo assinadas. Portanto, o seguinte é válido quando todos os valores estão em unidades de um LSB:
|largest negative value| = |largest positive value| + 1
Notação Q e U
Há várias notações para representação de ponto fixo em um número inteiro. Usamos a notação Q: Qm.n significa m bits inteiros e n bits fracionários. O "Q" conta como um bit, embora o valor seja expresso no complemento de dois. O número total de bits é m + n + 1.
Um.n é para números não assinados: m bits inteiros e n bits fracionários, e "U" conta como zero bits. O número total de bits é m + n.
A parte inteira pode ser usada no resultado final ou ser temporária. Nesse último caso, os bits que compõem a parte inteira são chamados de bits de guarda. Os bits de proteção permitem que um cálculo intermediário transborde, desde que o valor final esteja dentro do intervalo ou possa ser limitado para estar dentro do intervalo. Os bits de proteção de ponto fixo estão à esquerda, enquanto os dígitos de proteção de unidade de ponto flutuante são usados para reduzir o erro de arredondamento e estão à direita.
Representação de ponto flutuante
O ponto flutuante é uma alternativa ao ponto fixo, em que a localização do ponto pode variar. As principais vantagens do ponto flutuante incluem:
- Maior reserva dinâmica e intervalo dinâmico. A aritmética de ponto flutuante tolera o excesso de intervalos nominais durante a computação intermediária e apenas limita os valores no final.
- Suporte a valores especiais, como infinitos e NaN
- É mais fácil de usar em muitos casos
Historicamente, a aritmética de ponto flutuante era mais lenta do que a aritmética de ponto fixo ou de número inteiro, mas agora é comum que a de ponto flutuante seja mais rápida, desde que as decisões de fluxo de controle não sejam baseadas no valor de uma computação.
Formatos de áudio do Android
Os principais formatos de áudio do Android estão listados na tabela abaixo:
Propriedade | Q0.15 | Q0.7 1 | Q0.23 | Q0.31 | float | |
---|---|---|---|---|---|---|
bits do contêiner |
16 | 8 | 24 ou 32 2 | 32 | 32 | |
Bits significativos incluindo o sinal |
16 | 8 | 24 | 24 ou 32 2 | 25 3 | |
Margem em dB |
0 | 0 | 0 | 0 | 126 4 | |
Intervalo dinâmico em dB |
90 | 42 | 138 | 138 a 186 | 900 5 |
Todos os formatos de ponto fixo acima têm um intervalo nominal de -1,0 a +1,0 menos um LSB. Há um valor negativo a mais do que o valor positivo devido à representação do complemento de dois.
Notas de rodapé:
-
Todos os formatos acima expressam valores de amostra assinados.
O formato de 8 bits é comumente chamado de "não assinado", mas
é na verdade um valor assinado com viés de
0.10000000
. - O Q0.23 pode ser empacotado em 24 bits (três bytes de 8 bits, little-endian) ou desempacotado em 32 bits. Se desempacotados, os bits significativos são justificados à direita em relação ao LSB com preenchimento de extensão de sinal em relação ao MSB (Q8.23), ou justificados à esquerda em relação ao MSB com preenchimento de zero em relação ao LSB (Q0.31). O Q0.31 teoricamente permite até 32 bits significativos, mas as interfaces de hardware que aceitam o Q0.31 raramente usam todos os bits.
- O ponto flutuante de precisão única tem 23 bits explícitos, mais um bit oculto e um bit de sinal, resultando em 25 bits significativos no total. Os números decimais têm menos bits significativos.
- O ponto flutuante de precisão única pode expressar valores de até ±1,7e+38, o que explica o grande headroom.
- O intervalo dinâmico mostrado é para denormals até o valor máximo nominal ±1,0. Algumas implementações de ponto flutuante específicas da arquitetura, como NEON, não oferecem suporte a denormais.
Conversões
Esta seção discute conversões de dados entre várias representações.
Conversões de ponto flutuante
Para converter um valor do formato Qm.n para ponto flutuante:
- Converte o valor para ponto flutuante como se fosse um número inteiro (ignorando o ponto).
- Multiplicar por 2-n.
Por exemplo, para converter um valor interno de Q4.27 em ponto flutuante, use:
float = integer * (2 ^ -27)
As conversões de ponto flutuante para ponto fixo seguem estas regras:
- O ponto flutuante de precisão única tem um intervalo nominal de ±1,0, mas o intervalo completo para valores intermediários é ±1,7e+38. A conversão entre ponto flutuante e ponto fixo para representação externa (como saída para dispositivos de áudio) considera apenas o intervalo nominal, com limite mínimo para valores que excedem esse intervalo. Mais especificamente, quando +1,0 é convertido em um formato de ponto fixo, ele é limitado a +1,0 menos um LSB.
- Valores denormalizados (subnormais) e +/- 0,0 são permitidos na representação, mas podem ser convertidos silenciosamente em 0,0 durante o processamento.
- Os infinitos vão passar pelas operações ou serão limitados silenciosamente a +/- 1,0. Geralmente, o segundo é para conversão em um formato de ponto fixo.
- O comportamento de NaN é indefinido: um NaN pode se propagar como um NaN idêntico ou pode ser convertido em um NaN padrão, pode ser limitado silenciosamente a +/- 1, 0 ou convertido silenciosamente em 0, 0, ou resultar em um erro.
Conversões de ponto fixo
As conversões entre diferentes formatos de Qm.n seguem estas regras:
- Quando m é aumentada, a extensão de sinal é aplicada à parte inteira à esquerda.
- Quando m é diminuída, a parte inteira é fixada.
- Quando n é aumentado, o zero estende a parte fracionária à direita.
- Quando n é diminuído, os bits fracionários em excesso são ditherizados, arredondados ou truncados à direita.
Por exemplo, para converter um valor Q4.27 em Q0.15 (sem dither ou arredondamento), mova o valor Q4.27 para a direita em 12 bits e limite os resultados que excedem o intervalo assinado de 16 bits. Isso alinha o ponto da representação Q.
Para converter Q7.24 em Q7.23, faça uma divisão assinada por 2 ou, de forma equivalente, adicione o bit de sinal à quantidade inteira Q7.24 e, em seguida, faça um deslocamento à direita assinado por 1. Um deslocamento à direita assinado simples não é equivalente a uma divisão assinada por 2.
Conversões com e sem perda
Uma conversão é sem perdas se for
inversível:
uma conversão de A
para B
para
C
resulta em A = C
.
Caso contrário, a conversão será com perda.
As conversões sem perdas permitem conversão de formato de ida e volta.
As conversões da representação de ponto fixo com 25 ou menos bits significativos para ponto flutuante não têm perda. As conversões de ponto flutuante para qualquer representação de ponto fixo comum são com perda.