Microphoneと音響スペクトル

「詳解 ActionScript 3.0 アニメーション」の5章では、マイク入力の扱い方を説明しています。Flash Player 10 までは、Microphone クラス単独では波形データを取得することができませんでしたが、Flash Player 10.1 では、SampleDataEvent.SAMPLE_DATAイベントのハンドラを設定すると、波形データを得ることができます。

SpectrumTest.swf 直
(↑クリックすると再生。Flash Player 10.1とマイクが必要です)

ソースは続き
SpectrumTest.as 直

package {
    import flash.system.Capabilities;
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.SampleDataEvent;
    import flash.media.Microphone;
    import flash.media.Sound;
    import flash.media.SoundMixer;
    import flash.utils.ByteArray;
    
    [SWC(width=256, height=256, backgroundColor=0xFFFFFF)]
    public class SpectrumTest extends Sprite {
        private var buf:Vector.<Number>;
        private var mic:Microphone;
        private var sound:Sound;

        public function SpectrumTest() {
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;

            var version:String = Capabilities.version;
            var vs:Array = version.split(/[, ]/);
            var v:Number = Number(vs[1]) + Number(vs[2]) / 10;
            if (v < 10.1) {
                var tf:TextField = new TextField();
                tf.width = 256;
                tf.height = 256;
                tf.appendText("Error\n");
                tf.appendText(" Flash Player 10.1 or later required.\n");
                tf.appendText(" Your Flash Player version: " + version);
                addChild(tf);
                return;
            }

            buf = new Vector.<Number>();

            mic = Microphone.getMicrophone();
            mic.rate = 44;
            mic.addEventListener(SampleDataEvent.SAMPLE_DATA, onMicSampleData);

            sound = new Sound();
            sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSoundSampleData);
            sound.play();

            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
        
        // event.data から波形データを取得する。
        private function onMicSampleData(event:SampleDataEvent):void {
            while (event.data.bytesAvailable) {
                var v:Number = event.data.readFloat();
                buf.push(v);
            }
        }

        // event.data に 8192サンプル分の波形データを追加する。
        private function onSoundSampleData(event:SampleDataEvent):void {
            for (var i:int = 0; i < 8192 && buf.length > 0; i++) {
                var v:Number = buf.shift();
                event.data.writeFloat(v); // 左
                event.data.writeFloat(v); // 右
            }
            for (; i < 8192; i++) {
                event.data.writeFloat(0);
                event.data.writeFloat(0);
            }
        }

        // 音響スペクトルを計算して描画する。
        private function onEnterFrame(event:Event):void {
            var bytes:ByteArray = new ByteArray();
            SoundMixer.computeSpectrum(bytes, true, 2);

            graphics.clear();
            graphics.lineStyle(0, 0x0000FF);
            graphics.moveTo(0, 100);
            // 左チャンネルのみ
            for (var i:int = 0; i < 256; i++) {
                var h:Number = bytes.readFloat() * 100;
                graphics.lineTo(i, 100 - h);
            }
        }
    }
}