/* 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.SFSignal;
import com.nerdscentral.sython.Caster;
import com.nerdscentral.sython.SFPL_Operator;
import com.nerdscentral.sython.SFPL_RuntimeException;
public class SF_MultipleResonantFilter implements SFPL_Operator
{
private static final long serialVersionUID = 1L;
private static class ResonantDescriptor
{
private final int delaySamples;
private final double volume;
public ResonantDescriptor(int delaySamplesIn, double volumeIn)
{
delaySamples = delaySamplesIn;
volume = volumeIn;
}
/**
* @return the delaySamples
*/
public int getDelaySamples()
{
return delaySamples;
}
/**
* @return the volume
*/
public double getVolume()
{
return volume;
}
}
@Override
public String Word()
{
return Messages.getString("SF_DirectResonate.0"); //$NON-NLS-1$
}
@Override
public Object Interpret(Object input) throws SFPL_RuntimeException
{
List<Object> lin = Caster.makeBunch(input);
SFSignal in = Caster.makeSFSignal(lin.get(0));
List<Object> lin2 = Caster.makeBunch(lin.get(1));
double forward = 1;
if (lin.size() > 2)
{
forward = Caster.makeDouble(lin.get(2));
forward = SFConstants.fromDBs(forward);
}
List<ResonantDescriptor> descriptors = new ArrayList<>(lin.size());
for (int i = 0; i < lin2.size(); ++i)
{
List<Object> llin = Caster.makeBunch(lin2.get(i));
double volume = Caster.makeDouble(llin.get(0));
int delay = (int) ((Caster.makeDouble(llin.get(1)) * SFConstants.SAMPLE_RATE_MS));
descriptors.add(new ResonantDescriptor(delay, SFConstants.fromDBs(volume)));
}
SFSignal out = in.replicate();
double r = in.getLength();
// Scale forward so it effect is the same as resonators are added or taken away
forward = Math.pow(forward, 1.0 / descriptors.size());
for (int n = 0; n < r; ++n)
{
double q = out.getSample(n);
for (ResonantDescriptor descriptor : descriptors)
{
double volume = descriptor.getVolume();
int delay = descriptor.getDelaySamples();
int index = n + delay;
if (n < delay)
{
q = q * volume;
out.setSample(n, q);
}
if (index < r)
{
out.setSample(index, out.getSample(index) * forward + q * volume);
}
}
}
return out;
}
}