/* For Copyright and License see LICENSE.txt and COPYING.txt in the root directory */
package com.nerdscentral.audio.time;
import java.util.ArrayList;
import java.util.List;
import com.nerdscentral.audio.core.SFConstants;
import com.nerdscentral.audio.core.SFData;
import com.nerdscentral.audio.core.SFSignal;
import com.nerdscentral.audio.pitch.algorithm.SFRBJFilter;
import com.nerdscentral.audio.pitch.algorithm.SFRBJFilter.FilterType;
import com.nerdscentral.sython.Caster;
import com.nerdscentral.sython.SFPL_Operator;
import com.nerdscentral.sython.SFPL_RuntimeException;
public class SF_AnalogueChorus implements SFPL_Operator
{
private static final long serialVersionUID = 1L;
@Override
public String Word()
{
return Messages.getString("SF_AnalogueChorus.0"); //$NON-NLS-1$
}
private static double sat(double x)
{
double y = x >= 0 ? x / (x + 1) : x / (1 - x);
return y;
}
@Override
public Object Interpret(Object input) throws SFPL_RuntimeException
{
List<Object> lin = Caster.makeBunch(input);
SFSignal inR = Caster.makeSFSignal(lin.get(0));
SFSignal mod = Caster.makeSFSignal(lin.get(2));
SFSignal in = SFData.realise(inR);
double filt = 5000.0;
if (lin.size() > 4)
{
filt = Caster.makeDouble(lin.get(5));
}
int delay = (int) ((Caster.makeDouble(lin.get(1))) * SFConstants.SAMPLE_RATE_MS);
double feedBack = Caster.makeDouble(lin.get(3));
double drive = Caster.makeDouble(lin.get(4));
double r = in.getLength();
double feedForward = 1.0 - feedBack;
FilterType type = FilterType.LOWPASS;
if (filt > 15000)
{
type = FilterType.ALLPASS;
filt = 5000.0;
}
SFRBJFilter filter = new SFRBJFilter();
filter.calc_filter_coeffs(type, filt, 1.0, 0);
SFSignal buff = in.replicateEmpty();
SFSignal outL = in.replicateEmpty();
SFSignal outR = in.replicateEmpty();
for (int n = 0; n < r; ++n)
{
buff.setSample(n, filter.filter(in.getSample(n)));
}
// reboot the filter
filter = new SFRBJFilter();
filter.calc_filter_coeffs(type, filt, 1.0, 0);
for (int n = 0; n < r; ++n)
{
double mix = 0;
int delayGet = n - delay - ((int) (mod.getSample(n) * SFConstants.SAMPLE_RATE_MS));
if (delayGet < r && delayGet > -1)
{
mix = buff.getSample(delayGet);
}
double q = in.getSample(n);
outL.setSample(n, (q + mix) / 2.0);
outR.setSample(n, (q - mix) / 2.0);
buff.setSample(n, drive * (buff.getSample(n) * feedForward + filter.filter(sat(mix)) * feedBack));
}
List<SFSignal> ret = new ArrayList<>(2);
ret.add(outL);
ret.add(outR);
return ret;
}
}