- 2009-08-07 (金) 9:06
- ActionScript3.0 | Flash

最近 FlashDevelop の話題しか書いてなかったのでちょっと違う話題を。
Embed について書くといったら意外と Twitter で反応があったので驚いた。
Embed は謎が多いとか、どうなってるの?などの疑問もあった。
今回は主に SWF や、Sound の Embed について実験結果などを元に書いていこうと思う。
Embed の基本から書こうと思ったが、Embed って何?という人が見てもなんのこっちゃ?
ってことになりそうなのでそのあたりは省くことにする。
※ ということを書いてから気づき30分近くを無駄にしたorz
詳細は以下から。
まずは SWF の Embed についての話。
以前こんな記事を書いた。
Flex と Flash CS3 の ハイブリッド SWF について (http://blog.bk-zen.com/2007/12/27/46/)
これでメインとなる話題は、どうやって Embed した SWF の root 、メインタイムラインにアクセスするのか。
ということだったが、「どうやって」は書いたが、「なぜ」を書くのを忘れていた。
というよりもこの時はまだ知らなかったといった方がいいかも知れない。
できたからこれでいいやと思っていた。
例では MXML を使用した作りになっているが当然 AS ファイルベースでも可能な方法だ。
とりあえずおさらいしておくと、
package
{
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.events.Event;
import mx.core.MovieClipLoaderAsset;
public class Main extends Sprite
{
[Embed(source = '/../asset/embedswf.swf')]
private const EmbedClass: Class;
public function Main()
{
var mc: MovieClipLoaderAsset = new EmbedClass();
Loader(mc.getChildAt(0)).contentLoaderInfo.addEventListener(Event.INIT, onInit);
}
private function onInit(e: Event ): void
{
var info: LoaderInfo = LoaderInfo(e.target);
info.removeEventListener(Event.INIT, onInit);
trace(info.content);
}
}
}
この onInit で trace している部分がメインになっているクラスだ。
Flash で作成した SWF の場合は メインタイムラインクラスのような名前になっている。
つまり SWF の root となっているクラスだ。
さて、たぶん疑問に思う部分が何か所ほどあると思う。
どうして new EmbedClass() だけではだめなのか。
mc.getChildAt(0) は何?なぜ Loader ? Event.INIT ?
new EmbedClass したインスタンスは何クラスなのかだが
これは Main_EmbedClass というクラスで定義されている。
Main_EmbedClass は mx.core.MovieClipLoaderAsset というクラスを継承し、
MovieClipLoaderAsset の movieClipData を オーバーライドしている。
movieClipData は ByteArray を返すだけの getter メソッドで、今回の Main_EmbedClass では Embed した SWF のデータが返される。
それが new した際に MovieClipLoaderAsset のコンストラクタ内で addChild() された Loader によって loadByte() されるわけだ。
つまり最初の mc.getChildAt(0) では MovieClipLoaderAsset のコンストラクタ内で addChild() された Loader を取得していて、
Loader は ByteArray から SWF のデータを複製していのだ。
Event.INIT は それが終了したよ。というイベントで、Event.COMPLETE でも特に問題はない。
次は Sound の Embed の話。
というのも先日 独学ActionScript さん(http://d.hatena.ne.jp/ActionScript/) のブログで
【AS3入門】読み込み可能なMP3ファイルのフォーマット (http://d.hatena.ne.jp/ActionScript/20090718/as3_mp3_embed_format)
という記事を見て触発されてしまったのでw
記事の内容としては Loader クラスを読み込んだときはエラーが出なかったのに Embed タグを使ったときにコンパイルエラーが出た。
という話と解決方法についてだ。
ここに「読み込み可能なMP3ファイルのフォーマット」として書いてある内容だが、
自分もそのサイトを参考にしていたし、そうだと思っていた。
でも実験してみた人はおそらくいないと思う。
なので、全力で実験してみた。
独学さんのところで LAME を紹介してくれていたので助かった。
さすがに全部のビットレートやサンプリングレートの MP3 ファイルを手動で作るのは無理だと思ったので。
LAMEはコマンドラインで動くので簡単にバッチファイルを作った。
中身はこれだけ。
for %%A in (8 16 24 32 40 48 56 64 80 96 112 128 144 160 192 224 256 320) do for %%B in (8 11.025 12 16 22.05 32 44.1 48) do lame -b %%A -m j --resample %%B e.wav e%%A_%%B.mp3
e.wav をそれぞれのビットレートとサンプリングレートで MP3 にエンコードする。
ちなみにこの数字がは LAME が対応しているビットレートとサンプリングレートになる。
18(ビットレート) × 8(サンプリングレート) = 144 ファイル書き出される。
記事中の表には ビットレート20 kbps とも書いてあったので SoundBooth を使い、それは手動で作った。
144 + 8(20kbps を 8サンプリングレート分) = 152 ファイル
まずは計 152 ファイルを全部 Embed してみることにした。
これもfor文を回してさっくりと作成。
いざコンパイル!
コンパイルエラーが出まくる。
コンパイルエラーが出なくなるまでひたすらコメント(これが一番辛かった)
すると、エラーが出ていたのは サンプリングレートが 44.100 と 22.050 と 11.025 (kHz)以外だということがわかった。
ビットレートではエラーが出ていない。
ということは表では抜けていたビットレートでも Embed は可能ということだ。
Embed 可能なMP3のビットレート(実証済み)は
8 16 20 24 32 40 48 56 64 80 96 112 128 144 160 192 224 256 320 (kbps)
ということだ。
その他いろんなエンコーダーをいくつか見たが、これ以外で書き出せるものはなかった。
つまり!
注意すべきはサンプリングレート。
そこさえ注意しておけば大体は大丈夫です。
コンパイルを通った 57個の Sound を全部 play してみたが特に問題なく音が流れたので大丈夫だと思う。
次に VBR と ABR の場合はどうなのか。
FFS はそもそも書き出せるソフトが見当たらなかったので無視する事にする。
表によると CBR 以外は × になっていたがどうだろうか。
ちなみにさっきのビットレートとサンプリングレートの実験はすべて CBR で書き出したものです。
VBR と ABR で書き出すくらいなら手動でもいいやということで手動で VBR と ABR のファイルを2つ書き出す。
設定は最大ビットレートを 224(kbps) 、サンプリングレートを 44.100(kHz) とした。
ABR の方は 目標ビットレートを 144(kbps) とした。
結果は VBR でも ABR でも Embed 可能。
この二つの結果を見ると、やはりビットレートで弾かれることはないのでは?と思った。
もしかしたら position などがうまくとれないのでは?と思い、スライダーバーのようなものも作ってみたが特に問題なく動いた。
次に、独学さんの記事の中に
それにしても、同じMP3ファイルでLoaderクラスならオッケーだったのはなぜでしょう? ここは未だに理由がわかりません。
とあったのでそれについての考察しながら答えを探してみる。
実験中に弾かれたサンプリングレートの MP3 ファイルを Sound の load で読み込んでみると確かにどれも再生できた。
次に Embed できた Sound は どんなクラスになっているのかについて調べてみた。
これも Main_EmbedSound のような名前のクラスで、mx.core.SoundAsset クラスを継承している。
Sound は ByteArray から loadByte() のようなことはできないが、SoundAsset は MovieClipLoaderAsset の作りとは明らかに違い、
そのつくりはほぼ Sound クラスと同じということ。
もしかしたら、
コンパイルする時に Sound を SWF の Sound フォーマットに変換しているのではないか?
その際に Sound フォーマットとして定義してある 44.100, 22.050, 11.025 (kHz) 以外は Sound のフォーマット定義から外れる為、
コンパイル時に弾いているのかもしれない。
ではロードした MP3 はなぜ SWF のフォーマット外のサンプリングレートでも大丈夫なのか。
それはおそらく MP3 として読み込んでいるからではないか。
http://www.adobe.com/devnet/swf/
これは SWF のファイルフォーマットだが、ここに Sound のフォーマットも書いてある。
ここの 216 ページあたりが答えに近いのではと思う。
Flash Player supports both CBR (constant bitrate) and VBR (variable bitrate) MP3 encoding.
とかさっきの実験の正式な回答まで書いてある・・・。
そして、答えらしきものを見つけた。218 ページだが、 MP3 データの構造の中に SamplingRate 項目がある。
たまたまなのか、これ以外のサンプリングレートが存在しないのかはわからないが試したものが全てこの中におさまっていた。
MP3 として読み込む分にはこのサンプリングレートなら大丈夫ということなのかもしれない。
自分の中での答えとしては
「Embed するものは Sound の定義内なら OK、ロードするなら MP3 の定義内なら OK。
ロードしたときに大丈夫だった MP3 ファイルがだめだったのは Sound の定義外だったということではないか。」
というのが自分の中の答えでした。
考察の部分はほぼ Embed とは別の話になってしまいましたが。
詳しい人がいらっしゃいましたら教えてください。
自分も答え合わせをしたいです。
Embedder を完成させるために Embed についてもっと調べる必要があったので今回いろいろと調べてみた。
Embed について何かその他質問がありましたらコメント欄へのコメントをお願いします。
できる限り調べてエントリーを書きますのでよろしくお願いします。
おまけ
Embedder について。
以前公開していたのですが、ちょっとバグがあって公開をやめていました。
Embedder Version 2 を作り今テストなどを行っています。
完成しだい Spark Project の方で公開します。
ちなみにこんな使い方します。
private var em: MyEmbedder; em = new MyEmbedder(); em.addEventListener(Event.COMPLETE, onComp); //onComp var mc: MovieClip = em.getMc(em.SWF); // Embed した SWF の root を返す var bmp: Bitmap = em.getBmp(em.BMP); // Embed した Bitmap を返す。 var bmd: BitmapData = em.getBmd(em.BMP) // Embed した Bitmap の BitmapData を返す。 var sound: Sound = em.getSnd(em.SND); // Embed した Sound を返す。 var xml: XML = em.getXml(em.EmbedXML); // Embed した XML を返す。 var font: Font = em.getFont(em.EmbedFont); // Embed したフォントを返す。 var obj: Object = em.getLib(em.SWF, "LibObj"); // Embed した SWF のリンケージに書き出されたクラスのインスタンスを返す。
などなど。
こんなのできたらいいなを教えてください。
当然ながら FD の補間効きます。
[追記]
Embedder 公開しました!http://blog.bk-zen.com/2009/08/17/207/
[追記]
スパムを消した勢いで間違えて トラックバックを消してしまったので・・・。
【AS3入門】続・読み込み可能なMP3ファイルのフォーマット(追検証とLAMEの仕様について)
http://d.hatena.ne.jp/ActionScript/20090808/as3_mp3_embed_lame
こちらは表にまとまっててきれいなので、「とりあえずまとめをわかりやすく書けよ」って思った人はこちらを参考にしてみてください。

