davideriboli
4/7/2016 - 8:14 PM

Surface Spectrogram #audioreactive #processing

Surface Spectrogram #audioreactive #processing

/**
 * Super3dvisualizer, a 3D Surface Spectogram Audio Visualizer in Processing
 *
 * @author Eliot Lash
 * @copyright Copyright (c) 2010-2012 Eliot Lash
 */
import ddf.minim.analysis.*;
import ddf.minim.*;
 
Minim minim;
AudioInput in;
AudioPlayer groove;
FFT fft;

static int sampleRate = 512;

int bufferStart = 0;
static int bufferMax = 100;
float countRad = 0;

static float power = 1.5;
static float xStretch = 5.0;
static float yStretch = 1.0;
static float zStretch = 5.0;

float cameraCenterX = 255;
float cameraCenterY = 0;
float cameraCenterZ = 255;

static float alphaCycle = 0.03;

float savedmouseX;
float savedmouseY;
float savedmouseZ = 220.0;

float[][] geomBuffer;

void setup()
{
  size(851, 800, P3D);
 
  minim = new Minim(this);
  //minim.debugOn();
 
  // get a line in from Minim, default bit depth is 16
  in = minim.getLineIn(Minim.STEREO, sampleRate);
  in.mute();
  
  groove = minim.loadFile("../../media/song.mp3", sampleRate);
  groove.play();
  
  fft = new FFT(groove.bufferSize(), groove.sampleRate());
    fft.logAverages(22, 3);
    
  geomBuffer = new float[bufferMax][fft.specSize()];
  
  for(int i = 0; i < fft.specSize(); i++)
  {    
    geomBuffer[bufferStart][i] = fft.getBand(i);
  }
  
  //frameRate(1);
//smooth();


}
 
void draw()
{
//  stroke(255);
//  // draw the waveforms
//  for(int i = 0; i < in.bufferSize() - 1; i++)
//  {
//    line(i, 50 + in.left.get(i)*50, i+1, 50 + in.left.get(i+1)*50);
//    line(i, 150 + in.right.get(i)*50, i+1, 150 + in.right.get(i+1)*50);
//  }
  
   // Change height of the camera with mouseY
 /*camera(30.0, mouseY * 10, 220.0, // eyeX, eyeY, eyeZ
         0.0, 0.0, 0.0, // centerX, centerY, centerZ
         0.0, 1.0, 0.0); // upX, upY, upZ*/
         
   //lights();
   
   background(10);
   
   specular(#00BFFF);
   lightSpecular(0, 191, 255);
   directionalLight(49, 140, 231, 0, 0, -1);
  //background((int)fft.calcAvg(10, 20000) * 10 + 80);
 
  
  //camera shit
  /*float cameraY = (height/2.0);
  float fov = (savedmouseX /float(width) * PI/2) * -1;
  float cameraZ = cameraY / tan(fov / 2.0);
  float aspect = float(width)/float(height);
  if (mousePressed) {
    aspect = aspect / 2.0;
  }
  perspective(fov, aspect, cameraZ/10.0, cameraZ*10.0);
  translate(width/2+30, height/2, 0);
  rotateX(-PI/6);
  rotateY(PI/3 + savedmouseY/float(height) * PI);*/
  
   camera(savedmouseX, savedmouseY, savedmouseZ, // eyeX, eyeY, eyeZ
         cameraCenterX, cameraCenterY, cameraCenterZ, // centerX, centerY, centerZ
         0.0, -1.0, 0.0); // upX, upY, upZ
         
 //draw FFT
 translate(0, -1*height, 0); 
 
 fft.forward(groove.mix);
 //fft.forward(groove.mix);
 //print(fft.calcAvg(10, 20000));
  
  //fill(bufferStart, bufferStart - 100, bufferStart -50);
  //fill(#FF7E00);
  //noStroke();
  float colorPercentage = ((sin(countRad) * 0.5 + 0.5) * 255);
  
  fill(#00BFFF, colorPercentage);
  //println(colorPercentage);
  stroke(#00BFFF);
  strokeWeight(3);

      //Evil hack to draw over the gap left by an error in how we implemented our ring buffer - this is the "scan line
     beginShape(QUAD_STRIP);
      for (int band = 0; band < fft.specSize(); band++) {
        int i = bufferStart % (geomBuffer.length - 1);
        
        if ((i + 1) < geomBuffer.length) {
        vertex((band)* xStretch, height + pow(geomBuffer[i][band], power) * yStretch, bufferStart * zStretch);
        vertex((band)* xStretch, height + pow(geomBuffer[i + 1][band], power) * yStretch, (bufferStart+1) * zStretch);
        } else {
          print ("i == "+ i +". geomBuffer.length == " + geomBuffer.length + ". i >= geomBuffer.length. Waaah!\n");
        }
      }
      endShape();
      
//      beginShape(TRIANGLE_STRIP);
//      int bufferHack = bufferStart - 1;
//      if (bufferHack != -1) {
//        for (int band = 0; band < fft.specSize(); band++) {
//          int i = bufferHack % (geomBuffer.length - 1);
//          
//          if ((i + 1) < geomBuffer.length) {
//          vertex((band)* xStretch, height + geomBuffer[i][band] * yStretch, bufferHack * zStretch);
//          vertex((band)* xStretch, height + geomBuffer[i + 1][band] * yStretch, (bufferHack+1) * zStretch);
//          } else {
//            print ("i == "+ i +". geomBuffer.length == " + geomBuffer.length + ". i >= geomBuffer.length. Waaah!\n");
//          }
//        }
//        endShape();
//      }
  
  float redFactor = 30;
  float greenFactor = 0;
  float blueFactor = 200;
  
  for (int zPosition = bufferStart + 1; zPosition != bufferStart;) {

    //;pow(geomBuffer[i + 1][band], power) * -1
   //println(bufferStart + " " + zPosition);


      for (int band = 0; band < fft.specSize(); band++) {
        greenFactor += 0.004;
        beginShape(TRIANGLE_STRIP);
        int i = (bufferStart + zPosition) % (geomBuffer.length -1);
        
        stroke(redFactor, greenFactor, blueFactor);
        
        if ((i + 1) < geomBuffer.length) {
        vertex((band)* xStretch, height + pow(geomBuffer[i][band], power) * yStretch, zPosition * zStretch);
        vertex((band)* xStretch, height + pow(geomBuffer[i + 1][band], power) * yStretch, (zPosition+1) * zStretch);
        } else {
          print ("i == "+ i +". geomBuffer.length == " + geomBuffer.length + ". i >= geomBuffer.length. Waaah!\n");
        }
        endShape();
      }

      
      
    zPosition++;
    if(zPosition >= geomBuffer.length)
    {
      zPosition = 0;
    }
  }
  
  //Update our FFT data
  for(int i = 0; i < fft.specSize(); i++)
  {    
    geomBuffer[bufferStart][i] = fft.getBand(i);
  }

  
  if (bufferStart < bufferMax - 1) {
    bufferStart++;
  } else {
    bufferStart = 0;
  }
  
  if (countRad < 6.28) {
    countRad += alphaCycle;
  } else {
    countRad = 0;
  }
  //Draw X, Y, Z axis
  stroke(255,0,0);
  line (0,height,0,50,height,0); //x+ axis
  stroke(0,255,0);
  line (0,height,0,0,height+50,0); //y+ axis
  stroke(0,0,255);
  line (0,height,0,0,height,50); //z axis
  stroke(255);
  fill(255);


}

void mouseDragged() {
   savedmouseX = mouseX;
   savedmouseY = mouseY;
}
 
void keyPressed() {
  if (key == CODED) {
    if (keyCode == UP) {
      savedmouseZ += 100;
    } else if(keyCode == DOWN) {
      savedmouseZ -= 100;
    } else if(keyCode == LEFT) {
      cameraCenterX -= 100;
    } else if (keyCode == RIGHT) {
      cameraCenterX += 100;
    }
  }
}
 
void stop()
{
  // always close Minim audio classes when you are done with them
  in.close();
  //groove.close();
  minim.stop();
 
  super.stop();
}