Sunday 8 January 2017

Modelling The EH Polychorus


/* For Copyright and License see LICENSE.txt and COPYING.txt in the root directory */
package com.nerdscentral.audio.time;

import java.util.List;
import java.util.ArrayList;

import com.nerdscentral.audio.SFConstants;
import com.nerdscentral.audio.SFSignal;
import com.nerdscentral.audio.SFData;
import com.nerdscentral.sython.Caster;
import com.nerdscentral.sython.SFPL_Context;
import com.nerdscentral.sython.SFPL_Operator;
import com.nerdscentral.sython.SFPL_RuntimeException;
import com.nerdscentral.audio.pitch.algorithm.SFRBJFilter;
import com.nerdscentral.audio.pitch.algorithm.SFRBJFilter.FilterType;

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, SFPL_Context context) throws SFPL_RuntimeException
    {
        List<Object> lin = Caster.makeBunch(input);
        try (
      SFSignal inR = Caster.makeSFSignal(lin.get(0));
      SFSignal mod = Caster.makeSFSignal(lin.get(2))
 ){
     try(SFData in = SFData.realise(inR))
     {
  if(inR instanceof SFData)
  {
      in.__pos__();
  } 
  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;
         SFRBJFilter filter = new SFRBJFilter();
  filter.calc_filter_coeffs(type, 5000.0, 1.0, 0);

  try (
       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, 5000.0, 1.0, 0);
      int last = 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));
      }
      Caster.prep4Ret(outL);
      Caster.prep4Ret(outR);
      List<SFSignal> ret=new ArrayList<>(2);
      ret.add(outL);
      ret.add(outR);
      return ret;
  }
            }
        }
    }
}

For an example of this effect using two out of phase polychorus models see this video:


No comments:

Post a Comment