Flash Music Player(エフェクト5個)
Windows Media Player のような感じにしてみる。
effects に 自分で作った EffectBase を継承したクラスを追加する。
classList に Class を追加すると中からランダムに選ばれて表示みたいな感じ。
クリックでエフェクトが変わるよ!
時々セキュリティエラーが出る・・・。何とかしないと。
Music by clockmaker 様
@author jc at bk-zen.com
どんどん Fork して追加してってくださいw
// forked from bkzen's Flash Music Player(Effectメイン)
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundLoaderContext;
import flash.media.SoundMixer;
import flash.media.SoundTransform;
import flash.net.URLRequest;
import flash.system.Security;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.utils.ByteArray;
/**
* Windows Media Player のような感じにしてみる。
* effects に 自分で作った EffectBase を継承したクラスを追加する。
* classList に Class を追加すると中からランダムに選ばれて表示みたいな感じ。
* クリックでエフェクトが変わるよ!
* 時々セキュリティエラーが出る・・・。何とかしないと。
* Music by clockmaker 様
* @author jc at bk-zen.com
* どんどん Fork して追加してってくださいw
*/
[SWF(width = "465", height = "465", backgroundColor = "0x000000", frameRate = "30")]
public class Player extends Sprite
{
private var classList: Array = [EffectA, EffectB, EffectA_A, EffectC, NightViewEffect]; /* of extends EffectBase */
private var effects: Array = [];
private const maxCnt: int = 150;
private var w: int;
private var h: int;
private var cnt: int;
private var effectCount: int;
private var byte: ByteArray;
private var nowEffect: EffectBase;
private var nowEffectNum: int;
private var bmp: Bitmap;
private var bmd: BitmapData;
private var sound: Sound;
private var soundTf: SoundTransform;
private var soundCh: SoundChannel;
private var soundContext: SoundLoaderContext;
private var compEffectCount: int;
private var txt: TextField;
/**
* ベースのプレイヤー、音楽とかの制御をする。
*/
public function Player()
{
super();
Security.loadPolicyFile("http://clockmaker.jp/crossdomain.xml");
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
/**
* 初期化
* @param e : <Event (default = null)>
*/
private function init(e: Event = null): void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
//
w = stage.stageWidth;
h = stage.stageHeight;
sound = new Sound();
bmd = new BitmapData(w, h, true, 0xFF000000);
bmp = new Bitmap(bmd);
byte = new ByteArray();
txt = new TextField();
txt.autoSize = TextFieldAutoSize.LEFT;
txt.scaleX = txt.scaleY = 3;
txt.textColor = 0xFFFFFF;
txt.text = "Now Loading...";
txt.x = (stage.stageWidth - txt.width) >> 1;
txt.y = (stage.stageHeight - txt.height) >> 1;
effectCount = classList.length;
makeEffects();
//nowEffectNum = Math.random() * effectCount;
nowEffectNum = 4;
nowEffect = effects[nowEffectNum];
sound.addEventListener(Event.COMPLETE, onComp);
soundContext = new SoundLoaderContext();
soundContext.checkPolicyFile = true;
// sound.load(new URLRequest("http://clockmaker.jp/labs/081031_pv3d_visualizer/bin/music.mp3"), soundContext);
sound.load(new URLRequest("http://clockmaker.jp/labs/081031_pv3d_visualizer/bin/music.mp3"));
addChild(bmp);
addChild(txt);
stage.addEventListener(MouseEvent.CLICK, onClick);
}
/**
* Effectレンダリング
* @param e : <Event>
*/
private function onEnter(e: Event): void
{
try
{
SoundMixer.computeSpectrum(byte, nowEffect.mode, nowEffect.stretchFactor);
bmd.lock();
nowEffect.render(byte, stage.mouseX, stage.mouseY);
bmd.unlock();
}
catch (e:Error)
{
}
cnt += int(Math.random() * 2);
if (cnt > maxCnt)
{
onClick();
}
}
/**
* effect class のインスタンスを作る。
*/
private function makeEffects(): void
{
var clazz: Class;
var eff: EffectBase;
while (classList.length > 0)
{
clazz = classList.shift();
eff = new clazz();
eff.eventDispatcher.addEventListener(Event.COMPLETE, onCompEffect);
eff.init(w, h);
effects.push(eff);
}
}
private function onCompEffect(e:Event):void
{
e.target.removeEventListener(Event.COMPLETE, onCompEffect);
compEffectCount++;
check();
}
private function check():void
{
if (compEffectCount == effectCount && sound.bytesLoaded == sound.bytesTotal && sound.bytesTotal != 0)
{
soundCh = sound.play(0, 999);
soundTf = soundCh.soundTransform;
soundTf.volume = 0.1;
soundCh.soundTransform = soundTf;
nowEffect.play(bmd);
addEventListener(Event.ENTER_FRAME, onEnter);
removeChild(txt);
}
else
{
txt.text = "Now Loading...\n" + (compEffectCount + int(sound.bytesLoaded / sound.bytesTotal)) + " / " + (effectCount + 1);
txt.x = (stage.stageWidth - txt.width) >> 1;
txt.y = (stage.stageHeight - txt.height) >> 1;
}
}
private function onComp(e:Event = null):void
{
check();
}
private function onClick(e:MouseEvent = null):void
{
// 以下エフェクト切り替え。(二つ以上は切り替えする。)
if (effects.length > 1)
{
cnt = 0;
nowEffect.end();
var nextEffectNum: int = Math.random() * effectCount;
if (nextEffectNum == nowEffectNum) nextEffectNum = (nextEffectNum == effects.length - 1 ? 0 : nextEffectNum + 1);
nowEffectNum = nextEffectNum;
nowEffect = effects[nowEffectNum];
nowEffect.play(bmd);
}
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shape;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.filters.BlurFilter;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.ByteArray;
class EffectBase
{
private var _data: BitmapData;
private var _w: int;
private var _h: int;
protected var _mode: Boolean = false;
protected var _stretchFactor: int = 0;
public var eventDispatcher: EventDispatcher;
/**
* Effect の ベースとなるクラス、これを継承して作る。
* @param mode : <Boolean (default = false)>
* @param stretchFactor : <int (default = 0)>
*/
public function EffectBase(mode: Boolean = false, stretchFactor: int = 0)
{
super();
_mode = mode;
_stretchFactor = stretchFactor;
eventDispatcher = new EventDispatcher();
}
/**
* 初期化する。
* 必要なものを作っておいたりする。
* 基本的に BitmapData はまだ作らない。
* play が呼ばれた時に作る方がよい。
* @param w : <int> 画面の幅
* @param h : <int> 画面の高さ
*/
public function init(w: int, h: int): void
{
_w = w;
_h = h;
}
/**
* 初期化が終了したら呼ぶ
*/
protected function initialized(): void
{
eventDispatcher.dispatchEvent(new Event(Event.COMPLETE));
}
/**
* エフェクトが開始される際に呼ばれる。render が呼ばれるよりも先に呼ばれる。
* @param data : <BitmapData> ここに描画する。
*/
public function play(data: BitmapData):void
{
_data = data;
}
/**
* このエフェクトが終了される際に呼ばれる。
* play 時に作成したものがあれば削除などを行う。
*/
public function end():void
{
_data = null;
}
/**
* レンダリングする (EnterFrame Event で呼ばれる) data の lock, unlock の必要はない。
* @param byte : <ByteArray> サウンドスペクトラムの ByteArray
* @param mouseX : <Number> マウスの X 座標 (たぶん使わない)
* @param mouseY : <Number> マウスの Y 座標 (たぶん使わない)
*/
public function render(byte: ByteArray, mouseX: Number, mouseY: Number): void
{
}
/**
* [read-only] 画面幅
*/
protected function get w(): int { return _w; }
/**
* [read-only] 画面高さ
*/
protected function get h(): int { return _h; }
/**
* [read-only] 画面に表示させる BitmapData
* これに描画していく。
*/
protected function get data(): BitmapData { return _data; }
/**
* [read-only] (default = false) コンストラクタで設定する。または 継承したクラスから _mode を直接変える。
* サウンドデータに対して最初にフーリエ変換を実行するかどうかを示すブール値です。
* このパラメータを true に設定すると、このメソッドは未処理のサウンド波形ではなく周波数スペクトルを返します。
* 周波数スペクトルでは、低い周波数は左側に、高い周波数は右側に表されます。
* (By livedocs)
*/
public function get mode(): Boolean { return _mode; }
/**
* [read-only] (default = 0) コンストラクタで設定する。または 継承したクラスから _stretchFactor を直接変える。
* サウンドサンプリングの解像度です。
* たとえば、stretchFactor 値に 0 を設定した場合、データは 44.1 KHz でサンプリングされ、1 の場合は 22.05 KHz、2 の場合は 11.025 KHz となります。
* (By livedocs)
*/
public function get stretchFactor(): int { return _stretchFactor; }
}
class EffectA extends EffectBase
{
private var blur: BlurFilter;
private var point: Point;
protected var max: int;
protected var rect: Rectangle;
protected var copy: BitmapData;
protected var matrix: Matrix;
public function EffectA()
{
super();
}
override public function init(w: int, h: int): void
{
super.init(w, h);
blur = new BlurFilter();
point = new Point();
max = 256;
rect = new Rectangle();
rect.width = w / max;
matrix = new Matrix(0.97, 0, 0, 0.97, (w >> 1) * 0.03, (h >> 1) * 0.03);
initialized();
}
override public function play(data: BitmapData): void
{
super.play(data);
copy = data.clone();
}
override public function end(): void
{
super.end();
copy.dispose();
copy = null;
}
override public function render(byte: ByteArray, mouseX: Number, mouseY: Number): void
{
var i: int;
var n: Number;
var size: int;
var color: uint;
while (i ++ < max)
{
n = byte.readFloat();
size = Math.min(h * n * 5, h);
color = 0xFF000000 | 0x33FF | ((0x3333 * n) << 8);
rect.x = i * rect.width;
rect.y = h - size;
rect.height = size;
data.fillRect(rect, color);
}
i = 0;
while (i ++ < max)
{
n = byte.readFloat();
size = Math.min(h * n * 5, h);
color = 0xFF000000 | 0xFF3300 | (0x3333 * n);
rect.y = 0;
rect.x = (max - i) * rect.width;
rect.height = size;
data.fillRect(rect, color);
}
copy.draw(data, matrix);
copy.applyFilter(copy, copy.rect, point, blur);
data.draw(copy);
}
}
class EffectB extends EffectA
{
function EffectB()
{
super();
_mode = true;
}
override public function init(w: int, h: int): void
{
super.init(w, h);
max = 32;
rect = new Rectangle();
rect.width = w / max;
initialized();
}
}
class EffectA_A extends EffectA
{
override public function init(w: int, h: int): void
{
super.init(w, h);
matrix = new Matrix(0.97, 0.03, -0.03, 0.97, w * 0.03);
initialized();
}
}
class EffectC extends EffectBase
{
private var rect: Rectangle;
private var colorTf: ColorTransform;
protected var sh: Shape;
private var color:uint;
function EffectC()
{
super(true);
}
override public function init(w: int, h: int): void
{
super.init(w, h);
rect = new Rectangle();
colorTf = new ColorTransform(1, 1, 1, 1, 0, 0, 0, -5);
initialized();
}
override public function play(data:BitmapData):void
{
super.play(data);
sh = new Shape();
color = 0x44000000 | ((Math.random() * 0x88 + 0x88) & 0xFF << 16) | ((Math.random() * 0x88 + 0x88) & 0xFF) << 8 | ((Math.random() * 0x88 + 0x88) & 0xFF);
}
override public function end():void
{
super.end();
sh.graphics.clear();
sh = null;
}
override public function render(byte: ByteArray, mouseX: Number, mouseY: Number): void
{
data.colorTransform(data.rect, colorTf);
var i: int;
var n: Number = 0;
var size: int = w >> 6;
sh.graphics.clear();
while (i++ < 32)
{
n = byte.readFloat();
sh.graphics.beginFill(downColor(color, n), 1);
sh.graphics.drawCircle(w >> 1, h >> 1, (w >> 1) - size * i);
sh.graphics.endFill();
}
data.draw(sh);
}
private function downColor(argb: uint, n: Number): uint
{
var alpha: uint = argb >> 24 & 0xFF;
var r: uint = argb >> 16 & 0xFF;
var g: uint = argb >> 8 & 0xFF;
var b: uint = argb & 0xFF;
return (alpha << 24) | (((r * n) & 0xFF) << 16) | (((g * n) & 0xFF) << 8) | ((b * n) & 0xFF);
}
}
class NightViewEffect extends EffectBase
{
protected var loader: WonderLoader;
private var bg1: BitmapData;
private var bg2: BitmapData;
private var p:Point;
private var max: int;
public function NightViewEffect()
{
super();
}
override public function init(w: int, h: int): void
{
super.init(w, h);
loader = new WonderLoader();
loader.addEventListener(WonderLoader.EVENT_COMP, onComp);
loader.load("0ee7133d97f027ae357545c2aaba8e252436933e");
}
private function onComp(e: Event): void
{
loader.removeEventListener(WonderLoader.EVENT_COMP, onComp);
bg1 = Bitmap(loader.getAssetFile("data2")).bitmapData;
bg2 = Bitmap(loader.getAssetFile("data3")).bitmapData;
trace(bg1);
p = new Point(0, (h - bg1.height) >> 1);
max = 256;
initialized();
}
override public function play(data: BitmapData): void
{
trace("play : " + bg1);
super.play(data);
data.fillRect(data.rect, 0xFF000000);
data.copyPixels(bg1, bg1.rect, p);
}
override public function render(byte: ByteArray, mouseX: Number, mouseY: Number): void
{
var i: int, alpha: Number = 0, n: Number = 0;
data.fillRect(data.rect, 0xFF000000);
data.copyPixels(bg1, bg1.rect, p);
while (i++ < max )
{
//n = Math.min(hh * byte.readFloat() * 25, hh);
n = Math.min(byte.readFloat() * 255 * 20, 255);
alpha = Math.max(n, alpha);
}
data.merge(bg2, bg2.rect, p, alpha, alpha, alpha, alpha);
}
}
/**
* WonderflLoader
* http://wonderfl.kayac.com/code/40c81f639df0e7ff92915fb633ed1bbf9f9bb025
*/
import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.system.LoaderContext;
import flash.display.Loader;
import flash.net.URLRequest;
class WonderLoader extends EventDispatcher
{
private const baseURL: String = "http://swf.wonderfl.net/swf/usercode/";
private var content: DisplayObject;
private var loader: Loader;
public static const EVENT_LOADED: String = "wl_loaded";
public static const EVENT_INIT: String = "wl_init";
public static const EVENT_COMP: String = "wl_comp";
public function WonderLoader()
{
super();
}
public function load(urlOrId: String, context: LoaderContext = null): void
{
var i: int = urlOrId.lastIndexOf("/");
var id: String = urlOrId.substr(i + 1);
var urlReq: URLRequest = new URLRequest(baseURL + id.substr(0, 1) + "/" + id.substr(0, 2) + "/" + id.substr(0, 4) + "/" + id + ".swf?t=" + new Date().time);
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComp);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
loader.load(urlReq, context);
}
private function onProgress(e:ProgressEvent):void { dispatchEvent(e.clone()); }
private function onIOError(e: IOErrorEvent): void { dispatchEvent(e.clone()); }
private function onComp(e: Event): void
{
e.target.removeEventListener(Event.COMPLETE, onComp);
content = loader.content;
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onComp);
loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onIOError);
loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress);
loader.unload();
loader = null;
dispatchEvent(new Event(EVENT_LOADED));
if (asset.hasOwnProperty("setup"))
{
content.addEventListener(ProgressEvent.PROGRESS, onProgress);
dispatchEvent(new Event(EVENT_INIT));
content.addEventListener(EVENT_COMP, onSetup);
asset.setup();
}
}
private function onSetup(e:Event):void
{
dispatchEvent(new Event(EVENT_COMP));
}
public function getAssetFile(name: String): * { return asset.getAssetFile(name); }
public function get asset(): Object { return Object(content); }
}