/** * ... * @author mattodesign * * 音素材は友人にもらいました。 * http://www.myspace.com/vancouvered * */ package { 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); // 音を読み込み Security.loadPolicyFile("http://mattodesign.com/crossdomain.xml"); _sourceSound = new Sound(); var context:SoundLoaderContext = new SoundLoaderContext(1000, true); _sourceSound.load(new URLRequest("http://mattodesign.com/wonderfl/soundfont/sound.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); // フォーカス時にテキストを消すイベント _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(e:MouseEvent):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() { } } Sound Font