Atualizações de áudio da Web no Chrome 49

Chris Wilson
Chris Wilson

O Chrome tem melhorado de forma consistente e silenciosa o suporte à API Web Audio. No Chrome 49 (Beta desde fevereiro de 2016, e esperado que seja estável em março de 2016), atualizamos vários recursos para acompanhar a especificação e também adicionamos um novo nó.

decodeAudioData() agora retorna uma promessa

O método decodeAudioData() em AudioContext agora retorna um Promise, permitindo o processamento de padrões assíncronos baseados em promessas. O método decodeAudioData() sempre usou funções de callback de sucesso e de erro como parâmetros:

context.decodeAudioData( arraybufferData, onSuccess, onError);

Mas agora você pode usar o método de promessa padrão para processar a natureza assíncrona da decodificação de dados de áudio:

context.decodeAudioData( arraybufferData ).then(
        (buffer) => { /* store the buffer */ },
        (reason) => { console.log("decode failed! " + reason) });

Embora em um único exemplo isso pareça mais detalhado, as promessas tornam a programação assíncrona mais fácil e consistente. Para compatibilidade, as funções de callback de sucesso e erro ainda têm suporte, conforme a especificação.

O OfflineAudioContext agora oferece suporte a suspend() e resume()

À primeira vista, pode parecer estranho ter suspend() em um OfflineAudioContext. Afinal, suspend() foi adicionado a AudioContext para permitir que o hardware de áudio entre no modo de espera, o que parece inútil em cenários em que você está renderizando para um buffer (para o qual OfflineAudioContext é destinado, é claro). No entanto, o objetivo desse recurso é construir apenas parte de uma "pontuação" por vez para minimizar o uso da memória. É possível criar mais nós enquanto está suspenso no meio de uma renderização.

Por exemplo, a Sonata ao Luar de Beethoven contém cerca de 6.500 notas. Cada "nota" provavelmente se decompõe em pelo menos alguns nós do gráfico de áudio (por exemplo, um AudioBuffer e um nó Gain). Se você quiser renderizar os sete minutos e meio em um buffer com OfflineAudioContext, provavelmente não vai querer criar todos esses nós de uma vez. Em vez disso, crie-as em intervalos de tempo:

var context = new OfflineAudioContext(2, length, sampleRate);
scheduleNextBlock();
context.startRendering().then( (buffer) => { /* store the buffer */ } );

function scheduleNextBlock() {
    // create any notes for the next blockSize number of seconds here
    // ...

    // make sure to tell the context to suspend again after this block;
    context.suspend(context.currentTime + blockSize).then( scheduleNextBlock );

    context.resume();
}

Isso vai permitir que você minimize o número de nós que precisam ser pré-criados no início da renderização e reduzir a demanda de memória.

IIRFilterNode

A especificação adicionou um nó para audiófilos que querem criar a própria resposta-impulso-infinita especificada com precisão: o IIRFilterNode. Esse filtro complementa o BiquadFilterNode, mas permite a especificação completa dos parâmetros de resposta do filtro, em vez do AudioParams de fácil uso do AudioParams para tipo, frequência, Q e assim por diante.BiquadFilterNode O IIRFilterNode permite a especificação precisa de filtros que não podiam ser criados antes, como filtros de ordem única. No entanto, o uso do IIRFilterNode requer algum conhecimento profundo de como os filtros IIR funcionam, e eles também não podem ser programados como BiquadFilterNodes.

Mudanças anteriores

Também quero mencionar algumas melhorias que foram feitas anteriormente: no Chrome 48, a automação de nó BiquadFilter começou a ser executada na taxa de áudio. A API não mudou nada para fazer isso, mas isso significa que as varreduras de filtro vão soar ainda mais suaves. Também no Chrome 48, adicionamos a vinculação ao método AudioNode.connect() retornando o nó ao qual estamos nos conectando. Isso facilita a criação de cadeias de nós, como neste exemplo:

sourceNode.connect(gainNode).connect(filterNode).connect(context.destination);

Por enquanto é isso. Continue arrasando!