Архитектура звука в 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
для использования при потоковом воспроизведении звука. Кроме того, он принимает несколько логических значений параметров, которые определяют поведение при загрузке и воспроизведении.
-
Параметр
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
определяет, когда приложение может начать воспроизведение звука, возможно, в ответ на действие пользователя, например нажатие кнопки «Play» (воспроизведение). Класс 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, который будет использоваться для отправки событий прогресса воспроизведения через регулярные интервалы.