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

DON forked from: Saqoosha challenge for professionals

音に反応するフォント FontDance
音が出るので注意して下さい
http://linkalink.jp/enok/?p=650
/**
 * Copyright linktale ( http://wonderfl.net/user/linktale )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/hTIz
 */

// 音に反応するフォント FontDance
// 音が出るので注意して下さい
// http://linktale.net/

package {
    import flash.display.Sprite; 
    import flash.display.StageQuality;
    import com.flashdynamix.utils.SWFProfiler;
    
    [SWF(backgroundColor="0xffffff", frameRate="30")] 

    public class FontDanceController extends Sprite { 
        public function FontDanceController():void {
            //SWFProfiler.init(stage, this);
            stage.quality = StageQuality.HIGH;
            
            //背景をしく
            graphics.beginFill(0x151515);
            graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
            graphics.endFill();
            //配置
            var trick:FontDance = new FontDance(this);
            addChild(trick);
        } 
    } 
}

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.DisplayObjectContainer;
import flash.display.GradientType;
import flash.display.SpreadMethod;
import flash.display.Sprite;
import flash.events.Event;
import flash.filters.ConvolutionFilter;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.media.SoundMixer;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.utils.ByteArray;
class FontDance extends Sprite {
    //この2つを設定すると色々な文字で同じ演出が可能
    //protected const TARGET_TEXT:String = "WONDERFL";
    //protected const SCALE:Number = 0.7; //文字大きさ(調整用)
    protected const TARGET_TEXT:String = "DON";
    protected const SCALE:Number = 1.0; //文字大きさ(調整用)
    
    protected var _s:DisplayObjectContainer;
    protected var _centerX:Number; //中心X
    protected var _centerY:Number; //中心Y
    
    protected var _soundM:soundManager;
    protected var _view:Sprite = new Sprite();
    protected var _pointList:Vector.<Point> = new Vector.<Point>(); //文字のアウトラインのポイント
    protected var _distList:Vector.<Number> = new Vector.<Number>(); //ポイントの真ん中からの距離
    protected var _radiusList:Vector.<Number> = new Vector.<Number>(); //ポイントの半径の長さ
    protected var _colorList:Vector.<uint> = new Vector.<uint>(); //ポイントの色
    protected var _colorPattern:Vector.<uint> = new Vector.<uint>(); //色パターン
    protected var _pointViewList:Vector.<Sprite> = new Vector.<Sprite>(); //各ポイントのビュー
        
    public function FontDance(s:DisplayObjectContainer):void {
        _s = s;
        //中点
        _centerX = s.stage.stageWidth / 2;
        _centerY = s.stage.stageHeight / 2;
        
        init();
    }
    
    protected function init():void {
        setColor(); //色初期化
        setPoint(); //文字アウトラインポイント初期化
        
        _soundM = new soundManager(false, true);
        
        //addChild(_view);
        _soundM.addEventListener(soundManager.SAMPLE_DATA, processSound);
        _soundM.addEventListener(soundManager.COMPLETE, complete);
        addEventListener(Event.ENTER_FRAME, update);
    }
    
    protected function setColor():void {
        //色設定
        _colorPattern.push(0x444444);
        _colorPattern.push(0x555555);
        _colorPattern.push(0x666666);
    }

    protected function setPoint():void {
        //テキスト設置
        var txt:TextField = new TextField();
        var tf:TextFormat = new TextFormat("_sans", 100);
        txt.defaultTextFormat = tf;
        txt.autoSize = TextFieldAutoSize.LEFT;
        txt.text = TARGET_TEXT;

        //ビットマップ設置
        var txtBmpData:BitmapData = new BitmapData( txt.width,  txt.height, true, 0xffffffff);
        txtBmpData.draw(txt);
        //文字のエッジ検出
        var cf : ConvolutionFilter = new ConvolutionFilter(3, 3, [-1, -1, -1, -1, 8, -1, -1, -1, -1]);
        txtBmpData.applyFilter(txtBmpData, txtBmpData.rect, new Point(), cf); 
        var txtBmp:Bitmap = new Bitmap(txtBmpData);
        //addChild(txtBmp);
        
        //ポイント設置
        var offset:Point = new Point(_centerX - txt.textWidth / 2, _centerY - txt.textHeight / 2);
        var p:Point, sp:Sprite;
        for ( var i:int = 0; i < txtBmpData.width; i++ ) {
            for ( var j:int = 0; j < txtBmpData.height; j++ ) {
                if (txtBmpData.getPixel(i, j) == 0xffffff) {
                    //初期化
                    _pointList.push(new Point(i, j).add(offset));
                }
            }
        }
        
        //ランダムに減らす
        var tmpList:Vector.<Point> = new Vector.<Point>();
        while (_pointList.length>512) {
            i = Math.floor(Math.random() * _pointList.length);
            tmpList = _pointList.slice(0, i);
            tmpList = tmpList.concat(_pointList.slice(i+1));
            _pointList = tmpList.slice();
        }
        
        for each(p in _pointList) {
            _distList.push(0.0);
            _radiusList.push(3.0);
            _colorList.push(_colorPattern[Math.floor(Math.random() * _colorPattern.length)]);
            
            sp = new Sprite();
            sp.blendMode = BlendMode.ADD; //ブレンドモードオン
            _pointViewList.push(addChild(sp) as Sprite);
        }
        
    }

    protected function processSound(e:Event):void {
         setSoundData();
    }
    
    private function setSoundData():void {
        var bytes:ByteArray = new ByteArray();
        const CHANNEL_LENGTH:int = 256;

        //stretchFactor高めに設定
        SoundMixer.computeSpectrum(bytes, true, 64);
        
        //左チャンネル
        for (var i:int = 0; i < CHANNEL_LENGTH; i++) {
            var val:Number = bytes.readFloat();
            _distList[i] = val * 0.01; //距離設定
            _radiusList[i] = val * 8 + 2; //半径設定
        }
        
        //右チャンネル
        for (i = CHANNEL_LENGTH; i > 0; i--) {
            val = bytes.readFloat();
            _distList[255 + i] = val * 0.01; //距離設定
            _radiusList[255 + i] = val * 8 + 2; //半径設定
        }
    }
    
    protected function complete(e:Event):void {
        trace("complete");
         _soundM.removeEventListener(soundManager.SAMPLE_DATA, processSound);
         removeEventListener(Event.ENTER_FRAME, update);
    }
    
    protected function update(e:Event):void {
        var xx:Number, yy:Number;
        var p:Point, mat:Matrix = new Matrix();;
        
        //_view.graphics.clear();
        for (var i:int=0; i < _pointList.length; i++ ) {
            p = _pointList[i];
            xx = (p.x - _centerX) * SCALE + _centerX;
            yy = (p.y - _centerY) * SCALE + _centerY;
            xx = (p.x - _centerX) * SCALE + _centerX;
            yy = (p.y - _centerY) * SCALE + _centerY;
            xx - _centerX > 0 ? xx += Math.pow(xx - _centerX, 2) * _distList[i] : xx -= Math.pow(xx - _centerX, 2) * _distList[i];
            yy - _centerY > 0 ? yy += Math.pow(yy - _centerY, 2) * _distList[i] * 2 : yy -= Math.pow(yy - _centerY, 2) * _distList[i] * 2;
            xx = xx - _radiusList[i] / 2;
            yy = yy - _radiusList[i] / 2;
            
            mat.createGradientBox(_radiusList[i] * 2, _radiusList[i] * 2, 0, -_radiusList[i], -_radiusList[i]);
            _pointViewList[i].graphics.clear();
            //見た目の演出
            _pointViewList[i].graphics.beginGradientFill(
                GradientType.RADIAL, [_colorList[i] , 0x222222], [1, 0.1], [0xAA, 0xFF], mat, SpreadMethod.REFLECT);
            _pointViewList[i].graphics.drawCircle(xx, yy, _radiusList[i]);
            //_view.graphics.drawCircle(xx, yy, _radiusList[i]);
        }
    }    
}

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.SampleDataEvent;
import flash.media.Sound;
import flash.media.SoundMixer;
import flash.net.URLRequest;
import flash.utils.ByteArray;

class soundManager extends EventDispatcher { 
    public static const COMPLETE:String = "COMPLETE";
    public static const SAMPLE_DATA:String = "SAMPLE_DATA"; //ディスパッチャ用
    private const TYPE:uint = 1;
    private const SOUND_SAMPLING_RATE:Number = 44.1; //サンプリングレート
    private const SOUND_BUFFER_LENGTH:Number = 2048; //サウンドの取得バッフャ数

    private var _sourceSnd:Sound; //元音源
    private var _outputSnd:Sound; //コピー音源
    private var _urlReq:URLRequest = new URLRequest("http://linkalink.jp/enok/wonderfl/font_dance/1.mp3");
    //private var _urlReq:URLRequest = new URLRequest("http://techno.to/sound/COR020-2/1.mp3");

    private var _soundBytes:ByteArray;
    private var _soundBytesPosition:uint;
    private var _soundBytesTotal:uint;

    private var _repeat:Boolean;
    private var _useFFTMode:Boolean;

    public function soundManager(repeat:Boolean = true, useFFTMode:Boolean=false):void {
        _repeat = repeat;
        _useFFTMode = useFFTMode;
        
        init();
        } 

    private function init():void {
        _sourceSnd = new Sound();
        _outputSnd = new Sound();
        
        _sourceSnd.load(_urlReq);
        _sourceSnd.addEventListener(Event.COMPLETE, loadSoundComplete);
    }

    private function loadSoundComplete(e:Event):void {
        _sourceSnd.removeEventListener(Event.COMPLETE, loadSoundComplete);
        //trace(_sourceSnd.length, _sourceSnd.length * SOUND_SAMPLING_RATE, _sourceSnd.length * SOUND_SAMPLING_RATE * 8);
        
        if (TYPE == 1) { 
            //音の全データを一括で取得
            _soundBytes = new ByteArray();
            _sourceSnd.extract(_soundBytes, _sourceSnd.length * SOUND_SAMPLING_RATE * 8);
            _soundBytesTotal = _soundBytes.length;
            _soundBytesPosition = 0;
        }
        
        _outputSnd = new Sound();
        _outputSnd.addEventListener(SampleDataEvent.SAMPLE_DATA, processSound);
        _outputSnd.play();
    }

    private function processSound(e:SampleDataEvent):void {
        var end:Boolean = false;
        if (TYPE == 1) { 
            for (var i:uint = 0; i < SOUND_BUFFER_LENGTH; ++i) {
                
                if(_soundBytesPosition > _soundBytesTotal - 8){
                    if (_repeat) {
                         _soundBytesPosition -= _soundBytesTotal;
                    }else {
                        _outputSnd.removeEventListener(SampleDataEvent.SAMPLE_DATA, processSound);
                        end = true;
                        dispatchEvent(new Event(COMPLETE));
                        break;
                    }
                }
                if(!end){
                    _soundBytes.position = _soundBytesPosition;
                    e.data.writeFloat( _soundBytes.readFloat() / 8 );
                    e.data.writeFloat( _soundBytes.readFloat() / 8 );
                
                    _soundBytesPosition += 8;
                }
            }
        }else if (TYPE == 2) { 
            //現在の音を取得するパターン、何故かビットレートが早くなってしまう
            var bytes:ByteArray = new ByteArray();
            _sourceSnd.extract(bytes, 512 * 8);
                
            bytes.position = 0;
            var cnt:uint = 0;
            while (bytes.bytesAvailable > 0) {        
                e.data.writeFloat(bytes.readFloat());
                e.data.writeFloat(bytes.readFloat());
                if (bytes.bytesAvailable > 0){
                    bytes.position += 8;
                }
                cnt++;
            }
        }
        
        dispatchEvent(new Event(SAMPLE_DATA));
    }
}