package jass.patches; import jass.engine.*; import jass.generators.*; /** Allpass with delay M 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}} y = H(z) x H(z) = (z^{-m} + a)/(1 + a*z^{-m})) Must have delay greater than the bufferSize. BUGS: Does not support removal of source. @author Kees van den Doel (kvdoel@cs.ubc.ca) */ public class AllPass extends InOut { protected float srate; protected float del; // delay in seonds protected float a=0; // Filter parameter protected Mixer mixer; protected Delay delay1; protected Delay delay2; /** Create. For derived classes. @param bufferSize Buffer size used for real-time rendering. */ public AllPass(int bufferSize) { super(bufferSize); } /** Create. For derived classes. @param bufferSize Buffer size used for real-time rendering. @param srate sampling rate in Hz */ public AllPass(int bufferSize,float srate) { super(bufferSize); this.srate = srate; init(); } /** Init and allocate. */ protected void init() { mixer = new Mixer(bufferSize,3); delay1 = new Delay(bufferSize,srate); delay2 = new Delay(bufferSize,srate); try { mixer.addSource(delay1); mixer.setGain(0,-a); mixer.addSource(delay2); mixer.setGain(1,1); delay1.addSource(mixer); } catch(SinkIsFullException e) { System.out.println(this+" "+e); } long t = getTime(); mixer.setTime(t); delay1.setTime(t); delay2.setTime(t); } /** Add source to Sink. Override to allow one input only and add to mixer with gain coefficient a and to delay 2. This will be called after init() so mixer will already have 2 inputs @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(2,a); delay2.addSource(s); // add to the superclass. THis is for administrative reasons only, // the source cache is not used here. return super.addSource(s); } } /** Set delay del. (=M/srate) @param del delay in seconds */ public void setM(float del) throws IllegalArgumentException { this.del = del; delay1.setRecursiveDelay(del); delay2.setRawDelay(del); } /** Set filter parameter a. @param a allpas parameter */ public void setA(float a) { this.a = a; mixer.setGain(0,-a); mixer.setGain(2,a); } /** Compute the next buffer and store in member float[] buf. */ protected void computeBuffer() { try { buf = mixer.getBuffer(getTime()); } catch(BufferNotAvailableException e) { System.out.println(this+" "+e); } } }