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);
}
}
}