//Magnus Pfleghar
import processing.sound.*;
SoundFile file;

FFT fft;
AudioIn audio;
int bands = 16;
audioBufferRow audioArray[]=new audioBufferRow[16];
int frame=0;
//float freq[]={ 20, 25, 31.5, 40, 50,63,80,100,125,150,160,200,250,315,400,500,630,800,1000,1250,2000,3150,4000,5000,6300,8000,10000,12500,16000,20000};
float freq[]=new float[bands];
void setup() {
  frameRate(60);
  
  size(800, 800, P3D);
  //file = new SoundFile(this, "drums.mp3");
  //file.loop();
  //file.rate(1);
  for (int i=0; i<audioArray.length; i++) {
    audioArray[i]=new audioBufferRow();
  }
  audio = new AudioIn(this, 0);
  audio.start();
  fft = new FFT(this, bands);
  //audio = new AudioIn(this, 0);
  //audio.start();
  fft.input(audio);
}

void draw() {
  background(0);
  fft.analyze();
  //if (frame==10000) {
  //frame=0;
  //}
  //frame++;
  translate(100, 450, -100);
  rotateX(-PI/4);
  rotateZ(PI);
  //rotateY(PI+PI/4);
  rotateY(PI+PI/4);
  int zOffset=0;
  audioArray[0].update(0);
  //if (frame%1==0) {
     for (int i=audioArray.length-1; i>0; i--) {
     audioArray[i]=new audioBufferRow();
     audioArray[i].aBc=audioArray[i-1].getRowDuplicate();
    // }
  }
  for (int i=0; i<audioArray.length; i++) {
    audioArray[i].show(zOffset,i);
    zOffset+=30;
  }
}
//Magnus Pfleghar
class audioBufferColumn{
  int heightOfColumn=15;
  int fr;
  audioBufferColumn(){
    
  }
  audioBufferColumn(int frOv){
    this.fr=frOv;
  }
  void update(int row){
    this.fr=floor(constrain(map(fft.spectrum[row]*200,0,10, 1,5),0,heightOfColumn));
  }
  void show(int widthOffset,int zOffset,int row){
    int heightOffset=0;
    //fft.getEnergy();
    
    //println(fft.spectrum[row]);
    for(int i=0; i<this.fr; i++){
      push();
      fill(map(i,0,this.fr,0,255),map(i,0,this.fr,255,0),0);
      translate(widthOffset, heightOffset, zOffset);
      box(10, 5, 10);
      heightOffset+=20;
      pop();
    }
  }
}
//Magnus Pfleghar
class audioBufferRow {
  boolean done=false;
  audioBufferColumn[] aBc=new audioBufferColumn[16];
  audioBufferRow() {
    for (int i=0; i<aBc.length; i++) {
      this.aBc[i]=new audioBufferColumn();
    }
  }
  void update(int row) {
      for (int i=0; i<aBc.length; i++) {
        this.aBc[i].update(i);
      }
      //println("update"+row+"#"+frame);
  }
  void show(int zOffset,int row) {
    int widthOffset=0;
    for (int i=0; i<aBc.length; i++) {
      aBc[i].show(widthOffset, zOffset,row);
      widthOffset+=30;
      //println("show"+row+"@column:"+i+"#"+frame);
    }
  }
  audioBufferColumn[] getRowDuplicate(){
   audioBufferColumn[] tmp=new audioBufferColumn[16];
   for(int i=0; i<tmp.length; i++){
     tmp[i]=new audioBufferColumn(aBc[i].fr);
   }
   return tmp;
  }
}