W ciągu ostatnich kilku miesięcy interfejs Web Audio API w WebKit stał się atrakcyjną platformą dla gier i aplikacji audio w internecie. W miarę jak deweloperzy poznają tę technologię, często pojawiają się podobne pytania. Ta krótka aktualizacja ma na celu odpowiedź na niektóre z najczęstszych pytań, aby korzystanie z Web Audio API było przyjemniejsze.
P: Pomocy, nie mogę odtwarzać dźwięków!
O: Jeśli dopiero zaczynasz korzystać z Web Audio API, zapoznaj się z samouczkiem dla początkujących lub z przepisem Erica na odtwarzanie dźwięku na podstawie interakcji użytkownika.
Pytanie: Ile kontekstów audio powinno być w mojej aplikacji?
O: Zwykle na każdej stronie powinna znajdować się jedna instancja AudioContext, a jeden kontekst audio może obsługiwać wiele połączonych z nim węzłów. Na jednej stronie możesz umieścić wiele obiektów AudioContext, ale może to negatywnie wpłynąć na wydajność.
P: Mam węzeł AudioBufferSourceNode, który właśnie odtworzyłem za pomocą funkcji noteOn(), i chcę go odtworzyć ponownie, ale noteOn() nic nie robi. Dlaczego
O: Gdy węzeł źródłowy zakończy odtwarzanie, nie może odtwarzać dalej. Aby ponownie odtworzyć bufor bazowy, utwórz nowy obiekt AudioBufferSourceNode i wywołaj metodę noteOn().
Ponowne tworzenie węzła źródłowego może wydawać się nieefektywne, ale węzły źródłowe są w dużym stopniu zoptymalizowane pod kątem tego wzorca. Jeśli zachowasz uchwyt do AudioBuffer, nie musisz wysyłać kolejnej prośby o zasób, aby ponownie odtworzyć ten sam dźwięk. Jeśli musisz powtórzyć ten wzorzec, umieść odtwarzanie w prostej funkcji pomocniczej, takiej jak playSound(buffer).
P: Dlaczego podczas odtwarzania dźwięku musisz za każdym razem tworzyć nowy węzeł źródłowy?
O: Celem tej architektury jest oddzielenie zasobu audio od stanu odtwarzania. Jeśli posłużymy się analogią do gramofonu, bufory są odpowiednikiem płyt, a źródła – głowic odtwarzających. Ten wzorzec jest niezbędny, ponieważ wiele aplikacji obejmuje odtwarzanie jednocześnie wielu wersji tego samego bufora.
P: Jak przetwarzać dźwięk z tagów audio i video?
O: Pracujemy nad MediaElementAudioSourceNode. Gdy będzie dostępny, będzie działać w przybliżeniu w ten sposób (dodając efekt 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 zgłoszeniu błędu. Pamiętaj, że w tej konfiguracji nie musisz wywoływać funkcji mediaSourceNode.noteOn(), ponieważ odtwarzaniem steruje tag audio.
P: Kiedy mogę uzyskać dźwięk z mikrofonu?
O: Część dotycząca wejścia audio zostanie zaimplementowana w ramach WebRTC przy użyciu 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ł(-a) odtwarzanie?
O: Obecnie musisz używać timera JavaScript, ponieważ interfejs Web Audio API nie obsługuje tej funkcji. Poniższy fragment z samouczka Wprowadzenie do interfejsu Web Audio API pokazuje to w praktyce:
// Assume source and buffer are previously defined.
source.noteOn(0);
var timer = setTimeout(function() {
console.log('playback finished');
}, buffer.duration * 1000);
Istnieje otwarty błąd, który sprawia, że interfejs Web Audio API implementuje mniej dokładne wywołanie zwrotne.
P: Wczytywanie dźwięków powoduje zablokowanie całego wątku UI i interfejs przestaje odpowiadać. Pomocy!**
O: Użyj interfejsu decodeAudioData API do asynchronicznego wczytywania, aby uniknąć blokowania wątku głównego. Zobacz ten przykład.
Pytanie: Czy interfejs Web Audio API może przetwarzać dźwięki szybciej niż w czasie rzeczywistym?
O: Tak, pracujemy nad rozwiązaniem. Wkrótce podamy więcej informacji na ten temat.
Pyt.: Mam świetną aplikację opartą na interfejsie Web Audio API, ale gdy karta, na której działa, przechodzi w tle, dźwięki zaczynają dziwnie brzmieć.
O: Prawdopodobnie używasz setTimeouts, które działają inaczej, gdy strona jest w tle. W przyszłości interfejs Web Audio API będzie mógł wywoływać funkcję zwrotną w określonych momentach, korzystając z wewnętrznego timera interfejsu Web Audio (atrybut context.currentTime). Więcej informacji znajdziesz w tej prośbie o dodanie funkcji.
Zazwyczaj warto zatrzymać odtwarzanie, gdy aplikacja przechodzi w tryb tła. Aby wykryć, kiedy strona przechodzi w tło, możesz użyć interfejsu Page Visibility API.
Pytanie: Jak mogę zmienić wysokość dźwięku za pomocą interfejsu Web Audio API?
O: Zmień playbackRate w węźle źródłowym.
P: Czy mogę zmienić wysokość dźwięku bez zmiany szybkości?
O: Interfejs Web Audio API może mieć w kontekście audio węzeł PitchNode, ale jest to trudne do wdrożenia. Wynika to z braku prostego algorytmu zmiany wysokości dźwięku w społeczności audio. Znane techniki tworzą artefakty, zwłaszcza w przypadku dużych zmian wysokości dźwięku. Istnieją 2 rodzaje podejścia do tego problemu:
- algorytmy w dziedzinie czasu, które powodują powtarzające się artefakty echa segmentu;
- Techniki dziedziny częstotliwości, które powodują artefakty dźwiękowe związane z pogłosem.
Chociaż nie ma natywnego węzła do stosowania tych technik, możesz to zrobić za pomocą JavaScriptAudioNode. Ten fragment kodu może posłużyć jako punkt wyjścia.
P: Jak utworzyć AudioContext z wybranym współczynnikiem próbkowania?
O: Obecnie nie ma takiej możliwości, ale pracujemy nad tym. Zobacz prośbę o dodanie funkcji.
Jeśli masz dodatkowe pytania, możesz je zadać na StackOverflow, używając tagu web-audio.