dynamic sound generate. ボールに合わせる。
ボールのバウンドに合わせて。
音の遅延に対する処理は適当。
/**
* Copyright sakef ( http://wonderfl.net/user/sakef )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/vRq9
*/
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.SampleDataEvent;
import flash.events.TimerEvent;
import flash.media.Sound;
import flash.utils.ByteArray;
import flash.utils.Timer;
[SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="40")]
public class Main extends Sprite
{
private static const SAMPLING:int = 2048; // バッファ
private static const SAMPLING_RATE:int = 44100; // サンプリングレート
private static const PI:Number = Math.PI * 2; // 1周期
private static const VOLUME:Number = 0.1; // ボリューム
private static const MAX:Number = 0.7; // 音の最大値
private var soundContainer:Array;
private var ballContainer:Array;
public function Main()
{
// コンテナ
soundContainer = [];
ballContainer = [];
// タイマーの初期化
var t:Timer = new Timer(1200);
t.addEventListener(TimerEvent.TIMER, addBall);
t.start();
addEventListener(Event.ENTER_FRAME, onFrame);
// サウンドの再生
var sound:Sound = new Sound;
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
sound.play();
}
// ボールの動きを制御する関数
private function onFrame(e:Event):void
{
var len:int=ballContainer.length;
while(len--)
{
var ball:Ball=ballContainer[len] as Ball;
ball.render(soundContainer);
if (ball.alpha <= 0)
{
ballContainer.splice(len, 1);
removeChild(ball);
ball=null;
}
}
}
// ボールを加える関数
private function addBall(e:TimerEvent):void
{
var ball:Ball=new Ball();
addChild(ball);
ballContainer.push(ball);
ball.x = 465 / 2;
ball.y = 465 / 2 - 50;
}
// 波形を書き込む
private function onSampleData(e:SampleDataEvent):void
{
var data:ByteArray = e.data;
var pos:Number = e.position;
var len:int = soundContainer.length;
var s:SoundData;
var i:int, n:int;
for(i=0 ; i<SAMPLING ; i++)
{
var d:Number = 0;
n = len;
// データを足し合わせていく。
while(n--)
{
s = soundContainer[n] as SoundData;
var w:Number = (PI * s.frequency / SAMPLING_RATE);
var phase:Number = ((pos + i) * w) % PI;
var dd:Number;
if(phase < Math.PI) dd = 1 - 2*phase/Math.PI;
else dd = -1 + 2 * (phase - Math.PI)/Math.PI;
d += dd*0.2*s.volume;
}
// データを範囲内に丸める
d = (d > -0.8)?(d):(-0.8);
d = (d < 0.8)?(d):(0.8);
// 書き込み
data.writeFloat(d);
data.writeFloat(d);
}
n = soundContainer.length;
while(n--)
{
s = (soundContainer[n] as SoundData);
s.renderSound();
if(s.state == 3) soundContainer.splice(n,1);
}
}
}
}
// 音データを保持するクラス
class SoundData
{
public var frequency:Number;
public var volume:Number;
public var state:int;
private var fadeIn:Number;
private var fadeOut:Number;
private var show:Number;
private var volMax:Number;
private var count:int;
public function SoundData(frequency:Number, fadeIn:Number, fadeOut:Number, show:int, volMax:Number)
{
this.frequency = frequency;
this.fadeIn = fadeIn;
this.fadeOut = fadeOut;
this.show = show;
this.volMax = volMax;
this.volume = this.state = this.count = 0
}
public function renderSound():void
{
switch(state)
{
// 音をフェードインさせる
case 0:
volume += fadeIn;
if(volume>=volMax)
{
volume = volMax;
state = 1;
}
break;
// 音を流す
case 1:
count ++;
if(count == show) state = 2;
break;
// 音をフェードアウトさせる
case 2:
volume -= fadeOut;
if(volume <= 0)
{
state = 3;
volume = 0;
}
break;
}
}
}
// ボールクラス
import flash.display.Shape;
class Ball extends Shape
{
private static const COLOR:Array=[0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff, 0x00ffff];
private static const COLOR_N:int=6;
private static const DRAG:Number = 0.99;
private static const GRAVITY:Number = 0.8;
private var xvel:Number;
private var yVel:Number;
private var frequency:Number;
private var prev:Number;
public function Ball()
{
xvel=7 * Math.random() - 3.5;
yVel=5;
frequency = 440 * Math.pow(2, (int(20*Math.random()))/12);
var c_index:int=COLOR_N * Math.random() >> 0;
var color:uint=COLOR[c_index];
graphics.beginFill(color, 1);
graphics.drawCircle(0, 0, 20);
graphics.endFill();
prev = 0;
}
public function render(sound:Array):void
{
alpha-=0.005;
x+=xvel;
y+=yVel;
yVel*=DRAG;
yVel+=GRAVITY;
scaleX=scaleY*=DRAG;
if(y > 220 && prev < 220) sound.push(new SoundData(frequency, 0.5, 0.015, 2, alpha*0.5));
prev = y;
if (y > 300)
{
y=300;
yVel=-yVel * 0.99;
}
}
}