package jass.patches; import jass.engine.*; import jass.generators.*; /** Delay line with a one pole low-pass. Used in Moorers reverb. See e.g. @book{Steiglitz96, title = {A Digital Signal Processing Primer with Applications to Digital Audio and Computer Music}, author = {Ken Steiglitz}, publisher = {Addison-Wesley}, address = {New York}, year = {1996}, pages = {290--295}} BUGS: Does not support removal of source. @author Kees van den Doel (kvdoel@cs.ubc.ca) */ public class LowPassComb extends InOut { protected float srate; protected float R=0; // feedback parameter protected float g=0; // low-pass parameter protected float del=0; // delay in seconds protected Mixer mixer; protected Delay delay; protected OnePoleLowPass lowpass; /** Create. For derived classes. @param bufferSize Buffer size used for real-time rendering. */ public LowPassComb(int bufferSize) { super(bufferSize); } /** Create. For derived classes. @param bufferSize Buffer size used for real-time rendering. @param srate sampling rate in Hz */ public LowPassComb(int bufferSize,float srate) { super(bufferSize); this.srate = srate; init(); } /** Init and allocate. */ protected void init() { mixer = new Mixer(bufferSize,2); delay = new Delay(bufferSize,srate); lowpass = new OnePoleLowPass(bufferSize); try { mixer.addSource(lowpass); lowpass.addSource(delay); delay.addSource(mixer); } catch(SinkIsFullException e) { System.out.println(this+" "+e); } long t = getTime(); mixer.setTime(t); delay.setTime(t); lowpass.setTime(t); } /** Add source to Sink. Override to allow one input only and add to mixer @param s Source to add. @return object representing Source in Sink (may be null). */ public Object addSource(Source s) throws SinkIsFullException { if(getSources().length > 0) { throw new SinkIsFullException(); } else { mixer.addSource(s); mixer.setGain(1,1f); // add to Vector so that other stuff like getSources will work // maybe not necessary?? return super.addSource(s); } } /** Set delay del. (=L/srate) @param del delay in seconds */ public void setL(float del) throws IllegalArgumentException { this.del = del; delay.setRecursiveDelay(del); } /** Set feedback R. @param R feedback */ public void setR(float R) { this.R = R; mixer.setGain(0,R); // 0 is the feedback input to the mixer } /** Set low-pass parameter g. @param g low-pass parameter g. */ public void setG(float g) { this.g = g; lowpass.setG(g); } /** Compute the next buffer and store in member float[] buf. */ protected void computeBuffer() { // Time has now been incremented and external Sources // have been called, but there are none since this has been // routed through the subpatch // Call getBuffer on the // contained subpatch. It will call getBuffer() on // atached Sources, but they are already at this time so will // just return their cached buffer. We are wasting only an extra method call. try { buf = mixer.getBuffer(getTime()); } catch(BufferNotAvailableException e) { System.out.println(this+" "+e); } } }