Diferenças
Aqui você vê as diferenças entre duas revisões dessa página.
c:processamento_de_audio [2023/08/01 19:13] – criada maziero | c:processamento_de_audio [2023/08/01 19:23] (atual) – edição externa 127.0.0.1 | ||
---|---|---|---|
Linha 1: | Linha 1: | ||
+ | ====== Processamento de áudio ====== | ||
+ | |||
+ | {{ progc_proj_audio.mkv |Video deste projeto}} | ||
+ | |||
+ | Este projeto consiste em criar filtros para arquivos de áudio em formato WAV, implementando operações como ajuste de volume, eco e normalização. | ||
+ | |||
+ | ===== Áudio digital ===== | ||
+ | |||
+ | Em um sistema digital, um som é normalmente codificado como um vetor de amostras (// | ||
+ | |||
+ | Trecho de áudio (duração 45 s): | ||
+ | |||
+ | {{ audio1.png | ||
+ | |||
+ | Detalhe do trecho de áudio acima (duração 300 ms): | ||
+ | |||
+ | {{ audio2.png | ||
+ | |||
+ | Detalhe do trecho de áudio acima (duração 30 ms): | ||
+ | |||
+ | {{ audio3.png | ||
+ | |||
+ | Detalhe do trecho de áudio acima (duração 0,3 ms): | ||
+ | |||
+ | {{ audio4.png | ||
+ | |||
+ | Visão conceitual da amostragem de áudio: | ||
+ | |||
+ | {{ amostragem.png? | ||
+ | |||
+ | Nessa figura podem ser identificados o **sinal analógico**, | ||
+ | |||
+ | [0, 10, 15, 9, -5, -9, -10, 0, 10, 14, 15, 5, 0, -5, ... ] | ||
+ | |||
+ | O padrão PCM ([[https:// | ||
+ | |||
+ | * **Taxa de amostragem**: | ||
+ | * **Resolução**: | ||
+ | |||
+ | No caso de sons com vários canais (estéreo ou // | ||
+ | |||
+ | ===== O formato WAV ===== | ||
+ | |||
+ | Para facilitar a leitura e escrita dos arquivos de áudio, neste projeto será adotado o [[https:// | ||
+ | |||
+ | Um arquivo WAV típico é organizado nos seguintes //chunks// (pedaços) básicos: | ||
+ | |||
+ | ^ Chunk ID ^ tamanho (bytes) ^ conteúdo ^ | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | |||
+ | <note important> | ||
+ | Em alguns arquivos WAV podem haver outros chunks, como LIST e INFO, que não precisam ser considerados neste projeto. | ||
+ | </ | ||
+ | |||
+ | Esses //chunks// têm os seguintes campos internos: | ||
+ | |||
+ | ^ Chunk ^ nome ^ tamanho ^ tipo ^ valor ^ significado ^ | ||
+ | | '' | ||
+ | | ::: | ChunkSize | 4 | '' | ||
+ | | ::: | Format | 4 | '' | ||
+ | | '' | ||
+ | | ::: | SubChunk1Size | 4 | '' | ||
+ | | ::: | Audio format | 2 | '' | ||
+ | | ::: | Number of channels | 2 | '' | ||
+ | | ::: | Sample rate | 4 | '' | ||
+ | | ::: | Byte rate | 4 | '' | ||
+ | | ::: | Block align | 2 | '' | ||
+ | | ::: | Bits per sample | 2 | '' | ||
+ | | '' | ||
+ | | ::: | SubChunk2Size | 4 | '' | ||
+ | | ::: | Audio data | variável | ||
+ | |||
+ | <note important> | ||
+ | Observe que os campos de tipo '' | ||
+ | </ | ||
+ | |||
+ | As amostras de áudio são armazenadas no //chunk// de dados ('' | ||
+ | |||
+ | L[0], R[0], L[1], R[1], L[2], R[2], L[3], R[3], ... | ||
+ | |||
+ | <note tip> | ||
+ | Para ler facilmente o cabeçalho de um arquivo WAV, basta definir um //struct// com os mesmos campos, tamanhos e ordem do cabeçalho descrito acima, e então ler os primeiros bytes do arquivo para dentro desse //struct//, usando a função de leitura '' | ||
+ | </ | ||
+ | |||
+ | Documentação adicional sobre o formato WAV: | ||
+ | |||
+ | * [[http:// | ||
+ | * [[http:// | ||
+ | |||
+ | Alguns exemplos de arquivos de áudio WAV para usar no projeto: | ||
+ | |||
+ | * {{music.wav? | ||
+ | * {{batida.wav? | ||
+ | * {{numbers.zip|Numbers}} (mono, 22050 KHz) | ||
+ | |||
+ | Você pode gerar seus próprios arquivos WAV usando programas de processamento de áudio, como o " | ||
+ | |||
+ | ===== Filtros ===== | ||
+ | |||
+ | Um filtro de áudio é um programa simples, que recebe como entrada um arquivo de áudio (que pode vir da entrada padrão //stdin//), realiza algum tipo de [[https:// | ||
+ | |||
+ | <note important> | ||
+ | Lembre-se que o filtro deve atuar em todos os canais do áudio da entrada. | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ==== Informações ==== | ||
+ | |||
+ | Este programa não é exatamente um filtro, pois produz como saída uma listagem das principais informações do áudio informado como entrada. | ||
+ | |||
+ | Forma de chamada: | ||
+ | |||
+ | wavinfo -i input | ||
+ | |||
+ | Exemplo de saída (para o arquivo '' | ||
+ | |||
+ | < | ||
+ | $ wavinfo -i music.wav | ||
+ | |||
+ | riff tag (4 bytes): " | ||
+ | riff size (4 bytes): 8061776 | ||
+ | wave tag (4 bytes): " | ||
+ | form tag (4 bytes): "fmt " | ||
+ | fmt_size | ||
+ | audio_format | ||
+ | num_channels | ||
+ | sample_rate | ||
+ | byte_rate | ||
+ | block_align | ||
+ | bits_per_sample (2 bytes): 16 | ||
+ | data tag (4 bytes): " | ||
+ | data size (4 bytes): 8061740 | ||
+ | bytes per sample | ||
+ | samples per channel | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ==== Ajuste de volume ==== | ||
+ | |||
+ | O filtro de ajuste de volume permite aumentar ou diminuir o volume de áudio do arquivo, de acordo com um fator de ajuste V (0.0 ≤ V ≤ 10.0, com default em 1.0). Ele consiste basicamente em multiplicar o valor de cada amostra de áudio por V. | ||
+ | |||
+ | Forma de chamada ('' | ||
+ | |||
+ | wavvol -l V -i input -o output | ||
+ | |||
+ | Exemplo de uso e saída: {{music-vol.wav? | ||
+ | |||
+ | wavvol -l 0.1 -i music.wav -o music-vol.wav | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ==== Normalização ==== | ||
+ | |||
+ | Este filtro faz a normalização do áudio, ou seja, o ajuste automático de volume. Para tal, é necessário encontrar o valor do maior pico no sinal de áudio (em todos os canais) e usá-lo para calcular um fator de ajuste, de modo que todas as amostras de todos os canais fiquem no intervalo de 16 bits com sinal [-32767 ... +32767]. | ||
+ | |||
+ | Forma de chamada: | ||
+ | |||
+ | wavnorm -i input -o output | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ==== Reversão ==== | ||
+ | |||
+ | Este filtro produz como saída um áudio invertido, ou seja, "de trás para a frente" | ||
+ | |||
+ | Forma de chamada: | ||
+ | |||
+ | wavrev -i input -o output | ||
+ | |||
+ | Exemplo de uso e saída: {{music-rev.wav? | ||
+ | |||
+ | wavrev -i music.wav -o music-rev.wav | ||
+ | |||
+ | <note tip> | ||
+ | Muitos músicos se divertiram com esse efeito, como nesta [[https:// | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ==== Eco ==== | ||
+ | |||
+ | Este filtro produz como saída um áudio com eco. O eco é controlado pelos parâmetros //delay// ( inteiro ≥ 0, default 1000 ms), que define o atraso do eco em milissegundos, | ||
+ | |||
+ | O efeito de eco pode ser definido por esta equação: sample< | ||
+ | |||
+ | Forma de chamada ('' | ||
+ | |||
+ | wavecho -t delay -l level -i input -o output | ||
+ | |||
+ | Exemplo de uso e saída (ambos com t=500ms e l=50%): {{batida-echo.wav? | ||
+ | |||
+ | wavecho -t 500 -l 0.5 -i music.wav -o music-echo.wav | ||
+ | |||
+ | <note tip> | ||
+ | Experimente aplicar este filtro a um arquivo de voz, com um atraso bem pequeno (10 a 50 ms) =) | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ==== Estéreo ampliado ==== | ||
+ | |||
+ | O filtro de estéreo ampliado permite aumentar a separação de canais em um sinal estéreo, gerando um som mais aberto. Este filtro só pode ser aplicado a sinais estéreo (com 2 canais). | ||
+ | |||
+ | Sendo R(t) e L(t) as amostras de entrada do canal direito e esquerdo em um instante t, a saída R'(t), L'(t) é calculada da seguinte forma: | ||
+ | |||
+ | diff = R(t) - L(t) | ||
+ | R'(t) = R(t) + k * diff | ||
+ | L'(t) = L(t) - k * diff | ||
+ | |||
+ | onde '' | ||
+ | |||
+ | Forma de chamada ('' | ||
+ | |||
+ | wavwide -l k -i input -o output | ||
+ | |||
+ | Exemplo de uso e saída: {{music-wide.wav? | ||
+ | |||
+ | cat music.wav | wavvol -l 0.5 | wavwide -l 5 | wavnorm > music-wide.wav | ||
+ | |||
+ | O exemplo acima mostra o uso de vários filtros concatenados: | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ==== Concatenação ==== | ||
+ | |||
+ | O filtro de concatenação recebe como entrada **um ou mais arquivos de áudio** e gera uma saída contendo a concatenação das entradas na sequência indicada. | ||
+ | |||
+ | Forma de chamada: | ||
+ | |||
+ | wavcat arq1.wav arq2.wav arq3.wav ... -o output | ||
+ | |||
+ | <note important> | ||
+ | A combinação de sinais de áudio com taxas de amostragem diferentes exige um procedimento chamado // | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ==== Mistura ==== | ||
+ | |||
+ | O filtro de mistura (mixagem) recebe como entrada um ou mais arquivos de áudio e gera uma saída contendo a mistura (mixagem) das entradas. | ||
+ | |||
+ | Forma de chamada: | ||
+ | |||
+ | wavmix arq1.wav arq2.wav arq3.wav ... -o output | ||
+ | |||
+ | <note important> | ||
+ | Ao somar as amostras, cuide para não saturar a saída, o que pode gerar distorção ([[https:// | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ==== Outros filtros (ideias) ==== | ||
+ | |||
+ | * extrair um canal de um áudio stereo | ||
+ | * juntar dois áudios mono em um áudio stereo | ||
+ | * recortar um áudio de t1 a t2 | ||
+ | * aplicar um atraso //t// a um áudio (t pode ser negativo, para adiantar o áudio) | ||
+ | * // | ||
+ | * efeito //phaser//, // | ||
+ | * compressor | ||
+ | * filtro de ruído: reduzir o volume de todas as amostras com nível abaixo de um certo valor (dado em % do volume máximo). | ||
+ | * ... (outras ideias são bem-vindas) | ||
+ | |||
+ | Mais conteúdo sobre efeitos de áudio: | ||
+ | |||
+ | * {{http:// | ||
+ | * {{http:// | ||
+ | * {{https:// | ||
+ | * {{http:// | ||
+ | * ... | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Atividade ===== | ||
+ | |||
+ | O projeto consiste em implementar os filtros acima definidos. | ||
+ | |||
+ | ==== Requisitos ==== | ||
+ | |||
+ | * Cada filtro é um comando separado. Por exemplo, o filtro de volume deve ser implementado em um arquivo '' | ||
+ | * Os filtros devem aceitar como entrada sons no formato WAV PCM 16 bits com sinal e devem gerar como saída sons nesse mesmo formato. | ||
+ | * As rotinas comuns (leitura/ | ||
+ | * Sempre que possível, as informações do som necessárias às funções devem ser transferidas como parâmetros (por valor ou por referência, | ||
+ | * Use alocação dinâmica de memória para os sons, para poder processar arquivos grandes. Só aloque a memória para as amostras após encontrar o número de amostras no cabeçalho. | ||
+ | * Construir um '' | ||
+ | * Ao menos os alvos '' | ||
+ | * CFLAGS = '' | ||
+ | * Compilar e ligar separadamente (gerar arquivos '' | ||
+ | * O que deve ser entregue ao professor: | ||
+ | * arquivos '' | ||
+ | * arquivo '' | ||
+ | * **não enviar** os sons de teste | ||
+ | |||
+ | <note tip> | ||
+ | Para simplificar a implementação e evitar erros, sugere-o o uso dos tipos inteiros de tamanho fixo ('' | ||
+ | </ | ||
+ | |||
+ | ==== Linha de comando ==== | ||
+ | |||
+ | * A opção '' | ||
+ | * A opção '' | ||
+ | * Todas as mensagens de erro devem ser enviadas para a saída de erro (// | ||
+ | |||
+ | Essas opções podem ser usadas em qualquer combinação, | ||
+ | |||
+ | < | ||
+ | // entrada e saída em arquivos | ||
+ | wavvol -i inputfile.wav | ||
+ | wavvol -o outputfile.wav -i inputfile.wav | ||
+ | |||
+ | // entrada em arquivo, saída em stdout, vice-versa ou ambos | ||
+ | wavvol -i inputfile.wav | ||
+ | wavvol -o outputfile.wav < inputfile.wav | ||
+ | wavvol | ||
+ | |||
+ | // as opções podem estar em qualquer ordem | ||
+ | wavvol -l 0.3 -i inputfile.wav -o outputfile.wav | ||
+ | wavvol -i inputfile.wav -l 0.3 -o outputfile.wav | ||
+ | wavvol -o outputfile.wav -i inputfile.wav -l 0.3 | ||
+ | </ | ||
+ | |||
+ | <note tip> | ||
+ | Para ler e tratar mais facilmente as opções da linha de comando, sugere-se usar funções já prontas para isso, como '' | ||
+ | </ | ||
+ | |||
+ | Como os filtros devem tratar a entrada e saída padrão, é possível combinar filtros usando //pipes// UNIX. Por exemplo, podemos usar pipes para construir o efeito [[https:// | ||
+ | |||
+ | wavrev -i input.wav | wavecho -t 500 -l 0.5 | wavrev -o output.wav | ||
+ | |||
+ | Caso a adição de eco provoque // | ||
+ | |||
+ | wavvol -l 0.5 -i input.wav | wavrev | wavecho -t 500 -l 0.5 | wavrev | wavnorm -o output.wav | ||
+ | |||
+ | <note tip> | ||
+ | Para tocar facilmente os arquivos de áudio, pode-se usar os comandos '' | ||
+ | </ | ||
+ | |||
+ | ==== Estrutura do código-fonte ==== | ||
+ | |||
+ | O código-fonte deve ser estruturado em diversos arquivos '' | ||
+ | |||
+ | {{ estrutura-wav.png? | ||