package com.codefixia.audio; import com.codefixia.drumcloud.DrumCloud; /** https://github.com/supercollider/supercollider/blob/master/server/plugins/FilterUGens.cpp */ public class RLPF implements Filter { float a0, b1, b2, y1, y2; float freq; float reson; float sampleRate; boolean changed; public RLPF(float sampleRate_) { this.sampleRate = sampleRate_; reset(); this.setFilter(sampleRate / 4, 0); } private void reset() { a0 = 0.f; b1 = 0.f; b2 = 0.f; y1 = 0.f; y2 = 0.f; //setFilter(sampleRate/2, 0); } /** f is in the range 0-sampleRate/2 */ public void setFilter(float f, float r) { // constrain // limit to 0-1 f = DrumCloud.constrain(f, 0, sampleRate/2); r = DrumCloud.constrain(r, 0, 1); // remap to appropriate ranges f = DrumCloud.map(f, 0, sampleRate/4, 30, sampleRate / 4); r = DrumCloud.map(r, 0, 1, 0.005f, 2); DrumCloud.println("rlpf: f "+f+" r "+r); this.freq = f * DrumCloud.TWO_PI / sampleRate; this.reson = r; changed = true; } public float applyFilter(float in) { float y0; if (changed) { float D = DrumCloud.tan(freq * reson * 0.5f); float C = ((1.f-D)/(1.f+D)); float cosf = DrumCloud.cos(freq); b1 = (1.f + C) * cosf; b2 = -C; a0 = (1.f + C - b1) * .25f; changed = false; } y0 = a0 * in + b1 * y1 + b2 * y2; y2 = y1; y1 = y0; if (Float.isNaN(y0)) { reset(); } return y0; } }