播放聲音

Flash Player 9 以及更新的版本,Adobe AIR 1.0 以及更新的版本

播放載入的聲音就像呼叫 Sound 物件的 Sound.play() 方法一樣簡單,如下所示:

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

使用 ActionScript 3.0 播放聲音時,您可以執行下列作業:

  • 從特定的開始位置播放聲音

  • 先暫停聲音,之後再從相同的位置繼續播放

  • 確實得知聲音完成播放的時間

  • 追蹤聲音的播放進度

  • 在聲音播放期間變更聲音或左右相位

若要在播放期間執行這些作業,請使用 SoundChannel、SoundMixer 和 SoundTransform 類別。

SoundChannel 類別可控制單一聲音的播放作業。您可以將 SoundChannel.position 屬性視為播放磁頭,指出正在播放的聲音資料中目前的點。

當應用程式呼叫 Sound.play() 方法時,就會建立 SoundChannel 類別的新實體以控制播放作業。

您可以將位置 (以毫秒為單位) 當做 Sound.play() 方法的 startTime 參數來傳遞,讓應用程式從特定的開始位置播放聲音。透過在 Sound.play() 方法的 loops 參數中傳遞數值,也可以指定固定次數以快速連續的方式重複播放聲音。

呼叫 Sound.play() 方法並搭配 startTime loops 參數時,每次都會從相同的起點重複播放聲音,如下列程式碼所示:

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

在此範例中,於聲音開始播放之後,就會從某個點播放聲音一秒鐘,並連續播放三次。

暫停和繼續聲音

如果應用程式播放較長的聲音,例如歌曲或 Podcast,您可能要讓使用者可暫停及繼續播放那些聲音。若是使用 ActionScript,則在播放期間無法以確實地暫停聲音,而只能停止聲音。不過,您可以從任何點開始播放聲音。因此,您可以在聲音停止時記錄它的位置,並在稍後從該位置開始重播聲音。

例如,假設下列程式碼會載入和播放聲音檔案:

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

在播放聲音期間, SoundChannel.position 屬性會指出聲音檔案中目前正在播放的那一點。您的應用程式可以在停止播放聲音之前儲存該位置值,如下所示:

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

若要繼續播放聲音,請傳遞之前儲存的位置值,以便從之前停止的相同點重新啟動聲音。

channel = snd.play(pausePosition);

監視播放作業

您的應用程式可能會想知道聲音何時停止播放,這樣它才可以開始播放另一個聲音,或是清除在先前播放期間所使用的某些資源。當 SoundChannel 類別的聲音完成播放時,此類別就會傳送 Event.SOUND_COMPLETE 事件。您的應用程式可以偵聽此事件並採取適當的行動,如下所示:

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."); 
}

SoundChannel 類別在播放期間不會傳送進度事件。若要報告播放進度,應用程式可以設定自己的時間機制,並追蹤聲音播放磁頭的位置。

若要計算已播放的聲音百分比,您可以將 SoundChannel.position 屬性的值除以正在播放的聲音資料長度:

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

不過,只有聲音資料在播放開始之前就已完全載入的情況下,此程式碼才會報告精確的播放百分比。 Sound.length 屬性會顯示目前載入的聲音資料大小,而不是整個聲音檔案的最終大小。若要追蹤仍然繼續在載入的串流聲音之播放進度,您的應用程式應該估計完整聲音檔案的最終大小,並在上述計算方式中使用該值。您可以使用 Sound 物件的 bytesLoaded bytesTotal 屬性,估算聲音資料的最終長度,如下所示:

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

下列程式碼會載入較大的聲音檔案,然後使用 Event.ENTER_FRAME 事件做為其計時機制,以顯示播放進度。它會定期報告播放百分比,而計算方式是以目前的位置值除以聲音資料的總長度:

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); 
}

在聲音資料開始載入之後,此程式碼會呼叫 snd.play() 方法,並將產生的 SoundChannel 物件儲存在 channel 變數中。接著,它會將事件偵聽程式加入 Event.ENTER_FRAME 事件的主要應用程式,並將另一個事件偵聽程式加入在播放完成時所發生之 Event.SOUND_COMPLETE 事件的 SoundChannel 物件。

每次應用程式到達其動畫中的新影格時,就會呼叫 onEnterFrame() 方法。 onEnterFrame() 方法會根據已經載入的資料量,估算聲音檔案的總長度,然後計算並顯示目前的播放百分比。

當整段聲音都已經播放時,就會執行 onPlaybackComplete() 方法,以移除 Event.ENTER_FRAME 事件的事件偵聽程式,這樣它才不會在播放完之後嘗試顯示進度更新。

每秒可以傳送許多次 Event.ENTER_FRAME 事件。在某些情況下,您不會想要這麼頻繁地顯示播放進度。在這些情況下,您的應用程式就可以使用 flash.util.Timer 類別來設定自己的計時機制。請參閱 使用日期與時間

停止串流聲音

在串流聲音 (也就是在播放聲音時,其資料仍然繼續載入) 的播放程序中,有一個特別的執行邏輯,就是:當您的應用程式針對正在播放串流聲音的 SoundChannel 實體呼叫 SoundChannel.stop() 方法時,聲音播放會停止一個影格,然後在下一個影格上,它會從聲音的開頭重新開始。會發生此情況是因為聲音載入程序還在進行中。若要停止串流聲音的載入和播放,請呼叫 Sound.close() 方法。