Odtwarzanie dźwięków

Flash Player 9 i nowsze wersje, Adobe AIR 1.0 i nowsze wersje

Odtwarzanie załadowanego dźwięku może sprowadzać się do wywołania dla obiektu Sound metody Sound.play() ; oto przykład:

var snd:Sound = new Sound(new URLRequest("smallSound.mp3")); 
snd.play();

Podczas odtwarzania dźwięków za pomocą programu ActionScript 3.0 można wykonać następujące operacje:

  • Odtworzyć dźwięk z określonej pozycji początkowej

  • Wstrzymać dźwięk i wznowić odtwarzania z tej samem pozycji później

  • Dowiedzieć się, kiedy dokładnie skończy się odtwarzanie dźwięku

  • Prześledzić postęp odtwarzania dźwięku

  • Zmienić głośność lub panoramowanie podczas odtwarzania dźwięku

W celu przeprowadzenia tych operacji podczas odtwarzania należy skorzystać z klas SoundChannel, SoundMixer i SoundTransform.

Klasa SoundChannel steruje odtwarzaniem pojedynczego dźwięku. Właściwość SoundChannel.position można rozumieć jako głowicę odtwarzania, wskazując bieżące położenie w odtwarzanych danych dźwiękowych.

Po wywołaniu przez aplikację metody Sound.play() tworzona jest nowa instancja klasy SoundChannel umożliwiająca sterowanie odtwarzaniem.

Tworzona aplikacja może odtwarzać dźwięki od określonego punktu — w tym celu konieczne jest przekazanie pozycji rozpoczęcia (w milisekundach) jako parametru startTime metody Sound.play() . Ponadto można również podać wymaganą liczbę powtórzeń, przekazując odpowiednią wartość numeryczną parametru loops metody Sound.play() .

Po wywołaniu metody Sound.play() wraz z parametrami startTime oraz loops dźwięk jest odtwarzany od tego samego punktu początkowego za każdym razem, zgodnie z poniższym kodem przykładowym.

var snd:Sound = new Sound(new URLRequest("repeatingSound.mp3")); 
snd.play(1000, 3);

W tym przykładzie dźwięk jest odtwarzany z punktu zlokalizowanego jedną sekundę za punktem początkowym dźwięku, trzy razy z rzędu.

Wstrzymywanie i wznawianie dźwięku

Jeśli aplikacja umożliwia odtwarzanie długich dźwięków, takich jak utwory lub podkasty, może okazać się przydatne udostępnienie użytkownikom możliwości wstrzymania, a następnie wznowienia odtwarzania tych dźwięków. Nie jest możliwe zwyczajne wstrzymanie dźwięku podczas odtwarzania w ActionScript; niestety można go wyłącznie zatrzymać. Dźwięk może być jednak odtwarzany z dowolnego punktu. Możliwe jest zarejestrowanie położenia odtwarzania dźwięku w chwili zatrzymania tego odtwarzania, a następnie ponowne uruchomienie odtwarzania tylko od tego punktu.

Na przykład, załóżmy że kod ładuje i odtwarza plik dźwiękowy jak w poniższym przykładzie:

var snd:Sound = new Sound(new URLRequest("bigSound.mp3")); 
var channel:SoundChannel = snd.play();

Podczas odtwarzania dźwięku właściwość SoundChannel.position wskazuje miejsce w pliku dźwiękowym, które jest obecnie odtwarzane. Aplikacja może zapisać wartość tego położenia przed zatrzymaniem odtwarzania dźwięku, w następujący sposób:

var pausePosition:int = channel.position; 
channel.stop();

W celu wznowienia odtwarzania dźwięku należy przekazać poprzednio zapisaną wartość położenia w celu ponownego uruchomienia dźwięku z tego samego punktu, w którym został on uprzednio zatrzymany.

channel = snd.play(pausePosition);

Monitorowanie odtwarzania

Może okazać się przydatne udostępnienie aplikacji informacji o chwili zatrzymania odtwarzania, tak aby mogła ona rozpocząć odtwarzanie innego dźwięku lub oczyścić zasoby używane podczas poprzedniego odtwarzania. Klasa SoundChannel dysponuje zdarzenie Event.SOUND_COMPLETE po zakończeniu odtwarzania dźwięku. Aplikacja może wykrywać to zdarzenie, wykonując wówczas odpowiednie czynności, zgodnie z przykładem poniżej:

import flash.events.Event; 
import flash.media.Sound; 
import flash.net.URLRequest; 
 
var snd:Sound = new Sound(); 
var req:URLRequest = new URLRequest("smallSound.mp3"); 
snd.load(req); 
 
var channel:SoundChannel = snd.play(); 
channel.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete); 
 
public function onPlaybackComplete(event:Event) 
{ 
    trace("The sound has finished playing."); 
}

Klasa SoundChannel nie dysponuje zdarzeń postępu podczas odtwarzania. W celu zgłoszenia postępów odtwarzania aplikacja może ustawić własny mechanizm odmierzania czasu i śledzenia położenia głowicy odtwarzania.

W celu obliczenia udziału procentowego odtworzonego dźwięku możliwe jest podzielenie wartości właściwości SoundChannel.position przez długość odtwarzanych danych dźwiękowych:

var playbackPercent:uint = 100 * (channel.position / snd.length);

Ten kod umożliwia jednak zaraportowanie dokładnych wartości procentowych odtwarzania wyłącznie, jeśli dane dźwiękowe został do końca załadowane, zanim odtwarzanie się rozpoczęło. Właściwość Sound.length wskazuje rozmiar ładowanych obecnie danych dźwiękowych nie zaś rozmiar końcowy całego pliku. Do celów śledzenia postępu odtwarzania dźwięku przesyłanego strumieniowo, który jest nadal ładowany, aplikacja szacuje końcowy rozmiar całego pliku dźwiękowego i tej wartości używa w obliczeniach. Możliwe jest oszacowanie końcowej długości danych dźwiękowych za pomocą właściwości bytesLoaded i bytesTotal obiektu Sound, zgodnie z poniższym przykładem:

var estimatedLength:int =  
    Math.ceil(snd.length / (snd.bytesLoaded / snd.bytesTotal)); 
var playbackPercent:uint = 100 * (channel.position / estimatedLength);

Poniższy kod powoduje załadowanie większego pliku dźwiękowego i używa zdarzenia Event.ENTER_FRAME w formie mechanizmu odmierzania czasu do celów prezentacji postępu odtwarzania. Okresowo zgłasza on wielkość procentową odtworzonego fragmentu, obliczaną jako wartość bieżącego położenia podzielona przez łączną długość danych dźwiękowych:

import flash.events.Event; 
import flash.media.Sound; 
import flash.net.URLRequest; 
 
var snd:Sound = new Sound(); 
var req:URLRequest = new  
    URLRequest("http://av.adobe.com/podcast/csbu_dev_podcast_epi_2.mp3"); 
snd.load(req); 
 
var channel:SoundChannel; 
channel = snd.play(); 
addEventListener(Event.ENTER_FRAME, onEnterFrame); 
channel.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete); 
 
function onEnterFrame(event:Event):void 
{ 
    var estimatedLength:int =  
        Math.ceil(snd.length / (snd.bytesLoaded / snd.bytesTotal)); 
    var playbackPercent:uint =  
        Math.round(100 * (channel.position / estimatedLength)); 
    trace("Sound playback is " + playbackPercent + "% complete."); 
} 
 
function onPlaybackComplete(event:Event) 
{ 
    trace("The sound has finished playing."); 
    removeEventListener(Event.ENTER_FRAME, onEnterFrame); 
}

Po rozpoczęciu ładowania danych dźwiękowych kod ten wywołuje metodę snd.play() i zapisuje wynikowy obiekt SoundChannel w zmiennej channel . Następnie dodaje on moduł wykrywania zdarzeń do aplikacji głównej dla zdarzenia Event.ENTER_FRAME oraz kolejny moduł wykrywania zdarzeń do obiektu SoundChannel dla zdarzenia Event.SOUND_COMPLETE mającego miejsce po ukończeniu odtwarzania.

Za każdym razem po osiągnięciu przez aplikację nowej klatki animacji wywoływana jest metoda onEnterFrame() . Metoda onEnterFrame() szacuje całkowitą długość pliku dźwiękowego w oparciu o ilość już załadowanych danych, a następnie oblicza je i wyświetla bieżącą wartość procentową dla odtwarzanego dźwięku.

Po odtworzeniu całego dźwięku wykonywana jest metoda onPlaybackComplete() usuwająca moduł wykrywania zdarzeń dla zdarzenia Event.ENTER_FRAME tak, że nie podejmuje on dalszych prób wyświetlania postępu.

Zdarzenie Event.ENTER_FRAME może być dysponowane wiele razy na sekundę. W niektórych przypadkach może okazać się, że wyświetlanie postępów odtwarzania tak często nie jest pożądane. W takich przypadkach aplikacja może ustawić własny mechanizm za pomocą klasy flash.util.Timer; patrz sekcja Praca z datami i czasem .

Zatrzymywanie przesyłania strumieniowego dźwięków

Istnieje pewna niedoskonałość w przetwarzaniu dźwięków przesyłanych strumieniowo, tj. dźwięków odtwarzanych przy jednoczesnym ładowaniu. Gdy aplikacja wywołuje metodę SoundChannel.stop() dla instancji SoundChannel odtwarzającej dźwięk przesyłany strumieniowo, odtwarzanie dźwięku dla jednej klatki jest zatrzymywane, a następnie, jest ono wznawiane wraz z kolejną klatką od początku dźwięku. Dzieje się tak, ponieważ w tle nadal trwa proces ładowania dźwięku. W celu zatrzymania zarówno ładowania, jak i odtwarzania przesyłanego strumieniowo dźwięku należy wywołać metodę Sound.close() .