ディレイ/ローファイ/シンプルFM forked from: ドラムンベース(っぽいもの)
// forked from kappaLab's ドラムンベース(っぽいもの)
package
{
import flash.display.Sprite
import flash.display.Shape
import flash.events.Event;
import flash.events.SampleDataEvent;
import flash.filters.BlurFilter;
import flash.media.Sound;
[SWF(backgroundColor=0x000000, frameRate=60)]
public class Drumnbass_3 extends Sprite
{
private const PI2:Number = Math.PI * 2;
private const SAMPLE_RATE:Number = 44100;
private const LATENCY:int = 4410 //2048~8192
private var sound:Sound;
private var delay:Delay = new Delay(LATENCY*6.05,1,-0.6,-0.2);
private var voices:Vector.<Voice> = new Vector.<Voice>()
private var particles:Vector.<Shape> = new Vector.<Shape>()
private var count:int = 0
public function Drumnbass_3()
{
init()
}
public function init():void
{
voices[0] = new Voice(60,.4,50,8000,10000,2.15,1,1200,4)
voices[1] = new Voice(320,.2,100,500,600,4,1,500)
voices[2] = new Voice(120,.5,50,500,600,7,6,100,8)
voices[3] = new Voice(880,.5,50,700,1200,3,6,400)
voices[4] = new Voice(640,.5,100,1000,1200,9,4,100,9)
voices[5] = new Voice(440,.5,50,1000,1200,3,9,800)
var stageWidth:Number = stage.stageWidth
var stageHeight:Number = stage.stageHeight
var n:int = voices.length;
for (var i:int = 0; i < n; i++)
{
var s:Shape = new Shape()
var x:Number = stageHeight * Math.random() * .5 - stageHeight * .25;
var y:Number = stageHeight * Math.random() * .5 - stageHeight * .25;
s.graphics.beginFill(0xFFFFFF * Math.random());
s.graphics.drawCircle(x, y, Math.random() * 20 + 20);
s.alpha = .5
s.x = stage.stageWidth / 2;
s.y = stage.stageHeight / 2;
particles[i] = s
addChild(s)
}
addEventListener(Event.ENTER_FRAME,
function(e:Event):void {
var n:int = particles.length
for (var i:int = 0; i < n; i++)
{
var p:Shape = particles[i]
p.rotation += i % 2 * 2 - 1;
p.scaleX += (1 - p.scaleX) * .4;
p.scaleY += (1 - p.scaleY) * .4;
}
})
filters = [new BlurFilter(5, 5)]
sound = new Sound()
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, updateVoice)
sound.play()
}
private function updateVoice(e:SampleDataEvent):void
{
var n:Number = LATENCY
count++
var c8:int = count %8
var c16:int = count %16
var c32:int = count %32
var c64:int = count % 64
if (c8 == 0 ||
c8 == 1 ||
c8 == 2 ||
c8 == 3 ) {
if (Math.random() > .3) {
voices[2].play();
particles[2].scaleX = particles[2].scaleY = 2
}else {
voices[3].play()
particles[3].scaleX = particles[3].scaleY = 2
}
}
if (c8 == 6 ||
c8 == 7 ) {
voices[1].play()
particles[1].scaleX = particles[1].scaleY = 2.5
}
if (count % 16 == 11) {
particles[0].scaleX = particles[0].scaleY = 3
voices[0].play()
}
if (count % 32 == 8) {
particles[4].scaleX = particles[4].scaleY = 3
voices[4].play()
}
if (count % 32 == 10 && Math.random()>.3){
particles[5].scaleX = particles[5].scaleY = 4
voices[5].play()
}
for (var i:int = 0; i < n; i++)
{
var sample:Number = 0
for each (var v:Voice in voices)
sample += v.pulse;
//ディレイ
sample = delay.process(sample)
sample = Math.max(-1,sample)
sample = Math.min(1,sample)
//ロービット
sample = int(sample*64)/64
e.data.writeFloat(sample)
e.data.writeFloat(sample)
}
}
}
}
class Delay {
public var time:int
public var dry:Number
public var wet:Number
public var feedback:Number
private var buf:Array=[]
private var position:Number
public function Delay(time:int, dry:Number=1, wet:Number=0.5, feedback:Number=0.3){
this.time = time
this.dry = dry
this.wet = wet
this.feedback = feedback
position = 0
}
public function process(sample:Number):Number{
var dSample:Number = 0
if(buf[position]!=undefined)
dSample = buf[position];
buf[(position+time)%time]=sample*wet+dSample*feedback
position++
position%=time
return sample*dry + dSample
}
}
class Voice {
private const PI2:Number = Math.PI * 2;
private const SAMPLE_RATE:Number = 44100;
private var phase:Number = 0
public var frequency:Number
public var volume:Number;
public var gain:Number;
public var attack:int;
public var decay:int;
public var sustain:int;
public var modFrequency:Number;
public var fmIndex:Number;
public var fmDecay:Number;
private var position:int = 0
private var amplifier:Number = 0;
private var fmAmplifier:Number = 0;
public function Voice(
frequency:Number = 440,
volume:Number = .2,
attack:int = 1000,
decay:int = 1000,
sustain:int = 5000,
modFrequency:Number = 1,
fmIndex:Number = 1,
fmDecay:int = 4000,
gain:Number = 1 )
{
this.frequency = frequency
this.volume = volume
this.attack = attack
this.decay = decay
this.sustain = sustain
this.modFrequency = modFrequency
this.fmIndex = fmIndex
this.fmDecay = fmDecay
this.gain = gain
}
public function get pulse():Number
{
updatePhase()
updateAmplifier()
var sample:Number
sample = Math.sin(phase+Math.sin(phase*modFrequency)*fmIndex*fmAmplifier) * amplifier;
if(gain!=1){
sample *= gain;
sample = Math.max(-1,sample)
sample = Math.min(1,sample)
}
return sample * volume
}
public function play():void
{
position = 0
amplifier = 0
fmAmplifier = 1
}
public function updatePhase():Number
{
phase += PI2 * frequency / SAMPLE_RATE
phase %= PI2;
return phase
}
public function updateAmplifier():Number
{
var position:int = (this.position++ )
if (position >= sustain) {
amplifier = 0
fmAmplifier = 1
}else if (position < attack) {
amplifier += 1/attack
}else if (position > (sustain-decay)) {
amplifier -= 1/decay
}
fmAmplifier -= 1/fmDecay
fmAmplifier = Math.max(fmAmplifier,0)
return amplifier;
}
}