Skip to content

Instantly share code, notes, and snippets.

@tompng
Last active August 29, 2015 14:23
Show Gist options
  • Save tompng/b4ffea7adce14e3bd1bf to your computer and use it in GitHub Desktop.
Save tompng/b4ffea7adce14e3bd1bf to your computer and use it in GitHub Desktop.
なだらかに変化する乱数列(乱数じゃないけどもそんなかんじの).js
function gaussRandom(){
var r=Math.sqrt(-2*Math.log(Math.random()));
var t=2*Math.PI*Math.random();
return r*Math.sin(t);
}
//smoothed with exp(kx)-2exp(2kx)+exp(3kx), k=1/tscale, variance=1
function SmoothRandom(tscale){
this.tscale=tscale||1;
this.a1=0;
this.a2=0;
this.a3=0;
this.scale=Math.sqrt(30);
this.next(Infinity);
}
SmoothRandom.covariantRandom3D=function(aa,bb,cc,ab,bc,ca){
var c0=Math.sqrt((aa*bc*bc+bb*ca*ca-2*ab*ca*bc)/(aa*bb-ab*ab));
var c2=Math.sqrt(cc-c0*c0);
var b0=bc/c0;
var a0=ca/c0;
var a1=Math.sqrt(aa-a0*a0);
var b1=(ab-a0*b0)/a1;
var r0=gaussRandom(),r1=gaussRandom(),r2=gaussRandom();
return {x:a0*r0+a1*r1,y:b0*r0+b1*r1,z:c0*r0+c2*r2};
}
SmoothRandom.prototype.next=function(dt){
if(!dt||dt<=0)dt=1;
var pn=Math.exp(-dt/this.tscale);
var s2=(1-pn*pn)/2;
var s3=(1-pn*pn*pn)/3;
var s4=(1-pn*pn*pn*pn)/4;
var s5=(1-pn*pn*pn*pn*pn)/5;
var s6=(1-pn*pn*pn*pn*pn*pn)/6;
var rand=SmoothRandom.covariantRandom3D(s2,s4,s6,s3,s5,s4);
if(isNaN(rand.x+rand.y+rand.z)){
var rnd=gaussRandom();
rand={x:Math.sqrt(s2)*rnd,y:Math.sqrt(s4)*rnd,z:Math.sqrt(s6)*rnd};
}
this.a1=this.a1*pn+rand.x;
this.a2=this.a2*pn*pn+rand.y;
this.a3=this.a3*pn*pn*pn+rand.z;
return this.scale*(this.a1+this.a3-2*this.a2);
}
//smoothed with (exp(kx)-2exp(2kx)+exp(3kx))*cos(wx), w=2pi*freq, k=w/strength, variance=1
function FreqRandom(freq, strength){
this.freq=freq||1;
this.strength=strength||2;
this.r1=this.i1=0;
this.r2=this.i2=0;
this.r3=this.i3=0;
this.scale=Math.sqrt(30);
this.next(Infinity);
}
FreqRandom.prototype.next=function(dt){
if(!dt||dt<=0)dt=1;
var w=2*Math.PI*this.freq;
var cos=Math.cos(w*dt);
var sin=Math.sin(w*dt);
if(dt==Infinity){cos=sin=0;}
var pn=Math.exp(-w*dt/this.strength);
var s2=(1-pn*pn)/2;
var s3=(1-pn*pn*pn)/3;
var s4=(1-pn*pn*pn*pn)/4;
var s5=(1-pn*pn*pn*pn*pn)/5;
var s6=(1-pn*pn*pn*pn*pn*pn)/6;
var randr=SmoothRandom.covariantRandom3D(s2,s4,s6,s3,s5,s4);
var randi=SmoothRandom.covariantRandom3D(s2,s4,s6,s3,s5,s4);
if(isNaN(randr.x+randr.y+randr.z+randi.x+randi.y+randi.z)){
var rnd1=gaussRandom(),rnd2=gaussRandom();
randr={x:Math.sqrt(s2)*rnd1,y:Math.sqrt(s4)*rnd1,z:Math.sqrt(s6)*rnd1};
randi={x:Math.sqrt(s2)*rnd2,y:Math.sqrt(s4)*rnd2,z:Math.sqrt(s6)*rnd2};
}
this.r1=pn*(this.r1*cos-this.i1*sin)+randr.x;
this.i1=pn*(this.r1*sin+this.i1*cos)+randi.x;
this.r2=pn*pn*(this.r2*cos-this.i2*sin)+randr.y;
this.i2=pn*pn*(this.r2*sin+this.i2*cos)+randi.y;
this.r3=pn*pn*pn*(this.r3*cos-this.i3*sin)+randr.z;
this.i3=pn*pn*pn*(this.r3*sin+this.i3*cos)+randi.z;
return this.scale*(this.r1+this.r3-2*this.r2);
}
//smoothed with exp(kx), k=1/tscale, variance=1
function NoiseRandom1(tscale){
this.tscale=tscale||1;
this.a=0;
this.next(Infinity);
this.scale=Math.sqrt(2);
}
NoiseRandom1.prototype.next=function(dt){
if(!dt||dt<=0)dt=1;
var pn=Math.exp(-dt/this.tscale);
var s2=(1-pn*pn)/2;
var r=gaussRandom();
var x=Math.sqrt(s2);
this.a=this.a*pn+r*x;
return this.scale*this.a;
}
//smoothed with exp(kx)-exp(2kx), k=1/tscale, variance=1
function NoiseRandom2(tscale){
this.tscale=tscale||1;
this.a1=0;
this.a2=0;
this.scale=Math.sqrt(12);
this.next(Infinity);
}
NoiseRandom2.prototype.next=function(dt){
if(!dt||dt<=0)dt=1;
var pn=Math.exp(-dt/this.tscale);
var s2=(1-pn*pn)/2;
var s3=(1-pn*pn*pn)/3;
var s4=(1-pn*pn*pn*pn)/4;
var r0=gaussRandom(),r1=gaussRandom();
var x0=Math.sqrt(s2);
var y0=s3/Math.sqrt(s2);
var y1=Math.sqrt((s4*s2-s3*s3)/s2);
if(isNaN(y0)||isNaN(y1)){y0=x0;y1=0;}
this.a1=this.a1*pn+x0*r0;
this.a2=this.a2*pn*pn+y0*r0+y1*r1;
return this.scale*(this.a1-this.a2);
}

#what's this?

sr = new SmoothRandom(10)
//series of smoothed random numbers
sr.next() //=>  0.1600
sr.next() //=>  0.1083
sr.next() //=>  0.0272
sr.next() //=> -0.0495
sr.next() //=> -0.1470
sr.next() //=> -0.2501
sr.next() //=> -0.3208
sr.next() //=> -0.3581
//with any step
sr.next(1)    //=> -0.3547
sr.next(1)    //=> -0.3299
sr.next(1)    //=> -0.2926
sr.next(0.01) //=> -0.2921
sr.next(0.01) //=> -0.2917
sr.next(0.02) //=> -0.2909
sr.next(0.04) //=> -0.2894
sr.next(1000) //=>  0.7815

#using with animation

prevTime=new Date();
// var posRand={x:new SmoothRandom(),y:new SmoothRandom()};
var posRand={x:new FreqRandom(0.25),y:new FreqRandom(0.25)};
var el=document.createElement('div');el.textContent='hoge';
document.body.appendChild(el);
function update(){
  var time=new Date();
  var dt=(time-prevTime)/1000;
  prevTime=time;
  el.style.position='fixed'
  el.style.left=400+200*posRand.x.next(dt)+'px';
  el.style.top=400+200*posRand.y.next(dt)+'px';
  setTimeout(update,10+20*Math.random())
}
update();

#sound

var samplerate = 44100;
var hz = 441;
fr = new FreqRandom(hz);
var sounddata = []
for(var i=0;i<samplerate;i++){
  sounddata[i]=0.25*fr.next(1/samplerate)*Math.exp(-8*i/samplerate);
}

#view

c=document.createElement('canvas');
document.body.appendChild(c);
c.width=1024;c.height=768;
g=c.getContext('2d');
g.fillRect(0,c.height/2,c.width,1);
function render(rnd,color){
  var x=0;
  g.fillStyle=color;
  for(var i=0;i<=c.width;i++){
    dx=1+8*(1+Math.cos(i/20))*i/c.width;
    x+=dx;
    var n=rnd.next(dx/300);
    g.fillRect(x/2,c.height*(0.5-0.5*n/6),2,2);
  };
}
render(new SmoothRandom(0.25),'red');
render(new FreqRandom(1),'blue');
render(new NoiseRandom1(0.25),'gray');
render(new NoiseRandom2(0.25),'green');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment