import java.awt.*;
import java.util.*;
public class FFT
 {
  static M parent;
  //FFTMP mp;
  //FFTCP cp;
  //FFTCtrl c;
  String name;
  String v="newbe";
  LC lc,lctl,lctr,lcbl,lcbr;
  Frame frame;
  double[] a,fr,fj,tr,tj;
  int length=0;
  boolean originCentered=false;
  boolean auw=true;
  int tpts=0;
  Rec[] rectr=new Rec[0];
  Rec[] rec=new Rec[0];
  Rec[] rectj=new Rec[0];
  Rec[] recfr=new Rec[0];
  Rec[] recfj=new Rec[0];
  double gw,gh,glx,dx;
  double tsc=500,fsc=100,grscy=100;
  int mri=0;
  dP  odp;
  Wav wav=null;
  FFT(M p,String n)
   {
    parent=p;
    name=n;
    p.te.teS("aLF "+name+"lf");
    p.te.teS("aLSpP "+name+"lspp("+name+"lf)");
    p.te.teS("aLSpP "+name+"tlspp("+name+"lspp,top,horz)");
    p.te.teS("aLSpP "+name+"blspp("+name+"lspp,bottom,horz)"); 
    p.te.teS("aRec ra(0,0,500,400) aRec rb(0,0,500,400)");
    p.te.teS("aLC "+name+"lctl ("+name+"tlspp,left,ra,rb)"); 
    p.te.teS("aLC "+name+"lctr ("+name+"tlspp,right,ra,rb)"); 
    p.te.teS("aLC "+name+"lcbl ("+name+"blspp,left,ra,rb)"); 
    p.te.teS("aLC "+name+"lcbr ("+name+"blspp,right,ra,rb)"); 
    lctl=(LC)Te.LCh.get(name+"lctl");
    lctl.edfft=true;
    //lctl.clearscreen();
    lctr=(LC)Te.LCh.get(name+"lctr");
    lctr.edfft=true;
    //lctr.clearscreen();
    lcbl=(LC)Te.LCh.get(name+"lcbl");
    lcbl.edfft=true;
    //lcbl.clearscreen();
    lcbr=(LC)Te.LCh.get(name+"lcbr");
    lcbr.edfft=true;
    //lcbr.clearscreen();
    //int origin=(originCentered)?length/2:0;
    initFFTS(128);
    p.te.schleep(2000);
    repaintViews();
    tta("FFT is ready");
   }
  public void tta(String s) { FFT.parent.tta(s); }
  public void tta1(String s) { FFT.parent.tta1(s); }
  public void u()
   {
    if(v.equals("tr") || v.equals("tj") ) transform(-1,tr,tj,fr,fj);
    if(v.equals("fr") || v.equals("fj") ) transform(1,fr,fj,tr,tj);
    repaintViews();
    if(auw) uw();
   }
  public void trt() { transform(-1,tr,tj,fr,fj); }
  public void trf() { transform(1,fr,fj,tr,tj); }
  private void transform(int sign,double[] sar,double[] sai,double[] bar,double[] bai) 
   {
    double ar[]=sar;
    double ai[]=sai;
    double br[]=bar;
    double bi[]=bai;
    for (int i=0; i<length; ++i) 
     {
      br[i]=ar[i];
      bi[i]=ai[i];
     }
    if (originCentered) 
     {
      for (int i=1; i<length; i+=2) 
       {
        br[i]=-br[i];
        bi[i]=-bi[i];
       }
     }
    FFTGuts.complexToComplex(sign,length,br,bi);
    if (originCentered) 
     {
      for (int i=1; i<length; i+=2) 
       {
        br[i]=-br[i];
        bi[i]=-bi[i];
       }
     }
   }
  void initFFTS(int l) 
   {
    setlength(l);
    initFFT();
   }
  void setlength(int l)
   {
    if(length==l ) return;
    length=l;
    fr=new double[length];
    fj=new double[length];
    tr=new double[length];
    tj=new double[length];
   }
  //void cw(String wavname) { wav=Wav.fftcw(parent,wavname,this); }  fix for changes from machd
  void uw() 
   {
    if(wav==null) { tta("for FFT:"+name+" wav is null"); }
    // 2020   else wav.fftuw(this); 
   }
  void initFFT()
   {
    fr[1]=1.0f;
    transform(1,fr,fj,tr,tj);
   }
  void repaintViews() 
   {
    drawFFTS("tr");
    drawFFTS("tj");
    drawFFTS("fr");
    drawFFTS("fj");
   }
  void setView(LC j)
   {
    if(j.name.equals(name+"lctl")) setView("fr");
    else if(j.name.equals(name+"lctr")) setView("fj");
    else if(j.name.equals(name+"lcbl")) setView("tr");
    else if(j.name.equals(name+"lcbr")) setView("tj");
    else tta("setView did not find j.name:"+j.name);
   }
  void listtr()
   {
    for(int i=0;i<tr.length;i++)
     {
      tta("i:"+i+" tr[i]:"+tr[i]);
     }
   }
  void setView(String vv)
   {
    if(v.equals(vv)) return;
    v=vv;
    if(v.equals("tr"))
     {
      lc=lcbl;
      a=tr;
      rec=rectr;
      grscy=tsc;
     }
    else if(v.equals("tj"))
     {
      lc=lcbr;
      a=tj;
      rec=rectj;
      grscy=tsc;
     }
    else if(v.equals("fr"))
     {
      lc=lctl;
      a=fr;
      rec=recfr;
      grscy=fsc;
     }
    else if(v.equals("fj"))
     {
      lc=lctr;
      a=fj;
      rec=recfj;
      grscy=fsc;
     }
    else tta("setView error v:"+v);
    //tta("setView v:"+v); 
    //tta("setView lc.name:"+lc.name);
   }
  void drawFFTS(String v)
   {
    if(tpts !=tr.length)
     {
      tpts=tr.length;
      rectr=new Rec[tpts];
      rectj=new Rec[tpts];
      recfr=new Rec[tpts];
      recfj=new Rec[tpts];
     }
    setView(v);
    drawFFTS();
   }
  void drawFFTS()
   {
    gw=lc.width;
    gh=lc.height;
    glx=-gw/2;
    lc.clearscreen();
    lc.drawLine(glx,0,glx+gw,0);
    dx=gw/(tpts-1);
    double x=glx;
    for (int i=0; i<tpts; ++i)
     {
      lc.drawLine(x,0,x,a[i]*grscy);
      rec[i]=new Rec(x-3,-3+a[i]*grscy,6,6);
      lc.offsgfill(rec[i].rect);
      x+=dx;
     }
    lc.repaint();
   }
  void mmdp(LC j,dP dp)
   {
    //tta("mmdp  LC:"+j.name);
   }
  boolean mpdp(LC j,dP dp)
   {
    setView(j);
    mri=-1;
    for(int i=0;i<tpts;i++) 
     {
      if(rec[i].contains(dp))
       {
        tta("rec i:"+i);
        mri=i;
        return true;
       }
     }
    return false;
   }
  boolean mcdp(LC j,dP dp)
   {
    tta("mcdp LC:"+j.name);
    return false;
   }
  void mddp(LC j,dP dp)
   {
    if(mri == -1) return;
    setView(j);
    a[mri]=dp.y/grscy;
    u();
   }
  void mrdp(LC j,dP dp)
   {
    mri=-1;
    //tta("mrdp LC:"+a.name);
   }
 }
// Simple Fast Fourier Transform.
class FFTGuts
 {
  public static void complexToComplex(int sign, int n, double ar[], double ai[]) 
   {
    double scale=(double)Math.sqrt(1.0f/n);
    int i,j;
    for (i=j=0; i<n; ++i) 
     {
      if (j>=i) 
       {
        double tempr=ar[j]*scale;
        double tempi=ai[j]*scale;
        ar[j]=ar[i]*scale;
        ai[j]=ai[i]*scale;
        ar[i]=tempr;
        ai[i]=tempi;
       }
      int m=n/2;
      while (m>=1 && j>=m) 
       {
        j -= m;
        m /= 2;
       }
      j += m;
     }
    int mmax,istep;
    for (mmax=1,istep=2*mmax; mmax<n; mmax=istep,istep=2*mmax) 
     {
      double delta=(double)sign*3.141592654f/(double)mmax;
      for (int m=0; m<mmax; ++m) 
       {
        double w=(double)m*delta;
        double wr=(double)Math.cos(w);
        double wi=(double)Math.sin(w);
        for (i=m; i<n; i+=istep) 
         {
          j=i+mmax;
          double tr=wr*ar[j]-wi*ai[j];
          double ti=wr*ai[j]+wi*ar[j];
          ar[j]=ar[i]-tr;
          ai[j]=ai[i]-ti;
          ar[i] += tr;
          ai[i] += ti;
         }
       }
      mmax=istep;
     }
   }
 }
