Mudanças no áudio da Web na versão m36

Chris Wilson
Chris Wilson

Mudanças no Web Audio

No Google, adoramos padrões. Nossa missão é criar a plataforma da Web definida por padrões. Uma das pequenas falhas que já dura algum tempo é a implementação com prefixo webkit da API Web Audio (principalmente o objeto webkitAudioContext) e alguns dos bits descontinuados do Web Audio que continuamos a oferecer suporte.

Originalmente, o Chrome 36 iria remover o suporte para o prefixo webkitAudioContext, já que começamos a oferecer suporte ao objeto AudioContext sem prefixo. Isso acabou sendo mais problemático do que o esperado. Por isso, o Chrome 36 oferece suporte a prefixos e sem prefixos. No entanto, mesmo no webkitAudioContext reintroduzido, vários métodos e atributos legados, como createGainNode e createJavaScriptNode, foram removidos. Em resumo, no Chrome 36, webkitAudioContext e AudioContext são aliases um do outro. Não há diferença na funcionalidade entre os dois.

Vamos remover o suporte ao prefixo completamente após o Chrome 36, provavelmente em algumas versões. Vamos fazer um anúncio aqui quando a mudança for iminente, e continuaremos entrando em contato com os autores para corrigir os apps do Web Audio.

Por que fizemos isso em vez de reverter para a implementação anterior? Bem, em parte, não queríamos voltar muito no tempo. Já removemos essas APIs, e como um bom efeito colateral desse mapeamento, os aplicativos podem funcionar bem no Firefox, que nunca ofereceu suporte a um objeto AudioContext com prefixo (e com razão!). O suporte ao Web Audio foi lançado no outono passado.

O restante desta atualização oferece um guia para corrigir problemas que possam ter ocorrido no código devido a essa mudança. A vantagem de corrigir esses problemas é que seu código provavelmente também vai funcionar no Firefox. Por muito tempo, pensei que meu aplicativo de Vocoder estava quebrado devido à implementação do Firefox, mas era um desses problemas.

Se você quiser começar a usar, confira uma biblioteca monkey-patch que escrevi para aplicativos criados com o código antigo do Web Audio. Ela pode ajudar você a começar a usar em um tempo mínimo, porque cria aliases para os objetos e métodos de maneira adequada. De fato, os patches listados pela biblioteca são um bom guia para as coisas que mudaram.

Em primeiro lugar

Todas as referências a window.webkitAudioContext precisam ser feitas para window.AudioContext. Geralmente, isso é corrigido com um simples:

window.AudioContext = window.AudioContext || window.webkitAudioContext;

Se o app responder com algo como "Infelizmente, seu navegador não oferece suporte ao Web Audio. Use o Chrome ou o Safari." É muito provável que ele esteja procurando explicitamente por webkitAudioContext. Desenvolvedor ruim! Você pode ter apoiado o Firefox por meses!

Mas há outras remoções de código mais sutis, algumas das quais podem ser menos óbvias.

  • As constantes de tipo enumerado do BiquadFilter para o atributo .type (que agora é uma string) não aparecem mais no objeto BiquadFilterNode, e não oferecemos suporte a elas no atributo .type. Assim, você não usa mais .LOWPASS (ou 0), e sim "lowpass".
  • Além disso, o atributo Oscillator.type agora é um tipo enumerado de string. Não há mais .SAWTOOTH.
  • PannerNode.type também é um tipo enumerado de string.
  • PannerNode.distanceModel também é um tipo enumerado de string.
  • createGainNode foi renomeado como createGain
  • createDelayNode foi renomeado como createDelay
  • createJavaScriptNode foi renomeado como createScriptProcessor
  • AudioBufferSourceNode.noteOn() foi substituído por start()
  • AudioBufferSourceNode.noteGrainOn() também foi substituído por start().
  • AudioBufferSourceNode.noteOff() foi renomeado como stop().
  • OscillatorNode.noteOn() foi renomeado como start().
  • OscillatorNode.noteOff() foi renomeado como stop().
  • AudioParam.setTargetValueAtTime() foi renomeado como setTargetAtTime().
  • AudioContext.createWaveTable() e OscillatorNode.setWaveTable() foram renomeados como createPeriodicWave() andsetPeriodicWave()
  • AudioBufferSourceNode.looping foi removido em favor de .loop
  • AudioContext.createBuffer(ArrayBuffer, boolean) para decodificar de forma síncrona um blob de dados de áudio codificados foi removido. Chamadas síncronas que demoram muito para serem concluídas são práticas de programação inadequadas. Use a chamada assíncrona decodeAudioData. Essa é uma das mudanças mais desafiadoras, porque você precisa mudar o fluxo lógico, mas é uma prática muito melhor. Ehsan Angkari, da Mozilla, escreveu um bom exemplo de como fazer isso na postagem sobre a conversão para o Web Audio padrão.

Muitas delas (como a renomeação de createGainNode e a remoção da decodificação síncrona em createBuffer) obviamente vão aparecer no console de ferramentas para desenvolvedores como um erro. No entanto, outras, como este uso:

MULTI_LINE_CODE_PLACEHOLDER_1

não vai aparecer e falhar silenciosamente (myFilterNode.BANDPASS agora será resolvido como indefinido, e a tentativa de definir .type como indefinido simplesmente não produzirá nenhum efeito. Isso, aliás, era o que estava causando a falha do vocoder. Da mesma forma, basta atribuir o filter.type a um número que funcionava:

myFilterNode.type = 2;

Mas agora você precisa usar a enumeração de string:

myFilterNode.type = bandpass;

Portanto, talvez você queira procurar no código os seguintes termos:

  • webkitAudioContext
  • .LOWPASS
  • .HIGHPASS
  • .BANDPASS
  • .LOWSHELF
  • .HIGHSHELF
  • .PEAKING
  • .NOTCH
  • .ALLPASS
  • .SINE
  • .SQUARE
  • .SAWTOOTH
  • .TRIANGLE
  • .noteOn
  • .noteGrainOn
  • .noteOff
  • .setWaveTable
  • .createWaveTable
  • .looping
  • .EQUALPOWER
  • .HRTF
  • .LINEAR
  • .INVERSE
  • .EXPONENTIAL
  • createGainNode
  • createDelayNode
  • .type (sim, isso vai gerar muitos falsos positivos, mas é a única maneira de detectar o último exemplo acima).

Mais uma vez, se você estiver com pressa e quiser começar a usar, pegue uma cópia da minha biblioteca monkeypatch webkitAudioContext e a inclua no seu aplicativo. Bom trabalho!