O Chrome tem aprimorado de forma consistente e silenciosa o suporte à API Web Audio. No Chrome 49 (Beta a partir de fevereiro de 2016, e esperamos que seja estável em março de 2016), atualizamos vários recursos para rastrear a especificação, além de adicionar 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 com base em promessas. O método decodeAudioData()
sempre teve
as funções de callback de sucesso e erro como parâmetros:
context.decodeAudioData( arraybufferData, onSuccess, onError);
Mas agora você pode usar o método Promise padrão para lidar com 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 mais consistente. Para compatibilidade, as funções de callback "Success" e "Error" ainda são compatíveis, conforme a especificação.
Off-lineAudioContext agora é compatível com suspend() e resume()
À primeira vista, pode parecer estranho ter suspend() em um OfflineAudioContext.
Afinal, suspend()
foi adicionado a AudioContext
para permitir colocar o hardware
de áudio no modo de espera, o que parece inútil em cenários em que você está
renderizando em um buffer, que é a finalidade de OfflineAudioContext
.
No entanto, o objetivo desse recurso é conseguir construir apenas parte de uma
"pontuação" por vez, para minimizar o uso da memória. É possível criar mais nós enquanto
suspensos no meio de uma renderização.
Como exemplo, a Sonata Moonlight de Beethoven contém cerca de 6.500 notas.
Cada "nota" provavelmente é desconstruída para pelo menos alguns nós de gráfico de áudio
(por exemplo, um AudioBuffer e um nó de ganho). Se você quer renderizar os
sete minutos e meio inteiros em um buffer com OfflineAudioContext
, provavelmente
não vai querer criar todos esses nós de uma só vez. Em vez disso, é possível criá-los em
períodos 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 permite minimizar o número de nós que precisam ser pré-criados no início da renderização e diminuir as demandas de memória.
IIRFilterNode
A especificação adicionou um nó para audiófilos que querem criar a própria
infinite-impulse-response
especificado 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
fácil de usar do BiquadFilterNode
para tipo, frequência, Q e similares. 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 exige
um conhecimento profundo de como os filtros IIR funcionam, e eles também não são programáveis
como BiquadFilterNodes.
Alterações anteriores
Também quero mencionar algumas melhorias anteriores: no
Chrome 48, a automação do nó BiquadFilter
começou a ser executada na taxa de áudio. A API
não mudou para fazer isso, mas isso significa que o processo de limpeza do filtro terá um som
ainda mais suave. Ainda no Chrome 48, adicionamos o encadeamento ao método AudioNode.connect()
,
retornando o nó a que estamos nos conectando. Isso simplifica a
criação de cadeias de nós, como neste
exemplo:
sourceNode.connect(gainNode).connect(filterNode).connect(context.destination);
Isso é tudo por enquanto, e continue assim!