import java.awt.*;
import java.util.Arrays;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.util.EventObject;
import java.util.Vector;
import javax.sound.sampled.*;
import javax.sound.sampled.DataLine.Info;
import javax.sound.sampled.SourceDataLine;
import javax.swing.*;
import javax.sound.sampled.AudioFormat;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.Enumeration;
import java.io.*;
public class Wave extends Thread
 {
  /*
  byte: The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive). The byte data type can be useful for saving memory in large arrays, where the memory savings actually matters. They can also be used in place of int where their limits help to clarify your code; the fact that a variable's range is limited can serve as a form of documentation.
  short: The short data type is a 16-bit signed two's complement integer. It has a minimum value of -32,768 and a maximum value of 32,767 (inclusive). As with byte, the same guidelines apply: you can use a short to save memory in large arrays, in situations where the memory savings actually matters.
  int: By default, the int data type is a 32-bit signed two's complement integer, which has a minimum value of -231 and a maximum value of 231-1. In Java SE 8 and later, you can use the int data type to represent an unsigned 32-bit integer, which has a minimum value of 0 and a maximum value of 232-1. Use the Integer class to use int data type as an unsigned integer. See the section The Number Classes for more information. Static methods like compareUnsigned, divideUnsigned etc have been added to the Integer class to support the arithmetic operations for unsigned integers.
  long: The long data type is a 64-bit two's complement integer. The signed long has a minimum value of -263 and a maximum value of 263-1. In Java SE 8 and later, you can use the long data type to represent an unsigned 64-bit long, which has a minimum value of 0 and a maximum value of 264-1. Use this data type when you need a range of values wider than those provided by int. The Long class also contains methods like compareUnsigned, divideUnsigned etc to support arithmetic operations for unsigned long.
  float: The float data type is a single-precision 32-bit IEEE 754 floating point. Its range of values is beyond the scope of this discussion, but is specified in the Floating-Point Types, Formats, and Values section of the Java Language Specification. As with the recommendations for byte and short, use a float (instead of double) if you need to save memory in large arrays of floating point numbers. This data type should never be used for precise values, such as currency. For that, you will need to use the java.math.BigDecimal class instead. Numbers and Strings covers BigDecimal and other useful classes provided by the Java platform.
  double: The double data type is a double-precision 64-bit IEEE 754 floating point. Its range of values is beyond the scope of this discussion, but is specified in the Floating-Point Types, Formats, and Values section of the Java Language Specification. For decimal values, this data type is generally the default choice. As mentioned above, this data type should never be used for precise values, such as currency.
  */
  int autoscale=1;
  int autowig=1;
  int tracecount=0;
  int tc=20;
  boolean graphrms=false; 
  boolean graphpeaks=false; 
  boolean graphdiff=false;
  static String type="Wave";
  int tflx=0;
  double tfsc=100000;
  int tfw=128;
  double d1=26000,d2=22000,d3=18000,d4=14000,d5=2000;
  double e1=1.1,e2=1.2,e3=1.3,e4=1.4,e5=1.6;
  int opoplx=0;
  int poppkint=0;
  boolean busy=false;
  boolean deb=true;
  boolean popoff=true;
  long popss=5000;
  double popmx=0;
  double popd=0;
  int popmxi=0;
  int popki=0;
  int popadv=10;
  int poppost=40;
  double popmxth=45;
  double popdy=0;
  double popddy=0;
  int popdyi=0;
  int popddyi=0;
  double popdyth=20;
  double popddyth=20;
  int popri=0;
  int popti=0;
  long tymo=800000,tyma=0,tymb=0;
  int ti=1;
  int disres=0;
  int dispa=1;
  int dispb=1;
  int dispc=0;
  int dispd=0;
  double offay=100;
  double offby=-100;
  double offcy=-100;
  double offdy=-100;
  double offy=0;
  int msab=0,msbb=0,msae=0,msbe=0,msa=0,msb=0;
  double mutefactor=.01;
  int beth=1000;
  int bedx=1000;
  int beax=0,bebx=0;
  int becut=0;
  int locmax=0;
  int crms=0;
  int trackguess=0,orms=0,czrms=0,tcrms=5800;
  int flower=8;
  boolean fc=true;
  int gb=1;
  Thread thr;
  long maxlength=1000000;
  boolean saveable;
  boolean stopable;
  int expo=2;
  int stpth=0;
  int lvlth=0;
  int conoff=0;
  int kth=0;
  int coth=0;
  int fsib;
  int blif;
  int blib;
  int nbr=0;
  boolean flashon=false;
  boolean flashoff=false;
  int rnglx=0;
  int rngux=0;
  int rmsss=8;
  short apk=0;
  short bpk=0;
  byte[] buff1;
  byte[][] budd;
  int buffi=0;
  int mode=0;
  boolean psdone=false;
  boolean boo;
  Rec rbrec=new Rec(0,0,1,1);
  double dx,glx,gly,gwx,gwy;
  double grscy=.01;
  double xa;
  int pkint=0;
  Te te;
  LC lc; 
  dP lcsc=new dP(1,1);
  Tu tu;
  static final double PI=Math.PI;
  static final double DR=PI/180;
  static final double RD=180/PI;
  static final double pipi=2*PI;
  int deg=2;
  int tpts;
  int mi=-1;
  int bi=0;
  int ei=0;
  double x=0,y=0;
  double orgpw=3;
  Point p;
  // Point2D p2d;
  dP dp;
  dP[] dpa=new dP[0];
  dP[] dpb=new dP[0];
  Rec[] reca=new Rec[0];
  Rec[] recb=new Rec[0];
  int msdpa=-1;
  int msdpb=-1;
  int pmode=1;
  dP odpa,odpb;
  Graphics2D g;
  boolean handles=true;
  boolean cs=true;
  double pw=3;
  boolean bige=false;
  boolean mkl=false;
  int bs;
  int ibs=(int)(2*2*10000000);
  double rf=440;
  double lf=880;
  int rc=1000;
  byte sd[];
  int lx=0;
  int olx=0;
  int ow=0;
  int w=0;
  int wig=7;
  int owig=0;
  boolean fixlxw=true;
  ByteArrayOutputStream baos;
  TargetDataLine tdline;
  SourceDataLine sdline;
  AudioFormat format;
  Info sdlineInfo;
  int capbufsize=65536;
  int pbs=65536;
  //int pbs=1024;
  boolean announce=true;
  int chs=1;
  int bcs;
  static M parent;
  short[] ca;
  short[] cb;
  short[] cc;
  short[] cd;
  int cai=0;
  int chbi=0;
  short[] cap;
  short[] cbp;
  short[] capk2,capk3,capk4,capk5,capk6,capk7,capk8,capk9,capk10,capk11,capk12,capk13,capk14,capk15,capk16,capk17,capk18,capk19,capk20,capk21,capk22,capk23,capk24;
  short[] cbpk2,cbpk3,cbpk4,cbpk5,cbpk6,cbpk7,cbpk8,cbpk9,cbpk10,cbpk11,cbpk12,cbpk13,cbpk14,cbpk15,cbpk16,cbpk17,cbpk18,cbpk19,cbpk20,cbpk21,cbpk22,cbpk23,cbpk24;
  short[] bca;
  short[] bcb;
  short[] bcc;
  short[] bcd;
  int[] pkaboo=new int[30];
  int peakint=0; 
  String name="wave";
  String fn="notset";
  AudioFormat af;
  byte[] a;
  float samplerate;
  float blockrate; // framerate
  double blockbytes; //framesize
  int samplebits; // sampleSizeInBits
  boolean mono=true;
  double databytes;
  long chshorts;
  double secs;
  float stdbr=44100;
  // 8,000 Hz	Adequate for human speech but without sibilance. Used in telephone/walkie-talkie.
  // 11,025 Hz	Used for lower-quality PCM, MPEG audio and for audio analysis of subwoofer bandpasses.
  // 16,000 Hz	Used in most VoIP and VVoIP, extension of telephone narrowband.
  // 22,050 Hz	Used for lower-quality PCM and MPEG audio and for audio analysis of low frequency energy.
  // 44,100 Hz	Audio CD, most commonly used rate with MPEG-1 audio (VCD, SVCD, MP3). Covers the 20 kHz bandwidth.
  //float sampleRate, int sampleSizeInBits, int channels, int frameSize, float frameRate,
  double freq1=262;
  double freq2=1000;
  double pamp=.5;
  double bufftime=.5;
  float scbr=stdbr;
  float scbp=(float)1.0/stdbr;
  public Wave(M p)
   {
    tta("Wav constructor no args");
    thr=new Thread(this,"main");
    parent=p;
    name="jj";
    tu=parent.tu;
    lc=parent.lc;
    lc.hh.put(name,type);
   }
  public Wave(M p,String fn) // argWave(i)  argWave()
   {
    thr=new Thread(this,"main");
    parent=p;
    String ss=fn.substring(1+fn.lastIndexOf("/"));
    name=ss.substring(0,ss.indexOf("."));
    tta("Wave.name:"+name);
    tu=parent.tu;
    lc=parent.lc;
    lc.hh.put(name,type);
    a=parent.fio.readbytefile(fn,maxlength);// has all header info.
    conn();
   }
  public Wave(M p,String n,int sb,float sr,int ch,double seconds) 
   { 
    parent=p;
    name=n;  
    fn="/webroot/ajlogo/html/ajlogo/version3beta/audio/"+n+".wav";
    samplebits=sb; 
    samplerate=sr; 
    chs=ch;
    secs=seconds; 
    coocoo();
   }
  public Wave(M p,String n,int sb,float sr,int ch,double seconds,boolean m,boolean b)
   {
    parent=p;
    name=n;  
    fn="/webroot/ajlogo/html/ajlogo/version3beta/audio/"+n+".wav";
    mono=m;
    bige=b;
    samplebits=sb; 
    samplerate=sr; 
    chs=ch;
    secs=seconds; 
    coocoo();
   }
  public void  coocoo()
   {
    thr=new Thread(this,"main"); // for schleep
    tu=parent.tu;
    lc=parent.lc; 
    lc.hh.put(name,type);
    mode=2; 
    /*if (sr != 192000 && sr != 176400 && sr != 96000 && sr != 88200 && sr != 64000 && sr != 48000 && sr != 44100 && sr != 32000 && sr != 22050 && sr != 16000 && sr != 11025 && sr != 8000 && sr != 6000 && sr != 3000 && sr != 1500 && sr != 750 && sr != 325) 
     {
      tta("bad samplerate:"+sr);
      return;
     }*/
    calcparams();
    w=(int)chshorts;
    lx=0;
    parent.te.teS("lx.ul "+ca.length+" = lx "+lx);
    parent.te.teS("w.ul "+ca.length+" = w "+w);
    //wig=7;
    parent.te.teS("= wig "+wig);
    psdone=true;
    conn();
    tta("Wave.constructor bottom");
   }
  public void calcparams() //req samplebits,samplerate,chs creates blockbytes blockrate chshorts databytes a[] ca[] cb[]
   {
    blockbytes=chs*(samplebits/8);
    blockrate=(float)(samplerate*blockbytes);  
    chshorts=Math.round(secs*samplerate); // not effected by chs samplebits 
    //databytes=Math.round(chs*secs*samplerate*samplebits/8);  
    databytes=Math.round(chshorts*chs*samplebits/8);
    a=new byte[44+(int)databytes];  
    ca=new short[(int)chshorts];
    if(chs==2)    cb=new short[(int)chshorts]; 
    else if(chs==4)
    {
    cb=new short[(int)chshorts]; 
    cc=new short[(int)chshorts];
    cd=new short[(int)chshorts]; 
    }
    mkhead(); 
   }
  public void mkhead()  
   { 
    a[0]='R';
    a[1]='I';
    a[2]='F';
    if(bige) a[3]='X';
    else a[3]='F';
    a[8]='W';
    a[9]='A';
    a[10]='V';
    a[11]='E';
    a[12]='f';
    a[13]='m';
    a[14]='t';
    a[15]=' ' ;
    a[16]=0x10;
    a[17]=0x0;
    a[18]=0x0;
    a[19]=0x0;
    a[20]=0x1;
    a[21]=0x0;
    a[36]='d';
    a[37]='a';
    a[38]='t';
    a[39]='a';
    setbade(a,36+databytes,4);   // 4-7 
    setbaie(a,chs,22); // 22-23
    setbade(a,samplerate,24); // 24-27
    setbade(a,blockrate,28);  // 28-31
    setbade(a,blockbytes,32); // 32-33
    setbaie(a,samplebits,34); // 34-35
    setbade(a,databytes,40);  // 40-43
   }
  void conn()   //inturpret head
   {
	  if( a[3]=='X') bige=true;
	  else if(a[3]=='F') bige=false;
	  
	
	tta("a[3] :"+a[3]+" bige:"+bige);
    chs=mkai(22);
    samplerate=mkaf(24);
    blockrate=mkaf(28);
    blockbytes=mkai(32);
    samplebits=mkai(34);
    databytes=mkaf(40); 
    secs=(databytes/(samplerate*chs*(samplebits/8))); 
   }
  void settings()
  {
    tta("secs:"+secs+" chs:"+chs+"  samplerate:"+samplerate+" blockrate:"+blockrate);
    tta("samplebits:"+samplebits+"  blockbytes:"+blockbytes);
    tta("databytes:"+databytes); 
    // tta("Wave.conn chshorts:"+chshorts+" ca.length:"+l); 
   }
  short mkashort(int i)
  { 
	 return a[i];
  }
  String mkastr(int i)
  {
	  String s="";
	  return s;
  }
  int mkai(int i)
   {
    int aa=a[i++];
    int bb=a[i];
    if(aa <0)aa+=256;
    if(bb <0)bb+=256;
    return aa+(bb<<8); 
   }
  float mkaf(int ind)
   {
    int i=ind;
    int aa=0;
    float rez=0;
    for(int t=0;t<25;t+=8) // 0 8 16 24
     {
      aa=a[i++];
      if(aa <0) aa+=256;
      if(t==0) rez=aa;
      else rez+=(aa<<t);
     }
    return rez;
   }
  double mkad(int i)
   {
    tta("Wave.mkad use mkaf");
    int aa=0;
    double rez=0;
    for(int t=0;t<25;t+=8)
     {
      aa=a[i++];
      if(aa <0) aa+=256;
      if(t==0) rez=aa;
      else rez+=(aa<<t);
     }
    return rez;
   }
  int getbaie(byte[] z,int i)
   {
    int aa=z[i++];
    int bb=z[i];
    if(aa <0)aa+=256;
    if(bb <0)bb+=256;
    return aa+(bb<<8); 
   }
  double getbade(byte[] z,int i)
   {
    int aa=0;
    double rez=0;
    for(int t=0;t<25;t+=8)
     {
      aa=z[i++];
      if(aa <0) aa+=256;
      if(t==0) rez=aa;
      else rez+=(aa<<t);
     }
    return rez;
   }
  void setbade(byte[] z,double vv,int ind) // sets element ind in the byte array z with the double value vv
   {                                       //   setbade(a,databytes,40);  // 40-43
    long v=(long)vv;
    byte b0=(byte)(v&0xff);
    byte b1=(byte)((v&0xff00)>>8);
    byte b2=(byte)((v&0xff0000)>>16);
    byte b3=(byte)((v&0xff000000)>>24);
    //tta("Wave.setbaie long v:"+v+" ind:"+ind+" b0:"+b0+" b1:"+b1+" b2:"+b2+" b3:"+b3);
    z[ind++]=(byte)(v&0xff);
    z[ind++]=(byte)((v&0xff00)>>8);
    z[ind++]=(byte)((v&0xff0000)>>16);
    z[ind]=(byte)((v&0xff000000)>>24); 
   } 
  void setbaie(byte[] z,int v,int ind) // sets element ind in the byte array z with the int value v
   {
    byte b0=(byte)(v&0xff);
    byte b1=(byte)(v&0xff00>>8);
    // tta("Wave.setbaie int v:"+v+" ind:"+ind+" b0:"+b0+" b1:"+b1);
    z[ind++]=(byte)(v&0xff);
    z[ind]=(byte)((v&0xff00)>>8);
   }
  void mka(double vv,int ind) // what samplebits??
   {
    long v=(long)vv;
    a[ind++]=(byte)(v&0xff);
    a[ind++]=(byte)((v&0xff00)>>8);
    a[ind++]=(byte)((v&0xff0000)>>16);
    a[ind]=(byte)((v&0xff000000)>>24);
   }
  void mka(int v,int ind)
   {
    a[ind++]=(byte)(v&0xff);
    a[ind]=(byte)((v&0xff00)>>8);
   }
  public void finalize()
   {
    sdline.stop();
    sdline.flush();
    sdline.close();
   }
  void mkl()
   {
    //if(mkl) return;
    tta("Wave.mkl force new AudioFormat SourceDataLine");
    sdline = null;
    // format=new AudioFormat(scbr,16,chs,true,bige);
    tta("Wave.mkl  format:"+format.toString());
    sdlineInfo=new Info(SourceDataLine.class, format);
    try
     {
      sdline=(SourceDataLine)AudioSystem.getLine(sdlineInfo);
      //sdline.open(format,ibs);
      sdline.open(format);
     }
    catch(LineUnavailableException e) { tta("There was no available sdline."); }
    tta("Wave.mkl()  sdline.start()");
    sdline.start();
    mkl=true;
   }
  void syde()
   {
    // synth and play
    bs=1*1024;
    int loopz=100;
    int loope=0;
    samplebits=16;
    samplerate=44100;
    chs=2;
    //  a=parent.fio.readbytefile(fn,maxlength);// has all header info.
    calcparams();  // requires samplebits,samplerate,chs 
    /* blockbytes=chs*(samplebits/8);
    blockrate=(float)(samplerate*blockbytes);  
    chshorts=Math.round(secs*samplerate);
    //databytes=Math.round(chs*secs*samplerate*samplebits/8);  
    databytes=Math.round(chshorts*chs*samplebits/8);
    a=new byte[44+(int)databytes];  
    ca=new short[(int)chshorts];
    cb=new short[(int)chshorts]; 
    mkhead();*/ 
    double freq=1000; 
    secs=3;
    double p2pamp=.5; 
    calcparams();
    conn();
    tta("Wave.syde");
    double scaledp2pamp=p2pamp*64*1023;
    double pamp=scaledp2pamp/2;
    double rscs=Math.round(samplerate/freq); // samples/period of F
    double rj=6.283185307179586D*freq/samplerate; 
    buff1=new byte[pbs]; 
    int i=0;
    format=new AudioFormat(samplerate,samplebits,chs,true,bige); 
    //AudioFormat(float sampleRate, int sampleSizeInBits, int channels, boolean signed, boolean bigEndian) 
    sdlineInfo=new Info(SourceDataLine.class, format); 
    try
     {
      sdline=(SourceDataLine)AudioSystem.getLine(sdlineInfo); 
      sdline.open(format);
      sdline.start();
      tta("Wave.syde sdline opened and started format:"+format.toString());
     }
    // catch(LineUnavailableException e) { tta("There was no available sdline."); }
    catch(Exception e)
     {
      tta("Wave.syde error"); 
      return;
     }
    // chshorts has nothing to do with buff1
    //  buff1 is byte array the size related to bs
    conn();
    mode=1;
    tta("Wave.syde pre while bs:"+bs);
    buff1=new byte[bs*4];
    short sh=0;
    int zi=0;
    int gb=1;
    while (mode==1 && loope<loopz)    
     {	 
      tta("loope:"+loope);
      for(int hi=0;hi<bs;hi++)
       {
        sh =(short)(int)Math.round(pamp * Math.sin(zi*rj)); 
        //16 bit 2channels for now     	   
        buff1[hi]=(byte)sh  ;
        buff1[1+hi]=(byte)(sh >>>8);  
        buff1[2+hi]=(byte)sh;
        buff1[3+hi]=(byte)(sh >>>8);  
        zi++;
       }
      // buff1=Arrays.copyOfRange(a,0,bs);     
      sdline.write(buff1,0,bs);
      if(gb==1)
       {
        mkbcs(buff1);
        lc.clearscreen();
        graphbuff();
        //gb=0;
       } 
      // loope++;
     }
    stopable=true;
    sdline.drain();
    sdline.close(); 
    tta("Wave.syde finished");
   }
  void syne()
   {
    // synth and play
    double freq=1000;
    secs=3;
    double p2pamp=.5;
    calcparams();
    conn();
    tta("Wave.syne p2pamp:"+p2pamp);
    double scaledp2pamp=p2pamp*64*1023;
    double pamp=scaledp2pamp/2;
    int l=ca.length;
    int al=a.length;
    if(l != (int)chshorts )
     {
      tta("Wave.syne chsorts:"+chshorts+" not equal to ca.length:"+l+" a.length:"+al);
      return;
     }
    tta("Wave.syne p2pamp:"+p2pamp+" scaledp2pamp:"+scaledp2pamp+" pamp:"+pamp);
    double rscs=Math.round(samplerate/freq); // samples/period of F
    double rj=6.283185307179586D*freq/samplerate; 
    for(int i=0;i<(int)chshorts; i++)
     {	 
      ca[i]=(short)(int)Math.round(pamp * Math.sin(i*rj));
      cb[i]=ca[i];
      cabi2ba(i);
     }
    tta("Wave.Syne synth done");
    conn();
    mkl=true;  
    gb=1;// graph the buffer
    int j=0;
    int i=44;
    stopable=false;
    mode=1;
    buff1=new byte[pbs];  
    format=new AudioFormat(samplerate,samplebits,chs,true,bige); 
    //AudioFormat(float sampleRate, int sampleSizeInBits, int channels, boolean signed, boolean bigEndian) 
    sdlineInfo=new Info(SourceDataLine.class, format); 
    try
     {
      sdline=(SourceDataLine)AudioSystem.getLine(sdlineInfo); 
      sdline.open(format);
      sdline.start();
      tta("Wave.play sdline opened and started format:"+format.toString());
     }
    // catch(LineUnavailableException e) { tta("There was no available sdline."); }
    catch(Exception e)
     {
      tta("Wave.play error"); 
      return;
     }
    int chunk=0;
    int bs=pbs;
    int offset= chunk*bs;
    int alm=a.length-44;
    tta("Wave.play buffersize:"+bs+" chunk:"+chunk+" alm:"+alm );
    conn();
    while(mode==1 && offset< alm)
     {
      if(offset+bs > alm ) bs=alm-offset;
      // tta("Wave.play while offset:"+offset+" bs:"+bs+" alm:"+alm);
      buff1=Arrays.copyOfRange(a,offset,offset+bs);         // buff1=Arrays.copyOfRange(a,i,i+pbs);   
      sdline.write(buff1,0,bs);
      if(gb==1)
       {
        mkbcs(buff1);
        lc.clearscreen();
        graphbuff();
        //gb=0;
       } 
      offset+=bs;
     }
    stopable=true;
    sdline.drain();
    sdline.close(); 
    parent.te.teS("play.i 0");  // depends on a Bu play
    tta("Wave.play finished");
   }
  void play()
   {  
    mkl=true;  
    gb=1;// graph the buffer
    int j=0;
    int i=44;
    stopable=false;
    mode=1;
    buff1=new byte[pbs];  
    conn();
    format=new AudioFormat(samplerate,samplebits,chs,true,bige); 
    //AudioFormat(float sampleRate, int sampleSizeInBits, int channels, boolean signed, boolean bigEndian) 
    sdlineInfo=new Info(SourceDataLine.class, format); 
    try
     {
      sdline=(SourceDataLine)AudioSystem.getLine(sdlineInfo); 
      sdline.open(format);
      sdline.start();
     // tta("Wave.play sdline opened and started format:"+format.toString());
     }
    // catch(LineUnavailableException e) { tta("There was no available sdline."); }
    catch(Exception e)
     {
      tta("Wave.play error"); 
      return;
     }
    int chunk=0;
    int bs=pbs;
    int offset= chunk*bs;
    int alm=a.length-44;
    //tta("Wave.play buffersize:"+bs+" chunk:"+chunk+" alm:"+alm );
    
    while(mode==1 && offset< alm)
     {
      if(offset+bs > alm ) bs=alm-offset;
      // tta("Wave.play while offset:"+offset+" bs:"+bs+" alm:"+alm);
      buff1=Arrays.copyOfRange(a,offset,offset+bs);         // buff1=Arrays.copyOfRange(a,i,i+pbs);   
      sdline.write(buff1,0,bs);
      if(gb==1)
       {
        mkbcs(buff1);
        lc.clearscreen();
        graphbuff();
        //gb=0;
       } 
      offset+=bs;
     }
    stopable=true;
    sdline.drain();
    sdline.close(); 
    parent.te.teS("play.i 0");  // depends on a Bu play
    tta("Wave.play finished");
   }
  void graphbuff()
   {
   
    K mk=new K(0,0,0,255);
    lc.spk(mk);
    double bw=bcs;
    double lgwx=lc.width;
    double lgwy=lc.height;
  //  tta("Wave.graphbuff chs:"+chs);
    dispb=0;
    dispc=0;
    dispd=0;
    dispa=1;
   
    if(chs==2) dispb=1;
    else if(chs==4)
    {
    	dispb=1;
    	dispc=1;
    	dispd=1;
    }
    if(dispa==1 && dispb==0 && dispc==0 && dispd==0)
    {
   	 
     grscy=lgwy/65000;
     offay=lgwy/2;
    
    }
    else if(dispa==1 && dispb==1 && dispc==0 && dispd==0)
     {
    	 
      grscy=lgwy/130000;
      offay=lgwy/4;
      offby=-lgwy/4;
     }
    else if(dispa==1 && dispb==1 && dispc==1 && dispd==1)
    {
  
     grscy=lgwy/260000;
     offay=lgwy*3/8;
     offby=lgwy/8;
     offcy=-lgwy/8;
     offdy=-lgwy*3/8;
     }
    else
     {
      grscy=lgwy/65000;
      offay=0;
      offby=0;
     }
    dx=lgwx/(bw-1);
    
    double lxa=-lgwx/2;
    glx=lxa;
    double ch1xa=lxa;   // xb ch1xa
    double ch1xb=ch1xa+dx;
    double ch1ya=offay+bca[0]*grscy;   //ya  ch1ya

    double ch1yb=offay+bca[1]*grscy;        // yb ch1yb
    lc.drawLine(ch1xa,ch1ya,ch1xb,ch1yb);
    for(int i=2;i<bw;i++)
     {
      
      ch1xb+=dx;
      ch1yb=offay+bca[i]*grscy;
      lc.drawLine(ch1xa,ch1ya,ch1xb,ch1yb);
      ch1xa=ch1xb;
      ch1ya=ch1yb;
     }
    if (dispb==0) return;
    double ch2xa=lxa;   // xb ch2xa
    double ch2xb=ch2xa+dx; 
    double ch2ya=offby+bcb[0]*grscy;   //ya  ch2ya
    double ch2yb=offby+bcb[1]*grscy;        // yb ch2yb 
    lc.drawLine(ch2xa,ch2ya,ch2xb,ch2yb);
    for(int i=2;i<bw;i++)
     {
      
      ch2xb+=dx;
      ch2yb=offby+bcb[i]*grscy;
      lc.drawLine(ch2xa,ch2ya,ch2xb,ch2yb);
      ch2xa=ch2xb;
      ch2ya=ch2yb;
     }
    if (dispc==0) return;
    double ch3xa=lxa;   // xb ch3xa
    double ch3xb=ch3xa+dx; 
    double ch3ya=offcy+bcc[0]*grscy;   //ya  ch3ya
    double ch3yb=offcy+bcc[1]*grscy;        // yb ch3yb 
    lc.drawLine(ch3xa,ch3ya,ch3xb,ch3yb);
    for(int i=2;i<bw;i++)
     {
      
      ch3xb+=dx;
      ch3yb=offcy+bcc[i]*grscy;
      lc.drawLine(ch3xa,ch3ya,ch3xb,ch3yb);
      ch3xa=ch3xb;
      ch3ya=ch3yb;
     }
    double ch4xa=lxa;   // xb ch4xa
    double ch4xb=ch4xa+dx; 
    double ch4ya=offdy+bcd[0]*grscy;   //ya  ch4ya
    double ch4yb=offdy+bcd[1]*grscy;        // yb ch4yb 
    lc.drawLine(ch4xa,ch4ya,ch4xb,ch4yb);
    for(int i=2;i<bw;i++)
     {
      
      ch4xb+=dx;
      ch4yb=offdy+bcd[i]*grscy;
      lc.drawLine(ch4xa,ch4ya,ch4xb,ch4yb);
      ch4xa=ch4xb;
      ch4ya=ch4yb;
     }
   }
  void oldgraphbuff()
  {
   long tymc=System.currentTimeMillis();
   K mk=new K(0,0,0,255);
   lc.spk(mk);
   double bw=bcs;
   double lgwx=lc.width;
   double lgwy=lc.height;
   tta("Wave.graphbuff chs:"+chs);
   
   
   if(chs==1)
    {
     dispb=0;
    }
   if(dispa==1 && dispb==1)
    {
     grscy=lgwy/130000;
     offay=lgwy/4;
     offby=-lgwy/4;
    }
   else
    {
     grscy=lgwy/65000;
     offay=0;
     offby=0;
    }
   dx=lgwx/(bw-1);
   
   double lxa=-lgwx/2;
   glx=lxa;
   double ya=bca[0]*grscy;
   double xb=lxa;
   double yb=0;
   //int h=1;
   long deltyme=System.currentTimeMillis()-tymc;
   //tta("tymc:"+deltyme);
   for(int i=1;i<bw;i++)
    {
     
     xb+=dx;
     yb=bca[i]*grscy;
     lc.drawLine(lxa,ya,xb,yb);
     lxa=xb;
     ya=yb;
    }
  }
  void rec()
   {
    saveable=false;
    mode=2;
    //prerec();
    if ( ! newprerec()) return;
    recmaine();
    recpost();
    saveable=true;
   }
  boolean newprerec()
   {
    mixer();
    Mixer.Info[] mixerInfo;
    mixerInfo = AudioSystem.getMixerInfo();
    Mixer mixer = AudioSystem.getMixer(mixerInfo[4]);
    // DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class,audioFormat);
    //TargetDataLine targetDataLine = (TargetDataLine)mixer.getLine(dataLineInfo); 
    
    /*
    Mixer.Info[] mixerInfo;
    mixerInfo = AudioSystem.getMixerInfo();
    Mixer mixer = AudioSystem.getMixer(mixerInfo[3]);
    TargetDataLine targetDataLine = (TargetDataLine)mixer.getLine(dataLineInfo);
    targetDataLine.open(audioFormat);
    targetDataLine.start();
    */

    
    
    
    psdone=false; 
    apk=0;
    bpk=0;
    samplerate=stdbr;
    samplebits=16;
    chs=2;
    blockbytes=4;
    blockrate=(float)(samplerate*blockbytes);
    mkhead();
    af=new AudioFormat((float)samplerate,samplebits,chs,true,false);
    //format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,44100,16,2,4,44100,true);
    DataLine.Info sdlineInfo= new DataLine.Info(TargetDataLine.class,af);
  // Info sdlineInfo = new Info(TargetDataLine.class,af);
    try
     {
      if (!AudioSystem.isLineSupported(sdlineInfo)) 
       {
        tta("Wave.newprerec Line matching " + sdlineInfo + " not supported.");
        return false;
       }
     }
    catch(Exception e)
     {
      tta("Wave.newprerec  "+ e.toString());
      return false;
     }
    try 
     {
      // orig  tdline = (TargetDataLine) AudioSystem.getLine(sdlineInfo); 
      tdline= (TargetDataLine)mixer.getLine(sdlineInfo); 
      //TargetDataLine targetDataLine = (TargetDataLine)mixer.getLine(dataLineInfo); 
      tdline.open(af,capbufsize); 
      //  targetDataLine.open(audioFormat); 
      tta("Wave.newprerec  capbufsize:"+capbufsize+"  actual:"+tdline.getBufferSize());
     }
    catch(IllegalArgumentException iae)
     {
      tta("Wave.newprerec IllegalArgumentException");
      return false;
     }
    catch (LineUnavailableException ex) 
     {
      tta("Wave.newprerec Unable to open the tdline");
      return false;
     }
    catch (SecurityException ex) 
     {
      tta(ex.toString());
      return false;
     }
    catch (Exception ex) 
     {
      tta("Wave.newprerec  "+ ex.toString());
      return false;
     }
    fsib=af.getFrameSize();
    blif=tdline.getBufferSize()/8;
    blib=blif*fsib;
    buff1=new byte[blib];
    budd=new byte[flower][blib];
    ckbuffprep(buff1);
    baos=new ByteArrayOutputStream();
    a=new byte[44];
    mkhead();
    for(int jj=0;jj<44;jj++) baos.write(a[jj]); // array copy
    tdline.start();
    //  targetDataLine.start();     
    databytes=0;
    nbr=tdline.read(buff1,0,blib);
    return true;
   }
  void prerec() 
   { 
    psdone=false; 
    apk=0;
    bpk=0;
    samplerate=stdbr;
    samplebits=16;
    chs=2;
    blockbytes=4;
    blockrate=(float)(samplerate*blockbytes);
    mkhead();
    af=new AudioFormat((float)samplerate,samplebits,chs,true,false);
    //format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,44100,16,2,4,44100,true);
    tta("Quiet on the set");
    sdlineInfo = new Info(TargetDataLine.class,af);
    if (!AudioSystem.isLineSupported(sdlineInfo)) 
     {
      tta("Wave.recpre Line matching " + sdlineInfo + " not supported.");
      return;
     }
    try 
     {
      tdline = (TargetDataLine) AudioSystem.getLine(sdlineInfo); 
      tdline.open(af,capbufsize); 
      tta("Wave.recpre  capbufsize:"+capbufsize+"  actual:"+tdline.getBufferSize());
     }
    catch(IllegalArgumentException iae)
     {
      tta("Wave.recpre IllegalArgumentException");
     }
    catch (LineUnavailableException ex) 
     {
      tta("Wave.recpre Unable to open the tdline");
      return;
     }
    catch (SecurityException ex) 
     {
      tta(ex.toString());
      return;
     }
    catch (Exception ex) 
     {
      tta("Wave.recpre  "+ ex.toString());
      return;
     }
    fsib=af.getFrameSize();
    blif=tdline.getBufferSize()/8;
    blib=blif*fsib;
    buff1=new byte[blib];
    budd=new byte[flower][blib];
    ckbuffprep(buff1);
    baos=new ByteArrayOutputStream();
    a=new byte[44];
    mkhead();
    for(int jj=0;jj<44;jj++) baos.write(a[jj]); // array copy
    tdline.start();
    databytes=0;
   }
  void recmaine()
   {
    int rms=0;
    locmax=0;
    tyma=System.currentTimeMillis();
    while(mode==2)
     {
      if(tdline ==null)
       {
        tta("Wave.recmaine tdline is null");
        return;
       }
      nbr=tdline.read(buff1,0,blib);
      if(nbr== -1) tta("Wave.recmaine bail out");
      baos.write(buff1,0,nbr);
      if(gb==1)
       {
        mkbcs(buff1);
        lc.clearscreen();
        graphbuff();
        //gb=0;
       } 
      databytes+=nbr;
      if(databytes> maxlength) 
       {
        mode=0;
        tta("Wave.recmaine Maxlength reached");
       }
     } // end of recmaine while loop
    tdline.stop();
    tdline.close();
    tdline=null;
   }
  void mon()
   {
    if(mode==2)
     {
      tta("Monitoring and Recording");
      return;
     }
    else tta("Monitoring");
    mode=3;
    prerec();
    monmaine();
   }
  void monmaine()
   {
    locmax=0;
    while(mode==3)
     {
      if(tdline !=null)
       {
        nbr=tdline.read(buff1,0,blib);
        if(nbr== -1) tta("bail out");
        for(int i=1;i<blib;i+=2)
         {
          if(Math.abs(buff1[i])>locmax)
           {
            locmax=Math.abs(buff1[i]);
            tta("locmax:"+locmax);
           }
         }
        databytes+=nbr;
       }
     }
    tdline.stop();
    tdline.close();
    tdline=null;
   }
  void recpost()
   {
    tta("Wave.recpost");
    a=baos.toByteArray();
    if(databytes==a.length-44) tta("Good match:"+databytes);
    else
     {
      double db=a.length-44;
      tta("Wave.recpost  Mismatch a.length-44:"+db+"  databytes:"+databytes);
      databytes=db;
     }
    // commb();
    tta("Wave.recpost  Recording complete");
    psdone=false;
    if(mode==21)
     {
      mode=0;
      parent.te.teS("durp2");
     }
   }
  void ckbuffprep(byte[] buff)
   {
    chshorts=buff.length/(chs*(samplebits/8));
    if(chs==2) cb=new short[(int)chshorts];
    ca=new short[(int)chshorts];
   }
  void mkbcs(byte[] buff)
   {
    //tta("mkbcs wig:"+wig);
    int lwig=wig;
    //tta("buff.length:"+buff.length+" lwig:"+lwig+" chs:"+chs+" samplebits:"+samplebits);
    bcs=buff.length/(lwig*chs*(samplebits/8)); // hmmmm
    int bl=buff.length;
     
    tta("Wave.mkbcs bcs:"+bcs+" buff.length:"+bl);
    bca=new short[bcs];
    
    	 bcb=new short[bcs];
    	bcc=new short[bcs];
    	bcd=new short[bcs];
    	 
    //tta("Wave.mkbcs bcs:"+bcs+" bca.length:"+bca.length);
    int ci=0;
    int ai=0;
    double t=0;
    while(ci< bcs)
     {
      tta("ci:"+ci+" ai:"+ai); 
      bca[ci++]=(short)(buff[ai++] & 0xff | buff[ai++] << 8);
      if(chs==2)
       { 
        bcb[ci++]=(short)(buff[ai++] & 0xff | buff[ai++] << 8);
       }
    	else if(chs==4)
        {    
         bcb[ci++]=(short)(buff[ai++] & 0xff | buff[ai++] << 8); 
         bcc[ci++]=(short)(buff[ai++] & 0xff | buff[ai++] << 8);
         bcd[ci++]=(short)(buff[ai++] & 0xff | buff[ai++] << 8);
        }
      
        ai+=(wig-1)*4; // zippy should be *2 for ch==1 ??
       if(chs==1) continue;
      
        ai+=(wig-1)*4;
        if(chs==2) continue;
      
       ai+=(wig-1)*4;
       ai+=(wig-1)*4;
      
     
      
     }
   }
  void save(String s) 
   {
    save(s,a); // std byte array
   }
  void save(String s,byte[] z) 
   {
    String fn=s;
    int jo=z.length;
    if(fn.indexOf("/")==-1) fn="/webroot/ajlogo/html/ajlogo/version3beta/audio/"+fn;
    tta("Wave.save  fn:"+fn+" file size:"+jo);
    try
     {
      parent.fio.wfba(fn,z); 
     }
    catch(Exception e)
     {
      tta("Wave.save  error fn:"+fn);
      return;
     }
    tta("save complete fn:"+fn);
   }
  void schtop()
   {
    mode=0;
    tta("Wave.schtop  mode:"+mode);
    if(mode==1) playstop();
    else if(mode==2) recstop();
    else if(mode==3) monstop();
   }
  void playstop()
   {
    mode=0;
    int count=0;
    while(! stopable && count < 10)
     {
      tta("sleeping:"+ stopable);
      schleep(1000);
      count++;
     }
    if(sdline !=null)
     {
      sdline.drain();
      sdline.close(); 
     }
    tta("stopped");
   }
  void monstop()
   {
    mode=0;
   }
  void recstop() 
   {
    tta("Wave.recstop");
    mode=0; 
    while(! saveable)
     {
      tta("rec stop sleeping not saveable");
      schleep(1000);
     }
    tta("Wave.recstop   saveable");
   }
  void psdo()
   {
    tta("Wave.psdo removed");
   }
  short cai2Short(int i)
   {
    return ca[i];
   }
  short bai2Short(int i)  // byte array index to short unknown channel 
   {
    int bai=i;
    return (short)(a[bai++] & 0xff | a[bai] << 8); 
   }
  void bai2cab(int i) // ba indexes ca and cb shorts
   {	  
    int ai=i;
    if(samplebits!=16)
     {
      tta("Wave.ba2cab only 16 samplebits for now");
      return;
     }
    int ci=ai-44; //
    if(chs==1)
     { 
      ca[ci]=(short)(a[ai++] & 0xff | a[ai] << 8); 
     }
    else if(chs==2)
     {  
      ca[ci]=(short)(a[ai++] & 0xff | a[ai++] << 8); 
      cb[ci++]=(short)(a[ai++] & 0xff | a[ai] << 8);  
     }
   }
  void ba2cab()  // full bytearray a to channel shorts ca  cb
   {
    int l=a.length-44;
    tta("Wave.ba2cab a.length-44:"+l+" databytes:"+databytes);
    if(chs==2) cb=new short[(int)chshorts];
    ca=new short[(int)chshorts];
    int ai=44; // a[] index
    int ci=0; // ca[] index
    if(samplebits!=16)
     {
      tta("Wave.ba2cab only 16 samplebits for now");
      return;
     }
    if(chs==1)
     { 
      while(ai<44+databytes)  ca[ci++]=(short)(a[ai++] & 0xff | a[ai++] << 8); 
     }
    else if(chs==2)
     { 
      while(ai<44+databytes)
       {
        ca[ci]=(short)(a[ai++] & 0xff | a[ai++] << 8); 
        cb[ci++]=(short)(a[ai++] & 0xff | a[ai++] << 8); 
       }
     }
   }
  int cai2bai(int i) // convert  'a' channel array index to databyte array index
   { 
    int chai=i;
    if(samplebits==16) 
     {
      if(chs==1)  return (int)(44+2*chai);
      else if(chs==2)  return (int)(44+4*chai);
     }
    else if(samplebits==8)
     {
      if(chs==1)   return  (int)(44+chai);
      else if(chs==2) return (int)(44+2*chai);
     }
    return -1;
   }
  int cbi2bai(int i)// convert  'b' channel array index to databyte array index
   {
    int cbi=i;
    if(samplebits==16)
     {
      return (int)(46+4*chbi);
     }
    else if(samplebits==8)
     {
      return (int)(46+2*chbi);
     }
    return -1;
   }
  short cai2gbav(int i)
   {
    int cai=i;
    int bai=cai2bai(i);
    if(samplebits!=16)
     {
      tta("Wave.cai2gba only 16 samplebits for now");
      return -1;
     }
    return (short)(a[bai++] & 0xff | a[bai] << 8); 
   }
  void ave()
   {
    ave(0,(int)chshorts,4);
   }
  void ave(int x,long ww,int sam)
   {
    int www=(int)ww;
    short cc[]= new short[ca.length];
    for (int i=x;i< x+ww;i++)
     {
      int sum=0;
      int s=0;
      for(int j=i-sam;j<i+2*sam;j++)
       {
        if(j>=x && j<= x+ww)
         {
          s++;
          sum+=ca[j];				  
         }
       }
      cc[i]=(short)(sum/s);
     } 
    System.arraycopy(ca, 0, cc, 0, cc.length);
   }
  void setWig()
   {
    setWig(-1);
   }
  void setWig(int ww)
   {
    if (ww==-1) // override autowig
     {
      wig=(w/100000)-4; // w below 60000 wig =1
     }
    else wig=ww;
    if(wig <=0) wig=1; 
    if(wig != owig) 
     {
      M.te0.teS("= wig "+wig);
      tta("setWig wig:"+wig);
     }
    owig=wig;
   }
  void modify()
   {
    tta("starting a array modify");
    for(int i=0;i<(int)chshorts;i++) cabi2ba(i);
    tta("done modify");
    psdone=false;
    psdo();
    //ssl();
   }
  void cai2gba(int i)
   {
    if(samplebits==16)
     {
      if(chs==1)
       {
        a[44+2*i]=(byte)ca[i];
        a[45+2*i]=(byte)(ca[i] >>>8);
       }
      else if(chs==2) 
       {
        a[44+4*i]=(byte)ca[i];   // was ca[i]
        a[45+4*i]=(byte)(ca[i] >>>8); // zilog was ca[i]
       }
     }
   }
  void cabi2ba(int i)   //channel short(s (if two channels)) placed into wav file array (after header)
   {
    int hi=i;
    cai2ba(hi);
    cbi2ba(hi);
   }
  void cabcdi2ba(int i)   //channel short(s (if two channels)) placed into wav file array (after header)
  {
   int hi=i;
   cai2ba(hi);
   cbi2ba(hi);
   cci2ba(hi);
   cdi2ba(hi);
  }
  void cai2ba(int i) // channel a short value at index placed into wavefile bytearray
   {
    // if(i%100 ==0) tta("Wave.cai2ba  i:"+i+" samplebits:"+samplebits+" chs:"+chs); 
    int ci=i;
    int hi=i;
    if(samplebits==16)
     {
      if(chs==1)
       {
        a[44+2*hi]=(byte)ca[ci];
        a[45+2*hi]=(byte)(ca[ci] >>>8);
       }
      else if(chs==2) 
       {
        a[44+4*hi]=(byte)ca[ci];   
        a[45+4*hi]=(byte)(ca[ci] >>>8);  
       }
      else if(chs==4)
      {
    	  a[44+6*hi]=(byte)ca[ci];   
          a[45+6*hi]=(byte)(ca[ci] >>>8);  
          a[44+8*hi]=(byte)ca[ci];   
          a[45+8*hi]=(byte)(ca[ci] >>>8);  
      }
     }
    else if(samplebits==8)
     {
      if(chs==1) a[44+hi]=(byte)ca[ci];
      else if(chs==2) a[44+2*hi]=(byte)ca[ci];  
     }
   }
  void cbi2ba(int i)
   {
    int ci=i;
    int hi=i;
    if(samplebits==16)   
     {
      if(chs==2)
      {
      a[46+4*hi]=(byte)cb[ci];
      a[47+4*hi]=(byte)(cb[ci] >>>8);
      }
      else if(chs==4)
      {
    	  a[46+6*hi]=(byte)cb[ci];
          a[47+6*hi]=(byte)(cb[ci] >>>8); 
      }
     }
    else if(samplebits==8) a[45+2*hi]=(byte)cb[ci];
   }
  void cci2ba(int i)
  {
   int ci=i;
   int hi=i;
   if(samplebits==16)  // assumes 4 chan
    {
     a[48+6*hi]=(byte)cc[ci];
     a[49+6*hi]=(byte)(cc[ci] >>>8);
    }
   else if(samplebits==8) a[46+2*hi]=(byte)cc[ci];
  }
  void cdi2ba(int i)
  {
   int ci=i;
   int hi=i;
   if(samplebits==16)  // assumes b channel means 2 channels 
    {
     a[50+6*hi]=(byte)cd[ci];
     a[51+6*hi]=(byte)(cd[ci] >>>8);
    }
   else if(samplebits==8) a[47+2*hi]=(byte)cd[ci];
  }
  int cw2baw(int i) // convert chann
   {
    int ci=i;
    int hi=i;
    if(samplebits==16)
     {
      if(chs==1)   return (int)(2*ci);
      else if(chs==2) return (int)(4*ci);
     }
    else if(samplebits==8)
     {
      if(chs==1)   return (int)(ci);
     }
    return -1;
   }
  void sypp()
   { 
    bige=true;
    samplerate=44100;
    samplebits=16;
    chs=1;
    mono=true;
    bufftime = .0500; 
    int sps = (int)(bufftime*samplerate*samplebits/8); // number of bytes per loop	  
    freq1=262;
    pamp=.5;
    double phase=0; // phase of cycle 
    try  
     { 
      AudioFormat af = new AudioFormat(samplerate,samplebits, chs,mono,bige); 
      DataLine.Info info = new DataLine.Info(SourceDataLine.class, af, sps*2); // Ask for buffer size at least 2*sps
      if (!AudioSystem.isLineSupported(info))  throw new LineUnavailableException(); 
      sdline = (SourceDataLine)AudioSystem.getLine(info); 
      sdline.open(af);   
      sdline.start(); 
     } 
    catch (LineUnavailableException e)  
     { 
      tta("sdline of that type is not available"); 
      e.printStackTrace();             
      System.exit(-1); 
     } 
    tta("Requested sdline buffer size:" + sps*2+" Actual buffer size:" + sdline.getBufferSize()); 
    ByteBuffer bytebuff = ByteBuffer.allocate(sps); 
    mode=1;
    double deltaphase=freq1/samplerate; 
    int zapp=(int)Math.round(bufftime*samplerate); 
    while (mode==1) 
     {  //Each sample is spaced 1/samplerate apart in time 
     
      deltaphase=freq1/samplerate; 
        bytebuff.clear();  //clear samples from previous pass
      for (int i=0; i<zapp; i++)  //   bufftime*samplerate
       { 
        bytebuff.putShort((short)(pamp*Short.MAX_VALUE * Math.sin(pipi*phase))); 
        phase +=deltaphase;
       } 
      //Write sdline buffer  If buffer full block until enough room, no writing unless enough space. 
      sdline.write(bytebuff.array(), 0, bytebuff.position());     
      //Wait here until there are less than sps samples in the buffer 
      //(Buffer size is 2*sps at least, so there will be room for at least sps samples when this is true) 
    //  tta("sdline buffersize:"+sdline.getBufferSize()+" available:"+sdline.available());
     } 
    sdline.drain(); 
    sdline.close(); 
   } 

   
	  void  Sine(double freq,double s,double pamp,int c) // 1= +- 32k-1
	   {
    // mess with secs to end on zero crossing for smooth repeat
    secs=s;
    chs=c;
    samplerate=44100;
    samplebits=16;
    calcparams();  
   // double rscs=Math.round(samplerate/freq); // samples/period of F
    double rj=6.283185307179586D*freq/samplerate; 
    int z=0;
    for(int i=0;i<(int)chshorts; i++)
     {	 
    	  z=44+2*chs*i;
          ca[i]=(short)(int)Math.round(pamp *32767D * Math.sin(i*rj));
          a[z++]=(byte)(ca[i]); 
          a[z++]=(byte)(ca[i] >>>8);
         if(chs==1) continue; 
    	  cb[i]=ca[i];
    	  a[z++]=(byte)(cb[i]); 
          a[z++]=(byte)(cb[i] >>>8);
    	  if(chs==2) continue; 
          cc[i]=ca[i];
    	  a[z++]=(byte)(cc[i]); 
          a[z++]=(byte)(cc[i] >>>8);
          cd[i]=ca[i];
    	  a[z++]=(byte)(cd[i]); 
          a[z]=(byte)(cd[i] >>>8); 
     }
    tta("Wave.Sine synth done");
    conn();
   }
 
  void Ramp(double s,int ramps,double p2pamp,int c)  //  (double s,1,1)
   {
	  tta("Fix Ramp");
	  /*
    secs=s;
    chs=c;
    calcparams();
    int chsamples=(int)(secs*samplerate);
    int stepsperramp=(int)chsamples/ramps;
    //double ystep=65536D/(int)chshorts;
    double ystep=65536D/stepsperramp;  // fixed 16 bit
    double yValue=-32767D;
    tta("Wave.Ramps secs:"+secs+" ramps:"+ramps+" (int)chshorts:"+(int)chshorts+" ystep:"+ystep);
    int j=0;
    int z=0;
    for(int r=0;r<ramps;r++)
     {
      tta("Wave.Ramps ramp:"+r+" old yValue:"+yValue+" j:"+j);
      yValue=-32767D;
      
      for(int i=0;i<stepsperramp;i++) 
       {
        ca[j]=(short)(int)Math.round(yValue);
        cb[j]=ca[j];
        cabi2ba(j);
        yValue+=ystep;
        j++;
       }
     }
     */
   }
  void dubRamp(double s,int ramps,double p2pamp)  //  (double s,1,1)
  {
   bige=false;
   secs=s;
   samplebits=16;
   samplerate=44100;
   chs=2;
   calcparams();
   int chsamples=(int)(secs*samplerate);
   int stepsperramp=(int)chsamples/ramps;
   //double ystep=65536D/(int)chshorts;
   double ystep=65536D/stepsperramp;  // fixed 16 bit
   double yaValue=-32767D;
   double ybValue=+32767D; 
   int j=0;
   int z=0;
   for(int r=0;r<ramps;r++)
    { 
     yaValue=-32767D;
     ybValue=32767D; 
     for(int i=0;i<stepsperramp;i++) 
      {
       ca[j]=(short)(int)Math.round(yaValue);
       cb[j]=(short)(int)Math.round(ybValue);
       z=44+4*j;
       if( j % 100 ==0)        tta("z:"+z+" j:"+j+" yaValue:"+yaValue+" chshorts:"+chshorts);
       a[z++]=(byte)(ca[j]); 
       a[z++]=(byte)(ca[j] >>>8);
       a[z++]=(byte)(cb[j] ); //MSB
       a[z]=(byte)(cb[j]>>>8); //LSB
       yaValue+=ystep;
       ybValue-=ystep;
     
       j++;
      }
    }
   tta("dubramp done");
  }

  void  Quad(double freqa,double freqb,double freqc,double freqd,double s,double pamp)
  {
   bige=false;
   secs=s;
   samplebits=16;
   samplerate=44100;
   chs=4;
   calcparams(); 
   int l =a.length;
   int m=(int)(44+8*chshorts); 
   double rja=6.283185307179586D*freqa/samplerate; 
   double rjb=6.283185307179586D*freqb/samplerate; 
   double rjc=6.283185307179586D*freqc/samplerate; 
   double rjd=6.283185307179586D*freqd/samplerate;  
   int z=0;
   int i=0;
   for(i=0;i<(int)chshorts; i++)
    {	
	 //hi=2*i;
     ca[i]=(short)(int)Math.round(pamp*32767D * Math.sin(i*rja)); 
	 cb[i]=(short)(int)Math.round(pamp*32767D * Math.sin(i*rjb));
     cc[i]=(short)(int)Math.round(pamp*32767D * Math.sin(i*rjc));
     cd[i]=(short)(int)Math.round(pamp*32767D * Math.sin(i*rjd));
     z=44+8*i;
     a[z++]=(byte)(ca[i]); 
     a[z++]=(byte)(ca[i] >>>8); 
     a[z++]=(byte)(cb[i] ); //MSB
     a[z++]=(byte)(cb[i]>>>8); //LSB
     a[z++]=(byte)(cc[i]);
     a[z++]=(byte)(cc[i] >>>8);
     a[z++]=(byte)(cd[i]);
     a[z]=(byte)(cc[i] >>>8); 
    }
   tta("Quad synth done  i:"+i+" z:"+z);
  }
 
 // steps,secs  ll,ul,steps,secs   
 // (pattern)  (1,0,-,-,1,1,1,0,1,0,0,0,-,1,-,1,1,0,1,-,0,0,-,0), secs/step
 // level(x) continuous play (can be shoooort)
  void  Binaural(double freqa,double freqb,double s,double pamp)
   {
    secs=s;
    chs=2;
    samplebits=16;
    samplerate=44100;
    calcparams();
    // mess with secs to end on zero crossing
    //stdCommb(secs); // creates (int)chshorts
    //double rscsa=Math.round(samplerate/freqa); // samples/period of Fa
    double rja=6.283185307179586D*freqa/samplerate; 
    double rjb=6.283185307179586D*freqb/samplerate;
    int z=0;
    int i=0;
    for(i=0;i<(int)chshorts; i++)
     {	  
      ca[i]=(short)(int)Math.round(pamp*32767D * Math.sin(i*rja)); 
      cb[i]=(short)(int)Math.round(pamp*32767D * Math.sin(i*rjb));
      z=44+4*i;
      a[z++]=(byte)(ca[i]); 
      a[z++]=(byte)(ca[i] >>>8);
      a[z++]=(byte)(cb[i] ); //MSB
      a[z++]=(byte)(cb[i]>>>8); //LSB
     }
    tta("Binaural synth done");
   }
  // steps,secs  ll,ul,steps,secs   
  // (pattern)  (1,0,-,-,1,1,1,0,1,0,0,0,-,1,-,1,1,0,1,-,0,0,-,0), secs/step
  // level(x) continuous play (can be shoooort)
  void Stair()
   {
   }
  void  Sweep(double bf,double ef,double s,double pamp,int c)
   {
	  tta("Fix Sweep");
	  /*
    secs=s;
    chs=c;
    samplebits=16;
    samplerate=44100; 
    calcparams();
    //  stdCommb(secs); // creates chshorts
    double df=Math.abs(ef-bf)/(int)chshorts;
    int z=0;
    for(int i=0;i<(int)chshorts; i++)
     {
      double rscs=samplerate/(bf+i*df);
      double yValue =pamp* 32767D * Math.sin(i*6.283185307179586D/rscs);
      ca[i]=(short)(int)Math.round(yValue);
      cb[i]=ca[i];
      z=44+4*i;
      a[z++]=(byte)(ca[i]); 
      a[z++]=(byte)(ca[i] >>>8);
      a[z++]=(byte)(cb[i] ); //MSB
      a[z++]=(byte)(cb[i]>>>8); //LSB
       
     }
    tta("synth done");
    */
   }
  void setTDL(int i)
   {/*
    Mixer.Info[] mixerInfo;
    mixerInfo = AudioSystem.getMixerInfo();
    Mixer mixer = AudioSystem.getMixer(mixerInfo[3]);
    TargetDataLine targetDataLine = (TargetDataLine)mixer.getLine(dataLineInfo);
    targetDataLine.open(audioFormat);
    targetDataLine.start();
    tta("ind:"+cnt+"  name:"+mixerInfo[cnt].getName()); */
   }
  void mixer()
   {
    Mixer.Info[] mixerInfo;
    mixerInfo = AudioSystem.getMixerInfo();
    Line.Info targetDLInfo = new Line.Info(TargetDataLine.class);
    int i=mixerInfo.length;
    for(int cnt = 0; cnt < i; cnt++)
     {
      Mixer currentMixer = AudioSystem.getMixer(mixerInfo[cnt]);
      if( currentMixer.isLineSupported(targetDLInfo) )
       {
        tta("ind:"+cnt+"  name:"+mixerInfo[cnt].getName());
       }
      else  tta("not supported ind:"+cnt+"  name:"+mixerInfo[cnt].getName());
     }
   }
  void da2Wave(String daname)
   {
    double[] da=te.dahg(daname);
    da2Wave(da);
   }
  void da2Wave(double[] da)
   {
    tta("Wave.da2Wave  needs attention");
    int chansamples=da.length; // number of (16 bit) channelsamples
    secs=chansamples/samplerate; 
    tu=parent.tu;
    lc=parent.lc;
    mode=2;
    samplerate=stdbr;
    samplebits=16;
    chs=2;
    blockbytes=4; // chs*(samplebits/8)
    blockrate=(float)(samplerate*blockbytes);
    databytes=(int)(4*samplerate*secs);
    //  a=commb(new byte[44+(int)databytes],databytes,2,samplerate,blockrate,4,16);
    chshorts=(int)databytes/(chs*(samplebits/8));
    ca=new short[(int)chshorts];
    cb=new short[(int)chshorts];
    for(int i=0;i<chansamples;i++)
     { 
      ca[i]=(short)(int) da[i];
      cb[i]=(short)(int) da[i];
      cabi2ba(i);
     }
    tta("Wave.da2Wav done   chshorts:"+chshorts);
   }
  void synth()
   {
    tu=parent.tu;
    lc=parent.lc;
    mode=2;
    samplerate=stdbr;
    samplebits=16;
    chs=2;
    blockbytes=4; // chs*(samplebits/8)
    blockrate=(float)(samplerate*blockbytes);
    databytes=4*samplerate*600; // 60 sec
    // a=commb(new byte[44+(int)databytes],databytes,2,samplerate,blockrate,4,16);
    chshorts=(int)databytes/(chs*(samplebits/8));
    ca=new short[(int)chshorts];
    cb=new short[(int)chshorts];
    int tr=44100;
    int ttr=4410;
    int j=0;
    int jj=ttr;
    double yValue = 32767D;
    double oyV = 32767D;
    double yV = 32767D;
    double ny = 0D;
    int kt=6;
    for(int i=0;i<(int)chshorts; i++)
     {
      if(j==0)
       {
        j=tr;
        oyV=yV;
        // 65536 ;
        if(yV == 32767D) yV=0D;
        else if(yV == 16384D) yV=0D;
        else if(yV == 0D) yV=-16384D;
        else if(yV == -16384D) yV=-32767D;
        else if(yV == -32767D) yV=32767D;
        jj=ttr;
       }
      if(jj > 0) jj--;
      yValue= yV+((oyV-yV)*jj/ttr);
      if(yValue<0) yValue=65536D+yValue;
      ca[i]=(short)(int)Math.round(yValue);
      cb[i]=ca[i];
      cabi2ba(i);
      j--;
     }
    tta("synth done");
   }
  void pulsesynth()
   {
    tu=parent.tu;
    lc=parent.lc;
    mode=2;
    samplerate=stdbr;
    samplebits=16;
    chs=2;
    blockbytes=4; // chs*(samplebits/8)
    blockrate=(float)(samplerate*blockbytes);
    databytes=4*samplerate*600; // 60 sec
    //a=commb(new byte[44+(int)databytes],databytes,2,samplerate,blockrate,4,16);
    chshorts=(int)databytes/(chs*(samplebits/8));
    ca=new short[(int)chshorts];
    cb=new short[(int)chshorts];
    int j=0;
    int tr=100;
    double yValue = 32767D;
    double oyV = 32767D;
    double yV = 32767D;
    int kt=1;
    for(int i=0;i<(int)chshorts; i++)
     {
      if(j==0)
       {
        tr=100;
        oyV=yValue;
        j=(int)(100+kt*1000);
        kt++;
        yV = 9767D*(-1+(int)(3*Math.random()));
       }
      if(tr==0) yValue=yV;
      else 
       {
        yValue= yV+((oyV-yV)*tr/100);
        tr--;
       }
      //double rscs=Math.round(samplerate/440);
      //double cf=sf+((ef-sf)*i/(int)chshorts);
      //double rscs=Math.round(samplerate/cf);
      //double rscs=samplerate/cf;
      //  double yValue = 32767D * Math.sin(i*6.283185307179586D/rscs);
      ca[i]=(short)(int)Math.round(yValue);
      cb[i]=ca[i];
      cabi2ba(i);
      j--;
     }
    tta("synth done");
   }
  void singlesynth()
   {
    tu=parent.tu;
    lc=parent.lc;
    mode=2;
    samplerate=stdbr;
    samplebits=16;
    chs=2;
    blockbytes=4; // chs*(samplebits/8)
    blockrate=(float)(samplerate*blockbytes);
    databytes=4*samplerate*600; // 60 sec
    //a=commb(new byte[44+(int)databytes],databytes,2,samplerate,blockrate,4,16);
    chshorts=(int)databytes/(chs*(samplebits/8));
    ca=new short[(int)chshorts];
    cb=new short[(int)chshorts];
    double sf=100;
    double ef=.01;
    for(int i=0;i<(int)chshorts; i++)
     {
      //double rscs=Math.round(samplerate/440);
      double cf=sf+((ef-sf)*i/(int)chshorts);
      //double rscs=Math.round(samplerate/cf);
      double rscs=samplerate/cf;
      double yValue = 32767D * Math.sin(i*6.283185307179586D/rscs);
      ca[i]=(short)(int)Math.round(yValue);
      cb[i]=ca[i];
      cabi2ba(i);
     }
    tta("synth done");
   }
  void synthsweep()
   {
    tu=parent.tu;
    lc=parent.lc;
    mode=2;
    samplerate=stdbr;
    samplebits=16;
    chs=2;
    blockbytes=4; // chs*(samplebits/8)
    blockrate=(float)(samplerate*blockbytes);
    databytes=4*samplerate*600; // 60 sec
    // a=commb(new byte[44+(int)databytes],databytes,2,(double)stdbr,(double)4*stdbr,4,16);
    chshorts=(int)databytes/(chs*(samplebits/8));
    ca=new short[(int)chshorts];
    cb=new short[(int)chshorts];
    double sf=5;
    double ef=.01;
    for(int i=0;i<(int)chshorts; i++)
     {
      //double rscs=Math.round(samplerate/440);
      double cf=sf+((ef-sf)*i/(int)chshorts);
      //double rscs=Math.round(samplerate/cf);
      double rscs=samplerate/cf;
      double yValue = 32767D * Math.sin(i*6.283185307179586D/rscs);
      ca[i]=(short)(int)Math.round(yValue);
      cb[i]=ca[i];
      cabi2ba(i);
     }
    tta("synth done");
   }
  void square()
   {
    square(1);
   }
  void compab()
   {
    tta("Start compab");
    for(int i=0;i<(int)chshorts; i++)
     {	     
      cb[i]=(short)-ca[i]; 
      cabi2ba(i);
     } 
   }
  void compba()
   {
    tta("Start compab");
    for(int i=0;i<(int)chshorts; i++)
     {	     
      ca[i]=(short)-cb[i]; 
      cabi2ba(i);
     } 
   }
  void cpab()
   {
    tta("Start cpab");
    for(int i=0;i<(int)chshorts; i++)
     {	     
      cb[i]=ca[i]; 
      cabi2ba(i);
     } 
   }
  void cpba()
   {
    tta("Start cpba");
    for(int i=0;i<(int)chshorts; i++)
     {	     
      ca[i]=cb[i]; 
      cabi2ba(i);
     } 
   }
  void square(int lode)
   {
    tta("Start square lode:"+lode);
    if(lode==1)
     {
      for(int i=0;i<(int)chshorts; i++)
       {
        if(ca[i]< -27000) ca[i]=-30000;
        else if(ca[i]<3000) ca[i]=0;
        else ca[i]=30000;
        // cb[i]=ca[i]; keep cb
        cabi2ba(i);
       } 
     }
    else if(lode==2)
     {
      for(int i=0;i<(int)chshorts; i++)
       { 
        if(ca[i]< -27000) ca[i]=-30000;
        else if(ca[i]<3000) ca[i]=0;
        else ca[i]=30000;
        // cb[i]=ca[i]; keep cb
        int j=i;
        double ave=0;
        while(j>0 &&j > i-31)
         {
          ave+=ca[j];
          j--;
         }
        ave/=30;
        cb[i]=(short)(ave);
        cabi2ba(i);
       } 
     }
    if(lode==3)
     {
      for(int i=0;i<(int)chshorts; i++)
       {
        if(ca[i]< -21000) ca[i]=-30000;
        else if(ca[i]>=-21000 && ca[i]<21000) ca[i]=0;
        else ca[i]=30000;	    
        cb[i]=(short)-ca[i]; 
        cabi2ba(i);
       } 
     }
    tta("End square");
   }
  public void bigg() // https://www.codejava.net/coding/how-to-play-back-audio-in-java-with-examples
   {
    loadbigg(); 
   }
  public void loadbigg()
   {
    String audioFilePath="/webroot/ajlogo/html/ajlogo/version3beta/audio/3sec.wav";
    File audioFile = new File(audioFilePath);
    try
     {
      AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
      AudioFormat format = audioStream.getFormat();
      tta("bigg format:"+format.toString()); 
      sdlineInfo = new Info(SourceDataLine.class, format); 
      sdline = (SourceDataLine) AudioSystem.getLine(sdlineInfo);
      sdline.open(format);
      sdline.start(); // must be started 
      buff1=new byte[pbs]; 
      int bytesRead = -1; 
      int chunk=0; 
      while ((bytesRead = audioStream.read(buff1)) != -1)
       {
        for (int rko=0;rko<20;rko++)  tta("rko:"+rko+" buff1[rko]:"+buff1[rko]); 
        tta("chunk:"+chunk);
        chunk++;
        sdline.write(buff1, 0, bytesRead);
       }       
      sdline.drain();
      sdline.close();
      audioStream.close();
     }
    catch (UnsupportedAudioFileException ex)
     {
      tta("The specified audio file is not supported.");
      ex.printStackTrace();
     } 
    catch (LineUnavailableException ex)
     {
      tta("Audio line for playing back is unavailable.");
      ex.printStackTrace();
     } 
    catch (IOException ex)
     {
      tta("Error playing the audio file.");
      ex.printStackTrace();
     }
   }
  public String toStr()
   {
    //  public Wav(M p,String n,int sb,double sr,int ch,double seconds)
    secs=(chshorts/samplerate);
    return "aWav "+name+","+samplebits+","+samplerate+","+chs+","+secs;
   }
  public static void tta(String s) { parent.tta(s); }
  public static void tta1(String s) { parent.tta1(s); }
  void schleep(long zzz)
   {
    try { thr.sleep(zzz); }
    catch(InterruptedException e) { }
   }
 }
