Najczęstsze pytania dotyczące Web Audio

W ciągu kilku ostatnich miesięcy interfejs Web Audio API firmy WebKit okazał się atrakcyjną platformą dla gier i aplikacji audio w internecie. Gdy deweloperzy już się z nią zapoznają, coraz częściej pojawiają się podobne pytania. Ta krótka aktualizacja to próba odpowiedzi na niektóre z najczęstszych pytań, która ma na celu ułatwienie korzystania z interfejsu Web Audio API.

P: Pomocy, nie mogę wydawać dźwięków.

O: Jeśli dopiero zaczynasz korzystać z interfejsu Web Audio API, zapoznaj się z samouczkiem dla początkujących lub przepisem Eryka na odtwarzanie dźwięku na podstawie interakcji użytkownika.

P: Ile kontekstów audio trzeba mieć?

O: Zasadniczo na każdej stronie powinna znajdować się 1 element AudioContext, a jeden kontekst audio może obsługiwać wiele połączonych z nią węzłów. Choć na jednej stronie możesz umieścić wiele elementów AudioContext, może to prowadzić do zwiększenia wydajności.

P: Mam element AudioBufferSourceNode, który właśnie odtworzyłem w usłudze noteOn(). Chcę odtworzyć go jeszcze raz, ale noteOn() nic nie robi. Potrzebuję pomocy.

O: Po zakończeniu odtwarzania węzła źródłowego nie można go już odtworzyć. Aby ponownie odtworzyć ten bufor, musisz utworzyć nowy element AudioBufferSourceNode i wywołać noteOn().

Ponowne tworzenie węzła źródłowego może wydawać się nieefektywne, ale węzły źródłowe są mocno zoptymalizowane pod kątem tego wzorca. Ponadto, jeśli zachowasz nick bufora dźwięku, nie musisz wysyłać kolejnego żądania do zasobu, aby ponownie odtworzyć ten sam dźwięk. Jeśli musisz powtarzać ten wzorzec, uwzględnij odtwarzanie za pomocą prostej funkcji pomocniczej, np. playSound(buffer).

P: Dlaczego podczas odtwarzania dźwięku trzeba za każdym razem tworzyć nowy węzeł źródłowy?

O: Ideą tej architektury jest oddzielenie zasobu audio od stanu odtwarzania. Podobnie jak w przypadku gramofonów, bufory pełnią rolę płyt i źródeł przed suwakami odtwarzania. Ponieważ wiele aplikacji używa jednocześnie wielu wersji tego samego bufora, ten wzorzec jest istotny.

P: Jak mogę przetworzyć dźwięk z tagów audio i video?

O: Projekt MediaElementAudioSourceNode jest gotowy. Jeśli jest to możliwe, będzie ono działać mniej więcej w następujący sposób (dodanie efektu filtra do próbki odtwarzanej za pomocą tagu audio):

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

Ta funkcja jest śledzona w tym crbug. Pamiętaj, że w tej konfiguracji nie musisz wywoływać funkcji mediaSourceNode.noteOn(), ponieważ tag dźwięku steruje odtwarzaniem.

P: Kiedy mogę uzyskać dźwięk z mikrofonu?

O: Wejściowa część danych audio zostanie zaimplementowana w ramach WebRTC za pomocą getUserMedia i będzie dostępna jako specjalny węzeł źródłowy w interfejsie Web Audio API. Będzie działać w połączeniu z createMediaElementSource.

P: Jak sprawdzić, kiedy AudioSourceNode skończy grać?

O: Obecnie musisz używać licznika czasu w języku JavaScript, ponieważ interfejs Web Audio API nie obsługuje tej funkcji. Oto przykład, jak to zrobić w samouczku interfejsu Web Audio API:

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

Występuje otwarty błąd, który pozwala zaimplementować w interfejsie Web Audio API dokładniejsze wywołanie zwrotne.

P: Po wczytaniu dźwięków cały wątek UI się blokuje, a mój interfejs użytkownika nie odpowiada. Pomocy**

O: Użyj interfejsu API decodeAudioData do wczytywania asynchronicznego, aby uniknąć zablokowania wątku głównego. Zobacz ten przykład.

P: Czy można używać interfejsu Web Audio API do przetwarzania dźwięków szybciej niż w czasie rzeczywistym?

O: Tak, pracujemy nad rozwiązaniem. Sprawdź ją za jakiś czas!

P: Udało mi się stworzyć niesamowitą aplikację interfejsu Web Audio API, ale gdy jej aplikacja przechodzi w tle, dźwięk wydaje się dziwny.

O: Prawdopodobnie jest to spowodowane tym, że używasz pola setTimeouts, które działa inaczej, gdy strona działa w tle. W przyszłości interfejs Web Audio API będzie mieć możliwość wywołania zwrotnego o określonych porach za pomocą wewnętrznego licznika czasu dźwięku z internetu (atrybut context.currentTime). Aby uzyskać więcej informacji, przeczytaj tę prośbę o dodanie funkcji.

Ogólnie dobrym pomysłem jest zatrzymanie odtwarzania, gdy aplikacja pracuje w tle. Jeśli strona działa w tle, możesz to sprawdzić za pomocą interfejsu Page Visibility API.

P: Jak mogę zmienić tonację dźwięku za pomocą interfejsu Web Audio API?

O: Zmień playbackRate w węźle źródłowym.

P: Czy mogę zmienić ton bez zmiany prędkości?

O: Interfejs Web Audio API może zawierać PitchNode w kontekście dźwięku, ale jest to trudne do wdrożenia. Wynika to z tego, że w społeczności twórców audio nie ma prostego algorytmu zmiany tonacji. Znane techniki powodują generowanie artefaktów, zwłaszcza w przypadkach, gdy zmiana tonacji jest duża. Można rozwiązać ten problem na 2 sposoby:

  • algorytmy domen czasu, które powodują powtarzające się odbijanie segmentów;
  • Techniki związane z domeną częstotliwości, które powodują powstawanie artefaktów dźwiękowych.

Chociaż nie ma węzła natywnego do wykonania tych technik, możesz to zrobić w elemencie JavaScriptAudioNode. Jako punktu wyjścia może służyć ten fragment kodu.

P: Jak mogę utworzyć kontekst audio z wybraną przeze mnie częstotliwością próbkowania?

O: Obecnie nie mamy takiej możliwości, ale pracujemy nad tym. Zapoznaj się z tą prośbą o dodanie funkcji.

Jeśli masz więcej pytań, możesz je zadać na StackOverflow, używając tagu web-audio.