SwaySound
今回はSound.extract()を使って波形をとってみた。次は変形させて再生に挑戦。
ところでローディング開始まで異常に長いのなんで。。orz
/**
* Copyright rettuce ( http://wonderfl.net/user/rettuce )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/5VaYC
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.display.Graphics;
import flash.display.MovieClip;
import flash.display.Shape;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.ProgressEvent;
import flash.events.SampleDataEvent;
import flash.filters.BlurFilter;
import flash.filters.DisplacementMapFilter;
import flash.filters.DisplacementMapFilterMode;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundLoaderContext;
import flash.net.URLRequest;
import flash.media.SoundMixer;
import flash.text.TextField;
import flash.utils.ByteArray;
import flash.display.BlendMode;
[SWF(width = 465, height = 465, backgroundColor = 0x000000, frameRate = 40)]
/**
* ...
* @author rettuce
*
* 前回はSoundMixer.computeSpectrumを使用したので
* 今回はSound.extractを使用して音データをとってみる
*
* 音はTsabeat より拝借
* http://www.ektoplazm.com/2010/highpersonic-whomen-alternative-energysource
*/
public class Main extends MovieClip
{
private var _sound:Sound;
private var _channel:SoundChannel;
private var _byteArray:ByteArray;
private var _filterFlg:Boolean = false;
private var _bm:Bitmap;
private var shape_left:Shape;
private var shape_right:Shape;
private var g_left:Graphics;
private var g_right:Graphics;
private var _hane:int = 120; // 振幅の幅値
private var wave_scale:int = 1; // 波形の取得数 大きいほど細かい
private var line:int = 2000; // 波形の取得数 大きいほど細かい
private var mapFilter:DisplacementMapFilter;
private var mapImage:BitmapData;
private var componentX:uint = BitmapDataChannel.RED;
private var componentY:uint = BitmapDataChannel.GREEN;
private var _scaleX:Number = 0;
private var _scaleY:Number = 50;
private var mapImagePoint:Point;
private var mode:String = DisplacementMapFilterMode.IGNORE;
public function Main()
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init );
}
private function init(e:Event = null ):void
{
removeEventListener(Event.ADDED_TO_STAGE, init );
_bm = new Bitmap( new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x000000 ) );
addChild(_bm);
_byteArray = new ByteArray();
stage.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void{
if (!_filterFlg) _filterFlg = true;
else _filterFlg = false;
})
// 波形描画用シェイプ
shape_left = new Shape();
shape_left.x = 0;
shape_left.y = stage.stageHeight/2 ;
g_left = shape_left.graphics;
shape_right = new Shape();
shape_right.x = 0;
shape_right.y = stage.stageHeight/2;
g_right = shape_right.graphics;
addChild(shape_left);
addChild(shape_right);
// MAP作成
mapImage = new BitmapData( stage.stageWidth, stage.stageHeight );
mapImage.perlinNoise( stage.stageWidth, stage.stageHeight, 4, 0, false, true );
mapImagePoint = mapImage.rect.topLeft;
mapFilter = new DisplacementMapFilter( mapImage, mapImagePoint, componentX, componentY, _scaleX, _scaleY, mode );
// addChild(new Bitmap(mapImage));
setStage();
soundSet();
loaderInfo.addEventListener(Event.UNLOAD, function(e:Event):void {
_channel.stop();
stage.removeEventListener(Event.RESIZE, resizeEvent);
stage.removeEventListener(MouseEvent.CLICK, function(e:MouseEvent):void { if (!_filterFlg) _filterFlg = true;
else _filterFlg = false; } );
removeEventListener(Event.ENTER_FRAME, soundAnimation );
loaderInfo.removeEventListener(Event.UNLOAD, arguments.callee );
});
}
private function setStage():void {
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.addEventListener(Event.RESIZE, resizeEvent);
resizeHandler();
}
private function resizeEvent(e:Event = null):void {
resizeHandler();
}
public function resizeHandler(): void
{
shape_left.x = shape_right.x = _bm.x = _bm.y = 0;
shape_left.y = shape_right.y = stage.stageHeight / 2;
_bm.width = stage.stageWidth;
_bm.height = stage.stageHeight;
}
private function soundSet():void
{
// 再生用 sound クラスの 生成と sampleDataEvent 取得
_sound = new Sound();
_sound.load(new URLRequest("http://lab.rettuce.com/common/src/PieceOfCake.mp3"), new SoundLoaderContext( 100 , true ));
var txt:TextField = new TextField();
txt.width = 120;
txt.x = stage.stageWidth / 2 -60;
txt.y = stage.stageHeight / 2;
txt.textColor = 0xFFFFFF;
addChild(txt);
_sound.addEventListener (ProgressEvent.PROGRESS, function(e:ProgressEvent):void {
txt.text = "Now loading... "+Math.floor(e.bytesLoaded / e.bytesTotal * 100) + "%";
});
_sound.addEventListener(Event.COMPLETE, function(e:Event):void {
_sound.removeEventListener(ProgressEvent.PROGRESS, function(e:ProgressEvent):void {
txt.text = Math.floor(e.bytesLoaded / e.bytesTotal * 100) + "%";
});
removeChild(txt);
_channel = _sound.play( 0, 1 );
addEventListener(Event.ENTER_FRAME, soundAnimation );
});
}
private function soundAnimation(e:Event):void
{
if (_sound && _channel) {
// グラフィッククリア
g_left.clear();
g_left.lineStyle ( 1.0 , 0xFFFFFF*Math.random() , 0.6 );
g_right.clear();
g_right.lineStyle ( 1.0 , 0xFFFFFF*Math.random() , 0.2 );
// サウンドデータを取得
var buffer:ByteArray = new ByteArray();
var begin:Number = Math.floor( _channel.position / line * 44100);
begin = Math.floor(begin / wave_scale) * wave_scale; // ズレ防止
var sampling:Number = Math.floor(line * wave_scale);
sampling = _sound.extract(buffer, sampling, begin);
var i:int;
var data:Array;
data = new Array();
for (i = 0; i < sampling; i += wave_scale) {
buffer.position = Math.floor(i) * 4 ;
data.push(buffer.readFloat());
}
if (data.length) {
g_left.moveTo ( 0 , -data[0] * _hane );
}
for (i = 1; i < line; i++) {
g_left.lineTo ( i / line * stage.stageWidth , -data[i] * _hane - Math.sin(i/line*Math.PI)*130 );
}
data = new Array();
for (i = 0; i < sampling; i += wave_scale) {
buffer.position = Math.floor(i) * 4 + 4;
data.push(buffer.readFloat());
}
if (data.length) {
g_right.moveTo ( 0 , -data[0] * _hane );
}
for (i = 1; i < line; i++) {
g_right.lineTo ( i / line * stage.stageWidth , -data[i] * _hane + Math.sin(i/line*Math.PI)*100*Math.cos( line/2 - i * Math.PI ) );
}
// エフェクト
if( !_filterFlg ) _bm.bitmapData.draw(shape_left, new Matrix( 1, 0, 0, 1, 0, stage.stageHeight/2 ), new ColorTransform( 1, 1, 1, 1, 0, 0, 0, 0), BlendMode.ADD );
_bm.bitmapData.applyFilter( _bm.bitmapData, _bm.bitmapData.rect, _bm.bitmapData.rect.topLeft, mapFilter);
_bm.bitmapData.applyFilter( _bm.bitmapData, _bm.bitmapData.rect, _bm.bitmapData.rect.topLeft, new BlurFilter( 10 , 15 ) );
}
}
}
}