You are not recognized as the original poster of this topic.
function mod(n,m){return(n%m+m)%m;}
class Delay{
constructor(maxDelay){
this.maxDelay=maxDelay;
this.buffer=new Array(maxDelay+1).fill(0);
this.writeIndex=0;
this.delay=maxDelay;
}
setDelay(delay){this.delay=Math.min(delay,this.maxDelay);}
tick(input){
this.buffer[this.writeIndex]=input;
const readIndex=mod(this.writeIndex-this.delay+this.buffer.length,this.buffer.length),
output=this.buffer[readIndex];
this.writeIndex=(this.writeIndex+1)%this.buffer.length;
return output;
}
nextOut(){return this.buffer[mod(this.writeIndex-this.delay+this.buffer.length,this.buffer.length)];}
clear(){this.buffer.fill(0);this.writeIndex=0;}
}
class OnePole{
constructor(){this.a1=0;this.b0=1;this.state=0;}
setPole(pole){
this.a1=pole;
this.b0=1-pole; //Lowpass with unity DC gain
}
tick(input){
this.state=input*this.b0+this.a1*this.state;
return this.state;
}
clear(){this.state=0;}
}
function isPrime(n){
if(n<=1)return false;if(n<=3)return true;
if(n%2===0||n%3===0)return false;
let i=5;while(i*i<=n){if(n%i===0||n%(i+2)===0)return false;i+=6;}
return true;
}
class JCRev{
constructor(T60,sampleRate=44100){
if(T60<=0)throw new Error("T60 must be positive");
this.sampleRate=sampleRate;
this.lastFrame=[0,0];
const originalLengths=[1116,1356,1422,1617,225,341,441,211,179],
scaler=sampleRate/44100;
//Adjust delay lengths to be odd primes
this.delayLengths=originalLengths.map(len=>{
let delay=Math.floor(scaler*len);
if(delay%2===0)delay++;
while(!isPrime(delay))delay+=2;
return delay;
});
//Initialize allpass delays (using indices 4,5,6 from original lengths)
this.allpassDelays=[];
for(let i=0;i<3;i++){
const len=this.delayLengths[i+4],
delay=new Delay(len);
delay.setDelay(len);
this.allpassDelays.push(delay);
}
//Initialize comb delays (indices 0-3)
this.combDelays=[];
for(let i=0;i<4;i++){
const len=this.delayLengths[i],
delay=new Delay(len);
delay.setDelay(len);
this.combDelays.push(delay);
}
//Initialize comb lowpass filters (one-pole with pole at 0.2)
this.combFilters=[];
for(let i=0;i<4;i++){
const filter=new OnePole();
filter.setPole(.2);
this.combFilters.push(filter);
}
//Decorrelation delays (indices 7 and 8)
this.outLeftDelay=new Delay(this.delayLengths[7]);
this.outLeftDelay.setDelay(this.delayLengths[7]);
this.outRightDelay=new Delay(this.delayLengths[8]);
this.outRightDelay.setDelay(this.delayLengths[8]);
this.allpassCoefficient=.7;
this.effectMix=.3;
this.combCoefficients=new Array(4).fill(0);
this.setT60(T60);
this.clear();
}
clear(){
this.allpassDelays.forEach(d=>d.clear());
this.combDelays.forEach(d=>d.clear());
this.combFilters.forEach(f=>f.clear());
this.outLeftDelay.clear();
this.outRightDelay.clear();
this.lastFrame=[0,0];
}
setT60(T60){
if(T60<=0)throw new Error("T60 must be positive");
for(let i=0;i<4;i++){
const delayTime=this.combDelays[i].delay;
this.combCoefficients[i]=Math.pow(10,(-3*delayTime)/(T60*this.sampleRate));
}
}
tick(input){
let current=input;
for(let i=0;i<3;i++){ //Process through three allpass filters in series
const delay=this.allpassDelays[i],
delayed=delay.nextOut(),
allpassOutput=-current+delayed,
delayInput=current+delayed*this.allpassCoefficient;
delay.tick(delayInput);
current=allpassOutput;
}
let combSum=0;
for(let i=0;i<4;i++){ //Process through four comb filters in parallel
const combDelay=this.combDelays[i],
combFilter=this.combFilters[i],
coeff=this.combCoefficients[i],
delayed=combDelay.nextOut(),
filtered=combFilter.tick(delayed),
feedback=filtered*coeff;
combDelay.tick(current+feedback);
combSum+=delayed;
}
//Apply decorrelation delays to left and right channels
const left=this.outLeftDelay.tick(combSum),
right=this.outRightDelay.tick(combSum);
//Mix wet/dry signals
const dryMix=1-this.effectMix,wetMix=this.effectMix;
this.lastFrame[0]=input*dryMix+left*wetMix;
this.lastFrame[1]=input*dryMix+right*wetMix;
return this.lastFrame;
}
}
let r=new JCRev(2.1,32000),tick=0,p=(x,y)=>Math.pow(Math.abs(x),y)*Math.sign(x);
function f(t){
let o=0;
for(let i=0;i<5;i++){
o+=p(sin(t*2000*(2**((i**1.75)/9))),2)*p(sin((t-8.4)*(1+i)),3000)*sin(t*(10-i)*8)*.1;
}
//if(tick%10000===0)r.clear();
tick++;
o=r.tick(o);
for(let i=0;i<o.length;i++){
o[i]=Math.tanh(o[i]);
}
return o;
}
let array=[],SR=16000,len=SR*10;
for(let i=0;i<len;i++){array.push([...f(i/SR)]);}
function lerp(a,b,x){return a+x*(b-a);}
function lerp2(a,b,x){return[a[0]+x*(b[0]-a[0]),a[1]+x*(b[1]-a[1])];}
function read(a,i){return lerp2(a[mod(floor(i),a.length)],a[mod(floor(i)+1,a.length)],(i%1+1)%1);}
let r2=new JCRev(3,32000);
return function DSP(t){
let o=[0,0];
for(let i=0;i<6;i++){
//let add=read(array,mod((t*-.5*SR*(1+i**1.4))+(sin(t*(i+2)*.4)*sin(t*(i+1))*SR*1.2),max(100,min((1-abs(sin(t*.001+i)))*array.length,array.length))));
let add=read(array,SR*sin(t*.3+6*i)*(i+1));
o[0]+=add[0]*.6;o[1]+=add[1]*.6;
}
return r2.tick((o[0]-o[1])*.4);
}