In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

「あ」のうた -ah song-

デザイン「あ」 の 「あ」のうた http://www.nhk.or.jp/design-ah/ah-song/
がすごい好きだったので真似して作って見ました。
フルスクリーンで見ると綺麗かもしれません。

「あ」のうたのインターフェースで「あ」のうた以外の曲を流すという邪道っぷりですが、お許し下さい。
曲も真似して作ろうと思ったんですが、技量が足りませんでした...


環境によってはマイクの反応が悪い場合があります。マイクに近づくか大きな声で発音してください。
ノートPCなどスピーカーとマイクが近い場合はマイクがスピーカーの音を拾ってしまうのでイヤホンでお聴きください。


mp3アップロードはmakc3dさんの
http://wonderfl.net/c/wzzu
にあるClientMP3Loaderをお借りしました。

GitHub
https://github.com/ton1517/DesignAh
/**
 * Copyright ton ( http://wonderfl.net/user/ton )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/9Zhv
 */

/*
 * デザイン「あ」 の 「あ」のうた http://www.nhk.or.jp/design-ah/ah-song/
 * がすごい好きだったので真似して作って見ました。
 * フルスクリーンで見ると綺麗かもしれません。
 * 
 * 「あ」のうたのインターフェースで「あ」のうた以外の曲を流すという邪道っぷりですが、お許し下さい。
 * 曲も真似して作ろうと思ったんですが、技量が足りませんでした...
 * 
 * 
 * 環境によってはマイクの反応が悪い場合があります。マイクに近づくか大きな声で発音してください。
 * ノートPCなどスピーカーとマイクが近い場合はマイクがスピーカーの音を拾ってしまうのでイヤホンでお聴きください。
 * 
 * 
 * mp3アップロードはmakc3dさんの
 * http://wonderfl.net/c/wzzu
 * にあるClientMP3Loaderをお借りしました。
 */

package  
{
    import caurina.transitions.*;
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.system.*;
    import flash.text.*;
    import flash.ui.*;
    import frocessing.color.ColorHSV;
    
    [SWF(width = 465, height = 465, backgroundColor = 0xffffff, frameRate = 30)]
    public class DesignAh extends Sprite 
    {
        private var lang:Namespace;
        private namespace ja;
        private namespace en;
        
        private var descriptionTxt:TextField;
        public static const FONT_NAME:String = "_sans";
        private const FONT_SIZE:int = 24;
        
        private var texts:Array/*String*/ = [];
        private const DESCRIPTION1:int = 0;
        private const READY:int = 1;
        private const CANCEL:int = 2;
        private const OK:int = 3;
        private const THANKS:int = 4;
        private const ENJOY:int = 5;
        private const NEXT:int = 6;
        private const SELECT_MUSIC:int = 7;
        private const WELCOME:int = 8;
        private const MIC:int = 9;
        private const SOUND:int = 10;
        private const THEME_LEFT:int = 11;
        private const THEME_RIGHT:int = 12;
        
        private var drawingPanel:DrawingPanel;
        private var centerDrawingPanel:Sprite;
        
        private var soundButton:NavigationButton;
        private var micButton:NavigationButton;
        private var nextButton:NavigationButton;
        
        private var cancelButton:NavigationButton;
        private var okButton:NavigationButton;
        
        private var maxLines:int;
        private var displayLines:int;
        
        private var defaultSound:AhSound;
        private var loadedDefaultSound:Boolean = false;
        
        private var sounds:Vector.<AhSoundBase>;
        private var loadCount:int = 0;
        private var maxSounds:int;
            
        private var panelClasses:Vector.<Class>;
        private var listPanel:ListPanel;
        private var panels:Vector.<DisplayPanel>;
        
        private var extendMode:Boolean;
        private var color:ColorHSV = new ColorHSV(0, 0.7);

        private var bg:Shape;
        
        public function DesignAh() {
            stage.align = StageAlign.TOP;
            stage.scaleMode = StageScaleMode.SHOW_ALL;
            
            bg = new Shape();
            bg.graphics.beginFill(0);
            bg.graphics.drawRect( -465, 0, 465 * 3, 465);
            bg.graphics.endFill();
            addChild(bg);    
            
            checkLanguage();
            lang::init();
            initDescriptionTxt();
            initDrawingPanel();
            initButton();
            initPanelClasses();
            initDefaultSound();
            extendKey();
            maskStage();
            
            sounds = new Vector.<AhSoundBase>();
            
            startWelcomMessage();

        }
        
        private function extendKey():void {
            stage.addEventListener(KeyboardEvent.KEY_DOWN, function(e:KeyboardEvent):void {
                if (e.keyCode == Keyboard.SHIFT)extendMode = true;
            });
            
            stage.addEventListener(KeyboardEvent.KEY_UP, function(e:KeyboardEvent):void {
                if (e.keyCode == Keyboard.SHIFT)extendMode = false;
            });
        }
        
        private function initDefaultSound():void {
            defaultSound = new AhSound("http://www.takasumi-nagai.com/soundfiles/sound001.mp3", "SOUND");
            defaultSound.addEventListener(Event.COMPLETE, onCompleteDefaultSound);
            defaultSound.addEventListener(IOErrorEvent.IO_ERROR, onDefaultSoundIOError);
        }
        
        private function onDefaultSoundIOError(e:IOErrorEvent):void { loadedDefaultSound = true;}
        private function onCompleteDefaultSound(e:Event):void { loadedDefaultSound = true;}
        
        private function checkLanguage():void {
            lang = Capabilities.language == "ja" ? ja : en;
        }
        
        ja function init():void {
            texts[DESCRIPTION1] = "画面に「あ」と書いてください。";
            texts[READY] = "これでいいですか?";
            texts[CANCEL] = "書きなおす";
            texts[OK] = "はい";
            texts[THANKS] = "ありがとうございました。\n\n\n\n\n\n\n\n\n\n";
            texts[ENJOY] = "それではどうぞお楽しみください。";
            texts[NEXT] = "次へ";
            texts[SELECT_MUSIC] = "再生したい音楽を選んでください。\n\n\n\n\n\n\n\n\n\n";
            texts[WELCOME] = "「あ」のうたへ ようこそ。\n\n\n\n\n\n\n\n\n\n";
            texts[MIC] = "マイク";
            texts[SOUND] = "サウンド";
            texts[THEME_LEFT] = "「";
            texts[THEME_RIGHT] = "」のテーマ";
            
            maxLines = 3;
            displayLines = 3;
        }
        
        en function init():void {
            texts[DESCRIPTION1] = "please write 'A' on the screen.";
            texts[READY] = "are you ready?";
            texts[CANCEL] = "try again";
            texts[OK] = "ok";
            texts[THANKS] = "thank you.\n\n\n\n\n\n\n\n\n\n";
            texts[ENJOY] = "let's enjoy.";
            texts[NEXT] = "next";
            texts[SELECT_MUSIC] = "please select the music to play.\n\n\n\n\n\n\n\n\n\n";
            texts[WELCOME] = "welcome to the song of 'Ah'.\n\n\n\n\n\n\n\n\n\n";
            texts[MIC] = "Microphone";
            texts[SOUND] = "Sound";
            texts[THEME_LEFT] = "Theme of '";
            texts[THEME_RIGHT] = "'";
            
            maxLines = 3;
            displayLines = 2;
        }
        
        private function initDescriptionTxt():void {
            descriptionTxt = new TextField();
            descriptionTxt.autoSize = TextFieldAutoSize.CENTER;
            descriptionTxt.selectable = false;
            
            descriptionTxt.defaultTextFormat = new TextFormat(FONT_NAME, FONT_SIZE, 0xffffff);
            descriptionTxt.text = " ";
            descriptionTxt.y = stage.stageHeight / 2 - descriptionTxt.height;
            descriptionTxt.x = stage.stageWidth / 2 - descriptionTxt.width / 2;
            addChild(descriptionTxt);
        }
        
        private function initDrawingPanel():void {
            drawingPanel = new DrawingPanel(stage, 3);
            drawingPanel.x = -drawingPanel.width / 2;
            drawingPanel.y = -drawingPanel.height / 2;
            
            centerDrawingPanel = new Sprite();
            centerDrawingPanel.addChild(drawingPanel);
            centerDrawingPanel.x = stage.stageWidth / 2;
            centerDrawingPanel.y = stage.stageHeight / 2;
        }
        
        private function initPanelClasses():void {
            panelClasses = new Vector.<Class>();
            panelClasses.push(Spring);
            panelClasses.push(FlyingCircle);
            panelClasses.push(Outline);
            panelClasses.push(Mosaic);
            
            maxSounds = panelClasses.length;
        }
        
        private function initButton():void {
            var offsetX:int = 10;
            var offsetY:int = 20;
            
            soundButton = new NavigationButton(texts[SOUND], FONT_SIZE, false);
            soundButton.x = stage.stageWidth / 2 - soundButton.width / 2;
            soundButton.y = stage.stageHeight / 2 - soundButton.height / 2 + offsetY;
            soundButton.addEventListener(MouseEvent.CLICK, onSoundSet);
            
            micButton = new NavigationButton(texts[MIC], FONT_SIZE, false);
            micButton.x = stage.stageWidth / 2 - micButton.width / 2;
            micButton.y = soundButton.y - micButton.height - 20 - offsetY;        
            micButton.addEventListener(MouseEvent.CLICK, onMicSet);
            
            nextButton = new NavigationButton(texts[NEXT], FONT_SIZE, false);
            nextButton.x = stage.stageWidth - nextButton.width - offsetX;
            nextButton.y = stage.stageHeight - nextButton.height - offsetY;
            nextButton.addEventListener(MouseEvent.CLICK, onNext);
            
            cancelButton = new NavigationButton(texts[CANCEL], FONT_SIZE, true);
            cancelButton.x = offsetX;
            cancelButton.y = stage.stageHeight - cancelButton.height - offsetY;
            cancelButton.addEventListener(MouseEvent.CLICK, onDrawCancel);
            
            okButton = new NavigationButton(texts[OK], FONT_SIZE, false);
            okButton.x = stage.stageWidth - okButton.width - offsetX;
            okButton.y = stage.stageHeight - okButton.height - offsetY;
            okButton.addEventListener(MouseEvent.CLICK, onDrawOK);
        }
        
        private function maskStage():void {
            var m:Shape = new Shape();
            m.graphics.beginFill(0x0, 0);
            m.graphics.drawRect(-stage.stageWidth, 0, stage.stageWidth*3, stage.stageHeight);
            m.graphics.endFill();
            addChild(m);
            mask = m;            
        }
        
        private function startWelcomMessage():void {            
            TypeWriterAnimation.startAnimation(descriptionTxt, texts[WELCOME], 100, function():void {
                TypeWriterAnimation.startAnimation(descriptionTxt, texts[SELECT_MUSIC], 100, nextAnimation);
            });
            
            function nextAnimation():void {
                Tweener.addTween(descriptionTxt, { y:30, time:1, transition:"easeOutCubic" } );    
                
                var toX:Number = soundButton.x;
                soundButton.x = stage.stageWidth * 2;
                Tweener.addTween(soundButton, {x:toX, time:0.5, transition:"easeOutCubic" } );                
                addChild(soundButton);
                
                toX = micButton.x;
                micButton.x = stage.stageWidth * 2;
                Tweener.addTween(micButton, {x:toX, time:0.5, delay:0.1, transition:"easeOutCubic" } );                
                addChild(micButton);
                
                toX = nextButton.x;
                nextButton.x = -stage.stageWidth * 2 - nextButton.width;
                Tweener.addTween(nextButton, {x:toX, time:0.5,delay:0.2, transition:"easeOutCubic" } );                    
                addChild(nextButton);
            }
        }
        
        private function onNext(e:MouseEvent):void {
            nextButton.removeEventListener(MouseEvent.CLICK, onNext);
            
            if (loadCount == 0) sounds.push(defaultSound);
            
            if (contains(soundButton)) removeChild(soundButton);
            if (contains(micButton)) removeChild(micButton);
            removeChild(nextButton);
            
            if (extendMode && sounds.length == 1) {
                sounds[0].addEventListener(AhSoundEvent.ACTIVE_COUNT, extendActiveCount);
            }
                        
            descriptionTxt.text = " ";
            descriptionTxt.y = stage.stageHeight / 2 - descriptionTxt.height;
            startDrawMessage();
        }
        
        private function onMicSet(e:MouseEvent):void {
            micButton.removeEventListener(MouseEvent.CLICK, onMicSet);
            removeChild(micButton);            
            var s:AhMicrophone = new AhMicrophone();
            s.addEventListener(Event.COMPLETE, onSoundComplete);
        }
        
        private function extendActiveCount(e:AhSoundEvent):void {
            if(listPanel && listPanel.running){
                for (var i:int = 0; i < panels.length; i++ ) {
                    var panel:DisplayPanel = panels[i];
                    color.h = Math.random() * 360;
                    panel.color = color.value;
                }
            }
            
        }
        
        private function onSoundSet(e:MouseEvent):void {
            var s:AhSoundLocal = new AhSoundLocal();
            s.addEventListener(Event.COMPLETE, onSoundComplete);
        }        
        
        private function onSoundComplete(e:Event):void {
            var sound:AhSoundBase = e.currentTarget as AhSoundBase;
            sounds.push(sound);
            loadCount++;
            if (loadCount == maxSounds) {
                removeChild(soundButton);
                if (contains(micButton)) removeChild(micButton);
            }
        }
        
        private function startDrawMessage():void {
            TypeWriterAnimation.startAnimation(descriptionTxt, texts[DESCRIPTION1], 100, nextAnimation);

            function nextAnimation():void {
                Tweener.addTween(descriptionTxt, { y:20, time:1, delay:1, transition:"easeOutCubic" } );
                
                centerDrawingPanel.alpha = 0;
                centerDrawingPanel.scaleX = centerDrawingPanel.scaleY = 0;
                addChild(centerDrawingPanel);
            
                Tweener.addTween(centerDrawingPanel, { alpha:1, scaleX:1, scaleY:1, time:1, delay:1, transition:"easeOutCubic", onComplete:function():void {
                    drawingPanel.start();
                    drawingPanel.addEventListener(ProgressEvent.PROGRESS, onDrawProgress);                        
                }} );
            }            
        }
        
        private function onDrawOK(e:MouseEvent):void {
            drawingPanel.stop();        
            removeDrawPanelButton();
            ready();
        }
        
        private function onDrawCancel(e:MouseEvent):void {
            drawingPanel.init();
            drawingPanel.start();
            removeDrawPanelButton();
            TypeWriterAnimation.startAnimation(descriptionTxt, texts[DESCRIPTION1], 100);        
        }
        
        private function addDrawPanelButton():void {            
            cancelButton.alpha = okButton.alpha = 0;
            addChild(cancelButton);
            addChild(okButton);
            
            Tweener.addTween(cancelButton, {alpha:1, time:1, transition:"easeOutCubic" } );
            Tweener.addTween(okButton, { alpha:1, time:1, transition:"easeOutCubic" } );
        }
                
        private function removeDrawPanelButton():void {
            cancelButton.alpha = okButton.alpha = 0;        
            removeChild(cancelButton);
            removeChild(okButton);            
            
        }
        
        private function onDrawProgress(e:ProgressEvent):void {
            if (drawingPanel.lineLength == displayLines) {
                addDrawPanelButton();
                
                TypeWriterAnimation.startAnimation(descriptionTxt, texts[READY], 100);
            }
        }

        
        private function ready():void {
            centerDrawingPanel.removeChild(drawingPanel);
            removeChild(descriptionTxt);
            
            descriptionTxt.y = stage.stageHeight / 2 - descriptionTxt.height;
            Tweener.addTween(descriptionTxt, { time:1, onComplete:function():void {
                TypeWriterAnimation.startAnimation(descriptionTxt, texts[THANKS], 100, function():void {
                    TypeWriterAnimation.startAnimation(descriptionTxt, texts[ENJOY], 100, function():void {
                        Tweener.addTween(descriptionTxt, { delay:1, time:2, alpha:0, onComplete:function():void { 
                            removeChild(descriptionTxt); 
                            startDrawingAnimation();
                        }} );                        
                    });
                });
                addChild(descriptionTxt);
            } } );

        }        
        
        private function startDrawingAnimation():void {
            panels = new Vector.<DisplayPanel>();
            listPanel = new ListPanel(stage, new Rectangle(0, 0, stage.stageWidth, stage.stageHeight));
            listPanel.x = stage.stageWidth * 2;
            
            var lines:Vector.<Line> = drawingPanel.lines;
            
            listPanel.addFirst(new ThemeOfAh(Line.cloneLines(lines), texts[THEME_LEFT], texts[THEME_RIGHT]));
            
            for (var j:int = 0; j < panelClasses.length; j++) {
                var PanelClass:Class = panelClasses[j];
                var panel:DisplayPanel = new PanelClass(stage, Line.cloneLines(lines), sounds[j % sounds.length]);
                panels.push(panel);
                listPanel.add(panel);
            }
            
            if (loadedDefaultSound) {
                start();
            }else {
                addEventListener(Event.ENTER_FRAME, function(e:Event):void {
                    if (loadedDefaultSound) {
                        e.currentTarget.removeEventListener(e.type, arguments.callee);
                        start();
                    }
                });
            }
            
            function start():void{
                addChild(listPanel);
                Tweener.addTween(listPanel, { x:0, time:2, transition:"easeOutQuint", onComplete:function():void {
                    for (var i:int = 0; i < sounds.length; i++) sounds[i].start();                    
                    listPanel.start();                    
                }} );
            }
        }
    }
}

import caurina.transitions.*;
import com.codeazur.as3swf.*;
import com.codeazur.as3swf.data.*;
import com.codeazur.as3swf.tags.*;
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.media.*;
import flash.net.*;
import flash.system.*;
import flash.text.*;
import flash.utils.*;

/*//////////////////////////////////////////////////
 * 
 * 文字を描く時のクラス
 * 
/*//////////////////////////////////////////////////

/**
 * 「あ」の文字を描く時のパネル
 */
class DrawingPanel extends Sprite {
    
    private const RECT_SIZE:int = 300;
    private const RECT_OFFSET:int = 3;
    private const SPACES:int = 20;
    
    private const COLOR:uint = 0xffffff;
    private const LINE_SIZE:int = 7;
    
    private var _drawCount:int;
    private var _lines:Vector.<Line>;
    private var _line:Line;
    
    private var _stage:Stage;
    private var _maxLines:int;
    
    private var _canvases:Vector.<Shape>;
    private var _canvas:Shape;
    
    private var _resultPanel:Spring;
    
    public function DrawingPanel(stage:Stage, maxLines:int) {
        this._stage = stage;
        this._maxLines = maxLines;

        drawBaseLine();        
        init();
    }
    
    public function init():void {
        if (_canvases) {
            for (var i:int = 0; i < _canvases.length; i++) {
                if(contains(_canvases[i]))
                    removeChild(_canvases[i]);
            }
        }
        _canvases = new Vector.<Shape>();
        
        if (_resultPanel) {
            removeChild(_resultPanel);
            _resultPanel.removeEventListener(Event.ENTER_FRAME, resultUpdate);
        }
        
        _lines = new Vector.<Line>();
        _drawCount = 0;

    }
    
    public function start():void {
        _stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);        
    }
    
    public function stop():void {
        _stage.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
    }
    
    public function get lineLength():int {
        return lines.length;
    }
    
    public function get lines():Vector.<Line> {
        return _lines;
    }
    
    
    private function onMouseDown(e:MouseEvent):void {
        var x:Number = mouseX;
        var y:Number = mouseY;        
        if(x >= RECT_OFFSET && x <= RECT_SIZE - RECT_OFFSET && y >= RECT_OFFSET && y <= RECT_SIZE - RECT_OFFSET){
            _stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
            _stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
            _line = new Line(new Rectangle(0, 0, RECT_SIZE, RECT_SIZE));
            
            _canvas = new Shape();
            addChild(_canvas);
            _canvas.graphics.lineStyle(LINE_SIZE, COLOR, 1, false, LineScaleMode.NORMAL, CapsStyle.SQUARE, JointStyle.BEVEL);        
            _canvas.graphics.moveTo(x, y);
        }
    }
    
    private function onMouseMove(e:MouseEvent):void {
        var x:Number = mouseX;
        var y:Number = mouseY;
        
        if (x < RECT_OFFSET) {
            x = RECT_OFFSET;
        }else if(x > RECT_SIZE - RECT_OFFSET){
            x = RECT_SIZE - RECT_OFFSET;
        }
        
        if (y < RECT_OFFSET) {
            y = RECT_OFFSET;
        }else if (y > RECT_SIZE - RECT_OFFSET) {
            y = RECT_SIZE - RECT_OFFSET;
        }
        
        _line.add(new Point(x, y));
        _canvas.graphics.lineTo(x, y);
    }
    
    private function onMouseUp(e:MouseEvent):void {
        _stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
        _stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
        
        var length:int = _line.length;
        
        if (length > 10 && length < 400) {
            _canvases.push(_canvas);
            _lines.push(_line);    
            
            dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS, false, false, lineLength, _maxLines));
            
            _drawCount++;
            if (_drawCount == _maxLines) {
                for (var i:int = 0; i < _canvases.length; i++) {
                    if(contains(_canvases[i]))
                        removeChild(_canvases[i]);
                }
            
                _resultPanel = new Spring(_stage, Line.cloneLines(_lines), null);
                _resultPanel.addEventListener(Event.ENTER_FRAME, resultUpdate);
                addChild(_resultPanel);
                
                stop();
                dispatchEvent(new Event(Event.COMPLETE, false, false));
            }            
        }else {
            removeChild(_canvas);
        }
    }
    
    private function resultUpdate(e:Event):void {
        _resultPanel.update();
    }
    
    private function drawBaseLine():void {
        graphics.lineStyle(1, COLOR);
        graphics.beginFill(COLOR, 0.01);
        graphics.drawRect(0, 0, RECT_SIZE, RECT_SIZE);

        graphics.moveTo(0, RECT_SIZE / 2);
        graphics.lineTo(RECT_SIZE, RECT_SIZE / 2);
        
        graphics.moveTo(RECT_SIZE / 2, 0);
        graphics.lineTo(RECT_SIZE / 2, RECT_SIZE);
        
        graphics.lineStyle(0, COLOR, 0.2);
        var dist:Number = RECT_SIZE / 20;
        var i:int;
        
        for (i = dist; i < RECT_SIZE; i += dist) {
            graphics.moveTo(i, 0);
            graphics.lineTo(i, RECT_SIZE);
        }
        
        for (i = dist; i < RECT_SIZE; i += dist) {
            graphics.moveTo(0, i);
            graphics.lineTo(RECT_SIZE, i);
        }            
        
        graphics.endFill();
    }
}

/**
 * 描いた線の情報を保持するクラス
 */
class Line {
    
    private var _points:Vector.<Point>;
    private var _region:Rectangle;
    private var _normalized:Boolean = false;
    
    public function Line(region:Rectangle) {
        _region = region;
        _points = new Vector.<Point>();
    }
    
    public function add(p:Point):void {_points.push(p);}
    
    public function get(index:int):Point {return _points[index];}
    
    public function get length():int {return _points.length;}
    
    public function get normalized():Boolean {return _normalized;}
    
    public function get region():Rectangle {return _region;}
    
    public function optimize(d:int = 3):void {
        
        var newPoints:Vector.<Point> = new Vector.<Point>();
        
        newPoints.push(_points[0]);
        for (var j:int = d; j < _points.length - 1; j += d) {
            newPoints.push(_points[j]);
        }
        newPoints.push(_points[_points.length - 1]);

        _points =  newPoints;
    }    
    
    public function normalize():void {
        if (normalized) return;
        
        _normalized = true;
        
        for (var i:int = 0; i < _points.length; i++) {
            var p:Point = _points[i];
            p.x /= region.width;
            p.y /= region.height;
        }
    }
    
    public function denormalize(region:Rectangle):void {
        if (!normalized) return;
        
        _normalized = false;
        
        _region = region;
        
        for (var i:int = 0; i < _points.length; i++) {
            var p:Point = _points[i];
            p.x *= region.width;
            p.y *= region.height;
        }    
    }
    
    public function clone():Line {
        var line:Line = new Line(new Rectangle(region.x, region.y, region.width, region.height));
        
        for (var i:int = 0; i < this.length; i++) {
            var p:Point = this.get(i);
            line.add(new Point(p.x, p.y));
        }
        
        return line;
    }        
    
    public static function cloneLines(lines:Vector.<Line>):Vector.<Line> {
        var nl:Vector.<Line> = new Vector.<Line>();
        for (var i:int = 0; i < lines.length; i++) {
            nl.push(lines[i].clone());
        }
        
        return nl;
    }    
}

/*//////////////////////////////////////////////////
 * 
 * 「あ」のパネルを並べてスライドさせるクラス
 * 
/*//////////////////////////////////////////////////


/**
 * パネルを並べて表示するクラス
 */
class ListPanel extends Sprite {
    
    private var _stage:Stage;
    private var _region:Rectangle;
    
    private var _wrapPanels:Vector.<WrapPanel>;
    
    private var _drag:Boolean = false;
    private var _prevMouseX:Number = 0;
    private var _prevEnterMouseX:Number = 0;
    private var _tweenObj:Object = new Object();
    private var _running:Boolean = false;
    
    private var _topPos:Number;
    
    private var _first:Boolean = true;
    
    private var _themePanel:DisplayPanel;
    
    public function ListPanel(stage:Stage, region:Rectangle) {
        _stage = stage;
        _region = region;
        
        _topPos = region.width;
        
        _wrapPanels = new Vector.<WrapPanel>();
        
        buttonMode = true;
        useHandCursor = true;
        
        graphics.beginFill(0, 0);
        graphics.drawRect( -_region.width, 0, _region.width * 3, _region.height);
        graphics.endFill();
    }
    
    public function add(panel:DisplayPanel):void {
        var wp:WrapPanel = new WrapPanel(panel, _region);
        wp.x = _topPos + _region.width * _wrapPanels.length;
        addChild(wp);
        _wrapPanels.push(wp);
    }
    
    public function addFirst(themePanel:DisplayPanel):void {
        _themePanel = themePanel;
        _themePanel.x = _region.width / 2 - _themePanel.width / 2;
        _themePanel.y = _region.height / 2 - _themePanel.height / 2;
        addChild(_themePanel);
    }
    
    public function start():void {
        if (_running) return ;
        
        _running = true;
        _stage.addEventListener(Event.ENTER_FRAME, onUpdate);
        _stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
        _stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
        _stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
        
        for (var i:int = 0; i < _wrapPanels.length; i++){
            _wrapPanels[i].displayPanel.start();
        }
    }

    public function stop():void {
        if (!_running) return ;
        
        _running = false;
        _stage.removeEventListener(Event.ENTER_FRAME, onUpdate);
        _stage.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
        _stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
        _stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);

        for (var i:int = 0; i < _wrapPanels.length; i++){
            _wrapPanels[i].displayPanel.stop();
        }        
    }
    
    private function onUpdate(e:Event):void {
        if (!_drag) move( -3);
        _prevEnterMouseX = mouseX;
    }
    
    private function onMouseDown(e:MouseEvent):void {
        _drag = true;
    }    
    
    private function onMouseUp(e:MouseEvent):void {
        _drag = false;
        
        _tweenObj.x = (mouseX - _prevEnterMouseX) ;
        Tweener.addTween(_tweenObj, { x:0, time:0.5, transition:"easeOutQuint", onUpdate:function():void {
            move(_tweenObj.x);
        }} );
    }
    
    private function onMouseMove(e:MouseEvent):void {
        if (_drag) move(mouseX - _prevMouseX);
        
        _prevMouseX = mouseX;    
    }    
    
    private function move(dx:Number):void {
        if (dx < 0 ) {
            //左
            if (_topPos < -_region.width * 2) {
                if (_first) {
                    _first = false;
                    removeChild(_themePanel);
                }
                
                var e1:WrapPanel = _wrapPanels.shift();
                _wrapPanels.push(e1);
                _topPos = _wrapPanels[0].x;
            }
        }else if(!_first){
            //右
            if (_topPos >= -_region.width) {
                _topPos = _wrapPanels[0].x - _region.width;
                var e2:WrapPanel = _wrapPanels.pop();
                _wrapPanels.unshift(e2);
            }
        }
        
        _topPos += dx;        
        
        if(_first) _themePanel.x += dx;
        
        for (var i:int = 0; i < _wrapPanels.length; i++) {
            var panel:WrapPanel = _wrapPanels[i];
            panel.x = _topPos + _region.width * i;
            
            if (panel.x >= -_region.width*2 && panel.x <= _region.width*2) {
                panel.displayPanel.start();
            }else {
                panel.displayPanel.stop();
            }
        }        
    }
    
    public function get running():Boolean {    return _running;}
}

class WrapPanel extends Sprite {
    
    private var _panel:DisplayPanel;
    private var _acp:ActiveCountPanel;
    private var _region:Rectangle;
    
    public function WrapPanel(panel:DisplayPanel, region:Rectangle) {
        _panel = panel;
        _region = region;
        
        graphics.beginFill(0x0, 0);
        graphics.drawRect(0, 0, _region.width, _region.height);
        graphics.endFill();

        panel.x = _region.width/2 - panel.width / 2;
        panel.y = _region.height/2 - panel.height / 2;
        addChild(panel);
        
        _acp = new ActiveCountPanel(panel.sound, panel.sound.voiceName);
        _acp.x = 10;
        _acp.y = _region.height - _acp.height - 10;
        addChild(_acp);
    }
    
    public function get displayPanel():DisplayPanel {return _panel;}
    public function get activeCountPanel():ActiveCountPanel {return _acp;}
}

/*//////////////////////////////////////////////////
 * 
 * 「あ」をアニメーションさせるクラス
 * 
/*//////////////////////////////////////////////////

/**
 * 「あ」をアニメーションさせるパネルのベース
 */
class DisplayPanel extends Sprite {

    public const RECT_SIZE:int = 300;

    protected var lines:Vector.<Line>;
    protected var container:Stage;
    
    private var _sound:AhSoundBase;
    private var _running:Boolean = false;
    private var _color:uint = 0xffffff;
    
    private var dummy:Shape;

    public function DisplayPanel (container:Stage, lines:Vector.<Line>, sound:AhSoundBase) {
        this.lines = lines;
        this.container = container;
        
        _sound = sound;

        dummy = new Shape();
        dummy.graphics.beginFill(0x0, 0);
        dummy.graphics.drawRect(0, 0, RECT_SIZE, RECT_SIZE);
        dummy.graphics.endFill();
        addChild(dummy);
    }
    
    public function start():void {
        if (_running) return ;
        
        _running = true;
        addEventListener(Event.ENTER_FRAME, onUpdate);
        sound.addEventListener(AhSoundEvent.ACTIVE, onActive);
        sound.addEventListener(AhSoundEvent.ACTIVE_COUNT, onActiveCount);
    }

    public function stop():void {
        if (!_running) return ;
        
        _running = false;
        removeEventListener(Event.ENTER_FRAME, onUpdate);
        sound.removeEventListener(AhSoundEvent.ACTIVE, onActive);
        sound.removeEventListener(AhSoundEvent.ACTIVE_COUNT, onActiveCount);
    }
    
    public function get running():Boolean {return _running;}
    public function get color():uint {return _color;}
    public function set color(value:uint):void {_color = value;}
    public function get sound():AhSoundBase {return _sound;}
    
    private function onUpdate(e:Event):void {update();}
    private function onActive(e:AhSoundEvent):void {active();}    
    private function onActiveCount(e:AhSoundEvent):void {activeCount();}
    
    public function update():void {}    
    public function active():void {}    
    public function activeCount():void {}    
}

/**
 * 最初に流れる 「あ」のテーマ の文字
 */
class ThemeOfAh extends DisplayPanel {
    
    private const FONT_SIZE:int = 50;
    private const AH_SIZE:int = 80;
    
    public function ThemeOfAh(lines:Vector.<Line>, leftText:String, rightText:String) {
        super(null, lines, null);
        
        var lt:TextField = new TextField();
        lt.autoSize = TextFieldAutoSize.LEFT;
        lt.selectable = false;
        lt.defaultTextFormat = new TextFormat(DesignAh.FONT_NAME, FONT_SIZE, 0xffffff);
        lt.text = leftText;
        lt.y = this.height / 2 - lt.height / 2;
        addChild(lt);
        
        var ah:Shape = new Shape();
        for (var i:int = 0; i < lines.length; i++) {
            var l:Line = lines[i];
            l.normalize();
            l.denormalize(new Rectangle(0, 0, AH_SIZE, AH_SIZE));
            
            ah.graphics.lineStyle(5, 0xffffff, 1, false, LineScaleMode.NORMAL, CapsStyle.SQUARE, JointStyle.BEVEL);
            ah.graphics.moveTo(l.get(0).x, l.get(0).y);
            for (var j:int = 0; j < l.length; j++) {
                ah.graphics.lineTo(l.get(j).x, l.get(j).y);
            }
        }
        ah.x = lt.x + lt.width;
        ah.y = this.height / 2 - ah.height / 2;
        addChild(ah);
        
        var rt:TextField = new TextField();
        rt.autoSize = TextFieldAutoSize.LEFT;
        rt.selectable = false;
        rt.defaultTextFormat = new TextFormat(DesignAh.FONT_NAME, FONT_SIZE, 0xffffff);
        rt.text = rightText;
        rt.x = ah.x + AH_SIZE;
        rt.y = this.height / 2 - rt.height / 2;
        addChild(rt);
        
        if (Capabilities.os.indexOf("Mac") != -1) {
            lt.y += 4;
            rt.y += 4;
        }
    }
}

/**
 * 円がランダムで飛んでいくアニメーションのパネル
 */
class FlyingCircle extends DisplayPanel {
    
    private const RANDOM_DIST:Number = 4;
    
    private var _circles:Vector.<Circle>;
    
    public function FlyingCircle(container:Stage, lines:Vector.<Line>, sound:AhSoundBase) {
        super(container, lines, sound);

        _circles = new Vector.<Circle>();
        
        for (var i:int = 0; i < lines.length; i++) {
            lines[i].optimize();
            for (var j:int = 0; j < lines[i].length; j++) {
                var p:Point = lines[i].get(j);
                var circle:Circle = new Circle(p.x, p.y, 3 + Math.random() * 8, Math.random() * 2 * Math.PI, this.graphics);
                _circles.push(circle);
            }
        }        
        
    }

    override public function update():void {
        graphics.clear();
        graphics.beginFill(color);
        
        var circle:Circle;
            
        for (var i:int = 0; i < _circles.length; i++) {
            circle = _circles[i];
            
            if (!Tweener.isTweening(circle)){                
                circle.angle += Math.random() * 2 - 1;
                circle.x += Math.random() * RANDOM_DIST * Math.sin(circle.angle);
                circle.y += Math.random() * RANDOM_DIST * Math.cos(circle.angle);
                circle.size -= (circle.size - circle.initSize) / 10;
            }
            
            circle.update();
        }
    }
    
    override public function activeCount():void {
        graphics.clear();
        graphics.beginFill(color);
        
        var circle:Circle;
        
        for (var j:int = 0; j < _circles.length; j++) {
            circle = _circles[j];
            
            Tweener.addTween(circle, 
            {     x:circle.initX, 
                y:circle.initY, 
                size:circle.size  + circle.initSize * 0.5, 
                time:0.3, 
                transition:"easeOutExpo"
            } );
            
            circle.update();
        }                
    }
}

/**
 * 円
 */
class Circle {
    
    public var initX:Number;
    public var initY:Number;
    public var initSize:Number;
    
    public var x:Number;
    public var y:Number;
    public var angle:Number;
    public var size:Number;
    
    private var canvas:Graphics;
    
    public function Circle(x:Number, y:Number, size:Number, angle:Number, canvas:Graphics) {
        this.initX = x;
        this.initY = y;
        this.initSize = size;
        
        this.x = x;
        this.y = y;
        this.size = size;
        this.angle = angle;
        this.canvas = canvas;
    }
    
    public function update():void {
        canvas.drawCircle(x, y, size);
    }
}


/**
 * 「あ」の輪郭がゆれるアニメーションのパネル
 */
class Outline extends DisplayPanel {
    
    private const D:Number = 13;
    
    public function Outline(container:Stage, lines:Vector.<Line>, sound:AhSoundBase) {
        super(container, lines, sound);
        
        var newLines:Vector.<Line> = new Vector.<Line>();
        
        for (var i:int = 0; i < lines.length; i++) {
            lines[i].optimize(4);
            
            var line:Line = new Line(lines[i].region);
            newLines.push(line);
            
            var j:int;
            var p1:Point;
            var p2:Point;
            var np:Point;
            
            for (j = 0; j < lines[i].length-1; j++) {
                p1 = lines[i].get(j);
                p2 = lines[i].get(j+1);
                
                np = calcPoint(p1, p2, Math.PI/2);                
                line.add(np);
            }
            for (j = lines[i].length - 1; j > 0; j--) {
                p1 = lines[i].get(j);
                p2 = lines[i].get(j-1);
                
                np = calcPoint(p1, p2, Math.PI/2);
                
                line.add(np);
            }
        }
        this.lines = newLines;
    }
    
    private function calcPoint(p1:Point, p2:Point, rotateAngle:Number = Math.PI/2):Point {
        var dx:Number = p1.x - p2.x;
        var dy:Number = p1.y - p2.y;
        var centerP:Point = new Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
        
        var angle:Number = Math.atan2(dy, dx);
        angle += rotateAngle;
        
        centerP.x += D * Math.cos(angle);
        centerP.y += D * Math.sin(angle);
        
        return centerP;
    }
    
    override public function update():void {
        graphics.clear();
        
        var level:Number = sound.activityLevel / 100 * 80 + 2;
        var lineW:Number = sound.activityLevel / 100 * 8;
        for (var i:int = 0; i < lines.length; i++) {
            graphics.lineStyle(lineW, color);

            var first:Point = new Point(lines[i].get(0).x + Math.random() * level - level / 2, lines[i].get(0).y + Math.random() * level - level / 2);
            graphics.moveTo(first.x, first.y);

            for (var j:int = 1; j < lines[i].length; j++) {
                graphics.lineTo(lines[i].get(j).x + Math.random() * level - level / 2, lines[i].get(j).y + Math.random() * level - level / 2);
            }
            
            graphics.lineTo(first.x, first.y);
        }
    }
}

/**
 * バネの動きをするアニメーション
 */
class Spring extends DisplayPanel {
    
    private const D:Number = 13;
        
    private var springs:Vector.<SpringBall>;
    private var mouseDown:Boolean = false;
    private var turn:Boolean = false;
    
    public function Spring(container:Stage, lines:Vector.<Line>, sound:AhSoundBase) {
        super(container, lines, sound);
        
        var drawLines:Vector.<Line> = new Vector.<Line>();
        var springLines:Vector.<Line> = new Vector.<Line>();
        drawLines = new Vector.<Line>();
        
        var i:int;
        var j:int;
        
        for (i = 0; i < lines.length; i++) {
            lines[i].optimize();
            
            var springLine:Line = new Line(lines[i].region);
            springLines.push(springLine);
            var drawLine:Line = new Line(lines[i].region);
            drawLines.push(drawLine);
            
            var p1:Point;
            var p2:Point;
            var np:Point;
            var length:int = lines[i].length - 1;
            
            for (j = 0; j < length; j++) {
                p1 = lines[i].get(j);
                p2 = lines[i].get(j+1);
                
                np = calcPoint(p1, p2, Math.PI / 2);                
                springLine.add(np);
                drawLine.add(np);
                
                np = calcPoint(p1, p2, -Math.PI / 2);
                drawLine.add(np);
            }
            
            length = drawLine.length - 1;
            for (j = length; j >= 0; j -= 2) {
                np = drawLine.get(j);
                springLine.add(np);
            }
        }
        
        springs = new Vector.<SpringBall>();
        var s:SpringBall;
        for (i = 0; i < drawLines.length; i++) {
            var l:Line = drawLines[i];
            
            for (j = 0; j < l.length; j++) {
                s = new SpringBall(l.get(j));
                springs.push(s);                
            }        
        }
        
        this.lines = drawLines;    
        
        addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
        addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
        update();
    }

    private function calcPoint(p1:Point, p2:Point, rotateAngle:Number = Math.PI/2):Point {
        var dx:Number = p1.x - p2.x;
        var dy:Number = p1.y - p2.y;
        var centerP:Point = new Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
        
        var angle:Number = Math.atan2(dy, dx);
        angle += rotateAngle;
        
        centerP.x += D * Math.cos(angle);
        centerP.y += D * Math.sin(angle);
        
        return centerP;
    }
    
    override public function update():void {
        if (mouseDown) addSpring(mouseX, mouseY, turn);

        for (var i:int = 0; i < springs.length; i++) {
            var s:SpringBall = springs[i];
            s.x += Math.random() * 2 - 1;
            s.y += Math.random() * 2 - 1;
            
            s.startingX = s.initX;
            s.startingY = s.initY;
        
            s.update();
        }        
        
        updateDraw();    
    }
    
    override public function activeCount():void {
        addSpring(Math.random() * RECT_SIZE, Math.random() * RECT_SIZE, turn);
        
        updateDraw();
    }
    
    private function addSpring(x:Number, y:Number, attract:Boolean):void {
        var c:int = attract ? 1 : -1;
        
        for (var i:int = 0; i < springs.length; i++) {
            var s:SpringBall = springs[i];
            
            var dx:Number = x - s.x;
            var dy:Number = y - s.y;
            var d:Number = Math.sqrt(dx * dx + dy * dy);
            
            var f:Number = 30 / d;
            f = f > 10 ? 10 : f;
            
            s.startingX = s.x + c * dx * f;
            s.startingY = s.y + c * dy * f;
            if(f > 1 ){
                s.vx *= 1.5;
                s.vy *= 1.5;    
            }
            s.update();
        }                
    }
    
    private function onMouseDown(e:MouseEvent):void {
        mouseDown = true;    
        turn = !turn;
    }
    
    private function onMouseUp(e:MouseEvent):void {
        mouseDown = false;
    }
    
    private function updateDraw():void {
        graphics.clear();
        
        for (var i:int = 0; i < lines.length; i++) {
            var l:Line = lines[i];

            for (var j:int = 0; j < lines[i].length; j+=2) {
                if (j + 3 <= lines[i].length) {
                    graphics.beginFill(color);
                    moveTo(l.get(j));
                    lineTo(l.get(j + 1));
                    lineTo(l.get(j + 3));
                    lineTo(l.get(j + 2));
                }
            }
        }
        graphics.endFill();
    }
    
    private function moveTo(p:Point):void {
        graphics.moveTo(p.x, p.y);
    }
    
    private function lineTo(p:Point):void {
        graphics.lineTo(p.x, p.y);
    }
}

class SpringBall {
    
    private static const SPRING:Number = 0.3;
    private static const FRICTION:Number = 0.8;
    
    private var _ball:Point;
    private var _handles:Vector.<Point>;

    public var initX:Number;
    public var initY:Number;
    
    public var startingX:Number;
    public var startingY:Number;
    
    public var vx:Number = 0;
    public var vy:Number = 0;
    
    public var x:Number;
    public var y:Number;
        
    public function SpringBall(ball:Point) {
        _ball = ball;
        initX = _ball.x;
        initY = _ball.y;
        
        startingX = initX;
        startingY = initY;
        
        x = ball.x;
        y = ball.y;
    }
    
    public function get ball():Point {
        return _ball;
    }
    
    public function update():void {
        var dx:Number = startingX - x;
        var dy:Number = startingY - y;            
            
        vx += dx * SPRING;
        vy += dy * SPRING;
        
        vx *= FRICTION;
        vy *= FRICTION;
        
        _ball.x += vx;
        _ball.y += vy;
        
        x = _ball.x;
        y = _ball.y;
    }
}

/**
 * モザイクのような「あ」
 */
class Mosaic extends DisplayPanel {
    
    private var mosaics:Vector.<Vector.<MosaicCircle> >;
    private var increment:int = 1;
    private var index:int = 0;
    
    public function Mosaic(container:Stage, lines:Vector.<Line>, sound:AhSoundBase) {
        super(container, lines, sound);
        
        for (var i:int = 0; i < lines.length; i++) {
            var l:Line = lines[i];
        graphics.lineStyle(20, 0xffffff, 1, false, LineScaleMode.NORMAL, CapsStyle.SQUARE, JointStyle.BEVEL);
            graphics.moveTo(l.get(0).x, l.get(0).y);
            for (var j:int = 1; j < lines[i].length; j++) {
                graphics.lineTo(l.get(j).x, l.get(j).y);
            }
        }
        
        mosaics = new Vector.<Vector.<MosaicCircle> >();
        
        for (i = 1; i <= 64; i += i) mosaics.push(createMosaic(this, i));        
        
        graphics.clear();
    }
    
    private function createMosaic(canvas:DisplayObject, partitions:int):Vector.<MosaicCircle> {
        var points:Vector.<MosaicCircle> = new Vector.<MosaicCircle>();
        var bmd:BitmapData = new BitmapData(canvas.width, canvas.height, false, 0x00);
        bmd.draw(canvas);
        
        for (var i:int = 0; i < partitions; i++) {
            var ws:int = i * canvas.width / partitions;
            var we:int = (i + 1) * canvas.width / partitions;
            
            for (var j:int = 0; j < partitions; j++) {
                var hs:int = j * canvas.height / partitions;
                var he:int = (j + 1) * canvas.height / partitions;
                
                var count:int = 0;
                for (var width:int = ws; width < we; width++) {
                    for (var height:int = hs; height < he; height++) {
                        var color:uint = bmd.getPixel(width, height);
                        if(color >= 0xffffff) count++;
                    }
                }
                
                var total:int = (we - ws) * (he - hs);
                
                if (count / total >= 0.05) {
                    var c:MosaicCircle = new MosaicCircle((ws + we) / 2, (hs + he) / 2, (we-ws) / 2 - 1);
                    points.push(c);
                }
                
            }
        }
        
        return points;
    }
    
    public override function activeCount():void {
        graphics.clear();
        graphics.beginFill(color);

        index += increment;
        
        for (var i:int = 0; i < mosaics[index].length; i++) {
            var c:MosaicCircle = mosaics[index][i];
            graphics.drawCircle(c.x, c.y, c.radius);
        }
        
        if (index == 0 || index == mosaics.length-1) {
            increment *= -1;
        }
    }
}

class MosaicCircle {
    
    private var _x:Number;
    private var _y:Number;
    private var _radius:Number;
    
    public function MosaicCircle(x:Number, y:Number, radius:Number) {
        _x = x;
        _y = y;
        _radius = radius;
    }
    
    public function get radius():Number {return _radius;}
    public function get y():Number {return _y;}
    public function get x():Number {return _x;}
}


/*//////////////////////////////////////////////////
 * 
 * サウンドに反応した回数をカウントするクラス
 * 
/*//////////////////////////////////////////////////

/**
 * 反応した回数をカウントするパネル
 */
class ActiveCountPanel extends Sprite {
    
    private var _sound:AhSoundBase;
    
    private var _count:int = -1;
    
    private var _circles:Array /*CountCircle*/ = [];
    private var _txt:TextField;
    private var _text:String;
    
    private var _indicator:Indicator;

    private var _delay:int = 100;
    private var _delayCnt:int = 0;
    
    private var _isMic:Boolean;
    private var _initY:Number;
    
    public function ActiveCountPanel(sound:AhSoundBase, text:String = "VOICE") {
        _sound = sound;
        _text = text;
        _sound.addEventListener(AhSoundEvent.ACTIVE_COUNT, onCount);
        
        for (var i:int = 0; i < 5; i++) {
            var circle:CountCircle = new CountCircle();
            circle.x = i * (CountCircle.SIZE * 3) + CountCircle.SIZE;
            circle.y = CountCircle.SIZE / 2;
            addChild(circle);
            
            _circles[i] = circle;
        }
        
        _txt = new TextField();
        _txt.selectable = false;
        _txt.autoSize = TextFieldAutoSize.LEFT;
        _txt.defaultTextFormat = new TextFormat(DesignAh.FONT_NAME, 16, 0xffffff, true);
        _txt.mouseEnabled = false;
        _txt.x = -1;
        _txt.y = CountCircle.SIZE + 5;
        addChild(_txt);
        setText(_count);
        
        _indicator = new Indicator();
        _indicator.y = _txt.y + _txt.height + 3;
        addChild(_indicator);
        
        _isMic = sound is AhMicrophone ? true : false;
    }
    
    override public function get y():Number {
        return super.y;
    }
    
    private var first:Boolean = true;
    override public function set y(value:Number):void {
        if(first){
            _initY = value;
            first = false;
        }
        super.y = value;
    }
    
    private function setText(count:int):void {
        _txt.text = "SONG OF DESIGN AH ! \n" + _text + " : " + (count + 1) + " HITS";
    }
    
    private function onCount(e:AhSoundEvent):void {
        _count++;
        activeCircles();
        setText(_count);

        _delayCnt = getTimer();
        _indicator.active();
        
        if (_isMic) {
            Tweener.addTween(this, { y: this.y - 10, time:0.2, transition:"easeOutCubic", onComplete:function():void {
                Tweener.addTween(this, { y:_initY, time:0.4, transition:"easeOutBounce" } );
            }} );
        }
    }
    
    private function activeCircles():void {
        var l:int = _count % 6;
        if (l != _circles.length) {
            _circles[l].active();
        }else {
            for (var i:int = 0; i < _circles.length; i++ ) _circles[i].deactive();
        }            
    }
}

/**
 * ActiveCountPanelの丸
 */
class CountCircle extends Shape {
    public static const SIZE:Number = 8;
    private const ACTIVE_COLOR:uint = 0xffffff;
    private const DEACTIVE_COLOR:uint = 0x555555;
    
    public function CountCircle() {
        deactive();
    }
    
    public function active():void {
        drawCircle(ACTIVE_COLOR);
    }
    
    public function deactive():void {
        drawCircle(DEACTIVE_COLOR);
    }
    
    private function drawCircle(color:uint):void {
        graphics.clear();
        graphics.beginFill(color);
        graphics.drawCircle(0, 0, SIZE);
        graphics.endFill();
    }
}

/**
 * ActiveCountPanelの下のゲージ
 */
class Indicator extends Sprite {
    
    public static const WIDTH:Number = 5;
    public static const HEIGHT:Number = 30;
    public static const NUM:int = 10;
    
    private var _bar:Shape;
    private var _maskBar:Shape;
    private var _maskBar2:Shape;
    
    public function Indicator() {
        _bar = createBar();
        
        _maskBar = createMaskBar();
        _maskBar2 = createMaskBar();
        
        addChild(_maskBar);
        _bar.mask = _maskBar;
        
        addChild(_maskBar2);
        addChild(_bar);
    }
    
    private function createBar():Shape {
        var bar:Shape = new Shape();
        bar.graphics.beginFill(0xffffff);
        bar.graphics.drawRect(0, 0, WIDTH * NUM * 2 - WIDTH, HEIGHT);
        bar.graphics.endFill();
        bar.scaleX = 0;
        return bar;
    }
    
    private function createMaskBar():Shape {
        var maskBar:Shape = new Shape();
        maskBar.graphics.beginFill(0x555555);
        for (var i:int = 0; i < NUM; i++) {
            maskBar.graphics.drawRect(i * WIDTH * 2, 0, WIDTH, HEIGHT);
        }
        maskBar.graphics.endFill();
        return maskBar;
    }
    
    public function active():void {
        Tweener.removeTweens(_bar);
        Tweener.addTween(_bar, {scaleX:1, time:0.1,    onComplete:function():void {
                Tweener.addTween(_bar, {scaleX:0, time:0.3, transition:"easeOutCubic"} );
        }} );
    }
}

/*//////////////////////////////////////////////////
 * 
 * 文字のアニメーションクラス
 * 
/*//////////////////////////////////////////////////

/**
 * カタカタ文字を打っているようなアニメーション
 */
[Event(name = "complete", type = "flash.events.Event")]
class TypeWriterAnimation extends EventDispatcher{
    
    private static var taDic:Dictionary = new Dictionary();
    
    private var _textField:TextField;
    private var _texts:Array/*String*/;
    private var _interval:Number;
    
    private var _timer:Timer;
    
    public function TypeWriterAnimation(textField:TextField, text:String, interval:Number) {
        this._textField = textField;
        this._textField.text = "";
        
        this._texts = text.split("");
        this._interval = interval;
        
        _timer = new Timer(interval, text.length);
        _timer.addEventListener(TimerEvent.TIMER, onTick);
        _timer.addEventListener(TimerEvent.TIMER_COMPLETE, onComplete);
    }    
    
    private function onComplete(e:TimerEvent):void {
        dispatchEvent(new Event(Event.COMPLETE, false, false));
    }
    
    private function onTick(e:TimerEvent):void {
        _textField.appendText(_texts[_timer.currentCount-1]);
    }
    
    public function start():void {_timer.start();}
    
    public function stop():void {_timer.stop();}
    
    public function get running():Boolean {return _timer.running;}
    
    public static function startAnimation(textField:TextField, text:String, interval:Number, onComplete:Function = null):TypeWriterAnimation {
        if (taDic[textField]) {
            taDic[textField].stop();
        }
        
        var ta:TypeWriterAnimation = new TypeWriterAnimation(textField, text, interval);
        taDic[textField] = ta;
        ta.addEventListener(Event.COMPLETE, function(e:Event):void {
            delete taDic[textField];
            if (onComplete != null)     onComplete();
        } );
        ta.start();
        
        return ta;
    }
}

/*//////////////////////////////////////////////////
 * 
 * ボタン関係のクラス
 * 
/*//////////////////////////////////////////////////

/**
 * ボタンのベースクラス
 */
class Button extends Sprite {
    
    private var _upState:Sprite;
    private var _overState:Sprite;
    private var _downState:Sprite;
    private var _hitTestState:Sprite;
    
    public function Button() {
        buttonMode = true;
        useHandCursor = true;
        
        addEventListener(MouseEvent.MOUSE_OVER, onOver);
        addEventListener(MouseEvent.MOUSE_OUT, onOut);
        addEventListener(MouseEvent.MOUSE_UP, onUp);
        addEventListener(MouseEvent.MOUSE_DOWN, onDown);
        addEventListener(Event.ADDED, onAdded);
    }

    private function onAdded(e:Event):void {add(_upState);}
    private function onOver(e:MouseEvent):void {add(_overState);}
    private function onUp(e:MouseEvent):void {add(_upState);}
    private function onOut(e:MouseEvent):void {add(_upState);}
    private function onDown(e:MouseEvent):void {add(_downState);}
    
    private function add(state:DisplayObject):void {
        if(state) addChild(state);
        if(_hitTestState) addChild(_hitTestState);
    }    
    
    protected function get upState():Sprite {return _upState;}    
    protected function set upState(value:Sprite):void {
        add(value);        
        _upState = value;
    }
    
    protected function get overState():Sprite {return _overState;}
    protected function set overState(value:Sprite):void {
        add(value);        
        _overState = value;
    }
    
    protected function get downState():Sprite {return _downState;}
    protected function set downState(value:Sprite):void {
        add(value);                
        _downState = value;
    }
    
    protected function get hitTestState():Sprite {return _hitTestState;}
    protected function set hitTestState(value:Sprite):void {
        add(value);                
        _hitTestState = value;
        _hitTestState.alpha = 0;        
    }
}

/**
 * ナビゲーションボタン
 */
class NavigationButton extends Button {
    
    private var _text:String;
    private var _size:int;
    private var _left:Boolean;
    
    private const BUTTON_OFFSET:int = 3;
    
    private const UP_COLOR:uint = 0x888888;
    private const OVER_COLOR:uint = 0xffffff;
    
    public function NavigationButton(text:String, size:int, left:Boolean = true) {
        this._text = text;
        this._size = size;
        this._left = left;
        
        upState = createState(UP_COLOR);
        overState = createState(OVER_COLOR);
        downState = overState;
        hitTestState = createHitState();
    }
    
    private function createState(color:uint):Sprite {
        var state:Sprite = new Sprite();

        var txt:TextField = new TextField();
        txt.autoSize = TextFieldAutoSize.LEFT;
        txt.selectable = false;
        txt.defaultTextFormat = new TextFormat(DesignAh.FONT_NAME, _size, color);
        txt.text = _text;
        txt.y = -2;
        
        if (Capabilities.os.indexOf("Mac") != -1) txt.y += 4;
        
        state.addChild(txt);
        
        var mark:ButtonMark = new ButtonMark(color);
        mark.y = txt.height / 2;
        state.addChild(mark);
        
        if (_left) {
            mark.x = mark.width / 2;
            txt.x = mark.width + BUTTON_OFFSET;
        }else {
            mark.scaleX = -1;
            mark.x = txt.width + BUTTON_OFFSET + mark.width/2;
        }
        
        return state;
    }
    
    private function createHitState():Sprite {
        var state:Sprite = createState(UP_COLOR);
        var rect:Rectangle = state.getBounds(this);
        
        var hitState:Sprite = new Sprite();
        hitState.graphics.beginFill(0);
        hitState.graphics.drawRect(0, 0, rect.width, rect.height);
        hitState.graphics.endFill();
        
        return hitState;
    }
}

/**
 * ボタンの丸
 */
class ButtonMark extends Shape {
    
    public function ButtonMark(color:uint) {
        graphics.beginFill(color);
        graphics.drawCircle(0, 0, 18);
        graphics.endFill();
        
        graphics.lineStyle(3.5, 0, 1, false, LineScaleMode.NORMAL, CapsStyle.SQUARE);
        graphics.moveTo(2, -7);
        graphics.lineTo( -5, 0);
        graphics.lineTo(2, 7);
        graphics.endFill();
    }
}

/**
 * サウンドを追加するときのボタン
 */
class AddSoundButton extends Button {
    
    public function AddSoundButton(label:String, size:int) {
        upState = createState(label, 0xffffff, size, 0xffffff, 0x0);
        overState = upState;
        downState = createState(label, 0x0, size, 0x0, 0xffffff);
        hitTestState = createState(label, 0xffffff, size, 0xffffff, 0x0);
    }
    
    private function createState(label:String, textColor:uint, textSize:int, lineColor:uint, bgColor:uint):Sprite {
        var s:Sprite = new Sprite();
        var _tf:TextField = new TextField();
        _tf.selectable = false;
        _tf.autoSize = TextFieldAutoSize.LEFT;
        _tf.mouseEnabled = false;
        _tf.defaultTextFormat = new TextFormat(DesignAh.FONT_NAME, textSize, textColor);
        _tf.text = label;
        _tf.x = 4;
        _tf.y = 2;
        s.addChild(_tf);
        s.graphics.beginFill(bgColor);
        s.graphics.lineStyle(4, lineColor, 1, false, LineScaleMode.NORMAL, CapsStyle.SQUARE);
        s.graphics.drawRect(0, 0, _tf.width+8, _tf.height+4);
        s.graphics.endFill();
        
        return s;
    }
}


/*//////////////////////////////////////////////////
 * 
 * サウンド関係のクラス
 * 
/*//////////////////////////////////////////////////

/**
 * サウンド用のイベント
 */
class AhSoundEvent extends Event {
    
    public static const ACTIVE:String = "active";
    public static const ACTIVE_COUNT:String = "activeCount";
    
    public function AhSoundEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false) {
        super(type, bubbles, cancelable);
    }
}

/**
 * サウンドのベースクラス
 */
[Event(name = "active", type = "AhSoundEvent")] 
[Event(name = "activeCount", type = "AhSoundEvent")] 
[Event(name = "complete", type = "flash.events.Event")] 
class AhSoundBase extends EventDispatcher {
    
    private var _activityThreshold:Number = 25;
    
    protected var _running:Boolean = false;
    protected var _activityLevel:Number = 0;
    private var _prevActivityLevel:Number = 0;
    
    private var _delayCnt:Number = 0;
    private var _delay:Number = 100;
    
    private var _voiceName:String;
    
    public function AhSoundBase(voiceName:String = "") {
        _voiceName = voiceName;
    }
    
    protected function sampleData():void {
        _prevActivityLevel = _activityLevel;
        setActivityLevel();

        if (activityLevel > activityThreshold) {
            dispatchEvent(new AhSoundEvent(AhSoundEvent.ACTIVE));
            
            if (_activityLevel - _prevActivityLevel > _activityThreshold) {        
                dispatchEvent(new AhSoundEvent(AhSoundEvent.ACTIVE_COUNT));
            }
        }
    }    
    
    public function start():void {}
    public function stop():void { }
    
    public function get activityLevel():Number { return _activityLevel; }
    
    protected function setActivityLevel():void {}
    
    public function get activityThreshold():Number {return _activityThreshold;}
    
    public function set activityThreshold(value:Number):void {
        if (value < 0) value = 0;
        else if (value > 100) value = 100;
        
        _activityThreshold = value;
    }
    
    public function get running():Boolean {    return _running;}
    public function get voiceName():String { return _voiceName; }
    public function set voiceName(value:String):void { _voiceName = value; }
    
}

/**
 * サウンド
 */
[Event(name = "ioError", type = "flash.events.IOErrorEvent")]
[Event(name = "progress", type = "flash.events.ProgressEvent")]
class AhSound extends AhSoundBase {
    protected var _sound:Sound;
    private var _channel:SoundChannel;
    
    private var _dummy:Sprite;
    
    public function AhSound(url:String, voiceName:String) {
        super(voiceName);
        
        if(url){
            _sound = new Sound(new URLRequest(url));
            _sound.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
            _sound.addEventListener(ProgressEvent.PROGRESS, onProgress);
            _sound.addEventListener(Event.COMPLETE, onComplete);
        }
        
        _dummy = new Sprite();
    }    
    
    private function onProgress(e:ProgressEvent):void { dispatchEvent(e);}
    private function onIOError(e:IOErrorEvent):void {dispatchEvent(e);}
    private function onComplete(e:Event):void {dispatchEvent(e);}
    
    private function onUpdate(e:Event):void {
        sampleData();
        
    }
        
    override public function start():void {
        if (_running) return;
        
        _running = true;
        
        _channel = _sound.play((_channel ? _channel.position : 0));
        _channel.addEventListener(Event.SOUND_COMPLETE, onSoundComplete);
        _sound.addEventListener(SampleDataEvent.SAMPLE_DATA, sampleData);        
        _dummy.addEventListener(Event.ENTER_FRAME, onUpdate);
    }

    override public function stop():void {
        if (!_running) return;
        
        _running = false;
        
        _channel.stop();
        _channel.removeEventListener(Event.SOUND_COMPLETE, onSoundComplete);
        _sound.removeEventListener(SampleDataEvent.SAMPLE_DATA, sampleData);        
        _dummy.removeEventListener(Event.ENTER_FRAME, onUpdate);
    }
    
    override protected function setActivityLevel():void {
        _activityLevel = _channel ? Math.max(_channel.rightPeak, _channel.leftPeak) * 100 : 0;
    }
    
    
    private function onSoundComplete(e:Event):void {
        stop();
        _channel = null;
        start();
    }
        
}

/**
 * ローカルサウンド
 */
[Event(name = "cancel", type = "flash.events.Event")]
class AhSoundLocal extends AhSound {
    private var _mp3:ClientMP3Loader;
    
    public function AhSoundLocal() {
        super(null, "");
        
        _mp3 = new ClientMP3Loader();
        _mp3.addEventListener(Event.COMPLETE, onComplete);
        _mp3.addEventListener(Event.CANCEL, onCancel);
        _mp3.load();
    }
    
    private function onCancel(e:Event):void {
        dispatchEvent(e);
    }
    
    private function onComplete(e:Event):void {
        _sound = _mp3.sound;
        voiceName = _mp3.file.name.replace(".mp3", "");
        dispatchEvent(e);
    }
}


/**
 * マイク
 */
class AhMicrophone extends AhSoundBase{    
    private var _microphone:Microphone;
    
    public function AhMicrophone() {
        super("YOUR VOICE");        

        _microphone = Microphone.getMicrophone();
        _microphone.addEventListener(StatusEvent.STATUS, micStatus);
        _microphone.setSilenceLevel(0);        
        start();
        stop();
    
    }
    
    private function micStatus(e:StatusEvent):void {
        switch(e.code){
            case "Microphone.Muted" : dispatchEvent(new Event(Event.CANCEL));  break;
            case "Microphone.Unmuted" : dispatchEvent(new Event(Event.COMPLETE)); break;
        }
    }
    
    public function get microphone():Microphone {
        return _microphone;
    }
    
    public function get muted():Boolean {
        return _microphone.muted;
    }
    
    override public function start():void {
        if (_running) return;
        
        _running = true;
        _microphone.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);        
    }
    
    private function onSampleData(e:SampleDataEvent):void {
        sampleData();
    }
    
    override public function stop():void {
        if (!_running) return;
        
        _running = false;
        _microphone.removeEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
    }
    
    override protected function setActivityLevel():void {
        _activityLevel = _microphone.activityLevel;        
    }    
}


/**
 * This loads MP3 from HDD.
 * 
 * @see http://wiki.github.com/claus/as3swf/play-mp3-directly-from-bytearray
 * @see http://github.com/claus/as3swf/raw/master/bin/as3swf.swc
 */
class ClientMP3Loader extends EventDispatcher {

    /**
     * Use this object after Event.COMPLETE.
     */
    public var sound:Sound;

    /**
     * Call this to load MP3 from HDD.
     */
    public function load ():void {
        file = new FileReference;
        file.addEventListener (Event.CANCEL, onUserCancelled);
        file.addEventListener (Event.SELECT, onFileSelected);
        file.addEventListener (Event.COMPLETE, onFileLoaded);
        file.browse ([ new FileFilter ("MP3 files", "*.mp3") ]);
    }

    public var file:FileReference;
    private function onUserCancelled (e:Event):void { dispatchEvent (new Event (Event.CANCEL)); }
    private function onFileSelected (e:Event):void { file.load (); }
    private function onFileLoaded (e:Event):void {
        // Wrap the MP3 with a SWF
        var swf:ByteArray = createSWFFromMP3 (file.data);
        // Load the SWF with Loader::loadBytes()
        var loader:Loader = new Loader();
        loader.contentLoaderInfo.addEventListener(Event.INIT, initHandler);
        loader.loadBytes(swf);
    }

    private function initHandler(e:Event):void {
        // Get the sound class definition
        var SoundClass:Class = LoaderInfo(e.currentTarget).applicationDomain.getDefinition("MP3Wrapper_soundClass") as Class;
        // Instantiate the sound class
        sound = new SoundClass() as Sound;
        // Report Event.COMPLETE
        dispatchEvent (new Event (Event.COMPLETE));
    }

    private function createSWFFromMP3(mp3:ByteArray):ByteArray
    {
        // Create an empty SWF
        // Defaults to v10, 550x400px, 50fps, one frame (works fine for us)
        var swf:SWF = new SWF();
        
        // Add FileAttributes tag
        // Defaults: as3 true, all other flags false (works fine for us)
        swf.tags.push(new TagFileAttributes());

        // Add SetBackgroundColor tag
        // Default: white background (works fine for us)
        swf.tags.push(new TagSetBackgroundColor());
        
        // Add DefineSceneAndFrameLabelData tag 
        // (with the only entry being "Scene 1" at offset 0)
        var defineSceneAndFrameLabelData:TagDefineSceneAndFrameLabelData = new TagDefineSceneAndFrameLabelData();
        defineSceneAndFrameLabelData.scenes.push(new SWFScene(0, "Scene 1"));
        swf.tags.push(defineSceneAndFrameLabelData);

        // Add DefineSound tag
        // The ID is 1, all other parameters are automatically
        // determined from the mp3 itself.
        swf.tags.push(TagDefineSound.createWithMP3(1, mp3));
        
        // Add DoABC tag
        // Contains the AS3 byte code for the document class and the 
        // class definition for the embedded sound
        swf.tags.push(TagDoABC.create(abc));
        
        // Add SymbolClass tag
        // Specifies the document class and binds the sound class
        // definition to the embedded sound
        var symbolClass:TagSymbolClass = new TagSymbolClass();
        symbolClass.symbols.push(SWFSymbol.create(1, "MP3Wrapper_soundClass"));
        symbolClass.symbols.push(SWFSymbol.create(0, "MP3Wrapper"));
        swf.tags.push(symbolClass);
        
        // Add ShowFrame tag
        swf.tags.push(new TagShowFrame());

        // Add End tag
        swf.tags.push(new TagEnd());
        
        // Publish the SWF
        var swfData:SWFData = new SWFData();
        swf.publish(swfData);
        
        return swfData;
    }
    
    private static var abcData:Array = [
        0x10, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x07, 0x6d, 0x78, 0x2e, 0x63, 0x6f, 0x72, 0x65, 
        0x0a, 0x49, 0x46, 0x6c, 0x65, 0x78, 0x41, 0x73, 0x73, 0x65, 0x74, 0x0a, 0x53, 0x6f, 0x75, 0x6e, 
        0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x0b, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x6d, 0x65, 0x64, 
        0x69, 0x61, 0x05, 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x6d, 0x78, 0x2e, 0x63, 0x6f, 0x72, 0x65, 
        0x3a, 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x00, 0x15, 0x4d, 0x50, 0x33, 
        0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6c, 0x61, 
        0x73, 0x73, 0x0a, 0x4d, 0x50, 0x33, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x0d, 0x66, 0x6c, 
        0x61, 0x73, 0x68, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x06, 0x53, 0x70, 0x72, 0x69, 
        0x74, 0x65, 0x0a, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x05, 0x43, 0x6c, 
        0x61, 0x73, 0x73, 0x2a, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 
        0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x32, 0x30, 0x30, 0x36, 0x2f, 0x66, 0x6c, 
        0x65, 0x78, 0x2f, 0x6d, 0x78, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x07, 0x56, 
        0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x06, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x07, 0x33, 0x2e, 
        0x30, 0x2e, 0x30, 0x2e, 0x30, 0x0b, 0x6d, 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 
        0x6c, 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x0c, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x65, 
        0x76, 0x65, 0x6e, 0x74, 0x73, 0x0f, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x73, 0x70, 0x61, 
        0x74, 0x63, 0x68, 0x65, 0x72, 0x0d, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4f, 0x62, 0x6a, 
        0x65, 0x63, 0x74, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4f, 
        0x62, 0x6a, 0x65, 0x63, 0x74, 0x16, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4f, 0x62, 0x6a, 
        0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x0a, 0x16, 0x01, 0x16, 
        0x04, 0x18, 0x06, 0x16, 0x07, 0x18, 0x08, 0x16, 0x0a, 0x18, 0x09, 0x08, 0x0e, 0x16, 0x14, 0x03, 
        0x01, 0x01, 0x01, 0x04, 0x14, 0x07, 0x01, 0x02, 0x07, 0x01, 0x03, 0x07, 0x02, 0x05, 0x09, 0x02, 
        0x01, 0x07, 0x04, 0x08, 0x07, 0x04, 0x09, 0x07, 0x06, 0x0b, 0x07, 0x04, 0x0c, 0x07, 0x04, 0x0d, 
        0x07, 0x08, 0x0f, 0x07, 0x04, 0x10, 0x07, 0x01, 0x12, 0x09, 0x03, 0x01, 0x07, 0x04, 0x13, 0x07, 
        0x09, 0x15, 0x09, 0x08, 0x02, 0x07, 0x06, 0x16, 0x07, 0x06, 0x17, 0x07, 0x06, 0x18, 0x0d, 0x00, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x05, 0x00, 0x02, 0x00, 0x02, 0x03, 0x09, 0x03, 0x01, 
        0x04, 0x05, 0x00, 0x05, 0x02, 0x09, 0x05, 0x00, 0x08, 0x00, 0x06, 0x07, 0x09, 0x07, 0x00, 0x0b, 
        0x01, 0x08, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x04, 0x01, 0x0a, 0x06, 0x01, 0x0b, 0x11, 0x01, 
        0x07, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x01, 0x0c, 0x06, 0x00, 0x00, 0x08, 0x08, 0x03, 0x01, 0x01, 
        0x04, 0x00, 0x00, 0x06, 0x01, 0x02, 0x04, 0x00, 0x01, 0x09, 0x01, 0x05, 0x04, 0x00, 0x02, 0x0c, 
        0x01, 0x06, 0x04, 0x01, 0x03, 0x0c, 0x00, 0x01, 0x01, 0x01, 0x02, 0x03, 0xd0, 0x30, 0x47, 0x00, 
        0x00, 0x01, 0x00, 0x01, 0x03, 0x03, 0x01, 0x47, 0x00, 0x00, 0x03, 0x02, 0x01, 0x01, 0x02, 0x0a, 
        0xd0, 0x30, 0x5d, 0x04, 0x20, 0x58, 0x00, 0x68, 0x01, 0x47, 0x00, 0x00, 0x04, 0x02, 0x01, 0x05, 
        0x06, 0x09, 0xd0, 0x30, 0x5e, 0x0a, 0x2c, 0x11, 0x68, 0x0a, 0x47, 0x00, 0x00, 0x05, 0x01, 0x01, 
        0x06, 0x07, 0x06, 0xd0, 0x30, 0xd0, 0x49, 0x00, 0x47, 0x00, 0x00, 0x06, 0x02, 0x01, 0x01, 0x05, 
        0x17, 0xd0, 0x30, 0x5d, 0x0d, 0x60, 0x0e, 0x30, 0x60, 0x0f, 0x30, 0x60, 0x03, 0x30, 0x60, 0x03, 
        0x58, 0x01, 0x1d, 0x1d, 0x1d, 0x68, 0x02, 0x47, 0x00, 0x00, 0x07, 0x01, 0x01, 0x06, 0x07, 0x03, 
        0xd0, 0x30, 0x47, 0x00, 0x00, 0x08, 0x01, 0x01, 0x07, 0x08, 0x06, 0xd0, 0x30, 0xd0, 0x49, 0x00, 
        0x47, 0x00, 0x00, 0x09, 0x02, 0x01, 0x01, 0x06, 0x1b, 0xd0, 0x30, 0x5d, 0x10, 0x60, 0x0e, 0x30, 
        0x60, 0x0f, 0x30, 0x60, 0x03, 0x30, 0x60, 0x02, 0x30, 0x60, 0x02, 0x58, 0x02, 0x1d, 0x1d, 0x1d, 
        0x1d, 0x68, 0x05, 0x47, 0x00, 0x00, 0x0a, 0x01, 0x01, 0x08, 0x09, 0x03, 0xd0, 0x30, 0x47, 0x00, 
        0x00, 0x0b, 0x02, 0x01, 0x09, 0x0a, 0x0b, 0xd0, 0x30, 0xd0, 0x60, 0x05, 0x68, 0x08, 0xd0, 0x49, 
        0x00, 0x47, 0x00, 0x00, 0x0c, 0x02, 0x01, 0x01, 0x08, 0x23, 0xd0, 0x30, 0x65, 0x00, 0x60, 0x0e, 
        0x30, 0x60, 0x0f, 0x30, 0x60, 0x11, 0x30, 0x60, 0x12, 0x30, 0x60, 0x13, 0x30, 0x60, 0x07, 0x30, 
        0x60, 0x07, 0x58, 0x03, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x68, 0x06, 0x47, 0x00, 0x00
    ];

    private static function abcDataToByteArray():ByteArray {
        var ba:ByteArray = new ByteArray();
        for (var i:uint = 0; i < abcData.length; i++) {
            ba.writeByte(abcData[i]);
        }
        return ba;
    }
    
    private static var abc:ByteArray = abcDataToByteArray();
}