/*
 * NewJApplet.java
 *
 * Created on January 23, 2008, 10:25 AM
 */

import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;


/**
 *
 * @author  root
 */
public class NewJApplet extends javax.swing.JApplet {
    int nsamples=16384;
    double samplerate=44100.0;
    double frequency=1000.0;
    double omega=2*frequency*Math.PI;
    double signal_amplitude=50.0;
    double noise_amplitude=50.0;
    int cutoff=100;
    int selector;
    int selectorn;
    double [] data;
    double [] RealIn;
    double [] ImagIn;
    double [] RealOut;
    double [] ImagOut;
    double [] RealF;
    double [] ImagF;
    double [] [] spect;
    double [][]  filt;
    
   
    
    /** Initializes the applet NewJApplet */
    public void init() {
        try {
            java.awt.EventQueue.invokeAndWait(new Runnable() {
                public void run() {
                    initComponents();
                }
            });
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        
        data=new double [nsamples];
        noises.setValue((int)noise_amplitude);
        signals.setValue((int)signal_amplitude);
      
        
        
        RealIn = new double[nsamples];
        ImagIn = new double[nsamples];
        RealOut = new double[nsamples];
        ImagOut = new double[nsamples];
        RealF=new double [nsamples];
        ImagF=new double[nsamples];
        spect=new double[nsamples][2];
        filt=new double[nsamples][2];
        initialize();
             noise();
        spectrum();
        filterweak();
    }
    
    /** This method is called from within the init() method to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new myPanel();
        jPanel2 = new javax.swing.JPanel();
        noises = new javax.swing.JSlider();
        signals = new javax.swing.JSlider();
        jLabel1 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jComboBox1 = new javax.swing.JComboBox();
        jComboBox2 = new javax.swing.JComboBox();
        cutoffs = new javax.swing.JSlider();
        jLabel4 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();

        jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 378, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 533, Short.MAX_VALUE)
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));

        noises.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                noisesMouseDragged(evt);
            }
        });

        signals.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                signalsMouseDragged(evt);
            }
        });

        jLabel1.setText("signal");

        jLabel3.setText("noise");

        jLabel2.setText("cutoff");

        jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "mono", "double", "rectangle" }));
        jComboBox1.setMaximumSize(new java.awt.Dimension(78, 23));
        jComboBox1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jComboBox1ActionPerformed(evt);
            }
        });

        jComboBox2.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "discrete", "constant", "Gaussian" }));
        jComboBox2.setMaximumSize(new java.awt.Dimension(78, 23));
        jComboBox2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jComboBox2ActionPerformed(evt);
            }
        });

        cutoffs.setMaximum(200);
        cutoffs.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                cutoffsMouseClicked(evt);
            }
            public void mousePressed(java.awt.event.MouseEvent evt) {
                cutoffsMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                cutoffsMouseReleased(evt);
            }
        });
        cutoffs.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                cutoffsMouseDragged(evt);
            }
            public void mouseMoved(java.awt.event.MouseEvent evt) {
                cutoffsMouseMoved(evt);
            }
        });
        cutoffs.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                cutoffsPropertyChange(evt);
            }
        });

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addGap(12, 12, 12)
                        .addComponent(cutoffs, javax.swing.GroupLayout.PREFERRED_SIZE, 147, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addGap(62, 62, 62)
                        .addComponent(jLabel2))
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addGap(61, 61, 61)
                        .addComponent(jLabel1))
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addGap(63, 63, 63)
                        .addComponent(jLabel3))
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(noises, javax.swing.GroupLayout.PREFERRED_SIZE, 147, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jComboBox2, javax.swing.GroupLayout.PREFERRED_SIZE, 132, javax.swing.GroupLayout.PREFERRED_SIZE)))
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(signals, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addGap(22, 22, 22)
                        .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, 131, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap(58, Short.MAX_VALUE))
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(signals, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(26, 26, 26)
                .addComponent(jLabel3)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jComboBox2, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(noises, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(57, 57, 57)
                .addComponent(jLabel2)
                .addGap(4, 4, 4)
                .addComponent(cutoffs, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jLabel4.setText("black = input");

        jLabel5.setText("red = Fourier spectrum");

        jLabel6.setText("blue = output");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLabel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLabel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLabel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap(27, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(36, 36, 36)
                        .addComponent(jLabel4)
                        .addGap(36, 36, 36)
                        .addComponent(jLabel5)
                        .addGap(36, 36, 36)
                        .addComponent(jLabel6))
                    .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

 public void noise()
    {
    int i,j,k; double x,y;
    
    for(i=0;i<nsamples;i++)
    {      x = i / samplerate;
           y=0;
           
           switch (selector)
           {
           
       case 0:    {y = (Math.sin(omega * x)) * signal_amplitude;
                           break;}
       case 1:    {y = (Math.sin(omega * x)) * signal_amplitude +
                         Math.sin(2.5*omega*x)*signal_amplitude*0.2  ; break;}
       case 2:    {y = Math.signum(Math.sin(omega * x)) * signal_amplitude  ; }
           }
           
           switch(selectorn)
           {
               
         case 0: {y=y+Math.signum(2.0*Math.random()-1.0)*noise_amplitude;break;}
         case 1: {y = y+noise_amplitude *  (2.0*Math.random()-1.0) ; break;}
         case 2: y=y+noise_amplitude*randgauss();
               
           }
           
           data[i]=y;    
    }
    }
 
 

 public boolean IsPowerOfTwo(int x)
 
{
  int i, y;

  y = 2;
  for (i = 1; i <= 15; i++) {
    if (x == y)
      return true;
    y <<= 1;
  }
  return false;
}


 
 public int NumberOfBitsNeeded(int PowerOfTwo)
 
{
  int  i,i1;
  i1=0;
  for (i = 0; i <= 16; i++) {
    if ((PowerOfTwo & (1 << i)) != 0)
      i1= i;
  }
  return i1;
}


 public int ReverseBits(int index, int NumBits)

{
  int i, rev;

  rev = 0;
  for (i = 0; i < NumBits; i++) {
    rev = (rev << 1) | (index & 1);
    index >>= 1;
  }
  return rev;
}

 void FourierTransform(double AngleNumerator, int nsamples, 
         double [] RealIn, double[]ImagIn,
			     double[] RealOut, double[] ImagOut)
 
{
  int NumBits, i, j, k, n, BlockSize, BlockEnd;
  double delta_angle, delta_ar, alpha, beta, tr, ti, ar, ai;

  NumBits = NumberOfBitsNeeded(nsamples);
  for (i = 0; i < nsamples; i++) {
    j = ReverseBits(i, NumBits);
    RealOut[j] = RealIn[i];
    ImagOut[j] = ImagIn[i];
  }

  BlockEnd = 1;
  BlockSize = 2;

  while (BlockSize <= nsamples) {
    delta_angle = AngleNumerator / BlockSize;
    alpha = Math.sin(0.5 * delta_angle);
    alpha = 2.0 * alpha * alpha;
    beta = Math.sin(delta_angle);
    i = 0;
    while (i < nsamples) {
      ar = 1.0;   /* cos(0) */
      ai = 0.0;   /* sin(0) */
      j = i;
      for (n = 0; n < BlockEnd; n++) {
	k = j + BlockEnd;
	tr = ar * RealOut[k] - ai * ImagOut[k];
	ti = ar * ImagOut[k] + ai * RealOut[k];
	RealOut[k] = RealOut[j] - tr;
	ImagOut[k] = ImagOut[j] - ti;
	RealOut[j] += tr;
	ImagOut[j] += ti;
	delta_ar = alpha * ar + beta * ai;
	ai += beta * ar - alpha * ai;
	ar -= delta_ar;
	j++;
      }
      i += BlockSize;
    }

    BlockEnd = BlockSize;
    BlockSize <<= 1;
  }
}



void fft(int nsamples, double[]RealIn, double[] ImagIn,
        double[] RealOut, double[] ImagOut)

{
  FourierTransform(2 * Math.PI, nsamples, RealIn, ImagIn, RealOut, ImagOut);
}


void ifft(int nsamples,  double[] RealIn, double[] ImagIn,
        double[] RealOut, double[] ImagOut)
{
  int i;

  FourierTransform(-2 * Math.PI, nsamples, RealIn, ImagIn, RealOut, ImagOut);

  /* Normalize the resulting time samples... */

  for (i = 0; i < nsamples; i++) {
    RealOut[i] /= nsamples;
    ImagOut[i] /= nsamples;
  }
}

public void spectrum()
{ int i; double x,y;
 for (i = 0; i < nsamples; i++) {
   
    RealIn[i] = data[i];
    ImagIn[i] = 0.0;
  }
  
 fft(nsamples, RealIn, ImagIn, RealOut, ImagOut);
 
 for (i = nsamples / 2 + 1; i < nsamples; i++) {
    /* reduction to first "Brillouin Zone"
       omega(N-j) is equivalent to omega(-j)
       */
    x = (double)((i - nsamples) * samplerate) / nsamples;
    spect[i][0]=x;
    spect[i][1]=Math.sqrt(RealOut[i]*RealOut[i]+ImagOut[i]*ImagOut[i]);
    
	/*frequency*/
  
  }

 
  for (i = 0; i < nsamples/2; i++) {
    
    x = (double)((i  * samplerate)) / nsamples;
	/*frequency*/
    spect[i][0]=x;
    spect[i][1]=Math.sqrt(RealOut[i]*RealOut[i]+ImagOut[i]*ImagOut[i]);
  }



}

public void filterweak()
{ int i; double re,im,y,x;
 for(i=0; i<nsamples; i++)
    {
    re = RealOut[i];
    im = ImagOut[i];
    y = Math.sqrt(re*re+im*im);
    
    if(y<cutoff*cutoff*5) { RealF[i] = 0.0; ImagF[i] = 0.0; }
    else { RealF[i] = RealOut[i]; ImagF[i] = ImagOut[i]; }
    }



  ifft(nsamples, RealF, ImagF, RealIn, ImagIn);


  for (i = 0; i < nsamples; i++) {
    x = (double)i / samplerate;   /*time in sec*/
    
    filt[i][0]=x;
    filt[i][1]=RealIn[i];

}
}

 public double randgauss()
{
double  x,r,phi,rho;

      r = Math.random();
      phi = 2.0*Math.PI*r;

      r = Math.random();
      rho=Math.sqrt(-Math.log(1-r));

      x = rho*Math.cos(phi)*Math.sqrt(2.0);



      return x;
}

 
    void initialize()
    { int i;
      
      for(i=0;i<nsamples;i++)
      {
      spect[i][0]=i; spect[i][1]=0;
      filt[i][0]=i; filt[i][1]=0;
      
        cutoffs.setValue(cutoff);
      }
    }
    

    private void cutoffsPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_cutoffsPropertyChange

    }//GEN-LAST:event_cutoffsPropertyChange

    private void cutoffsMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_cutoffsMouseReleased
        
       
        // TODO add your handling code here:
    }//GEN-LAST:event_cutoffsMouseReleased

    private void cutoffsMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_cutoffsMousePressed
       
        // TODO add your handling code here:
    }//GEN-LAST:event_cutoffsMousePressed

    private void cutoffsMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_cutoffsMouseClicked
       
         // TODO add your handling code here:
    }//GEN-LAST:event_cutoffsMouseClicked

    private void cutoffsMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_cutoffsMouseMoved
 
                // TODO add your handling code here:
    }//GEN-LAST:event_cutoffsMouseMoved

    private void cutoffsMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_cutoffsMouseDragged
     cutoff=cutoffs.getValue();
        filterweak();
    jPanel1.repaint();   // TODO add your handling code here:
    }//GEN-LAST:event_cutoffsMouseDragged

    private void signalsMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_signalsMouseDragged
        noise_amplitude=noises.getValue();
        signal_amplitude=signals.getValue();
        cutoff=cutoffs.getValue();
        initialize();
        noise();
        spectrum();
        filterweak();
        jPanel1.repaint();  // TODO add your handling code here:
    }//GEN-LAST:event_signalsMouseDragged

    private void noisesMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_noisesMouseDragged
        noise_amplitude=noises.getValue();
        signal_amplitude=signals.getValue();
        cutoff=cutoffs.getValue();
        initialize();
        noise();
        spectrum();
        filterweak();
        jPanel1.repaint();  // TODO add your handling code here:
    }//GEN-LAST:event_noisesMouseDragged

    private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBox1ActionPerformed
        selector=jComboBox1.getSelectedIndex();
        initialize();
        noise();
        spectrum();
        filterweak();
        jPanel1.repaint();  
        // TODO add your handling code here:
    }//GEN-LAST:event_jComboBox1ActionPerformed

    private void jComboBox2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBox2ActionPerformed
        selectorn=jComboBox2.getSelectedIndex();
        initialize();
        noise();
        spectrum();
        filterweak();
        jPanel1.repaint();  // TODO add your handling code here:
    }//GEN-LAST:event_jComboBox2ActionPerformed
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JSlider cutoffs;
    private javax.swing.JComboBox jComboBox1;
    private javax.swing.JComboBox jComboBox2;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JSlider noises;
    private javax.swing.JSlider signals;
    // End of variables declaration//GEN-END:variables
    public class myPanel extends javax.swing.JPanel{
       
    int iy0,iy1,i,ix0,ix1;
    void iterate()
    {
      
    }
 
    public void paintComponent(Graphics g)
{        
    
     super.paintComponent(g);  

    
    
    
     {
         
     g.setColor(Color.black);    
     for(i=0;i<500;i++)
     { iy0=(int)(100.0-data[i+500]*0.5); iy1=(int) (100.0-data[i+501]*0.5);
         g.drawLine(i,iy0,i+1,iy1);
     }
     
     g.setColor(Color.red);
     for(i=0;i<nsamples;i++)
     { ix0=(int)(spect[i][0]/40.0+200);
       iy0=(int)(spect[i][1]/2000.0);
       
       g.drawLine(ix0, 400, ix0, 400-iy0);
       
     }
     
     g.setColor(Color.green);
     g.drawLine(1, 400-cutoff*cutoff/400, 500, 400-cutoff*cutoff/400);
     
     g.setColor(Color.blue);
     
     
     for(i=0;i<500;i++)
     {  
         
         
      
       
       ix0=i;
       ix1=i+1;
       iy0=(int)(filt[i+500][1]*0.5);
       iy1=(int)(filt[i+501][1]*0.5);
       
     g.drawLine(ix0,450-iy0,ix1,450-iy1);
     }
    

    }
    }
}
}

