package nxm.dsp.test;

import nxm.sys.inc.ProvisionalUseOnly;
import nxm.sys.lib.BaseFile;
import nxm.sys.lib.Data;
import nxm.sys.lib.DataFile;
import nxm.sys.lib.Primitive;
import nxm.sys.libm.Window;

/** Creates FIR filter using a windowed Sinc<br>
   This filter is normalized by default

    @author  Jeanette McCall
    @since   NeXtMidas 3.9.1
*/
@ProvisionalUseOnly("Created for educational purposed and minimally tested")
public class firsinc extends Primitive {

  /** Filter type list */
  public static final String typeList = "LowPass,HighPass,BandPass";
  /** Low Pass Filter        */ public static final int LOW=1;
  /** High Pass Filter       */ public static final int HIGH=2;
  /** Band Pass Filter       */ public static final int BAND=3;
  /** Maximum number of taps */ public static final int MAXTAPS=131071;
  /** Default number of taps */ public static final int DEFTAPS = 1025;

  private DataFile ho;
  private Data dbw;
  private int type,ntap;
  boolean debug, inref, cmplx;
  private double freqCutoff;
  private double bandwidth;
  private String windowName;
  private float[]  window;
  private boolean normalize;

  /** default constructor */
  public firsinc () {}

  public int open() {

    debug = MA.getState("/DEBUG");

    // Get parameters
    freqCutoff = MA.getD("FREQ");

    // Open output file
    ho = MA.getDataFile("OUT","1000","SF",0);
    ho.open(BaseFile.OUTPUT);

    if (MA.isPresent("NTAPS") || !MA.isPresent("/BW")) {
      ntap = MA.getL("NTAPS",DEFTAPS);
      if (ntap > MAXTAPS) {
        M.warning("Maximum number of taps exceeded. Using default maximum of "+MAXTAPS);
        ntap = MAXTAPS;
      }
      else if ((ntap % 2) == 0) {
     // adjust if needed to make this an odd number of taps, so have center point
        ntap += 1;
        M.info("Adjusting number of taps to odd number:"+ ntap);
      }
    }
    else {
      // first at calculating ntaps from BW
      bandwidth = MA.getD("/BW",4.0/DEFTAPS);
      ntap = (int)((4/bandwidth) + 1);
      // adjust if needed to make this an odd number of taps, so have center point
      if ((ntap % 2) == 0) ntap += 1;
    }

    windowName = MA.getS("WIND", "BLAC");
    window = Window.get(windowName, ntap, 1);

    normalize = !MA.isPresent("/NONORM");

    dbw = new Data("SF",ntap);

    if (debug)  {
      System.out.println("ntap: "+ntap);
      System.out.println("type: "+type);
      System.out.println("freqC: "+freqCutoff);
      System.out.println("bandW: "+bandwidth);
    }

    sincwin(dbw, freqCutoff, ntap);
    ho.setSize(ntap);
    ho.write (dbw,ntap);
    ho.close();


    return FINISH;
  }

  private void sincwin (Data odata, double freqCutoff, int ntaps) {
    float outbuf[] = odata.castF(false);

    double twoPI = 2 * Math.PI;
    int center = (ntaps - 1)/2;
    double twoPITimesFreqC = twoPI * freqCutoff;
    double sum = 0;
    for (int i=0; i < ntaps; i++) {
      if (i!=center) {
        outbuf[i]=(float)(((Math.sin(twoPITimesFreqC*(i-center)))/(i-center))*window[i]);
      }
      else {
        outbuf[i] = (float)twoPITimesFreqC;
      }
      sum += outbuf[i];
    }
    if (normalize) {
      for (int i=0; i < ntaps; i++) {
        outbuf[i] /= sum;
      }
    }

    odata.uncast(outbuf, true);
    ntap = ntaps;
  }

}
