Web Audio API este un framework care permite programatorilor dar și artiștilor să realizeze aplicații web care valorifică puterea de procesare nativă. Se pot mixa surse de sunet diverse, aplica diferite efecte audio și se pot crea vizualizări, osciloscoape virtuale și multe altele. În rândurile de mai jos vom arăta că folosirea Web Audio API este relativ simplă, permițându-ne, totodată, să realizăm o serie de aplicații interesante.
Folosim un osciloscop virtual căruia îi vom schimba frecvențele de la 0 la 1000, cărora le vom adăuga o valoare de offset, pentru a obține o reprezentare mai bună. Putem selecta și tipul de undă utilizat de osciloscop. În funcție de acesta, obținem efecte destul de neobișnuite și autentice.
Așa cum se poate vedea în codul de mai jos, începem prin instanțierea contextului audio și crearea oscilatorului. Odată pornit prin metoda start(), schimbarea valorii frecvenței sau a tipului semnalului oscilatorului va fi reflectată în sunetul reprodus. La final, metoda stop() va opri sunetul.
let audioContext =
new AudioContext();
const types=["sawtooth" , "sine" ,
"square" , "triangle"];
async function play() {
let oscillator = audioContext
.createOscillator();
oscillator.connect(
audioContext.destination);
oscillator.start();
for (const type of types) {
for (let i=0;i<3;i++){
await playFrequencies(
oscillator,i*600, type)
}
}
oscillator.stop();
}
async function playFrequencies(oscillator, offset,
type){
oscillator.type=type;
for (let i = 0; i < 1000; i+=10)
{
oscillator.frequency.value =
offset+i;
await sleep(20);
}
}
play()
În următorul exemplu, vom produce sunetele fiecărui generator în paralel. Pentru aceasta am folosit metoda connect() pentru conectarea unei surse la difuzorul calculatorului: audioContext.destination.
async function play() {
for (const type of types) {
for (let i = 0; i < 3; i++) {
playFrequencies(audioContext,
i * 600, type)
}
}
}
async function playFrequencies(audioContext,
offset, type){
let oscillator = audioContext
.createOscillator();
oscillator.start();
oscillator.connect(audioContext
.destination);
oscillator.type=type;
for (let i = 0; i < 1000; i+=10)
{
oscillator.frequency.value =
offset+i;
await sleep(20);
}
oscillator.stop();
}
De multe ori, în timpul evenimentelor online ne-am dorit să putem aplauda. Folosind Web Audio API putem rula așa cum am văzut în exemplul anterior mai multe surse simultan. O soluție practică ar implica și o comunicare WebSocket prin care să transmitem direct aplauzele participanților.
function play2(url){
const audio=new Audio();
audio.src=url;
audio.autoplay=true
document.body
.appendChild(audio);
let source=audioContext.createMediaElementSource(
audio);
source.connect(audioContext.destination);
}
play2("/res/Applause02.mp3");
play2("/res/Applause_OCP-1048-60.wav");
play2("/res/HUMAN_CROWD_Applause_Short_01.wav");
În exemplul de mai sus, utilizăm pagina web existentă pentru crearea unor noduri Audio pentru fiecare fișier audio rulat. Aplauzele sunt rulate simultan, de unde reiese și un efect de scenă garantat.
Nimic mai simplu. În exemplul de mai sus, vom intercala un nod ce controlează volumul între sursa sunetului și sistemul de sunet (audioContext.destiation).
let audioContext = new AudioContext();
const gainNode=new GainNode(audioContext);
gainNode.gain.value=5;
....
source.connect(gainNode).connect(audioContext
.destination);
Nodul gainValue poate avea următoarele valori:
0 - sunetul se oprește (mute);
1 - volumul standard;
Folosim metoda BaseAudioContext.createBiquadFilter pentru a crea un nod audio BiquadFilterNode. Valorile tipului de filtru pot fi următoarele: "allpass", "bandpass", "highpass", "highshelf", "lowpass", "lowshelf", "notch", "peaking"
let audioContext = new AudioContext();
const gainNode=new GainNode(audioContext);
gainNode.gain.value=1;
let filter = audioContext.createBiquadFilter();
filter.type = "lowpass";
function play2(url){
const audio=new Audio();
audio.src=url;
audio.autoplay=true
document.body.appendChild(audio);
let source=audioContext
.createMediaElementSource(audio);
source.connect(gainNode)
.connect(filter)
.connect(audioContext.destination);
}
play2("/res/Vocal_Pop_Logo.mp3");
Utilizăm un efect de pan prin care vom controla în ce parte a sistemului stereo se aude sunetul. Rezultatul dorit este să treacă sunetul dintr-o boxă în cealaltă. Folosim un nod StereoPannerNode căruia îi modificăm valoarea pan. Codul complet îl puteți vedea mai jos:
let audioContext = new AudioContext();
const gainNode=new GainNode(audioContext);
gainNode.gain.value=1;
let filter = audioContext.createBiquadFilter();
filter.type = "notch";
let stereoPanner = audioContext.createStereoPanner();
async function play2(url){
const audio=new Audio();
audio.src=url;
audio.autoplay=true
document.body.appendChild(audio);
let source=audioContext
.createMediaElementSource(audio);
source.connect(gainNode)
.connect(filter)
.connect(stereoPanner)
.connect(audioContext.destination);
let i=-1;
let step=0.1;
while (true){
stereoPanner.pan.value=i;
await sleep(200)
i+=step;
if (i<-0.9 || i>0.9 ) step=-step;
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve,
ms));
}
play2("/res/Vocal_Pop_Logo.mp3");
Web Audio API este un framework puternic care ne permite să controlăm profesionist sunetul într-o aplicație web. Am expus doar câteva operații de bază, deoarece aria de aplicare este mult mai mare și ar putea include elemente de vizualizare, mixere audio sau controlul sunetului într-o aplicație WebRTC.
de Ovidiu Mățan
de Andrei Miron
de Ovidiu Mățan
de Denisa Lupu
de Ovidiu Mățan