Veelgestelde vragen over Web Audio

Boris Smus

In de afgelopen maanden is de Web Audio API van WebKit uitgegroeid tot een aantrekkelijk platform voor games en audio-apps op het web. Terwijl ontwikkelaars ermee vertrouwd raken, hoor ik steeds weer dezelfde vragen. Met deze snelle update proberen we enkele van de meestgestelde vragen te beantwoorden om je ervaring met de Web Audio API aangenamer te maken.

V: Help, ik kan geen geluiden maken!

A: Als je nog niet bekend bent met de Web Audio API, neem je de tutorial Aan de slag door of het recept van Eric voor audio afspelen op basis van gebruikersinteractie.

V. Hoeveel audiocontexten moet ik hebben?

A: Over het algemeen moet je één AudioContext per pagina opnemen. Eén audiocontext kan veel knooppunten ondersteunen die eraan zijn gekoppeld. Hoewel je meerdere AudioContexts op één pagina kunt opnemen, kan dit de prestaties negatief beïnvloeden.

V: Ik heb een AudioBufferSourceNode die ik net heb afgespeeld met noteOn() en ik wil deze opnieuw afspelen, maar noteOn() doet niets. Help!

A: Nadat een bronknooppunt is afgelopen, kan het niet meer worden afgespeeld. Als je de onderliggende buffer opnieuw wilt afspelen, maak je een nieuwe AudioBufferSourceNode en roep je noteOn() aan.

Hoewel het misschien inefficiënt lijkt om het bronknooppunt opnieuw te maken, zijn bronknooppunten sterk geoptimaliseerd voor dit patroon. Als je een handgreep naar de AudioBuffer bewaart, hoef je geen nieuw verzoek naar de component te sturen om hetzelfde geluid opnieuw af te spelen. Als je dit patroon moet herhalen, kapsel je het afspelen in met een eenvoudige helperfunctie zoals playSound(buffer).

V: Waarom moet ik elke keer een nieuw bronknooppunt maken als ik een geluid afspeel?

A: Het idee achter deze architectuur is om audio-items los te koppelen van de afspeelstatus. Als we een platenspeler als voorbeeld nemen, zijn buffers vergelijkbaar met platen en bronnen met afspeelkoppen. Omdat veel toepassingen meerdere versies van dezelfde buffer tegelijk afspelen, is dit patroon essentieel.

V: Hoe verwerk ik geluid van audio- en video-tags?

A: MediaElementAudioSourceNode is in ontwikkeling. Als deze beschikbaar is, werkt deze ongeveer zo (een filtereffect toevoegen aan een voorbeeld dat wordt afgespeeld via de audiotag):

<audio src="sounds/sample.wav" controls>
var audioElement = document.querySelector('audio');
var mediaSourceNode = context.createMediaElementSource(audioElement);
mediaSourceNode.connect(filter);
filter.connect(context.destination);

Deze functie wordt bijgehouden in deze crbug. In deze instelling hoef je mediaSourceNode.noteOn() niet aan te roepen. De audiocode beheert de weergave.

V: Wanneer krijg ik geluid van een microfoon?

A: Het audio-invoergedeelte hiervan wordt als onderdeel van WebRTC geïmplementeerd met getUserMedia en is beschikbaar als speciaal bronknooppunt in de Web Audio API. De functie werkt in combinatie met createMediaElementSource.

V: Hoe kan ik checken wanneer een AudioSourceNode is afgelopen?

A: Op dit moment moet je een JavaScript-timer gebruiken, omdat de Web Audio API deze functionaliteit niet ondersteunt. Het volgende fragment uit de tutorial Aan de slag met de Web Audio API is een voorbeeld hiervan in actie:

// Assume source and buffer are previously defined.
source.noteOn(0);
var timer = setTimeout(function() {
    console.log('playback finished');
}, buffer.duration * 1000);

Er is een open bug om de Web Audio API een nauwkeurigere callback te laten implementeren.

V: Als ik geluiden laad, loopt de hele UI-thread vast en reageert mijn UI niet meer. Help!**

A: Gebruik de decodeAudioData API voor asynchroon laden om te voorkomen dat de hoofdthread wordt geblokkeerd. Bekijk dit voorbeeld.

V: Kan de Web Audio API worden gebruikt om geluiden sneller dan realtime te verwerken?

A: Ja, er wordt aan een oplossing gewerkt. Probeer het binnenkort nog eens!

V: Ik heb een geweldige Web Audio API-app gemaakt, maar als het tabblad waarop deze wordt uitgevoerd op de achtergrond komt, worden de geluiden heel raar.

A: Dit komt waarschijnlijk doordat je setTimeouts gebruikt. Deze gedragen zich anders als de pagina op de achtergrond wordt geplaatst. In de toekomst kan de Web Audio API op specifieke tijden een callback uitvoeren met de interne timer van de webaudio (het kenmerk context.currentTime). Ga naar dit functieverzoek voor meer informatie.

Over het algemeen is het misschien een goed idee om het afspelen te stoppen als je app naar de achtergrond gaat. Je kunt waarnemen wanneer een pagina naar de achtergrond gaat met de API voor paginazichtbaarheid.

V: Hoe kan ik de toonhoogte van een geluid wijzigen met de Web Audio API?

A: Wijzig de playbackRate in de bronnode.

V: Kan ik de toonhoogte wijzigen zonder de snelheid te wijzigen?

A: De Web Audio API kan een PitchNode in de audiocontext hebben, maar dit is moeilijk te implementeren. Dit komt omdat er geen eenvoudig algoritme voor toonhoogteverschuiving is in de audiocommunity. Bekende technieken maken artefacten, vooral als de toonhoogteverschuiving groot is. Je kunt dit probleem op 2 manieren oplossen:

  • Algoritmen voor tijddomeinen, die artefacten van herhaalde segmentecho's veroorzaken.
  • Technieken voor het frequentiedomein, die artefacten van nagalm veroorzaken.

Hoewel er geen systeemeigen knooppunt is om deze technieken uit te voeren, kunt u dit doen met een JavaScriptAudioNode. Dit codefragment kan als startpunt dienen.

V: Hoe maak ik een AudioContext met een samplingfrequentie naar keuze?

A: Op dit moment wordt dit niet ondersteund, maar we onderzoeken de mogelijkheden. Ga naar dit functieverzoek.

Als je nog vragen hebt, kun je die stellen op StackOverflow met de tag web-audio.