播放声音

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 参数中传递一个数值,指定快速且连续地将声音重复播放固定的次数。

使用 startTime 参数和 loops 参数调用 Sound.play() 方法时,每次将从相同的起始点重复播放声音,如以下代码中所示:

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

在此示例中,从声音开始后的 1 秒起连续播放声音三次。

暂停和恢复播放声音

如果应用程序播放很长的声音(如歌曲或播客),您可能需要让用户暂停和恢复播放这些声音。实际上,无法在 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 类在播放期间不调度 progress 事件。若要报告播放进度,应用程序可以设置其自己的计时机制并跟踪声音播放头的位置。

若要计算已播放的声音百分比,您可以将 SoundChannel.position 属性值除以所播放的声音数据长度:

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

但是,仅当在开始播放之前完全加载了声音数据时,此代码才会报告精确的播放百分比。Sound.length 属性显示当前加载的声音数据的大小,而不是整个声音文件的最终大小。若要跟踪仍在加载的声音流的播放进度,应用程序应估计完整声音文件的最终大小,并在其计算中使用该值。您可以使用 Sound 对象的 bytesLoadedbytesTotal 属性来估计声音数据的最终长度,如下所示:

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 事件的事件侦听器,并在 SoundChannel 对象中添加另一个事件侦听器,用于侦听在播放完成时发生的 Event.SOUND_COMPLETE 事件。

每次应用程序到达其动画中的新帧时,将调用 onEnterFrame() 方法。onEnterFrame() 方法基于已加载的数据量来估计声音文件的总长度,然后计算并显示当前播放百分比。

当播放完整个声音后,将执行 onPlaybackComplete() 方法来移除 Event.ENTER_FRAME 事件的事件侦听器,以使其在完成播放后不会尝试显示进度更新。

可以每秒多次调度 Event.ENTER_FRAME 事件。在某些情况下,您不需要频繁显示播放进度。在这些情况下,应用程序可以使用 flash.util.Timer 类来设置其自己的计时机制;请参阅使用日期和时间

停止声音流

在进行流式传输的声音(即,在播放的同时仍在加载声音)的播放过程中,有一个奇怪的现象。当应用程序对播放声音流的 SoundChannel 实例调用 SoundChannel.stop() 方法时,声音播放在一个帧处停止,随后在下一帧处从声音开头重新播放。发生这种情况是因为,声音加载过程仍在进行当中。若要同时停止声音流加载和播放,请调用 Sound.close() 方法。