import java.lang.*;
import java.util.*;
import java.io.*;

import javax.sound.sampled.*;



public class sampletablec {
  byte sample[]; 
  int size;
  double samplerate;
  static int wave_data_size = 0;
  static float FTT_data[][];
  int id;
  sampletablec(int size,double samplerate) {
    this.size = size;
    this.samplerate = samplerate;
    sample = new byte[size+3];
  }  
  static void rearrange() {
    int target = 0;
    for (int pos = 0;pos < wave_data_size;pos++) {
      if (target > pos) {
        float temp = FTT_data[target][0];
        FTT_data[target][0] = FTT_data[pos][0];
        FTT_data[pos][0] = temp;
        temp = FTT_data[target][1];
        FTT_data[target][1] = FTT_data[pos][1];
        FTT_data[pos][1] = temp;
      }
      int mask = wave_data_size;
      mask = mask >> 1;
      while ((target & mask) != 0) {
        target = target & ~mask;
        mask = mask >> 1;
      }
      target = target | mask;
    }
  }
  static void perform(boolean Inverse) {
    //float PI = (float) 3.14159265358979323846;
    //if (Inverse) {PI = (float) -3.14159265358979323846;}
    float PI = (float) Math.PI;
    if (Inverse) {PI = (float) -Math.PI;}
    int step = 1;
    while (step < wave_data_size) {
      int jump = step + step;
      float delta = PI / ((float) step);
      float s = (float) Math.sin(delta / 2.0);
      float Multiplier_real = -2.0f * s * s;
      float Multiplier_img = (float) Math.sin(delta);
      float factor_real = 1.0f;
      float factor_img = 0.0f;
      for (int group = 0;group < step;group++) {
        for (int pair = group;pair < wave_data_size;pair = pair + jump) {
          int match = pair + step;

          float product_real = (factor_real*FTT_data[match][0]);
          product_real = product_real - (factor_img*FTT_data[match][1]);
          float product_img = (factor_real*FTT_data[match][1]);
          product_img = product_img + (factor_img*FTT_data[match][0]);

          FTT_data[match][0] = FTT_data[pair][0] - product_real;
          FTT_data[match][1] = FTT_data[pair][1] - product_img;

          FTT_data[pair][0] = FTT_data[pair][0] + product_real;
          FTT_data[pair][1] = FTT_data[pair][1] + product_img;
        }
        float new_factor_real = (Multiplier_real*factor_real);
        new_factor_real = new_factor_real - (Multiplier_img*factor_img);

        float new_factor_img = (Multiplier_real*factor_img);
        new_factor_img = new_factor_img + (Multiplier_img*factor_real);

        factor_real = new_factor_real + factor_real;
        factor_img = new_factor_img + factor_img;
      }
      step = step + step;    
    }
  }  
  void output_to_file(String filename) {
    try {
      DataOutputStream outfile = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename,true)));
      for (int i = 0;i < size;i++) {
        byte b = sample[i];
        outfile.writeByte(b);
      }
      outfile.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  void make_instrument_sample(int ch,float freq,float bandwidth,float harmonic[],Random rand) {
    int num_harmonics = harmonic.length-1;
    //Random rand = new Random();
    //if (wave_data_size != size) {
    //  wave_data_size = size;
    //  FTT_data = new float[wave_data_size][2];
    //}
    for (int i = 1;i <= num_harmonics;i++) {
      float freq2 = freq * harmonic[i];
      if (freq2 >= ((wave_data_size / 2.0)+bandwidth)) {continue;}
      if (freq2 <= bandwidth) {continue;}
      int start_freq = ((int) (freq2-bandwidth+1.0));
      int end_freq = ((int) (freq2+bandwidth));
      for (int i2 = start_freq;i2 <= end_freq;i2++) {        
        int i3 = wave_data_size-i2;
        float e = (((float) i2)-freq2);
        if (e < 0) {e = -e;} 
        e = 1.0f - (e / bandwidth);   
        e = (e * 1.0f) / ((float) Math.sqrt(bandwidth)); 
        float am = rand.nextFloat();
        float p = (float) (rand.nextFloat()*Math.PI*2.0);
        float re = ((float) (Math.cos(p) * e * am) / harmonic[i]);
        float im = ((float) (Math.sin(p) * e * am) / harmonic[i]);
        if (i2 <= (wave_data_size / 2.0)) {
          if (ch == 0) {
            FTT_data[i2][0] = re;FTT_data[i3][0] =  re;
            FTT_data[i2][1] = im;FTT_data[i3][1] = -im;
          } else {  
            FTT_data[i2][0] = FTT_data[i2][0] + re;
            FTT_data[i2][1] = FTT_data[i2][1] + im;
            FTT_data[i3][0] = FTT_data[i3][0] - re;
            FTT_data[i3][1] = FTT_data[i3][1] + im;
          }
        }
      }
    }
  }
    
  void get_instrument_sample(int ch,float vol) {
    int clipping = 0;
    for (int i = 0;i < size;i++) {
      double s = (FTT_data[i][ch] * vol);
      if (s > 127.0) {s = 127.0;clipping++;}
      if (s < -127.0) {s = -127.0;clipping++;}
      sample[i] = (byte) s;
    }
    //System.out.println("clipping: " + clipping);
    for (int i = 0;i < 3;i++) {
    //sample[size] = sample[0]; 
      sample[size+i] = sample[i]; 
    }
  }
}



