動的に生成されたオーディオの操作

Flash Player 10 以降、Adobe AIR 1.5 以降

注意: オーディオの動的生成機能は、Flash Player 10 および Adobe AIR 1.5 以降で使用できます。

既存のサウンドを読み込んだりストリーミングしたりする代わりに、オーディオデータを動的に生成することもできます。オーディオデータを生成するには、Sound オブジェクトの sampleData イベントのイベントリスナーを割り当てる必要があります sampleData イベントは、flash.events パッケージの SampleDataEvent クラスで定義されています。この環境では、Sound オブジェクトはファイルからサウンドデータを読み込みません。代わりに、このイベントに割り当てた関数を使用して自身にストリーミングされるサウンドデータのソケットとして機能します。

Sound オブジェクトに sampleData イベントリスナーを追加すると、サウンドバッファーに追加するデータが定期的に要求されます。このバッファーには、Sound オブジェクトで再生するデータが格納されます。Sound オブジェクトの play() メソッドを呼び出すと、新しいサウンドデータの要求時に sampleData イベントが送出されます(Sound オブジェクトがファイルから mp3 データを読み込んでいない場合のみ)。

SampleDataEvent オブジェクトには、 data プロパティがあります。イベントリスナーでは、この data オブジェクトに ByteArray オブジェクトを書き込みます。このオブジェクトに書き込んだバイト配列は、バッファーに格納されたサウンドデータに追加され、Sound オブジェクトで再生されます。バッファー内のバイト配列は、-1 ~ 1 の浮動小数点数値のストリームです。各浮動小数点数値は、サウンドサンプルの 1 つのチャンネル(左または右)の振幅を表します。サウンドは、1 秒間に 44,100 回サンプリングされます。各サンプルには、バイト配列の浮動小数点数値としてインターリーブされた、左または右のチャンネルが格納されます。

ハンドラー関数では、 ByteArray.writeFloat() メソッドを使用して、 data プロパティ( sampleData イベント)に書き込みます。例えば、次のコードでは正弦波が生成されます。

var mySound:Sound = new Sound(); 
mySound.addEventListener(SampleDataEvent.SAMPLE_DATA, sineWaveGenerator); 
mySound.play(); 
function sineWaveGenerator(event:SampleDataEvent):void 
{ 
    for (var i:int = 0; i < 8192; i++) 
    { 
        var n:Number = Math.sin((i + event.position) / Math.PI / 4); 
        event.data.writeFloat(n); 
        event.data.writeFloat(n); 
    } 
}

Sound.play() を呼び出すと、アプリケーションがイベントハンドラーの呼び出しを開始し、サウンドサンプルデータを要求します。データの供給を中止するか、 SoundChannel.stop() を呼び出すまでは、サウンドが再生される間、アプリケーションはイベントを送信し続けます。

イベントの待ち時間はプラットフォームにより異なりますが、Flash Player および AIR の将来のバージョンでは変更できるようになります。特定の待ち時間に依存するのではなく、計算して求めてください。待ち時間を計算するには、次の式を使用します。

(SampleDataEvent.position / 44.1) - SoundChannelObject.position

イベントリスナーの各呼び出しでは、SampleDataEvent オブジェクトの data プロパティに 2048 ~ 8192 サンプルを指定します。最適なパフォーマンスを得るためには、できるだけ多くのサンプル数を指定します(最大 8192)。サンプル数が少ないと、再生中にクリック / ポップが発生する可能性が高くなります。この動作は、プラットフォームによって異なります。また、ブラウザーのサイズを変更したときなど、様々な状況で発生します。2048 サンプルだけを指定した場合、あるプラットフォームで機能するコードが、別のプラットフォームで実行した場合は機能しなくなる可能性があります。できるだけ待ち時間を小さくする必要がある場合は、データの量をユーザーが選択できるようにすることを検討してください。

sampleData イベントリスナーの 1 回の呼び出しごとのサンプル数を 2048 未満にすると、残りのサンプルの再生後にアプリケーションが停止します。SoundChannel オブジェクトは SoundComplete イベントを送出します。

MP3 データのサウンドの変更

Sound オブジェクトからデータを抽出するには、 Sound.extract() メソッドを使用します。そのデータを使用(および変更)して、再生用に別の Sound オブジェクトの動的ストリームに書き込むことができます。例えば、次のコードでは、読み込んだ MP3 ファイルのバイトを、フィルター関数 upOctave() を使用して渡しています。

var mySound:Sound = new Sound(); 
var sourceSnd:Sound = new Sound(); 
var urlReq:URLRequest = new URLRequest("test.mp3"); 
sourceSnd.load(urlReq); 
sourceSnd.addEventListener(Event.COMPLETE, loaded); 
function loaded(event:Event):void 
{ 
    mySound.addEventListener(SampleDataEvent.SAMPLE_DATA, processSound); 
    mySound.play(); 
} 
function processSound(event:SampleDataEvent):void 
{ 
        var bytes:ByteArray = new ByteArray(); 
        sourceSnd.extract(bytes, 8192); 
        event.data.writeBytes(upOctave(bytes)); 
} 
function upOctave(bytes:ByteArray):ByteArray 
{ 
    var returnBytes:ByteArray = new ByteArray(); 
    bytes.position = 0; 
    while(bytes.bytesAvailable > 0) 
    { 
        returnBytes.writeFloat(bytes.readFloat()); 
        returnBytes.writeFloat(bytes.readFloat()); 
        if (bytes.bytesAvailable > 0) 
        { 
            bytes.position += 8; 
        } 
    } 
    return returnBytes; 
}

生成されたサウンドに関する制限事項

Sound オブジェクトと共に sampleData イベントリスナーを使用する場合、Sound の他のメソッドのうち、使用できるのは Sound.extract() Sound.play() だけです。その他のメソッドまたはプロパティを呼び出すと、例外が発生します。SoundChannel オブジェクトのすべてのメソッドおよびプロパティは、引き続き使用できます。