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

forked from: FONT DANCE

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

// forked from enok's FONT DANCE
// forked from enok's DON forked from: Saqoosha challenge for professionals
// 音に反応するフォント FontDance
// 音が出るので注意して下さい
// http://linkalink.jp/enok/?p=650

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 = "醉解心语";
	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://qzone.net.cn/293299/醉解心语1z.mp3");
	//private var _urlReq:URLRequest = new URLRequest("http://qzone.net.cn/293299/醉解心语1z.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) { 
			//音の全データを一括で取得 extractなしでもいけるけど、テストも兼ねて
			_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) { 
			//現在の音を取得するパターン、何故かビットレートが早くなってしまう extractなしでもいけるけど、テストも兼ねて
			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));
	}
}