サウンド入力のキャプチャ

Flash Player 9 以降、Adobe AIR 1.0 以降

Microphone クラスにより、アプリケーションはユーザーのシステム上にあるマイクなどのサウンド入力デバイスに接続し、入力オーディオをシステムのスピーカーにブロードキャストしたり、オーディオデータを Flash Media Server などのリモートサーバーに送信したりできます。マイクから未処理のオーディオデータにアクセスし、そのデータを録音または処理することができます。また、システムのスピーカーに直接オーディオを送信したり、圧縮したオーディオデータをリモートサーバーに送信したりすることもできます。リモートサーバーに送信するデータには、Speex または Nellymoser コーデックを使用できます(Speex コーデックは、Flash Player 10 および Adobe AIR 1.5 以降でサポートされています)。

マイクロフォンへのアクセス

Microphone クラスにはコンストラクターメソッドはありません。代わりに、次のように静的な Microphone.getMicrophone() メソッドを使用し、新しい Microphone インスタンスを取得します。

var mic:Microphone = Microphone.getMicrophone();

パラメーターを指定せずに Microphone.getMicrophone() メソッドを呼び出すと、ユーザーのシステムで検出された最初のサウンド入力デバイスが返されます。

システムには複数のサウンド入力デバイスを接続できます。アプリケーションでは、 Microphone.names プロパティを使用して、使用可能なすべてのサウンド入力デバイスの名前の配列を取得できます。次に、 Microphone.getMicrophone() メソッドを、配列にあるデバイスの名前のインデックス値と一致する index パラメーターを指定して呼び出します。

システムには、マイクロフォンまたは他のサウンド入力デバイスが接続されていない場合があります。 Microphone.names プロパティまたは Microphone.getMicrophone() メソッドを使用すると、サウンド入力デバイスがインストールされているかどうかを確認できます。サウンド入力デバイスがインストールされていない場合は names 配列の長さがゼロになり、 getMicrophone() メソッドは null 値を返します。

アプリケーションが Microphone.getMicrophone() メソッドを呼び出すと、Flash Player の設定ダイアログボックスが表示されます。ここでは、Flash Player にシステムのカメラおよびマイクへのアクセスを許可するかどうかを指定することができます。このダイアログの「許可」または「拒否」ボタンをクリックすると、StatusEvent が送出されます。 その StatusEvent インスタンスの code プロパティは、次のように、マイクのアクセスが許可されているか、拒否されているかを示します。

import flash.media.Microphone; 
 
var mic:Microphone = Microphone.getMicrophone(); 
mic.addEventListener(StatusEvent.STATUS, this.onMicStatus); 
 
function onMicStatus(event:StatusEvent):void 
{ 
    if (event.code == "Microphone.Unmuted") 
    { 
        trace("Microphone access was allowed."); 
    }  
    else if (event.code == "Microphone.Muted") 
    { 
         trace("Microphone access was denied."); 
    } 
}

アクセスが許可されている場合は、 StatusEvent.code プロパティに "Microphone.Unmuted" があり、アクセスが拒否されている場合は "Microphone.Muted" があります。

Microphone.muted プロパティは、ユーザーがマイクへのアクセスを許可した場合は true に、拒否した場合は false にそれぞれ設定されます。ただし、 muted プロパティは、StatusEvent が送出されるまで Microphone インスタンスに設定されないので、 Microphone.muted プロパティを確認するには StatusEvent.STATUS イベントが送出されるまで待機する必要があります。

Flash Player で設定ダイアログを表示するには、ダイアログの大きさに合わせてアプリケーションウィンドウのサイズを拡大する必要があります(少なくとも 215 x 138 ピクセル)。この操作を行わないと、アクセスが自動的に拒否されます。

AIR アプリケーションサンドボックスで実行されるコンテンツでは、マイクにアクセスするためにユーザーの許可は不要です。したがって、マイクのミュートおよびミュート解除の status イベントは送出されません。アプリケーションサンドボックスの外部の AIR で実行されるコンテンツではユーザーの許可が必要なので、これらの status イベントを送出できます。

マイクロフォンのオーディオからローカルスピーカへのルーティング

Microphone.setLoopback() メソッドを呼び出してパラメーター値に true を指定することで、マイクロフォンからのオーディオ入力をローカルシステムのスピーカにルーティングできます。

ローカルマイクからのサウンドがローカルスピーカーに転送されると、オーディオフィードバックループが発生する恐れがあります。これにより、きしんだような音が鳴り、サウンドハードウェアが損傷する可能性もあります。 Microphone.setUseEchoSuppression() メソッドを呼び出してパラメーターに true を指定すると、オーディオフィードバックが発生するリスクは低下しますが、完全に除去することはできません。ヘッドホンなど、スピーカー以外のものからサウンドが再生されることが確実な場合を除き、 Microphone.setLoopback(true) を呼び出す前に必ず Microphone.setUseEchoSuppression(true) を呼び出すことをお勧めします。

次のコードでは、ローカルマイクロフォンからローカルシステムのスピーカにオーディオをルーティングする方法を示します。

var mic:Microphone = Microphone.getMicrophone(); 
mic.setUseEchoSuppression(true); 
mic.setLoopBack(true);

マイクロフォンのオーディオの変更

アプリケーションでは、マイクロフォンから入力されたオーディオデータを 2 つの方法で変更できます。1 つ目は、入力サウンドのゲインを変更することです。これにより、入力値が指定量の分だけ効果的に増加するので、サウンドを大きくまたは小さくすることができます。 Microphone.gain プロパティは、0 以上 100 以下の数値を受け入れます。50 という値は 1 を掛けるのと同じで、通常の音量を指定します。値 0 は 0 を掛けるのと同じで、結果として入力オーディオは消音されます。50 より大きい値を指定すると、通常の音量より大きくなります。

アプリケーションでは、入力オーディオのサンプリングレートを変更することもできます。サンプリングレートを高くするほどサウンドの品質は向上しますが、データストリームの密度も高くなり、送信と格納に必要なリソースの量が増加します。 Microphone.rate プロパティは、キロヘルツ(kHz)単位で測定されたオーディオサンプリングレートを表します。デフォルトのサンプリングレートは 8 kHz です。マイクロフォンがこれより高いレートをサポートしている場合は、 Microphone.rate プロパティに 8 kHz より高い値を設定できます。例えば、 Microphone.rate プロパティの値を 11 に設定すると、サンプルレートは 11 kHz になり、22 に設定すると、22 kHz になります。使用可能なサンプリングレートは、選択したコーデックによって異なります。Nellymoser コーデックを使用する場合は、サンプリングレートとして 5、8、11、16、22 および 44 kHz を指定できます。Speex コーデックを使用する場合は(Flash Player 10 および Adobe AIR 1.5 以降で使用可能)、16 kHz のみ指定できます。

マイクロフォンの動作の検出

帯域幅と処理のリソースを節約するため、Flash Player は、マイクからサウンドが伝送されていない状態を検知しようとします。 一定期間にわたり、マイクのアクティビティレベルが無音レベルのしきい値を下回っていると、Flash Player はオーディオ入力の伝送を停止し、代わりにシンプルな ActivityEvent を送出します。 Speex コーデックを使用する場合(Flash Player 10 および Adobe AIR 1.5 以降で使用可能)、オーディオデータの転送が連続的に実行されるようにするには無音レベルを 0 に設定してください。Speex の音声動作検出によって、帯域幅が自動的に軽減されます。

注意: アプリケーションでマイクを監視している場合、Microphone オブジェクトは Activity イベントのみを送出します。したがって、 setLoopBack( true ) を呼び出さない場合は、サンプルデータイベントのリスナーを追加するか、NetStream オブジェクトにマイクを付加してください。これで、activity イベントは送出されません。

Microphone クラスの 3 つのプロパティを使用して、動作の検出を監視および制御します。

  • 読み取り専用の activityLevel プロパティは、マイクロフォンが検出しているサウンドの大きさを、0 ~ 100 のスケールで示します。

  • silenceLevel プロパティは、マイクを有効にするために必要なサウンド量を指定し、 ActivityEvent.ACTIVITY イベントを送出します。 silenceLevel プロパティも 0 ~ 100 のスケールを使用し、デフォルト値は 10 です。

  • silenceTimeout プロパティは、 ActivityEvent.ACTIVITY イベントが送出されてマイクが無音状態であると判断されるまで、アクティビティレベルが無音レベルを下回る時間をミリ秒単位で指定します。 silenceTimeout のデフォルト値は 2000 です。

Microphone.silenceLevel プロパティと Microphone.silenceTimeout プロパティはどちらも読み取り専用ですが、 Microphone.setSilenceLevel() メソッドを使用して値を変更できます。

場合によっては、新しい動作が検出されたときにマイクロフォンをアクティブにする処理過程で短い遅延が発生する可能性があります。常にマイクロフォンをアクティブにしておくことで、アクティブ化に伴うこのような遅延を除去できます。 silenceLevel パラメーターをゼロに設定して Microphone.setSilenceLevel() メソッドを呼び出すと、サウンドが検知されなくてもマイクを常に有効にし、オーディオデータを継続的に収集するよう Flash Player に指示することができます。逆に、 silenceLevel パラメーターを 100 に設定すると、マイクロフォンがアクティブにならなくなります。

次の例では、マイクロフォンに関する情報を表示し、Microphone オブジェクトが送出する activity イベントと status イベントを報告します。

import flash.events.ActivityEvent; 
import flash.events.StatusEvent; 
import flash.media.Microphone; 
 
var deviceArray:Array = Microphone.names; 
trace("Available sound input devices:"); 
for (var i:int = 0; i < deviceArray.length; i++) 
{ 
    trace(" " + deviceArray[i]); 
} 
 
var mic:Microphone = Microphone.getMicrophone(); 
mic.gain = 60; 
mic.rate = 11; 
mic.setUseEchoSuppression(true); 
mic.setLoopBack(true); 
mic.setSilenceLevel(5, 1000); 
     
mic.addEventListener(ActivityEvent.ACTIVITY, this.onMicActivity); 
mic.addEventListener(StatusEvent.STATUS, this.onMicStatus); 
     
var micDetails:String = "Sound input device name: " + mic.name + '\n'; 
micDetails += "Gain: " + mic.gain + '\n'; 
micDetails += "Rate: " + mic.rate + " kHz" + '\n'; 
micDetails += "Muted: " + mic.muted + '\n'; 
micDetails += "Silence level: " + mic.silenceLevel + '\n'; 
micDetails += "Silence timeout: " + mic.silenceTimeout + '\n'; 
micDetails += "Echo suppression: " + mic.useEchoSuppression + '\n'; 
trace(micDetails); 
 
function onMicActivity(event:ActivityEvent):void 
{ 
    trace("activating=" + event.activating + ", activityLevel=" +  
        mic.activityLevel); 
} 
 
function onMicStatus(event:StatusEvent):void 
{ 
    trace("status: level=" + event.level + ", code=" + event.code); 
}

上記のコード例を実行する際は、システムのマイクに向かって発話するか音を出し、コンソールまたはデバッグウィンドウに表示されるトレースステートメントを確認します。

メディアサーバーとのオーディオの送受信

Flash Media Server(FMS)のようなストリーミングメディアサーバーと共に ActionScript を使用すると、オーディオ機能が追加されます。

具体的には、Microphone オブジェクトを NetStream オブジェクトに付加し、ユーザーのマイクからサーバーに直接データを送信することができます。オーディオデータはサーバーからアプリケーションにストリーミングされ、MovieClip の一部として、または Video オブジェクトを使用して再生されます。

Speex コーデックは、Flash Player 10 および Adobe AIR 1.5 以降で使用できます。メディアサーバーに送信されるオーディオの圧縮に使用するコーデックを指定するには、Microphone オブジェクトの codec プロパティを設定します。このプロパティには、SoundCodec クラスで列挙されている 2 つの値を設定できます。codec プロパティを SoundCodec.SPEEX に設定すると、オーディオの圧縮時に Speex コーデックスが選択されます。このプロパティを SoundCodec.NELLYMOSER (デフォルト)に設定すると、オーディオの圧縮に Nellymoser コーデックが選択されます。

詳しくは、 www.adobe.com/go/learn_fms_docs_jp でオンラインの Flash Media Server ドキュメントを参照してください。

マイクサウンドデータのキャプチャ

Flash Player 10.1 および AIR 2 以降では、マイクからのデータを浮動小数点値のバイト配列としてキャプチャできます。値はそれぞれモノラルオーディオデータの 1 つのサンプルを表します。

モノラルデータを取得するには、Microphone オブジェクトの sampleData イベントのイベントリスナーを設定します。Microphone オブジェクトは、マイクのバッファにサウンドサンプルが入力されると、 sampleData イベントを定期的に送出します。SampleDataEvent オブジェクトには、サウンドサンプルのバイト配列である data プロパティがあります。サンプルは、それぞれが浮動小数点値として表現され、モノラルサウンドサンプルを表します。

次のコードでは、マイクサウンドデータが soundBytes という ByteArray オブジェクトにキャプチャされます。

var mic:Microphone = Microphone.getMicrophone(); 
mic.setSilenceLevel(0, DELAY_LENGTH); 
mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler); 
function micSampleDataHandler(event:SampleDataEvent):void { 
    while(event.data.bytesAvailable)     { 
        var sample:Number = event.data.readFloat(); 
        soundBytes.writeFloat(sample); 
    } 
}

サンプルバイトは、Sound オブジェクトの再生オーディオとして再利用できます。再利用する場合は、Microphone オブジェクトの rate プロパティを 44 に設定します。これは、Sound オブジェクトで使用されるサンプルレートです(低いレートでキャプチャされたマイクサンプルを、Sound オブジェクトに必要な 44 kHz のレートに変換することもできます)。また、Microphone オブジェクトではモノラルのサンプルがキャプチャされることを覚えておいてください。Sound オブジェクトではステレオサウンドを使用するため、Microphone オブジェクトによってキャプチャされたバイトはそれぞれ Sound オブジェクトに 2 回ずつ書き込む必要があります。次の例では、4 秒のマイクデータをキャプチャし、Sound オブジェクトを使用して再生します。

const DELAY_LENGTH:int = 4000; 
var mic:Microphone = Microphone.getMicrophone(); 
mic.setSilenceLevel(0, DELAY_LENGTH); 
mic.gain = 100; 
mic.rate = 44; 
mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler); 
 
var timer:Timer = new Timer(DELAY_LENGTH); 
timer.addEventListener(TimerEvent.TIMER, timerHandler); 
timer.start(); 
 
function micSampleDataHandler(event:SampleDataEvent):void 
{ 
    while(event.data.bytesAvailable) 
    { 
        var sample:Number = event.data.readFloat(); 
        soundBytes.writeFloat(sample); 
    } 
} 
var sound:Sound = new Sound(); 
var channel:SoundChannel; 
function timerHandler(event:TimerEvent):void 
{ 
    mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler); 
    timer.stop(); 
    soundBytes.position = 0; 
    sound.addEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler); 
    channel.addEventListener( Event.SOUND_COMPLETE, playbackComplete ); 
    channel = sound.play(); 
} 
 
function playbackSampleHandler(event:SampleDataEvent):void 
{ 
    for (var i:int = 0; i < 8192 && soundBytes.bytesAvailable > 0; i++) 
    { 
        trace(sample); 
        var sample:Number = soundBytes.readFloat(); 
        event.data.writeFloat(sample); 
        event.data.writeFloat(sample); 
    } 
} 
 
function playbackComplete( event:Event ):void 
{ 
    trace( "Playback finished."); 
}

サウンドサンプルデータからサウンドを再生する方法について詳しくは、 動的に生成されたオーディオの操作 を参照してください。