De ActionScript 3.0-geluidsarchitectuur is krachtig, maar complex. In toepassingen waarvoor alleen elementaire functies voor het laden en afspelen en geluiden nodig zijn, kan een klasse worden gebruikt waarmee de complexiteit deels wordt verborgen door een vereenvoudigde set methodeaanroepen en gebeurtenissen te bieden. In de wereld van softwareontwerppatronen wordt een dergelijke klasse een facade genoemd.
De klasse SoundFacade biedt één enkele interface voor het uitvoeren van de volgende taken:
Geluidsbestanden laden met behulp van een object Sound, een object SoundLoaderContext en de klasse SoundMixer
Geluidsbestanden afspelen met behulp van het object Sound en het object SoundChannel
Gebeurtenissen over de voortgang van het afspelen verzenden
Het afspelen van het geluid onderbreken en hervatten met behulp van het object Sound en het object SoundChannel
De klasse SoundFacade probeert het merendeel van de functionaliteit van de ActionScript-geluidsklassen te bieden en daarbij de complexiteit beperkt te houden.
In de volgende code worden de klassendeclaratie, de klasseneigenschappen en de constructormethode SoundFacade() weergegeven:
public class SoundFacade extends EventDispatcher
{
public var s:Sound;
public var sc:SoundChannel;
public var url:String;
public var bufferTime:int = 1000;
public var isLoaded:Boolean = false;
public var isReadyToPlay:Boolean = false;
public var isPlaying:Boolean = false;
public var isStreaming:Boolean = true;
public var autoLoad:Boolean = true;
public var autoPlay:Boolean = true;
public var pausePosition:int = 0;
public static const PLAY_PROGRESS:String = "playProgress";
public var progressInterval:int = 1000;
public var playTimer:Timer;
public function SoundFacade(soundUrl:String, autoLoad:Boolean = true,
autoPlay:Boolean = true, streaming:Boolean = true,
bufferTime:int = -1):void
{
this.url = soundUrl;
// Sets Boolean values that determine the behavior of this object
this.autoLoad = autoLoad;
this.autoPlay = autoPlay;
this.isStreaming = streaming;
// Defaults to the global bufferTime value
if (bufferTime < 0)
{
bufferTime = SoundMixer.bufferTime;
}
// Keeps buffer time reasonable, between 0 and 30 seconds
this.bufferTime = Math.min(Math.max(0, bufferTime), 30000);
if (autoLoad)
{
load();
}
}
De klasse SoundFacade vormt een uitbreiding van de klasse EventDispatcher, zodat deze eigen gebeurtenissen kan verzenden. In de klassencode worden eerst eigenschappen voor een object Sound en een object SoundChannel gedeclareerd. In de klasse wordt ook de waarde van de URL van het geluidsbestand opgeslagen, evenals de eigenschap bufferTime voor gebruik bij streaming van het geluid. Bovendien worden er bepaalde Booleaanse parameterwaarden geaccepteerd, die invloed hebben op het laad- en afspeelgedrag:
Via de parameter autoLoad krijgt het object de opdracht om met het laden van het geluid te beginnen zodra dit object is gemaakt.
Met de parameter autoPlay wordt aangegeven dat het afspelen van het geluid moet starten zodra er voldoende geluidsgegevens zijn geladen. Als dit streaming geluid betreft, wordt het afspelen gestart zodra er voldoende gegevens, zoals opgegeven door de eigenschap bufferTime, zijn geladen.
Met de parameter streaming wordt aangegeven dat er met het afspelen van dit geluidsbestand kan worden begonnen voordat het laden is voltooid.
De parameter bufferTime is standaard ingesteld op -1. Als de constructormethode een negatieve waarde in de parameter bufferTime detecteert, wordt de eigenschap bufferTime ingesteld op de waarde van SoundMixer.bufferTime. Zo kan de toepassing desgewenst standaard worden ingesteld op de algemene waarde van SoundMixer.bufferTime.
Als de parameter autoLoad op true is ingesteld, roept de constructormethode onmiddellijk de volgende methode load() aan om te beginnen met het laden van het geluidsbestand:
public function load():void
{
if (this.isPlaying)
{
this.stop();
this.s.close();
}
this.isLoaded = false;
this.s = new Sound();
this.s.addEventListener(ProgressEvent.PROGRESS, onLoadProgress);
this.s.addEventListener(Event.OPEN, onLoadOpen);
this.s.addEventListener(Event.COMPLETE, onLoadComplete);
this.s.addEventListener(Event.ID3, onID3);
this.s.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
this.s.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onIOError);
var req:URLRequest = new URLRequest(this.url);
var context:SoundLoaderContext = new SoundLoaderContext(this.bufferTime, true);
this.s.load(req, context);
}
Met de methode load() wordt een nieuw object Sound gemaakt, waarna listeners voor alle belangrijke geluidsgebeurtenissen worden toegevoegd. Vervolgens krijgt het object Sound de opdracht het geluidsbestand te laden, waarbij een object SoundLoaderContext wordt gebruikt om de waarde voor bufferTime door te geven.
Aangezien de eigenschap url kan worden gewijzigd, kan er een instantie SoundFacade worden gebruikt om verschillende geluidsbestanden na elkaar af te spelen: wijzig eenvoudig de eigenschap url en roep de methode load() aan; het nieuwe geluidsbestand wordt geladen.
De volgende drie methoden voor gebeurtenislisteners laten zien hoe het object SoundFacade de voortgang van het laden traceert en bepaalt wanneer er wordt gestart met het afspelen van het geluid:
public function onLoadOpen(event:Event):void
{
if (this.isStreaming)
{
this.isReadyToPlay = true;
if (autoPlay)
{
this.play();
}
}
this.dispatchEvent(event.clone());
}
public function onLoadProgress(event:ProgressEvent):void
{
this.dispatchEvent(event.clone());
}
public function onLoadComplete(event:Event):void
{
this.isReadyToPlay = true;
this.isLoaded = true;
this.dispatchEvent(evt.clone());
if (autoPlay && !isPlaying)
{
play();
}
}
De methode onLoadOpen() wordt uitgevoerd zodra het laden van het geluid wordt gestart. Als het geluid in streaming modus kan worden afgespeeld, stelt de methode onLoadComplete() de markering isReadyToPlay direct in op true. De markering isReadyToPlay bepaalt of de toepassing met het afspelen van het geluid kan beginnen, bijvoorbeeld na een bepaalde gebruikershandeling, zoals het klikken op een afspeelknop. De klasse SoundChannel beheert de buffering van geluidsgegevens, wat betekent dat het niet nodig is om expliciet te controleren of er voldoende gegevens zijn geladen voordat de methode play() wordt aangeroepen.
De methode onLoadProgress() wordt periodiek aangeroepen tijdens het laadproces. Er wordt een kloon van het object ProgressEvent verzonden, die kan worden gebruikt door code die gebruikmaakt van dit object SoundFacade.
Wanneer de geluidsgegevens volledig zijn geladen, wordt de methode onLoadComplete() uitgevoerd en wordt zo nodig de methode play() voor niet-streaming geluiden aangeroepen. De methode play() zelf wordt hieronder weergegeven.
public function play(pos:int = 0):void
{
if (!this.isPlaying)
{
if (this.isReadyToPlay)
{
this.sc = this.s.play(pos);
this.sc.addEventListener(Event.SOUND_COMPLETE, onPlayComplete);
this.isPlaying = true;
this.playTimer = new Timer(this.progressInterval);
this.playTimer.addEventListener(TimerEvent.TIMER, onPlayTimer);
this.playTimer.start();
}
}
}
De methode play() roept de methode Sound.play() aan als het geluid gereed is om te worden afgespeeld. Het resulterende object SoundChannel wordt opgeslagen in de eigenschap sc. De methode play() maakt vervolgens een object Timer dat wordt gebruikt om gebeurtenissen over de voortgang van het afspelen met een regelmatig interval te verzenden.