ActionScript 3.0 的聲音架構非常強大,但卻也複雜。只需要基本聲音載入和播放功能的應用程式可以使用一個類別,藉由提供一組較簡單的方法呼叫與事件,隱藏某些複雜度。在軟體設計模式的世界中,這種類別就稱為「外觀」。
SoundFacade 類別會提供單一介面,以執行下列工作:
-
使用 Sound 物件、SoundLoaderContext 物件以及 SoundMixer 類別載入聲音檔案。
-
使用 Sound 物件和 SoundChannel 物件播放聲音檔案
-
傳送播放進度事件
-
使用 Sound 物件和 SoundChannel 物件來暫停和繼續播放聲音。
SoundFacade 類別會嘗試以較低的複雜度,提供 ActionScript 聲音類別的大部分功能。
下列程式碼會顯示類別宣告、類別屬性以及
SoundFacade()
建構函式方法:
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();
}
}
SoundFacade 類別會擴充 EventDispatcher 類別,讓它可以傳送屬於自己的事件。該類別程式碼首先會宣告 Sound 物件與 SoundChannel 物件的屬性。此類別也會儲存聲音檔案的 URL 值,以及串流聲音時要使用的
bufferTime
屬性值。除此之外,它還會接受一些會影響載入和播放行為的 Boolean 參數值:
-
autoLoad
參數會告訴物件,只要一建立物件就開始載入聲音。
-
autoPlay
參數會指出只要載入足夠的聲音資料就開始播放聲音。如果這是串流聲音,則只要已載入
bufferTime
屬性所指定的足夠資料就會開始播放。
-
streaming
參數會指出在完成載入之前,聲音檔案可以開始播放。
bufferTime
參數預設值為 -1。如果建構函式方法在
bufferTime
參數中偵測到負值,它會將
bufferTime
屬性設定為
SoundMixer.bufferTime
的值。這可以讓應用程式將預設值設定為所需的全域
SoundMixer.bufferTime
值。
如果
autoLoad
參數已設定為
true
,則建構函式方法會立即呼叫下列
load()
方法,開始載入聲音檔案:
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);
}
load()
方法會建立新的 Sound 物件,然後為所有重要的聲音事件增加偵聽程式。接著,它會告訴 Sound 物件使用 SoundLoaderContext 物件傳入
bufferTime
值,以載入聲音檔案。
由於您可以變更
url
屬性,因此可以使用 SoundFacade 實體來連續播放不同的聲音檔案:只需變更
url
屬性,再呼叫
load()
方法,就會載入新的聲音檔案。
下列三個事件偵聽程式方法將說明 SoundFacade 物件如何追蹤載入的進度,並決定何時開始播放聲音:
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();
}
}
onLoadOpen()
方法會在聲音載入作業開始時執行。如果可以在串流模式中播放聲音,則
onLoadComplete()
方法會立即將
isReadyToPlay
旗標設定為
true
。
isReadyToPlay
旗標會決定應用程式是否可以開始聲音播放,也許回應如按一下「播放」按鈕等使用者動作。由於 SoundChannel 類別會管理聲音資料的緩衝,因此在呼叫
play()
方法之前,不需要明確檢查是否已載入足夠的資料。
onLoadProgress()
方法會在載入程序期間定期執行。它會直接傳送其 ProgressEvent 物件之副本,供使用此 SoundFacade 物件的程式碼使用。
已完全載入聲音資料後,就會執行
onLoadComplete()
方法,並視需要為非串流聲音呼叫
play()
方法。
play(
) 方法本身如下所示。
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();
}
}
}
play()
方法會在聲音可以播放時呼叫
Sound.play()
方法。產生的 SoundChannel 物件是儲存在
sc
屬性中。
play()
方法接著會建立 Timer 物件,該物件將用以定期傳送播放進度事件。