中級
これまでのFlash Playerに搭載されていた「音」に関する機能というと、どんなものが思い浮かぶでしょうか? ざっと挙げてみましょう。
画像処理系APIの充実ぶりと比べると、お世辞にも充実しているとは言い難い内容です。しかし、Flash Playerの次期バージョン10では、ついに音関連機能にメスが入り、「Flash+音」の可能性をぐっと広げてくれる新たな機能が追加されました。その新機能が「Dynamic sound generation」です。
Dynamic sound generationとは、文字通りダイナミックに音を生成する機能です。この機能を使えば、音源(波形データ)がなくてもActionScriptで音を作りだしたり、ActionScriptで音源にエフェクトなどの処理を加えたりすることができ、そうして生成・加工した音をそのままFlash Player上で鳴らすことができます。
Dynamic sound generationの機能は、Soundクラスの機能拡張という形で提供されています。たとえば下のようなコードを書いてコンパイルすると、440Hzのサイン波(聴覚検査で聞くようなポーという音)がずっと鳴り続けます。サンプルの動作は、sine.swfをダウンロードして確認してください。
MEMO:この記事で紹介・配布しているサンプルを表示・動作させるには、Flash Player 10 Release Candidate(10,0,12,10以上)が必要です。以下のサイトから入手できます。
package
{
import flash.display.Sprite;
import flash.events.SampleDataEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
public class SineSample extends Sprite
{
private var phase:Number = 0;
private var freq:Number = 440;
private const PI2:Number = Math.PI * 2;
private var soundChannelObject:SoundChannel = new SoundChannel();
public function SineSample()
{
var soundObj:Sound = new Sound();
//まずはSAMPLE_DATAイベントにリスナー登録
soundObj.addEventListener(SampleDataEvent.SAMPLE_DATA,onSampleData);
//mp3などの音声を割り当てずにそのままplay()で再生開始すると、
//音のバッファが空になるたびにSAMPLE_DATAイベントが発生します。
soundChannelObject = soundObj.play();
}
private function onSampleData(e:SampleDataEvent):void
{
var smpl:Number;
var w:Number = PI2 * freq / 44100;
//レイテンシの計測【※1】
var latency:Number = e.position / 44.1 - soundChannelObject.position;
//一度のイベントごとに2048~8192サンプル×左右2チャンネル分のデータを書き込みます。
for (var i:int = 0; i < 4096; ++i) {
//波形データを生成【※2】
phase += w;
if (phase > PI2) {
phase -= PI2;
}
smpl = Math.sin(phase);
//SampleDataEvent.dataにwriteFloat()で波形データを書き込む【※2】
e.data.writeFloat(smpl);
e.data.writeFloat(smpl);
}
}
}
}
先ほどのサンプルコードの波形データを書き込むあたり【※2】を見てもわかるように、「どのような波形データを鳴らすか」はActionScriptで完全にコントロールできます。言い換えると、「プログラム上で波形データさえ作れれば、どのような音でも鳴らすことができる」ということです。これによってFlashで様々な音関連のアプリケーションを作ることが可能になります。たとえばですが、以下のようなものができるのではないかと思います(処理速度的な部分をクリアできれば、ですが)。
Dynamic sound generationを使う上で、一つ注意しなければならないことがあります。それは「レイテンシ(音の遅延)」です。Dynamic sound generationの仕様上、波形データを書き込んだタイミングと、その書き込んだ波形データが実際に鳴るタイミングには数百ミリ秒程度のズレがあります。「数百ミリ秒」と聞けば、非常にわずかなズレのように感じるかもしれませんが、実際に聞いてみるとその遅延に気づくものです。また、再生環境によってはさらにズレる可能性があります。
実際どの程度遅れているかは、上記サンプルコードの【※1】のような計算で計測することができます。
//レイテンシの計測【※1】
var latency:Number = e.position / 44.1 - soundChannelObject.position;
Dynamic sound generationの用途として、「音とアニメーションの同期」や「クリック時の効果音」なども考えられますが、レイテンシの問題があるため、それらの場合には旧来の方法を使うことをオススメします。
以上のことを踏まえて、Dynamic sound generationの活用例として筆者が実験的に作ってみたものが、以下の「Tenoran」です。
このサンプルを表示するにはFlashPlayer10 10,0,12,10以上 が必要です。
見ての通り、某電子楽器にインスパイアされて作ったものです。某楽器と同じような感覚で、16×16に並んだボタンをクリックしてオン・オフしてみてください。下5行分にはドラムの音サンプル、その上にはベースの音サンプルが割り当てられていいます。ボタンをクリックしてオン状態にしておくと、縦ラインが通過した時に、該当する音が鳴るようになっています。ちなみにベースの音は、1つのベース音の波形データをもとに、リアルタイムに音程を上下させて鳴らしています。また、下の方に並んでいるボタンやツマミには、BPM(テンポ)の変更やエフェクトなどの機能が割り当てられています。ぜひ、いじってみてください!
このデモを触ってもらえれば、これまでのFlash Playerでは難しかった
といったことができるようになっていることが、実際に体験していただけると思います。
いかがでしたでしょうか。 Flash Player10で実現可能になる「Flash+音」の可能性が少しでも伝われば幸いです。ちなみに「Tenoran」のソースコードは、Spark Projectで「sazameki」という音系ライブラリの一部として公開しています。
リポジトリ:興味ある方はぜひご覧になってみてください。