Flash Player 10 の動的サウンド生成機能 (Sound クラス)

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

function onSampleData(event:SampleDataEvent):void {
  for (var c:int=0; c<8192; c++) {
    var rad:Number = Number(c+event.position)/Math.PI/2;
    var amp:Number = Math.sin(rad) / 4;  // -1 から 1 の間の値なら OK
    event.data.writeFloat(amp);  // 左チャネルの音
    event.data.writeFloat(amp);  // 右チャネルの音
  }
}
 

データの計算式を変えると音色が変わると思いますので試してみてください。その際、サンプルデータの値が -1 から 1 の範囲を超えないようにご注意を。

さて、イベントハンドラ内では 2048 以上 8192 以下のサンプルデータを書き込みます。パフォーマンス上はできるだけ多くのサンプルデータを (つまり 8192 個) 書くのが有利と考えられます。

書き込まれたデータが 2048 以下の場合には、データを全て再生した時点で SoundChannel は再生を停止し soundComplete イベントを生成します。明示的に再生を停止したいときには SoundChannel.stop() を呼ぶこともできます。

sampleData イベントにより書き込みを求められている場所と再生中の箇所との時間差は以下の式で求めることができます。ここでの単位は ms になります。

event.position/44.1 - myChannel.position
 

あとは、Sound オブジェクトからオーディオデータを取得するために extract() というメソッドが用意されています。ある音源を読み込んだ Sound オブジェクトからオーディオデータを取り出して他の Sound オブジェクトで動的に再生したりするのに使えます。メソッドの定義は以下のようになっています。

public extract(target:ByteArray, length:Number, startPosition:Number = -1):Number // 
 

extract() は target で指定した ByteArray に length 分のサンプルデータを抽出します。startPosition は読み込みを開始するポジションの指定ですが、明示的に指定しないと、一回目はデータの先頭から、それ以降は続きから順番に読み込みます。

なお、Sound オブジェクトに sampleDataEvent 用のイベントハンドラを設定すると load() 等のメソッドは使えなくなります。

sampleDataEvent.data に書き込むのは 32 ビット big endian なので ShaderJob の結果がそのまま使えそうですね。

コメントする

2014年1月

Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
レンタルサーバー

月別 アーカイブ

Powered by Movable Type 4.261