Categorias
Convertendo WAV para MP3 e vice-versa
Este artigo aborda uma breve introdução sobre as janelas do Gerenciador de compressão de áudio API.
Esta é uma cópia de um artigo que escrevi para a Newsletter Delphi Developer.
Os componentes que eu escrevi para este artigo são parte de um projeto open-source e estão disponíveis na minha página inicial.
Gerenciador de compressão de áudio
Muitos anos atrás, antes de eu realmente saber o que era a internet, eu ouvi um boato de um "Telefone na Internet". Esta peça de software podia alegadamente transmitir uma conversa entre duas pessoas na internet, em tempo real, permitindo chamadas telefônicas mundiais pelo preço de uma chamada local. Com o irmão da Lyn morando nos E.U.A. e nós morando no Reino Unido, os telefonemas eram poucos e não muito freqüentes, e sempre muito caros. Então, você pode imaginar como esta tecnologia foi emocionante para nós. Tão excitante na verdade, que nós nos conectamos.
Para resumir, nós procuramos este software de telefone e ele era horrível! Tão ruim, que nós continuamos com nosso telefone normal e os ridículos encargos das ligações.
BOA NOTÍCIA! Isso foi há muito tempo, e desde então as coisas têm percorrido um longo caminho (e telefonemas também estão muito mais baratos). Com a crescente popularidade da Internet, meios de comunicação tornaram-se ainda de maior qualidade em tamanho menor.
Existem hoje cerca de inúmeros formatos de streaming de áudio por aí, e até mesmo vídeo streaming, e tudo isto tem se tornado acessível a pessoas com bandas de internet muito baixas. Isso não é tudo, não só esses formatos (Quicktime, RealAudio, e até mesmo MP3) se tornaram mais populares, eles também se tornaram mais acessíveis para o desenvolvedor.
Codecs
Algumas destas rotinas de compressão se tornaram acessíveis através da introdução de "codecs". Uma série de codecs são instalados por padrão quando o Windows é instalado (obrigado Microsoft!)
GSM - Creio que este formato é utilizado por algumas redes de telefone móvel
DSP TrueSpeech - Já ouvi uma demonstração de 1 bit de áudio neste formato, muito claro!
Fraunhofer IIS MP3- Esse é certamente o meu favorito de todos eles, permite que você faça seus próprios MP3s
PCM - O padrão utilizado pelas janelas, a maioria dos codecs pode converter de/para PCM
Nota:
A lista completa é conseguida na seção MultiMedia de seu painel de controle. Dê um duplo clique em "Multimídia", em seguida, clique na aba "dispositivos" e, em seguida, expandir compressão de áudio.
Então, qual é o objetivo de um codec? Bem, um codec é um pouco como um componente ActiveX. Componentes ActiveX permitem aos desenvolvedores implementar funcionalidades dentro de suas aplicações sem ter que escrever o código de todos os envolvidos (por exemplo, a incorporação de um documento Word). Codecs fazem o mesmo tipo de coisa, mas concentram-se em converter formatos de mídia em outros formatos de mídia. Por exemplo, se você queria escrever um aplicativo que pegou dados de áudio de um CD de áudio e, depois, converteu em um MP3, o único trabalho que você teria de fazer seria
• Extrair os dados de áudio da faixa
• Escrever um cabeçalho MP3 válido para o seu disco rígido
• Instruir o codec relevante para codificar os dados de áudio como MP3
ACM e API
Em primeiro lugar, gostaria de referir que ACM é a abreviação de "Audio Compression Manager". Esta é a biblioteca escrita pela Microsoft como parte do Windows que funciona como a interface do programador para os codecs.
O ACM pertence realmente em MMSystem.pas (que lida com o Windows multimédia), mas, por algum motivo, ele foi omitido. A primeira tarefa é, portanto, encontrar uma cópia de MSACM.pas, que é uma conversão API desta API. A mais útil que eu encontrei foi a conversão por Francois Piette, que foi postado no Projeto Jedi (www.Delphi-Jedi.org).
ACM exige que o desenvolvedor realize os seguintes passos no sentido de converter mídia entre formatos
• Você deve decidir sobre o seu formato de entrada e de saída. Este se baseia no gravador TWaveFormatEX, mas, atenção, esta estrutura de gravadores não é realmente grande o suficiente para armazenar as informações necessárias da maioria dos codecs.
É devido a isto que eu usei meu próprio gravador TACMFormat, o que não é mais do que um gravador TWaveFormatEX com alguns bytes extras no final. Realmente não tem nenhuma maneira (não que conheça) de sabermos o que
estes extras bytes significam, ou como eles devem ser definidos. Minha solução para este problema foi utilizar o acmFormatChoose para permitir que o desenvolvedor escolha os formatos em um momento designado, e então têm estes valores difundidos no IDE como uma propriedade personalizada (mais sobre isso depois).
• Você deve então abrir um stream ACM. Isto é feito chamando cmStreamOpen, passando os formatos de Entrada e Saída para que o ACM esteja consciente do que é exigido dele. Neste ponto, ou o ACM irá retornar como válido para fazer stream, ou vai retornar um código de erro, como ACMERR_NotPossible para indicar que a transformação requerida não pode ser realizada (mais sobre isso mais tarde).
• O próximo item a ser executado é determinar o tamanho do buffer de saída. Chamar acmStreamSize irá informar ao ACM quantos bytes você pretende lhes fornecer a cada vez, então ele irá retornar o tamanho do buffer de saída exigido (isto quase sempre será super estimado para assegurar que você forneça um buffer grande o suficiente).
• A etapa final de preparação é preparar um header. Tudo o que nós precisamos fazer aqui é chamar acmStreamPrepareHeader passando o stream que recebemos de acmStreamOpen. O header que nos preparamos também irá dizer ao ACM o endereço do nosso buffer "fonte" de, bem como o endereço do nosso buffer de "destino" (O ACM não atribui essa memória para nós, temos que atribuir isso nós mesmos).
Neste ponto, todo o nosso trabalho de preparação foi feito. Tudo que nós precisamos fazer agora é pedir que os dados sejam convertidos. Uma vez que toda a nossa preparação está completa, isto é, na verdade, um passo muito simples. É alcançado chamando acmStreamConvert. Esta rotina nos exige abastecer o Stream Handle (Para que ele saiba que estamos trabalhando com formatos), e o nosso Header Handle (de modo que ele saiba o tamanho dos buffers, localização da origem e destino). Esta rotina irá especificar o número atual de bytes usados na conversão configurando cbDstLengthUsed no header. Sua sessão ACM agora está pronta para um outro lote de dados!
Depois de ter acabado a sua sessão ACM é hora de liberar os recursos que utilizamos. Esta é a parte mais simples de todas. O header é liberado usando acmStreamUnprepareHeader, e o strem é liberado usando acmStreamClose.
Escolhendo um formato
Antes de empreender qualquer uma das etapas anteriores, devemos ter os nossos formatos de entrada e saída prontos. Como disse anteriormente, estes formatos são baseados em TwaveFormatEX (declarados em MMSystem.pas), que é apenas um registro especificando taxas de bits, freqüência, etc. A menos que você pretenda converter apenas entre formatos PCM diferentes (o que é muito pouco provável) , este formato não vai ser suficiente. O seguinte formato foi utilizado ao longo de todo o componente de código anexado.
________________________________________
TACMWaveFormat = packed record
case integer of
0: (Format: TWaveFormatEx);
1: (RawData: Array [0 .. 128] of byte);
end;
________________________________________
A idéia aqui é que ainda podemos acessar os dados TWaveFormatEX, referindo-se à parte Formato do gravador, ainda que RawData nos forneça espaço suficiente para quaisquer outros dados necessários para qualquer um dos codecs individuais.
Apesar de ainda não sabemos nem o tamanho destes dados adicionais, ou o que ele representa, é uma tarefa simples de conseguí-lo. Isto é feito usando acmFormatChoose.
AcmFormatChoose requer apenas um parâmetro do tipo TACMFormatChooseA. Este parâmetro é uma estrutura simples contendo as seguintes (relevantes) informações.
pwfx
Um ponteiro para uma estrutura TWaveFormatEX para receber o resultado (nós realmente passamos TACMFormat)
cbwfx
O tamanho em bytes do buffer que é o de receber o resultado.
cbStruct
O tamanho desta estrutura
Nota:
Outro ponto digno de menção é fdwStyle, que detém bandeiras especificando opções adicionais para a caixa de diálogo de seleção de formato. (Em especial, é a (muito longa) bandeira ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT, que informa a caixa de diálogo que o buffer apontado pelo pwfx já contém um formato válido, que deve ser exibido como padrão quando o dailog aparece).
Um pouco de telefone sem fio
Há pouco me referi ao erro ACMERR_NotPossible. Isso pode ocorrer por algumas razões.
Os duas primeiros a se notar (simplesmente porque são os mais fáceis de explicar) são
• O codec que você especificou na sua máquina, pode não estar disponível em uma máquina cliente
• Embora você possa converter a partir de um determinado formato de áudio, você não pode converter para ele. Este é o caso com a Fraunhofer IIS MP3. Enquanto os usuários do Windows NT e Windows 9x podem criar arquivos MP3 no coração do conteúdo, por alguma razão, a capacidade foi removida no Windows 2000 (Sim, obrigado novamente Microsoft). Embora usuários win2k possam ouvir o resultado, eles não têm permissão para gerá-los a menos que eles paguem alguém primeiro!
O final é um pouco mais complicado, e garante a frase
"Telefone sem fio".
Nem todos os formatos de ACM são intercambiáveis, por exemplo (estou apenas inventando estes, por isso, se eles realmente funcionam, não me escrevem dizendo que eu estava errado) você pode não ser capaz de converter
GSM 8bit MONO> MP3 8bit MONO
Você precisa encontrar um "intermediárui". Isso é muitas vezes um formato PCM, já que a maioria (se não todos) dos codecs foram concebidos para converter PCM em um formato mais adequado.
O exemplo acima seria, portanto, alcançado, se assim o desejar.
GSM 8bit MONO> PCM MONO 8bit> MP3 8bit MONO
Convertendo para "MP3 16BIT STEREO" provavelmente iria exigir mais uma etapa (entre o PCM e MP3, a fim de converter 8 bits PCM para 16 bits PCM).
Eu acho que você agora vai entender o porquê desta seção ser chamada de "Telefone sem fio". (Se alguém puder me dizer o significado dessa frase, eu vou gostar de saber!)
Os talentos ocultos do ACM
Você poderá ou não estar convencido de que o ACM é uma coisa boa. Isto parece ser bastante trabalho apenas para converter um formato de mídia em outro. Considerando a alternativa de escrever o seu próprio formato de áudio pequeno o suficiente para internet streaming, ou escrever a sua própria rotina de compressão MP3, ACM é o que nós chamamos de fácil.
Imagine uma simples aplicação que pega a saída do seu microfone, comprime-o para um formato adequado para streaming em uma banda muito baixa e, em seguida, envia-o para um PC de destino através de TCP / IP. Ao mesmo tempo que recebe dados comprimidos, descompacta-o, e depois toca no seu alto-falante (conhecido como, um simples telefone na internet).
Eu disse simples? Bem, na verdade, sim!
Isto soa como muito trabalho, e provavelmente é (exceto com os componentes fornecidos, na verdade é muito simples).
É aqui que os talentos ocultos do ACM entram em jogo. Muito poucos dos codecs ACM são Wave-mapeáveis. O que basicamente significa que eles podem ser tratados como um dispositivo padrão WAVE ao reproduzir / gravar áudio.
Por exemplo. É muito fácil abrir uma entrada para uma fonte sonora GSM. Depois de receber um buffer de dados do dispositivo de entrada wave, já é comprimido e pronto para a transmissão. Por outro lado, logo que os dados são recebidos através de seu soquete TCP / IP, é possível jogar esses dados diretamente através de um dispositivo wave.
• Dados do MIC
• Enviar dados através de soquete
• Dados do soquete
• Enviar dados ao dispositivo de saída wave
Os dados PCM padrão seriam muito grandes para streaming em tempo real através de um modem. Considerando que GSM 6.1 pode ser transmitidos a um nível tão baixo quanto 1.5k/segundo, e MP3 16BIT MONO pode ter stream a meros 2k/second.
Além do win2k não ser capaz (ou mesmo permitido) de criar MP3, não há outra coisa que vale a pena mencionar acerca deste formato. Embora possa ser facilmente tratado como um dispositivo de saída wave, parece não funcionar como dispositivo de entrada wave. É por isso que eu achei necessário converter os dados de PCM MP3 manualmente (o que acabou por se tornar um projeto demonstrativo bastante interessante)
Componentes, demos e código-fonte
Bem, é muito bonito falar sobre essas coisas, mas isso não é realmente muito útil sem alguma evidência para comprovar.
Por esta razão, eu incluí três componentes, e duas demonstrações (demos foram compiladas no Delphi 5). Esses componentes estão disponíveis para download no meu site Delphi.
Componentes
• TACMConvertor: Isto realmente serve para dois propósitos. Em primeiro lugar, converte os dados entre 2 diferentes formatos de mídia. Em segundo lugar, mesmo se você não pretende converter manualmente os dados brutos, este componente é útil para especificar formatos de entrada / saída de streams ACM. (O clique com o botão direito no editor componente permite que você selecione os formatos de diálogo acmFormatChoose no momento designado)
• TACMIn: Este componente é utilizado para a recepção de dados do seu microfone. Você pode especificar um formato PCM padrão, ou você pode especificar qualquer formato capaz de ser mapeado por meio do dispositivo WaveIn.
• TACMOut: Este componente é utilizado para a reprodução de áudio através de sua saída de áudio. Novamente, você pode selecionar a saída no formato PCM, ou qualquer outro formato capaz de ser mapeado por meio de seu dispositivo WaveOut. A propriedade NumBuffers especifica quantos buffers você quer que sejam preenchidos antes de começar a tocar. Isto não é muito usado quando queremos áudio instantâneo (telefones de Internet), mas pode ser muito útil quando você quer fazer radiodifusão do áudio pela internet, e que fazer o buffer de algum áudio extra no caso de a sua velocidade de conexão oscilar.
Demos
A primeira demo é realmente muito simples. O TACMConvertor é usado apenas para especificar os formatos de entrada e de saída. Esta demo abre um ACMIn e um ACMOut ao mesmo tempo. A entrada de áudio é canalizada de volta quase imediatamente, mas com um ligeiro atraso, fazendo-lhe parecer um pouco como Elvis Presley (Embora eu não seja um fã de Elvis, "All shook up" foi a primeira canção que me veio à mente quando eu testei)
A segunda demo é um pouco mais complicada e vem em duas partes.
A primeira parte (Demo2.dpr) age como um servidor. Possui um servidor soquete escutando na porta 6565 para novas conexões. Ao mesmo tempo PE,ga áudio do MIC, converte-o em MP3 16BIT 8khz Mono (2k/second) e os canaliza para todos os clientes conectados.
A segunda parte (Demo2Client.dpr)atua como um cliente. A primeira caixa de edição requer o endereço IP do servidor, enquanto que a segunda entrada (SpinEdit) é o número de buffers adicionais que você precisa. Depois de clicar em conectar (e o número de buffers solicitados tenha sido preenchido) você vai começar a ouvir o áudio a partir do servidor. MP3 16BIT 8khz Mono é surpreendentemente de boa qualidade, e também surpreendentemente de baixa largura de banda.
Bem, isso completou este artigo. Espero que tenha se beneficiado lendo sobre isso muito mais do que gostei de ter que colocado tudo isso pra fora!
A partir da versão 2.0 esses componentes agora estão disponíveis e comercializados em http://www.droopyeyes.com