forked from: forked from: Sound Font

by Leandro.Moreno forked from forked from: Sound Font (diff: 6)
...
@author mattodesign

音素材は友人にもらいました。
http://www.myspace.com/vancouvered

import com.flashdynamix.utils.SWFProfiler;
♥0 | Line 175 | Modified 2011-10-21 11:32:03 | MIT License
play

ActionScript3 source code

/**
 * Copyright Leandro.Moreno ( http://wonderfl.net/user/Leandro.Moreno )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/lm2O
 */

// forked from akisute's forked from: Sound Font
// forked from mattodesign's Sound Font
/**
 * ...
 * @author mattodesign
 * 
 * 音素材は友人にもらいました。
 * http://www.myspace.com/vancouvered
 * 
 */

package 
{
    import flash.ui.Mouse;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.filters.*;
    import flash.geom.ColorTransform;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.net.URLRequest;
    import flash.text.*;
    import flash.media.*;
    import flash.utils.ByteArray;
    import flash.utils.Timer;
    import flash.system.Security;
    
    //import com.flashdynamix.utils.SWFProfiler;
    
    [SWF(backgroundColor = 0x000000, width = "465", height = "465", frameRate = 60)]
    
    public class SoundFont extends Sprite 
    {
        private var _bmd:BitmapData;
        private var _tf:TextField;
        private var _btn:Sprite;
        private var _canvas:BitmapData;
        private var _pt:Point;
        private var _filter:GlowFilter;
        private var _outputSound:Sound;
        private var _cannel:SoundChannel;
        private var _sourceSound:Sound;
        private var _particleArray:Array;
        private const STAGE_WIDTH:int = stage.stageWidth;
        private const STAGE_HEIGHT:int = stage.stageHeight;
        private const COLOR_TRANSFORM:ColorTransform = new ColorTransform(1, 1, 1, 0.45, 0, 0, 0, 0);
        
        //========================================================================
        // コンストラクタ
        //========================================================================
        public function SoundFont():void 
        {
            // プロファイラの表示
            //SWFProfiler.init(stage, this);
            
            // 初期化
            init();
            
            // テキストフィールドを配置
            setText();
            
            // ボタンを配置
            setBtn();
        }
        
        //========================================================================
        // 初期化処理
        //========================================================================
        private function init():void
        {
            // 描画用のビットマップデータを作成
            _canvas = new BitmapData(STAGE_WIDTH, STAGE_HEIGHT, true, 0x00FFFFFF);
            _pt = new Point(0, 0);
            _filter = new GlowFilter(0xFFFFFF, 0.8, 10, 10, 1, BitmapFilterQuality.MEDIUM, false, false);
            _canvas.applyFilter(_canvas, _canvas.rect, _pt, _filter);
            addChild(new Bitmap(_canvas));
            
            // 一時格納用のビットマップデータを作成
            _bmd = new BitmapData(STAGE_WIDTH, STAGE_HEIGHT, false, 0x000000);
            
            // 音を読み込み
            // ※crossdomain.xmlなしでも動くかテスト、SoundLoaderContext(false)を使う
            //Security.loadPolicyFile("http://mattodesign.com/crossdomain.xml");
            _sourceSound = new Sound();
            var context:SoundLoaderContext = new SoundLoaderContext(1000, false);
            _sourceSound.load(new URLRequest("http://clockmaker.jp/labs/081031_pv3d_visualizer/bin/music.mp3"),context);
            _cannel = new SoundChannel();
            _cannel = _sourceSound.play(0,100);
        }
        
        //========================================================================
        // テキストフィールドをステージに生成
        // 文字数が多すぎると(多分)ステージサイズの関係でエラーとなります
        //========================================================================
        private function setText():void
        {
            _tf = new TextField();
            _tf.border = true;
            _tf.borderColor = 0x00AAFF;
            _tf.background = true;
            _tf.backgroundColor = 0x2D2D2D;
            _tf.alpha = 0.5;
            _tf.text = "Wonderfl";
            _tf.width = 240;
            _tf.height = 22;
            _tf.x = 90;
            _tf.y = STAGE_HEIGHT - 30;
            _tf.type = TextFieldType.INPUT;
            _tf.setTextFormat(new TextFormat("_sans", 15, 0xFFFFFF));
            
            addChild(_tf);
            onClickToBmp();
            
            // フォーカス時にテキストを消すイベント
            _tf.addEventListener(MouseEvent.CLICK, onFocus);
        }
        
        //========================================================================
        // テキストフィールドへのフォーカス時にテキストを消す
        //========================================================================
        private function onFocus(e:MouseEvent):void
        {
            e.target.text = "";
            _bmd.fillRect(_bmd.rect, 0x000000);
            _canvas.fillRect(_canvas.rect, 0x000000);
        }
        
        //========================================================================
        // ボタン作成
        //========================================================================
        private function setBtn():void
        {
            _btn = new Sprite();
            _btn.graphics.beginFill(0x00AAFF);
            _btn.graphics.drawRect(0, 0, 30, _tf.height);
            _btn.graphics.endFill();
            _btn.x = _tf.x + _tf.width + 10;
            _btn.y = _tf.y;
            addChild(_btn);
            
            var tf:TextField = new TextField();
            tf.text = "OK";
            tf.selectable = false;
            tf.autoSize = TextFieldAutoSize.LEFT;
            tf.x = _btn.width / 2 - tf.width / 2;
            tf.y = _btn.height / 2 - tf.height / 2;
            tf.setTextFormat(new TextFormat("_sans", null, 0xFFFFFF, true));
            _btn.addChild(tf);
            _btn.buttonMode = true;
            _btn.mouseChildren = false;
            
            // ボタンを押すとテキストをビットマップ化
            _btn.addEventListener(MouseEvent.CLICK, onClickToBmp);
        }
        
        //========================================================================
        // ビットマップへの変換
        //========================================================================
        private function onClickToBmp():void
        {
            // テキストが未入力の場合は"文字を入力してください"を表示
            if (_tf.length == 0)
            {
                _tf.text = "Wonderfl";
            }
            
            // 入力したテキストをビットマップ変換用のテキストフィールドに入れる
            var tf:TextField = new TextField();
            tf.text = _tf.text;
            tf.autoSize = TextFieldAutoSize.LEFT;
            tf.setTextFormat(new TextFormat("_sans", 10, 0xFFFFFF));
            
            // 入力したテキストを一時格納用ビットマップデータにdraw
            var matScale:Number = 50 / tf.length;
            var mat:Matrix = new Matrix(matScale, 0, 0, matScale, (STAGE_WIDTH - tf.width * matScale) >> 1, (STAGE_HEIGHT - tf.height * matScale) >> 1);
            _bmd.draw(tf, mat);
            
            // ビットマップの各ピクセルの色を走査
            _particleArray = new Array();
            var margin:int = 2;
            for (var i:int = 0; i < _canvas.width; i = i + margin)
            {
                for (var j:int = 0; j < _canvas.height; j = j + margin)
                {
                    if (_bmd.getPixel(i, j) != 0x000000)
                    {
                        var p:Particle = new Particle();
                        p.x = i;
                        p.y = j;
                        p.c = 0xFF00AAFF;
                        _particleArray.push(p);
                    }
                }
            }
            
            // タイマーイベントで音の波形を取得するループ処理
            var timer:Timer = new Timer(1);
            timer.addEventListener(TimerEvent.TIMER, loop);
            timer.start();
        }
        
        //========================================================================
        // ループ処理
        //========================================================================
        private function loop(e:TimerEvent):void
        {
            const PLOT_HEIGHT:int = STAGE_HEIGHT/2;
            const CHANNEL_LENGTH:int = 256;
            const BUFFER_LENGHT:Number = 4096;
            var alpha:Number = 0.1;
            var bytes:ByteArray = new ByteArray();
            var xrf:Number;
            var yrf:Number;
            var n:Number = 0;
            var p:Particle;
            var setX:Number;
            var setY:Number;
            
            // 波形データを取得
            SoundMixer.computeSpectrum(bytes, false, 0);
            
            // 波形データをパーティクルの動きに変換
            _canvas.lock();
            _canvas.colorTransform(_canvas.rect, COLOR_TRANSFORM);
            _canvas.applyFilter(_canvas, _canvas.rect, _pt, _filter);
            
            for (var i:int = 0; i < CHANNEL_LENGTH; i++)
            {
                xrf = bytes.readFloat();
                yrf = bytes.readFloat();
                
                for (i = 0; i < _particleArray.length; i++)
                {
                    p = _particleArray[i];
                    setX = p.x + Math.round(xrf * Math.random() * 300);
                    setY = p.y + Math.round(yrf * Math.random() * 300);
                    _canvas.setPixel32(setX, setY, p.c);
                }
            }
            _canvas.unlock();
        }    
    }
}

//========================================================================
// Particleクラス
//========================================================================
class Particle {
    public var x:Number = 0;
    public var y:Number = 0;
    public var c:int = 0;

    public function Particle()
    {
        
    }
}