/*
* HalfNES by Andrew Hoffman
* Licensed under the GNU GPL Version 3. See LICENSE file
*/
package com.grapeshot.halfnes.audio;
/**
*
* @author Andrew
*/
public class Reverberator implements AudioOutInterface {
AudioOutInterface iface;
CircularBuffer cb;
double echo, lp_coef, hp_coef;
public Reverberator(AudioOutInterface i, int length, double echo_gain, double lp_coef, double hp_coef) {
this.echo = echo_gain;
this.lp_coef = lp_coef;
this.hp_coef = hp_coef;
iface = i;
cb = new CircularBuffer(length);
}
int lpaccum = 0;
private int lowpass_filter(int sample) {
sample += lpaccum;
lpaccum -= sample * lp_coef;
return lpaccum;
}
private int dckiller = 0;
private int highpass_filter(int sample) {
//for killing the dc in the signal
sample += dckiller;
dckiller -= sample * hp_coef;//the actual high pass part
dckiller += (sample > 0 ? -1 : 1);//guarantees the signal decays to exactly zero
return sample;
}
@Override
public void outputSample(int sample) {
sample -= cb.read() * echo;
if (sample < -32768) {
sample = -32768;
//System.err.println("clip");
}
if (sample > 32767) {
sample = 32767;
//System.err.println("clop");
}
cb.write(lowpass_filter(highpass_filter(sample)));
if (!(iface == null)) {
iface.outputSample(sample);
}
}
@Override
public void flushFrame(boolean waitIfBufferFull) {
if (!(iface == null)) {
iface.flushFrame(waitIfBufferFull);
}
}
@Override
public void pause() {
if (!(iface == null)) {
iface.pause();
}
}
@Override
public void resume() {
if (!(iface == null)) {
iface.resume();
}
}
@Override
public void destroy() {
if (!(iface == null)) {
iface.destroy();
}
}
@Override
public boolean bufferHasLessThan(int samples) {
if (!(iface == null)) {
return iface.bufferHasLessThan(samples);
} else {
return false;
}
}
}