Informática Numaboa - Referências
WAVE
Seg 9 Jul 2007 07:18 |
- Detalhes
- Categoria: Formatos padrão
- Atualização: Terça, 21 Abril 2009 20:17
- Autor: vovó Vicki
- Acessos: 10633
O formato padrão WAVE serve para armazenar dados em arquivos de áudio digital. Baseando-se no formato IFF, a Microsoft criou este formato para adequá-lo a processadores Intel.
O formato WAVE talvez seja o mais avacalhado dos formatos IFF. Como vem sendo usado em todo o planeta há décadas, programadores inexperientes (ou até mesmo inescropulosos) fizeram do padrão uma colcha de retalhos cheia de particularidades e exceções que fogem da proposta inicial. Neste artigo serão abordadas apenas as características originais.
Para entender melhor a base do formato WAVE é imprescindível que você domine o formato IFF da Electronic Arts, principalmente o da classe FORM (não é à toa que este tipo de arquivo também é conhecido como waveform). Todas as informações sobre o IFF estão no tutorial sobre o formato IFF.
Algumas informações iniciais
Constantes: As explicações deste texto exigem valores em forma decimal e hexadecimal. Os hexadecimais serão notados com o prefixo 0x e os decimais não terão prefixo.
Organização dos dados: Todos os dados são armazenados em bytes (grupos de 8 bits) dispostos na ordem little endian exigida pelos processadores Intel 80x86. Os valores que ocupam vários bytes são armazenados com o byte menos significativo (ou seja, little endian) primeiro. Os bits são os seguintes (b- significa byte menos significativo e b+ significa byte mais significativo):
7 <- 0 +--------------+ char: | b- | +--------------+ 7 <- 0 15 <- 8 inteiro +--------------+--------------+ curto: | b- byte 0 | byte 1 b+ | +--------------+--------------+ 7 <- 0 15 <- 8 23 <- 16 31 <- 24 +--------------+--------------+--------------+--------------+ inteiro | b- byte 0 | byte 1 | byte 2 | byte 3 b+ | longo: +--------------+--------------+--------------+--------------+
Estrutura do arquivo: Um arquivo WAVE é uma coleção de vários tipos diferentes de chunks (nacos). Existe um chunk obrigatório de formato (ID = "fmt ") que contém parâmetros importantes descrevendo a waveform como, por exemplo, sua sample rate (taxa de amostragem). O chunk de dados, que contém os dados de áudio, também é obrigatório. Todos os outros são opcionais. Entre estes, há os que definem cue points (marcadores), parâmetros de lista de instrumentos, etc. Todos estes chunks serão descritos em detalhe mais adiante.
Os aplicativos que usam WAVE precisam ser capazes de ler os dois chunks obrigatórios e podem, seletivamente, ignorar os chunks opcionais. Um programa que faz cópias de arquivos WAVE deve copiar todos os chunks, mesmo os que não conseguir interpretar.
A ordem dos chunks dentro de um arquivo WAVE não importa, com exceção do chunk de Formato - este precisa preceder o chunk de Dados. Alguns programas esperam que o chunk de Formato seja o primeiro logo após o cabeçalho RIFF - são muito rígidos, porque a especificação não exige isto.
O arquivo WAVE mais enxuto é o que contém apenas o cabeçalho e os chunks de Formato e de Dados:
+------------------------------+ Cabeçalho | ID de grupo = 'RIFF' | | tipo riff = 'WAVE' | | ______________________ | Chunk de formato | | | | | | ID do chunk = 'fmt ' | | | |______________________| | | ______________________ | Chunk de dados | | | | (som) | | ID do chunk = 'data' | | | |______________________| | +------------------------------+
Sample Point e Sample Frame
Para interpretar corretamente um arquivo WAVE, os conceitos de sample point (ponto de amostragem) e de sample frame (grupo de amostragem) são essenciais.
Um ponto de amostragem é um valor que representa uma amostra de som num determinado momento. Para waveforms com resolução maior do que 8 bits, cada ponto de amostragem é armazenado linearmente como um valor complemento de dois que pode ter de 9 a 32 bits, de acordo com o que foi determinado pelo campo BitsPerSample (bits por amostra) no chunk de Formato. Por exemplo, cada ponto de amostragem numa waveform de 16 bits será um word (valor de 16 bits ou dois bytes) onde 32767 (0x7FFF) é o valor mais alto e -32768 (0x8000) o mais baixo. Para waveforms de 8 bits (ou menos), cada ponto de amostragem é um byte linear sem sinal onde 255 é o valor mais alto e 0 o mais baixo. Esta discrepância de valores com e sem sinal é uma das lambanças feitas pela Microsoft na época em que criou este formato. Mas deixa pra lá, é apenas uma numa imensa coleção de bobagens
Como as operações de leitura e escrita da maioria das CPUs usa bytes (8 bits), decidiu-se que um ponto de amostragem, quando é colocado num arquivo WAVE, deve ser ajustado para um tamanho múltiplo de 8 porque isto facilita colocar o WAVE na área de memória. Se o seu conversor analógico-digital (conhecido como ADC, analog-to-digital converter) produzir pontos de amostragem que variam de 1 a 8 bits, os pontos de amostragem devem ser armazenados como bytes de 8 bits, isto é, um char sem sinal. Se o ADC produzir pontos de amostragem de 9 a 16 bits, estes devem ser armazenados como words de 16 bits, isto é, um inteiro curto com sinal. Se o ADC produzir um ponto de amostragem que variam de 17 a 24 bits, os pontos de amostragem devem ser armazenados usando-se três bytes. Finalmente, se o ADC produzir pontos de amostragem de 25 a 32 bits, estes devem ser armazenados como double words de 32 bits, isto é, um inteiro longo com sinal. E por aí vai...
Além disto, os bits precisam ser alinhados à esquerda e os bits restantes, à direita, precisam ser preenchidos com zeros. Imagine como exemplo um ponto de amostragem de 12 bits. Como explicado acima, este ponto de amostragem precisa ser ajustado para 16 bits. Os 12 bits do ponto precisam ser alinhados à esquerda, ou seja, vão ocupar os bits 4 até 15. Os bits de 0 a 3 precisam ser zerados. Veja este exemplo abaixo, supondo que o valor binário seja 101000010111:
___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ | | | | | | | | | | | | | | | | | | 1 0 1 0 0 0 0 1 0 1 1 1 0 0 0 0 | |___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___| <---------------------------------------------> <-------------> Ponto de amostragem de 12 bits alinhado à esq. Ajuste com zeros
Mas não podemos esquecer que o formato WAVE usa o little endian da Intel. Na verdade, a disposição real dos bits é a seguinte:
___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ | | | | | | | | | | | | | | | | | | 0 1 1 1 0 0 0 0 | 1 0 1 0 0 0 0 1 | |___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|
Para áudio multicanal, os pontos de amostragem de cada um dos canais são entrelaçados. Vamos tomar como exemplo uma waveform de 2 canais (estéreo). Ao invés de inicialmente armazenar todos os pontos de amostragem do canal esquerdo e, depois, todos os pontos de amostragem do canal direito, os pontos são alternados: primeiro ponto do canal esquerdo, primeiro ponto do canal direito, segundo ponto do canal esquerdo, segundo ponto do canal direito, etc. Isto é chamado de entrelaçamento de dados. Nesta forma, todos os pontos dos dois canais são contíguos e podem ser enviados (quase que) simultaneamente para um conversor digital-analógico (DAC - digital-to-analog converter) para serem reproduzidos.
Os pontos de amostragem que devem ser "tocados" (enviados para um DAC) simultaneamente são chamados de grupo de amostragem (sample frame). No exemplo da waveform em estéreo, cada par de pontos de amostragem é um frame de amostragem.
frame 0 frame 1 frame N _____ _____ _____ _____ _____ _____ | c 1 | c 2 | c 1 | c 2 | . . . | c 1 | c 2 | |_____|_____|_____|_____| |_____|_____|
Numa waveform mono, um frame de amostragem é constituído apenas por um ponto de amostragem porque não há nada que possa ser entrelaçado. Para waveforms multicanal, deve-se seguir a seguinte convenção:
canais 1 2 __________ __________ | | | estéreo | esquerdo | direito | |__________|__________| 1 2 3 __________ __________ __________ | | | | 3 canais | esquerdo | direito | central | |__________|__________|__________| 1 2 3 4 __________ __________ __________ __________ | esquerdo | direito | esquerdo | direito | quad | frontal | frontal | traseiro | traseiro | |__________|__________|__________|__________| 1 2 3 4 __________ __________ __________ __________ | | | | | 4 canais | esquerdo | central | direito | surround | |__________|__________|__________|__________| 1 2 3 4 5 6 __________ __________ __________ __________ __________ __________ | esquerdo | | | direito | | | 6 canais | central | esquerdo | central | central | direito | surround | |__________|__________|__________|__________|__________|__________|
Os pontos de amostragem dentro de um frame de amostragem estão sempre juntos - não existem bytes não usados entre eles. Da mesma forma, os frames de amostragem também não possuem qualquer byte de ajuste.
Estas disposições do formato wave se referem apenas a chunks não comprimidos. Existem algumas técnicas para armazenar dados compactados que, obviamente, precisam ser descomprimidos para voltarem ao formato original quando se quer ouvir o som.
O chunk de Formato
O chunk de Formato (fmt) contém parâmetros fundamentais para os dados da waveform, tais como a taxa de amostragem (sample rate), bits de resolução e número de canais de áudio.
O chunk de Formato possui os seguintes campos:
ID chunkID ID do chunk inteiro longo com sinal chunkSize Tamanho do chunk inteiro curto com sinal FormatTag Tag de formato inteiro curto sem sinal Channels Canais inteiro longo sem sinal SamplesPerSec Amostras por segundo inteiro longo sem sinal AvgBytePerSec Média de bytes por segundo inteiro curto sem sinal BlockAlign Alinhamento de bloco inteiro curto sem sinal BitsPerSample Bits por amostra
A ID é sempre "fmt " (note o caractere de espaço no final da ID). O campo chunkSize é o tamanho do chunk, descontados os 8 bytes da ID e deste campo. O tamanho do chunk varia de acordo com o "formato" especificado em FormatTag.
Os dados WAVE podem ser armazenados sem compactação. Neste caso, os pontos de amostragem são armazenados como descrito no tópico Sample Points e Sample Frames. Por outro lado, vários tipos de compressão podem ser usados. O campo que indica se foi usado algum tipo de compressão é o FormatTag.
Se for usado algum tipo de compactação, o valor de FormatTag será diferente de 1 e o chunk de formato recebe alguns campos adicionais. Estes contêm informações necessárias para obter e descompactar os dados armazenados. O primeiro destes campos é um inteiro curto sem sinal que indica quantos bytes foram adicionados depois dele mesmo. Além disto, formatos comprimidos precisam de um chunk de Fato contendo um inteiro longo sem sinal indicando o tamanho (em pontos de amostragem) que a waveform precisa ter após ser descompactada. Existem inúmeros formatos comprimidos (na verdade, existem em excesso). Detalhes sobre estes formatos podem ser encontrados no site da Microsoft.
Um FormatTag = 1 indica que os dados não foram compactados e que não há campos adicionais no chunk de Formato.
O campo Channels contém o número de canais de áudio do som. O valor 1 indica som mono, 2 é para som estéreo, 4 para som de quatro canais, etc. Em sons multicanal, os pontos de amostragem são entrelaçados. Um conjunto de pontos de amostragem entrelaçados é chamado de frame de amostragem ou grupo de amostragem.
O campo SamplesPerSec é a taxa de amostragem usada para reproduzir o som, indicada em frames de amostragem por segundo (isto é, em hertz). As três taxas padrão para arquivos não comprimidos (MPC) são 11025, 22050 e 44100 KHz, mas outras taxas podem ser usadas.
O campo AvgBytePerSec indica quantos bytes são reproduzidos por segundo. Este valor pode ser usado por aplicativos para estimar o tamanho do buffer na RAM necessário para evitar problemas de latência durante a reprodução. O valor deste campo deve ser igual ao resultado obtido pela fórmula a seguir (arredondando o resultado para o próximo inteiro):
SamplesPerSec * BlockAlign
O campo BlockAlign deve ser o resultado arredondado para o próximo inteiro obtido através da fórmula
Channels * (BitsPerSample / 8)
O BlockAlign é o tamanho de um frame de amostragem medido em bytes. Por exemplo, um frame de amostragem de um wave mono de 16 bits tem 2 bytes, um frame de amostragem de um wave estéreo de 16 bits tem 4 bytes, etc.
O campo BitsPerSample indica a resolução em bits de um ponto de amostragem. Por exemplo, uma waveform de 16 bits tem um BitsPerSample = 16.
Um arquivo WAVE deve ter um, e apenas um chunk de Formato.
O chunk de Dados
O chunk de Dados (data) contém os frames de amostragem, isto é, todos os canais com os respectivos dados.
O chunk de Dados possui os seguintes campos:
ID chunkID ID do chunk inteiro longo chunkSize Tamanho do chunk char sem sinal waveformData[] Array com os dados
A ID é sempre data. O chunkSize é o número de bytes existentes no chunk, descontados 8 bytes da ID e dele próprio (o campo Tamanho do chunk). Também não inclui os bytes preenchidos com zeros usados para ajustar o tamanho do chunk para um número par.
O array waveformData contém os dados da waveform. Os dados estão arrumados em frames de amostragem, a esta altura nossos velhos conhecidos.
Pode-se determinar o número de bytes de um arquivo WAVE através do campo chunkSize. O número de frames de amostragem pode ser obtido dividindo-se o Tamanho do Chunk pelo valor do campo BlockAlign do chunk de Formato.
A presença do chunk de Dados é obrigatória, mesmo porque sem os dados, neca de som Mas um, e apenas um chunk de Dados deve estar presente num WAVE.
Finalmentes
Este é o formato básico de um arquivo de som WAVE. Existem mais uma porção de firulas, só para dar nó na cabeça da gente e esculhambar o padrão. Se você tiver curiosidade (ou precisar saber) o que um bando de programadores desgarrados andaram aprontando, leia o artigo Wave File Format no site MIDI is the language of gods (em Inglês). Lá você vai encontrar os Cue Chunk, Playlist Chunk, Associated Data List, Samples Chunk e o Instrument Chunk... além da linguagem pouco usual utilizada pelo autor do site que manda o internauta "cuidar da própria vida e deixá-lo em paz" quando se clica no link "about the author". Por este motivo não posso citar o nome do dito cujo, mesmo que as informações sejam de primeira linha e tenham servido de base para elaborar este artigo.
Mesmo assim, não posso deixar de dizer muito obrigada a este desconhecido desbocado