/* For Copyright and License see LICENSE.txt and COPYING.txt in the root directory */
package com.nerdscentral.audio.combine;
import java.util.ArrayList;
import java.util.List;
import com.nerdscentral.audio.core.SFConstants;
import com.nerdscentral.audio.core.SFSignal;
import com.nerdscentral.audio.core.SFSingleTranslator;
import com.nerdscentral.sython.Caster;
import com.nerdscentral.sython.SFMaths;
import com.nerdscentral.sython.SFPL_Operator;
import com.nerdscentral.sython.SFPL_RuntimeException;
public class SF_Granulate implements SFPL_Operator
{
class BaseTranslator extends SFSingleTranslator
{
@Override
protected double getInputSample(int index)
{
if (index >= super.getLength()) return 0;
return super.getInputSample(index);
}
final int start;
final int rolloff;
@Override
public int getLength()
{
return rolloff * 2;
}
protected BaseTranslator(SFSignal input, int startIn, int rolloffIn)
{
super(input);
start = startIn;
rolloff = rolloffIn;
}
@Override
public double getSample(int index)
{
if (index < rolloff)
{
return getInputSample(index);
}
double offset = rolloff * 2 - index;
double attenue = offset / rolloff;
return getInputSample(index) * attenue;
}
}
class MiddleTranslator extends BaseTranslator
{
protected MiddleTranslator(SFSignal input, int startIn, int rolloffIn)
{
super(input, startIn, rolloffIn);
}
@Override
public double getSample(int index)
{
int relIndex = index + start;
if (index < rolloff)
{
double offset = index;
double attenue = offset / rolloff;
return getInputSample(relIndex) * attenue;
}
double offset = rolloff * 2 - index;
double attenue = offset / rolloff;
return getInputSample(relIndex) * attenue;
}
}
class EndTranslator extends BaseTranslator
{
protected EndTranslator(SFSignal input, int startIn, int rolloffIn)
{
super(input, startIn, rolloffIn);
}
@Override
public double getSample(int index)
{
int relIndex = index + start;
if (index < rolloff)
{
double offset = index;
double attenue = offset / rolloff;
return getInputSample(relIndex) * attenue;
}
return getInputSample(relIndex);
}
}
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public Object Interpret(final Object input) throws SFPL_RuntimeException
{
List<Object> lin = Caster.makeBunch(input);
SFSignal data = Caster.makeSFSignal(lin.get(0));
int rollOffSamples = (int) (Caster.makeDouble(lin.get(1)) * SFConstants.SAMPLE_RATE_MS);
int randSamples = lin.size() > 2 ? (int) (Caster.makeDouble(lin.get(2)) * SFConstants.SAMPLE_RATE_MS) : 0;
rollOffSamples /= 2;
List<Object> retOuter = new ArrayList<>();
int len = data.getLength();
int start = 0;
while (true)
{
int rollOffSamplesOld = rollOffSamples;
rollOffSamples += SFMaths.random() * randSamples;
int k = rollOffSamples * 2;
int end = start + k;
BaseTranslator trans = null;
if (start == 0)
{
BaseTranslator x = new BaseTranslator(data, start, rollOffSamples);
trans = x;
}
else if (end >= len)
{
BaseTranslator x = new EndTranslator(data, start, rollOffSamples);
trans = x;
}
else
{
BaseTranslator x = new MiddleTranslator(data, start, rollOffSamples);
trans = x;
}
// add to retout,
List<Object> thisRet = new ArrayList<>(2);
thisRet.add(trans);
thisRet.add(start / SFConstants.SAMPLE_RATE_MS);
retOuter.add(thisRet);
// All done
if (end >= len) break;
// move on by rolloutsamples
start += rollOffSamples;
rollOffSamples = rollOffSamplesOld;
}
return retOuter;
}
@Override
public String Word()
{
return Messages.getString("SF_Granulate.0"); //$NON-NLS-1$
}
}