Notice: Welcome to TinyChan, an account has automatically been created and assigned to you, you don't have to register or log in to use the board, but don't clear your cookies unless you have set a memorable name and password. Alternatively, you can restore your ID. The use of this site requires cookies to be enabled; please cease browsing this site if you don't consent.

TinyChan

New reply in topic: Bytebeat/Floatbeat/Funcbeat

You are not recognized as the original poster of this topic.

:

You are required to fill in a captcha for your first 5 posts. Sorry, but this is required to stop people from posting while drunk. Please be responsible and don't drink and post!
If you receive this often, consider not clearing your cookies.

Please familiarise yourself with the rules and markup syntax before posting.


Replying to Anonymous F…

Silly filter test (did this on my phone)…
var sampleRate=32000,
    PI=Math.PI,TAU=PI*2;
class Filter{ //generated by o1
  constructor(fs=sampleRate,freq=1000,Q=0.707){
    this.fs=fs; //sampling frequency
    this.g=0; //coefficient
    this.R=1; //damping factor (computed from Q)
    this.S1=0;this.S2=0; //state variables
    this.type=0; //filter type parameter (continuous LP/BP/HP control, 0 to 2)
    this.freq=freq; //cutoff frequency
    this.Q=Q; //Q(uality) factor
  }
  setParams(freq,Q,type){
    this.freq=freq;this.Q=Q;this.type=type;
    var wd=TAU*freq, //digital angular frequency
        T=1/this.fs, //sampling period
        wa=(2/T)*Math.tan(wd*T/2); //pre-warping the frequency for bilinear transform
        this.g=wa*T/2; //compute filter coefficient
        this.R=1/(2*Q); //compute damping factor from Q
  }
  process(x){
    //calculate the intermediate value 'v' using the state variables
    var v=(x-this.S2-this.R*this.S1)/(1+this.g*this.R+this.g*this.g),
        //update the state variables for the next sample
        S1_next=this.g*v+this.S1,
        S2_next=this.g*S1_next+this.S2,
        //compute the filter outputs
        LP=S2_next, //low-pass
        BP=S1_next, //band-pass
        HP=x-this.R*S1_next-S2_next; //high-pass
    //update the state variables
    this.S1=S1_next;this.S2=S2_next;
    //blend the outputs based on the 'type' parameter
    return this.type<=1?
      LP*(1-this.type)+BP*this.type: //between low-pass and band-pass
      BP*(2-this.type)+HP*(this.type-1); //between band-pass and high-pass
  }
}
//GPT-4o mini's miniFilter
function miniFilter(){this.z=0;this.fc=0.5;this.q=1;this.a=0;this.b=0;this.set_fc(0.5);this.set_q(1);}
miniFilter.prototype.set_fc=function(fc){this.fc=fc<0?0:fc>1?1:fc;this.a=Math.sin(PI*this.fc)/(2*this.q);};
miniFilter.prototype.set_q=function(q){this.q=q<0.1?0.1:q>10?10:q;};
miniFilter.prototype.run=function(x){this.b=this.a*(x-this.z)+this.z;this.z=this.b;return this.b;};
/* This is what a real/working filter looks like:
function DiodeFilter(){
  this.k=0;
  this.A=0;
  this.z=[0,0,0,0,0];
  this.ah;this.bh;this.fc;
  this.set_q(0);
  this.set_hpf(0.5);
  this.set_fc(.5);
}
DiodeFilter.prototype.set_hpf=function(fc){
  var K=fc*PI;
  this.ah=(K-2)/(K+2);
  this.bh=2/(K+2);
};
DiodeFilter.prototype.reset=function(){if(this.k<17)this.z=[0,0,0,0,0];};
DiodeFilter.prototype.set_q=function(q){
  this.k=20*q;this.A=1+.5*this.k;
};
DiodeFilter.prototype.set_fc=function(cutoff){
  cutoff*=cutoff;
  this.fc=cutoff<=0
    ?.02
    :(cutoff>=1?.999:cutoff);
};
function clip(x){return x/(1+Math.abs(x));}
DiodeFilter.prototype.run=function(x){
  var a=PI*this.fc;
  a=2*Math.tan(.5*a); //dewarping, not required with 2x oversampling
  var ainv=1/a,
      a2=a*a,
      b=2*a+1,
      b2=b*b,
      c=1/(2*a2*a2-4*a2*b2+b2*b2),
      g0=2*a2*a2*c,
      g=g0*this.bh,
      //current state
      s0=(a2*a*this.z[0]+a2*b*this.z[1]+this.z[2]*(b2-2*a2)*a+this.z[3]*(b2-3*a2)*b)*c,
      s=this.bh*s0-this.z[4],
      //solve feedback loop (linear)
      y5=(g*x+s)/(1+g*this.k),
      //input clipping
      y0=clip(x-this.k*y5);
  y5=g*y0+s;
  //compute integrator outputs
  var y4=g0*y0+s0,
      y3=(b*y4-this.z[3])*ainv,
      y2=(b*y3-a*y4-this.z[2])*ainv,
      y1=(b*y2-a*y3-this.z[1])*ainv;
  //update filter state
  this.z[0]+=4*a*(y0-y1+y2);
  this.z[1]+=2*a*(y1-2*y2+y3);
  this.z[2]+=2*a*(y2-2*y3+y4);
  this.z[3]+=2*a*(y3-2*y4);
  this.z[4]=this.bh*y4+this.ah*y5;
  return this.A*y4;
};
*/
function note(n,base=440,keys=12){return base*Math.pow(2,n/keys);}
var f=[],//new Filter(),
    c=[0,3,7,10,14,15,17,22,26];
for(let i=0;i<c.length;i++){f.push(new Filter());}
function dsp(t){
  /*var x=(t*60)%1<.5;
  f.setParams(
    1300+(Math.sin(t*3)*650),
    4,.2
  );
  return f.process(x)*.5;*/
  var x=0,i=0;
  for(;i<c.length;i++){
    f[i].setParams(
      1400+(Math.sin(t*(1.3+i)*1.3)*650),
      14,(((Math.sin((t+(i*TAU/c.length))*5)+1)/2)**7)*2
    );
    x+=f[i].process(
      ((t*note(c[i]+[5,10,3,8,1,6,-1][Math.floor(t*.8)%7],131.4,12.18))%1)-.5
    );
  }
  return x/16;
}
return dsp;