forked from: サイン波形の生成を高速にやってみたつもりだったが…
forked from サイン波形の生成を高速にやってみたつもりだったが… (diff: 54)
ActionScript3 source code
/**
* Copyright atsushi015 ( http://wonderfl.net/user/atsushi015 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/hCHZ
*/
// forked from atsushi015's サイン波形の生成を高速にやってみたつもりだったが…
// forked from terra1119's flash on 2010-3-7
package {
import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.KeyboardEvent
import flash.events.MouseEvent;
import flash.events.SampleDataEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.filters.BlurFilter;
import net.hires.debug.Stats;
import Box2D.Common.*;
import Box2D.Common.Math.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Dynamics.*;
import Box2D.Dynamics.Joints.*;
[SWF(width="400", height="300", frameRate="30", backgroundColor="#000000")]
public class Main extends Sprite {
public static const SINE:String = "sine";
public static const SAW:String = "saw";
public static const TRIANGLE:String = "triangle";
public static const PULSE:String = "pulse";
public static const NOISE:String = "noise";
private var sound:Sound;
private var channel:SoundChannel;
private var frequency:Number;
private var keyboardTable:Array;
private var waveType:String;
private var volume:Number;
private var isKeyDown:Boolean=false;
private var blurObj:BlurFilter;
private var noteNumber:uint;
private var frequencyArray:Array=[];
private var world:b2World;
private var source:b2Body;
private var dest:b2Body;
private var selectedKey:uint;//現在の鍵盤番号を格納する変数
public function Main() {
stage.scaleMode = StageScaleMode.NO_SCALE;
init();
}
private function init():void {
//frequencyArray=create_fs_array();
initKeyboardTable();
waveType = SINE;
volume = 0.5;
sound = new Sound();
sound.addEventListener(SampleDataEvent.SAMPLE_DATA,waveGenerator);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
// デバッグ用のスタッツを表示しています
addChild(new Stats);
var worldAABB:b2AABB = new b2AABB();
worldAABB.lowerBound.Set(-100, -100);
worldAABB.upperBound.Set(100, 100);
world = new b2World(worldAABB, new b2Vec2(0, 0), true);
var boxDef:b2PolygonDef = new b2PolygonDef();
boxDef.density = 1;
boxDef.SetAsBox(5, 3);
var bBodyDef:b2BodyDef = new b2BodyDef;
bBodyDef.position.Set(-0, 0);
source = world.CreateBody(bBodyDef);
source.CreateShape(boxDef);
source.SetMassFromShapes();
bBodyDef.position.Set(-0, -30);
dest = world.CreateBody(bBodyDef);
dest.CreateShape(boxDef);
dest.SetMassFromShapes();
//DistanceJoint
var jointDef:b2DistanceJointDef = new b2DistanceJointDef();
jointDef.Initialize(source , dest, new b2Vec2(0, -1.5), new b2Vec2(0, -30+1.5) );
jointDef.frequencyHz = 512.0 / 44100;
jointDef.dampingRatio = Math.exp(-1);
world.CreateJoint(jointDef);
// DebugDraw
var draw:b2DebugDraw = new b2DebugDraw;
draw.m_fillAlpha = 0.3;
draw.m_drawScale = 1;
draw.m_sprite = this;
draw.m_lineThickness = 1;
draw.m_drawFlags = b2DebugDraw.e_shapeBit|b2DebugDraw.e_jointBit;
/* world.SetDebugDraw(draw);
source.ApplyForce(new b2Vec2(0, 20), source.GetPosition());
world.Step(30, 100);
*/ }
private function keyDownHandler(e:KeyboardEvent):void {
stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
isKeyDown=true;
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
if(getNote(e.keyCode)){
frequency =noteNumber2frequency(noteNumber);
if(isKeyDown)channel = sound.play();
isKeyDown=false;
createBall();
}
//if(isKeyDown)channel = sound.play();
//isKeyDown=false;
//createBall();
};
private function keyUpHandler(e:KeyboardEvent):void {
isKeyDown=false;
stage.removeEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
channel.stop();
}
private function getNote(num:int):Boolean {
switch(num){//numの値で評価する
case 65://キーコードが65(A)の時
noteNumber=60;//音階をド(C4 MIDIノートナンバー=60)に設定する
selectedKey=0;//現在の鍵盤番号を0にする
break;
case 87://キーコードが87(W)の時
noteNumber=61;//音階をド#(C#4 MIDIノートナンバー=61)に設定する
selectedKey=1;//現在の鍵盤番号を1にする
break;
case 83://キーコードが83(S)の時
noteNumber=62;//音階をレ(D4 MIDIノートナンバー=62)に設定する
selectedKey=2;//現在の鍵盤番号を2にする
break;
case 69://キーコードが69(E)の時
noteNumber=63;//音階をレ#(D#4 MIDIノートナンバー=63)に設定する
selectedKey=3;//現在の鍵盤番号を3にする
break;
case 68://キーコードが68(D)の時
noteNumber=64;//音階をミ(E4 MIDIノートナンバー=64)に設定する
selectedKey=4;//現在の鍵盤番号を4にする
break;
case 70://キーコードが70(F)の時
noteNumber=65;//音階をファ(F4 MIDIノートナンバー=65)に設定する
selectedKey=5;//現在の鍵盤番号を5にする
break;
case 84://キーコードが84(T)の時
noteNumber=66;//音階をファ#(F#4 MIDIノートナンバー=66)に設定する
selectedKey=6;//現在の鍵盤番号を6にする
break;
case 71://キーコードが71(G)の時
noteNumber=67;//音階をソ(G4 MIDIノートナンバー=67)に設定する
selectedKey=7;//現在の鍵盤番号を7にする
break;
case 89://キーコードが89(Y)の時
noteNumber=68;//音階をソ#(G#4 MIDIノートナンバー=68)に設定する
selectedKey=8;//現在の鍵盤番号を8にする
break;
case 72://キーコードが72(H)の時
noteNumber=69;//音階をラ(A4 MIDIノートナンバー=69)に設定する
selectedKey=9;//現在の鍵盤番号を9にする
break;
case 85://キーコードが85(U)の時
noteNumber=70;//音階をラ#(A#4 MIDIノートナンバー=70)に設定する
selectedKey=10;//現在の鍵盤番号を10にする
break;
case 74://キーコードが74(J)の時
noteNumber=71;//音階をシ(B4 MIDIノートナンバー=71)に設定する
selectedKey=11;//現在の鍵盤番号を11にする
break;
case 75://キーコードが75(K)の時
noteNumber=72;//音階をド(C5 MIDIノートナンバー=72)に設定する
selectedKey=12;//現在の鍵盤番号を12にする
break;
default://それ以外の場合
return false;//falseを返す
}
return true;//trueを返す
}
private function initKeyboardTable():void {
keyboardTable =
[
[0, "F"],
[0, "F#"],
[0, "G"],
[0, "G#"],
[1, "A"],
[1, "A#"],
[1, "B"],
[1, "C"],
[1, "C#"],
[1, "D"],
[1, "D#"],
[1, "E"],
[1, "F"],
[1, "F#"],
[1, "G"],
[1, "G#"],
[2, "A"],
[2, "A#"],
[2, "B"],
[2, "C"],
[2, "C#"],
[2, "D"],
[2, "D#"],
[2, "E"]
]
}
private function setFreqency(keyNum:uint):void {
var keyStep:uint = keyNum % 12;
keyStep = keyStep < 5 ? keyStep + 7 : keyStep - 5;
var octave:Number = 110.5* Math.pow(2, keyboardTable[keyNum - 1][0]);
//frequency = octave * Math.pow(2, keyStep / 12);
frequency =noteNumber2frequency(keyNum);
}
private function noteNumber2frequency(v:uint):Number {
if (v > 127)v = 127;
return 440 * Math.pow(2, (v - 69) / 12);
}
private function waveGenerator(e:SampleDataEvent):void {
var sample:Number;
var f0:Number = frequency / 44100;
var f1:Number = 44100 / frequency;
var PI2:Number = 2 * Math.PI;
var ere:Number = Math.cos(PI2 * f0);
var eim:Number = Math.sin(PI2 * f0);
var presamplere:Number = Math.cos(PI2 * f0 * Number(e.position-1));
var presampleim:Number = Math.sin(PI2 * f0 * Number(e.position-1));
var vec2 = new b2Vec2(0, 20);
for ( var c:int=0; c < 2048; c++ ) {
switch(waveType) {
//サイン波
case SINE:
sample = presamplere * eim + presampleim * ere;
presamplere = presamplere * ere - presampleim * eim;
presampleim = sample;
break;
//矩形波
case PULSE:
sample = (Math.sin(PI2 * f0 * Number(c + e.position)) < 0) ? 1 : -1;
break;
//のこぎり波
case SAW:
sample = 2 * (f0 + Math.sin(PI2 * f0 * Number(c + e.position)) * 0.15) * ((c + e.position) % f1) - 1;
break;
//三角波
case TRIANGLE:
sample = (Math.sin(PI2 * f0 * Number(c + e.position)) < 0) ?
(4 * f0 * ((c + e.position) % (f1 / 2)) - 1) :
(-4 * f0 * ((c + e.position) % (f1 / 2)) + 1);
break;
//ホワイトノイズ
case NOISE:
sample = Math.random() * 2 - 1;
break;
default: break;
}
//音量調節
sample *= volume;
//範囲外チェック
sample = (sample < -1) ? -1 : sample;
sample = (sample > 1) ? 1 : sample;
vec2.y = sample * 0.1;
source.ApplyForce(vec2.y, source.GetPosition());
// world.Step(1 / 44100, 1);
e.data.writeFloat(sample);
e.data.writeFloat(sample);
}
}
private function createBall():void {
blurObj=new BlurFilter();
blurObj.blurX=2;
blurObj.blurY=2;
var ball:Sprite=new Sprite();
addChild(ball);
ball.graphics.beginFill(Math.random()*0xFFFFFF);
ball.graphics.drawCircle(0,0,frequency/10);
ball.graphics.endFill();
ball.blendMode="add";
ball.filters=[blurObj];
ball.x=Math.random()*400;
ball.y=Math.random()*300;
ball.addEventListener(Event.ENTER_FRAME,efHandler);
}
private function efHandler(e:Event):void {
var targetSprite:Sprite=e.target as Sprite;
targetSprite.alpha-=0.05;
blurObj.blurX+=2;
blurObj.blurY+=2;
targetSprite.filters=[blurObj];
if (targetSprite.alpha<0) {
targetSprite.removeEventListener(Event.ENTER_FRAME,efHandler);
removeChild(targetSprite);
targetSprite=null;
}
}
}
}