notsoreverb

fake reverb effect I ported over. really laggy probably

Log in to post a comment.

ditty.bpm = 170;

// it's extremely minified because it's reused from a schroeder algorithm I had made. also, some of the implementations
// might be wrong
class CircularBuffer{constructor(size){this.buffer=Array(size).fill(0);this.bufferLength=size;this.head=this.tail=0}cubicInterpolation(y0,y1,y2,y3,mu){var a0=0;var a1=0;var a2=0;var a3=0;var mu2=mu*mu;a0=-.5*y0+1.5*y1-1.5*y2+.5*y3;a1=y0-2.5*y1+2*y2-.5*y3;a2=-.5*y0+.5*y2;a3=y1;return a0*mu*mu2+a1*mu2+a2*mu+a3}getSample(inValue){this.tail=this.head-inValue;if(this.tail>this.bufferLength-1){this.tail-=this.bufferLength}else if(this.tail<0){this.tail+=this.bufferLength}return this.buffer[this.tail]}write(inValue){this.head=(this.head+=1)%this.bufferLength;this.buffer[this.head]=inValue}readCubic(index){var mu=index-Math.floor(index);return this.cubicInterpolation(this.getSample(Math.floor(index)+1),this.getSample(Math.floor(index)),this.getSample(Math.floor(index)-1),this.getSample(Math.floor(index)-2),mu)}}
class AllPass{constructor(inValue,inG,sr){this.delayLength=inValue;this.g=inG;this.delayedSample=this.feedForwardSample=0;this.buffer=new CircularBuffer(sr)}process(sample){this.delayedSample=this.buffer.readCubic(this.delayLength);this.buffer.write(sample+this.delayedSample*this.g);this.feedForwardSample=sample*-this.g;return this.delayedSample+this.feedForwardSample}setFeedback(i){this.g=i}}

class Reverb {
	constructor (SR,delays,decay=.5,dry=1.,wet=.5,enableLowpass=true,cutoff=.4) {
		this.SR = SR;
		this.options = {decay:decay,dry:dry,wet:wet};

		this.t = Array(delays.length).fill(0);
		this.bufs = delays.map(x=>Array(x).fill(0));
		this.alls = delays.map(x=>new AllPass(x,Math.random()/4+.25,SR))

		this.eLP = enableLowpass;
		this.l = 0;
		this.rl = 0
		this.cutoff = cutoff;
	}

	changeOptions (opt) {
		for (let i=0;i<Object.values(opt).length;i++) {
			this.options[Object.keys(opt)[i]] = Object.values(opt)[i];
		}
	}

	process (x) {
		for (let i=0;i<this.bufs.length;i++) {
			this.t[i] = (this.t[i]+1)%this.bufs[i].length;
			this.bufs[i][this.t[i]] = (i==0?x:this.bufs[i-1][this.t[i-1]])+this.alls[i].process(this.bufs[i][this.t[i]]*(this.options.decay))||0
		}
		let o;
		if (this.eLP) {
			this.l = this.bufs[this.bufs.length-1][this.t[this.bufs.length-1]]*this.cutoff+this.l*(1-this.cutoff);
			this.rl = x*this.cutoff+this.rl*(1-this.cutoff);
			o = this.l;
		}
		else {
			o=this.bufs[this.bufs.length-1][this.t[this.bufs.length-1]]-x;
		}

		return (o-(this.eLP?this.rl:0))*this.options.wet+x*this.options.dry
	}
}

let StereoReverbPreset = filter.def(class {
	constructor (options) {
		this.SR = 48e3;
        this.eff = [new Reverb(48e3,[5481,9547,12287,13256],.5,1.,.2),new Reverb(48e3,[5485,9549,12288,13257],.5,1.,.2)];
        this.x = [0,0]; // i'm adding a hp filter because it's really unstable sometimes
	}

    process (input,options) {
        let unFiltOut = [this.eff[0].process(input[0]),this.eff[1].process(input[1])];
        // there might be a quicker method for this but idrk
        unFiltOut.forEach((x,i)=>{
            this.x[i] += (x - this.x[i])/80;
        })
        return this.x.map((x,i)=>x-unFiltOut[i]);
    }
}
)

const syn = synth.def( (phase, env) => ((phase*2&1)-.5) * env.value );
const syn2 = synth.def( (phase, env) => ((phase%1)-.5) * env.value );


loop( () => {

    scale(db,scales.minor,1).forEach(x=>{
        syn.play(x);
        sleep(1)
    })
    
    scale(db,scales.minor,1).forEach(x=>{
        syn2.play(x);
        sleep(.5)
    })
        scale(db,scales.minor,1).forEach(x=>{
        syn2.play(x-12);
        sleep(.5)
    })

}).connect(StereoReverbPreset.create());