Recently in Flash Player API Category

Flash Player 10 から動的に生成したサウンドを再生する機能がサポートされています。ベータ 2 で変更された点などもありますので遅ればせながらご紹介します。

まず、この機能を使うには Sound オブジェクトに Event.SAMPLE_DATA のイベントハンドラを設定します。そうすると Sound オブジェクトの動作が通常と変わり、定期的にイベントハンドラを呼び出しては再生するデータを読み込むようになります。このとき SoundChannel は読み込まれたデータを一連のオーディオデータストリームとして再生します。

var mySound:Sound = new Sound();
mySound.addEventListener(Event.SAMPLE_DATA, onSampleData);
var myChannel:SoundChannel = mySound.play();
 
function onSampleData(event:SampleDataEvent):void 
{
  // この中で SoundChannel にデータを書き込む
}
 

SAMPLE_DATA 用イベントハンドラ内では、イベントオブジェクトから渡される ByteArray オブジェクトにオーディオデータを書き込みます。イベントオブジェクトの型は Flash Player 10 から新しく追加された sampleDataEvent で、以下の属性が利用できます。

public data : ByteArray   // オーディオストリーム内のデータ
public position : Number  // オーディオストリーム内の位置
 

ByteArray オブジェクト (event.data) に書き込む値は 32 ビット big endian 浮動小数点数形式の 44.1KHz ステレオデータです。従って一つのサンプルデータの大きさは 8 バイト (4 バイトのデータが左右それぞれ) になります。

下は sampleData イベントハンドラの例です。単純なサイン波形をデータとして書き込んでいます。再生すると聴覚検査で聴くような音がすると思います 。

Flash Player 10 ではローカルファイルを直接 Flash アプリケーションに読み込んだり Flash アプリケーション内のデータを直接ローカルファイルに書き出す機能が追加されています。

Flash Player 9 でも FileReference を使ってローカルファイルにアクセスすることは可能です。が、その機能はファイルのアップロード/ダウンロードを行うためのもので、Flash アプリケーションからは、一旦サーバを経由しないとローカルファイルのデータを扱うことができませんでした。直接ファイル I/O の出来る日が来ることを心待ちにしていた方も多いことでしょう。

というわけで、Flash Player 10 では flash.net.FileReference クラスに以下の API が追加されています。

public function get data():ByteArray // 読み込まれたデータ (読み取り専用のプロパティ)
public function load():void          // 指定されたファイルの読み込み開始
public function save(data:*, name:String = null):void 
                                     // 保存先を選択するダイアログを表示、その後データ保存開始
 

ファイルの読み込みを開始するには load() メソッドを使用します。読み込むファイルの指定は、browse() メソッドを呼ぶとダイアログが表示されるので、その中でユーザが行います。

このときプログラムから読み込むファイルを指定することはできません。これは SWF がロードされたら勝手にローカルファイルを送信してしまうといった類のアタックからユーザを保護するためです。

load() は呼び出されるとすぐに戻るので、その後の進み具合はイベント経由で確認することになります。このあたりは従来の FileReference の使い方と同じです。

下は、ファイルを読み込む簡単なサンプルです。

引き続きエンコード関連の関数を紹介します。今回は URI をエンコードするための関数です。

encodeURI() 関数と decodeURI() 関数

encodeURI() 関数 (livedocs@lab) は URI 文字列を UTF-8 値にエンコードします。英数字は変換の対象外ですが、他にも URI の一部として使われる記号は変換されません。

var str:String = "http://w.c/a?b+ま&";
trace(encodeURI(str)); // http://w.c/a?b+%E3%81%BE& が出力される

escape() 関数と unescape() 関数

escape() 関数は (livedocs@lab) は文字列を URL エンコードのフォーマットに変換するグローバル関数です。基本的に、英数字以外の文字であれば % 付の16進数に変換されます。+ などいくつか変換されない文字もあります。

trace(escape("1+3%2=0")); // 1+3%252%3D0 が出力される
trace(escape("h:m@u/a?b&c")); // h%3Am@u/a%3Fb%26c が出力される
trace(escape("ハロー")); // %u30CF%u30ED%u30FC が出力される

describeType() メソッド (livedocs@lab) は引数に渡されたオブジェクトの情報を XML 形式で返します。引数には ActionScript の任意のオブジェクトを(クラスや int なども)渡すことができます。

var mc:MovieClip = new MovieClip();
var typeInfo:XML = describeType(mc);

返される XML オブジェクトに含まれる情報は引数として渡されたオブジェクトの属性やメソッド等です。Java のリフレクションと同じような機能です。

ようやく new Dictionary() が実行できるようになったので続きです。

weak-value ディクショナリー

以前の記事に書いたように、Dictionary クラスは weak-key ディクショナリーの機能を持っています。キーオブジェクトへの参照が弱い参照のため、使われなくなったキーとそのエントリーを自動的に開放するという使い方ができます。

一方、値として管理されているオブジェクトがしばらく参照されなかったら自動的に開放するという使い方はできません。

Dictionay クラス (livedocs@lab) は beta2 から追加されたクラスで、オブジェクトをキーとして値を管理することができます。Object を使っても同じように連想配列を実現できますが、Dictionary ではいわゆる”弱い参照”が使えます。

また、Object では文字列がキーとして扱われるため toString() の値が同じオブジェクトは全て同じキーとして扱われますが、Dictionary では別々のオブジェクトであれば toString() の値に関わらず異なるキーとして扱われます。

StringBuilder クラス (livedocs@lab) は String と同じように文字列を扱うクラスですが、特に文字列に追加や挿入などの操作を何回も行うような場合に使います。String と違い、操作の度に新しいオブジェクトを生成したりしないため、メモリをより有効に使用することができます。特に、細かな追加を何回も行う場合には String と比べて高速です。

StringBuilder のインスタンスを生成するにはコンストラクタを使用します。String のように直接文字列で初期化することはできません。

Proxy クラス (livedocs@lab) は既存のオブジェクトの振る舞いを変えたいときに使います。例えば、Proxy のサブクラスである ObjectProxy クラス (livedocs@lab) は属性が変更されたとき、イベントでそれを知らせることができるようになっています。(注:ObjectProxy は Flex 2 フレームワークのクラスです)

Proxy クラスにはコンストラクタがありません。従って、Proxy クラスを使用する際は、サブクラスを定義しメソッドをオーバーライドするのが基本です。オーバーライドしていないメソッドが呼ばれた場合は例外が投げられます。

Timer クラス (livedocs@lab) は一定の間隔毎に処理を行いたい場合に使用します。Timer のインスタンスは、予め設定された時間が経つとイベントをディスパッチします。

Timer クラスは AS2 の setInterval() / getInterval() を置き換えるものです。AS3 でも setInterval() / getInterval() は共に flash.util パッケージ下にあり使用可能ですが、これは既存のコードとの互換性を持たせるためと考えるのがよさそうです。

Timer を使用するには、まずインスタンスを作成します。コンストラクタの引数にはイベントまでの待ち時間をミリ秒単位で指定します。