ViewSoundWaveLR_2nd
↓ViewSoundWaveLR
http://wonderfl.net/c/l6gF
のバージョンUP版
WAVE_STEPで刻んだ秒毎に円のエフェクトを更新してます。
今だと0.01秒毎に更新しています。(まぁ実際は違うけどねfps30だから)
指定した秒刻みで波形のデータを持ってくる、う~ん、どう使おうかなぁ…
追記:少し修正しました。
追記:バージョンUP版→http://wonderfl.net/c/kB4R
/**
* Copyright snowsunny ( http://wonderfl.net/user/snowsunny )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/uYmx
*/
package
{
import flash.media.SoundChannel;
import flash.events.Event;
import flash.display.Sprite;
import flash.geom.ColorTransform;
import flash.media.Sound;
import flash.utils.ByteArray;
import flash.net.URLRequest;
public class ViewSoundWaveLR_2nd extends Sprite
{
public function ViewSoundWaveLR_2nd()
{
//必要データ作成&設定&イベント登録---------------------------------------------↓
//内部系データ------------------------------------------------↓
//~.mp3へのパス
var SoundPass:String = "http://sunny-experience.com/wonderfl/BGM_House.mp3";
//mp3をロードするSound
var TargetSound:Sound = new Sound();
TargetSound.addEventListener(Event.COMPLETE, COMP_SoundLoad);
TargetSound.load(new URLRequest(SoundPass));
//TagetSoundのSoundChannel
var TSC:SoundChannel;
//TargetSoundから抽出した生の音データを格納するByteArray
var SoundArray:ByteArray = new ByteArray();
//波形の刻み:x(sec) * 8(左右の音データ一つ分) * 44100(Hz)
const WAVE_STEP:int = Math.round(0.01 * 8 * 44100);
//刻まれた波形の番号(最初は0)
var StepNum:int = -1;
//波形の高さ(最大値):x(px) / 2(±補正用計算)
var WAVE_HEIGHT:Number = 128 / 2;
//左右の波形データを保存するArray
var LineData_L:Array = [], LineData_R:Array = [];
//内部系データ------------------------------------------------↑
//描画系データ------------------------------------------------↓
//左音源の波形生成用Sprite
var LineSpriteL:Sprite = new Sprite();
LineSpriteL.x = 0;
LineSpriteL.y = stage.stageHeight / 4;
LineSpriteL.graphics.lineStyle(1, 0x6666cc);
addChild(LineSpriteL);
//右音源の波形生成用Sprite
var LineSpriteR:Sprite = new Sprite();
LineSpriteR.x = 0;
LineSpriteR.y = stage.stageHeight - stage.stageHeight / 4;
LineSpriteR.graphics.lineStyle(1, 0xcc6666);
addChild(LineSpriteR);
//PlayLine用Sprite
var PlayLine:Sprite = new Sprite();
PlayLine.graphics.lineStyle(3, 0xaaaaaa, 0.5);
PlayLine.graphics.lineTo(0, 0);
PlayLine.graphics.lineTo(0, stage.stageHeight);
addChild(PlayLine);
//EffectSpriteL,R
var EffectColor:ColorTransform = new ColorTransform();
var EffectSpriteL:Sprite = new Sprite();
EffectSpriteL.x = stage.stageWidth / 4;
EffectSpriteL.y = stage.stageHeight / 2;
EffectSpriteL.graphics.beginFill(0x888888, 0.3);
EffectSpriteL.graphics.drawCircle(0, 0, stage.stageHeight/2);
EffectSpriteL.graphics.endFill();
EffectSpriteL.scaleX = 0;
EffectSpriteL.scaleY = 0;
addChild(EffectSpriteL);
var EffectSpriteR:Sprite = new Sprite();
EffectSpriteR.x = stage.stageWidth - stage.stageWidth / 4;
EffectSpriteR.y = stage.stageHeight / 2;
EffectSpriteR.graphics.beginFill(0x888888, 0.3);
EffectSpriteR.graphics.drawCircle(0, 0, stage.stageHeight/2);
EffectSpriteR.graphics.endFill();
EffectSpriteR.scaleX = 0;
EffectSpriteR.scaleY = 0;
addChild(EffectSpriteR);
//描画系データ------------------------------------------------↑
//必要データ作成&設定&イベント登録---------------------------------------------↑
//Soundのロードが終わった後、データを抽出・ラインデータ作成・サウンド終了後のイベント登録・Event.ENTER_FRAME登録
function COMP_SoundLoad(e:Event):void
{
//TargetSoundから秒数*44100(Hz)の音データを抽出、SoundArrayに格納
TargetSound.extract(SoundArray, TargetSound.length/1000 * 44100);
CreateLineData();
TSC = TargetSound.play(0);
TSC.addEventListener(Event.SOUND_COMPLETE, COMP_SoundPlay);
addEventListener(Event.ENTER_FRAME, CheckWaveEvent);
}
//サウンドが終了したら呼び出される関数
function COMP_SoundPlay(e:Event):void
{
//StepNumを初期化
StepNum = -1;
//TargetSoundをループ再生
TSC = TargetSound.play(0);
TSC.addEventListener(Event.SOUND_COMPLETE, COMP_SoundPlay);
}
//DrawLineに送るラインデータを作成する関数
function CreateLineData():void
{
for(var i:Number = 0; i < SoundArray.length; i += WAVE_STEP)
{
SoundArray.position = i;
//SoundArrayから左右の音データをreadFloatを使って4Byteずつ取得
LineData_L.push(SoundArray.readFloat() * WAVE_HEIGHT);
LineData_R.push(SoundArray.readFloat() * WAVE_HEIGHT);
}
//最後の音データを挿入
SoundArray.position = SoundArray.length - 8;
LineData_L.push(SoundArray.readFloat() * WAVE_HEIGHT);
LineData_R.push(SoundArray.readFloat() * WAVE_HEIGHT);
//DrawLineに左右のLineDataと、ステージの横幅ぴったりになる様な値を渡す
DrawLine(LineData_L, LineData_R, stage.stageWidth / (SoundArray.length/WAVE_STEP));
}
//引数で受け取ったデータを使ってラインを描く関数
function DrawLine(LD:Array, RD:Array, X_STEP:Number):void
{
//ラインを描くX,Y用変数
var MoveX:Number = 0, MoveY:Number = 0;
//受け取ったデータの数だけラインを描く
for (var i:int = 0; i < LD.length; i++)
{
MoveY = LD[i];
LineSpriteL.graphics.lineTo(MoveX, MoveY);
MoveY = RD[i];
LineSpriteR.graphics.lineTo(MoveX, MoveY);
MoveX += X_STEP;
}
}
//PlayLine更新とWAVE_STEPで刻んだ秒毎にEffectSpriteL,Rを更新する関数
function CheckWaveEvent(e:Event):void
{
//PlayLineを再生時間に合わせて移動
PlayLine.x = (stage.stageWidth/TargetSound.length) * TSC.position;
//更新用の値を取得
var mem:int = int(TSC.position / ((WAVE_STEP/8/44100)*1000));
if(StepNum < mem)
{
//波の刻み番頭を更新
StepNum = mem;
//EffectSpriteL,Rの色を変更(Lは0~360、Rは360~0に色相を変更)
var ECH:Number = (360/TargetSound.length) * TSC.position;
EffectColor.color = ChangeHSVtoRGB(ECH);
EffectSpriteL.transform.colorTransform = EffectColor;
EffectColor.color = ChangeHSVtoRGB(360-ECH);
EffectSpriteR.transform.colorTransform = EffectColor;
//EffectSpriteL,Rの大きさをLineDataの配列から取得(0~1)・設定
EffectSpriteL.scaleX = Math.abs(LineData_L[StepNum] / WAVE_HEIGHT);
EffectSpriteL.scaleY = Math.abs(LineData_L[StepNum] / WAVE_HEIGHT);
EffectSpriteR.scaleX = Math.abs(LineData_R[StepNum] / WAVE_HEIGHT);
EffectSpriteR.scaleY = Math.abs(LineData_R[StepNum] / WAVE_HEIGHT);
}
}
//HSVからRGBに変換する関数
function ChangeHSVtoRGB(H:Number, S:Number=1, V:Number=1):uint
{
//変換したRGBを入れる変数を作成
var RGB:uint;
//Sが0の時、Hは不必要となるのでVのみでRGBを設定する
if(S == 0)
{
//RGBにビットをシフトしながら値を格納
RGB = V * 255 << 16 | V * 255 << 8 | V * 255;
}
else
{
//変換に必要な変数を作成・設定
var Hi:Number = Math.floor(H / 60) % 6;
var f:Number = (H / 60 - Hi);
var p:Number = V * (1 - S);
var q:Number = V * (1 - f * S);
var t:Number = V * (1 - (1 - f) * S);
//HiによってRGBに格納する値を変更
//↓
//RGBにビットをシフトしながら値を格納
switch(Hi)
{
case 0:
RGB = V * 255 << 16 | t * 255 << 8 | p * 255 ;
break;
case 1:
RGB = q * 255 << 16 | V * 255 << 8 | p * 255 ;
break;
case 2:
RGB = p * 255 << 16 | V * 255 << 8 | t * 255 ;
break;
case 3:
RGB = p * 255 << 16 | q * 255 << 8 | V * 255 ;
break;
case 4:
RGB = t * 255 << 16 | p * 255 << 8 | V * 255 ;
break;
case 5:
RGB = V * 255 << 16 | p * 255 << 8 | q * 255 ;
break;
}
}
return RGB;
}
}
}
}