Totally new to this (sound visualisation)

edited November 2014 in How To...

Hi everyone, I have discovered processing because I am a student and I am trying to figure a way to have soundforms turn into beautiful art works for a project I am on.

I came across John Locke (http://gracefulspoon.com/blog/2009/04/02/visualizing-sound-in-processing/#more-395) and it is the perfect example of what I am trying to achieve.

I just need to know how to have a song or file and create those sorts of works using processing. I really appreciate any help, as deadline is approaching and I really am interested in this side of Soundwave art.

many thanks Paul

Tagged:

Answers

  • _vk_vk
    Answer ✓

    Look for minim examples bundled with Processing. It's a start point...

  • Thanks I will do but in the meantime, I still want to be able to get the soundwaves just like he did.. his source code is there but doesn't seem to work for me

  • Please be more specific. "Doesn't work" doesn't help us, could be one of 100 things. Post the error it gives you.

    (I'm guessing you're missing a library or the code is old)

    Also, more descriptive subject lines please.

  • ok, there were comments on that page that the code had been mangled by the blog with less thans treated as starts of html tags and quotes replaced by smart quotes etc.

    i've tidied it up so that it compiles now, but i don't have dxf or the fonts or the music files so i've not run this

    // tidied up version of this
    // gracefulspoon.com/blog/2009/04/02/visualizing-sound-in-processing/#more-395
    // by John Locke 2009
    import processing.dxf.*;
    import ddf.minim.analysis.*;
    import ddf.minim.*;
    
    FFT fftLog1;
    FFT fftLog2;
    Waveform myRects;
    Minim minim;
    AudioPlayer groove1;
    AudioPlayer groove2;
    boolean record;
    
    PFont font;
    PFont fontoutline;
    
    void setup() {
      size(1200, 600, P3D);
      noStroke();
      minim = new Minim(this);
      groove1 = minim.loadFile("groove_iggy.mp3");
      groove2 = minim.loadFile("groove_wagner.mp3");
      groove1.loop();//repeat each song
      groove2.loop();
      font = loadFont("HelveticaNeueLT-Bold-18.vlw");
      fontoutline = loadFont("HelveticaNeueLT-Bold-18.vlw");
      fftLog1 = new FFT(groove1.bufferSize(), groove1.sampleRate()); //create the FFT logarithmic scale
      fftLog2 = new FFT(groove2.bufferSize(), groove2.sampleRate());
      fftLog1.logAverages(22, 4);   //adjust numbers to adjust spacing
      fftLog2.logAverages(22, 4);
      float w1 = float ((fftLog1.avgSize()+fftLog2.avgSize())/2);
      float x = w1;
      float y = 0;
      float z = 50;
      myRects = new Waveform(x, y, z);
    }
    
    void draw() {
      background(15);
      directionalLight(126, 126, 126, sin(radians(frameCount)), cos(radians(frameCount)), 1);
      ambientLight(152, 152, 152);
      for (int i = 0; i < fftLog1.avgSize(); i++) {
        int w = int(width/fftLog1.avgSize());
        float zoom = 1;
        float jitter = (max(fftLog1.getAvg(i)*200, fftLog2.getAvg(i)*200 )); //jitter in camera influenced by waveform
        PVector foc = new PVector((myRects.x*.5+jitter*.5), myRects.y+jitter, 0);
        PVector cam = new PVector(zoom, zoom, -zoom);
        if (frameCount < 260) {
          camera(foc.x+cam.x, foc.y+(cam.y-1500*(cos(radians(-frameCount+60)))), foc.z+cam.z-400, 
              foc.x, foc.y, foc.z-100, 
              0, 0, 1);
          //println(-1500*(cos(radians(-frameCount+60))));
        }
        else {
          camera(foc.x+cam.x, foc.y+(cam.y+1418.278), foc.z+cam.z-400, foc.x, foc.y, foc.z-100, 0, 0, 1);
        }
      }
      fftLog1.forward(groove1.mix); //play each song
      fftLog2.forward(groove2.mix);
      myRects.update1();  //update each waveform+boolean
      myRects.update2();
      myRects.update3();
      myRects.textdraw1();  //draw z height for song waveforms
      myRects.textdraw2();
      if (record) {
        beginRaw(DXF, "output.dxf");
      }
      // DXF will export the stuff drawn between here.
      myRects.plotBoolean();  //create surfaces
      myRects.plotTrace1();
      myRects.plotTrace2();
      if (record) {
        endRaw();
        record = false;
        println("Done DXF!");
      }
    }
    
    void stop() {
      groove1.close(); // always close Minim audio classes when you finish with them
      groove2.close();
      minim.stop(); // always stop Minim before exiting
      super.stop();
    }
    
    class Waveform {
      float x, y, z;
      PVector[] pts1 = new PVector[fftLog1.avgSize()];
      PVector[] pts2 = new PVector[fftLog2.avgSize()];
      PVector[] pts3 = new PVector[fftLog1.avgSize()]; //needed for boolean waveform
      PVector[] trace1 = new PVector[0];
      PVector[] trace2 = new PVector[0];
      PVector[] trace3 = new PVector[0]; //needed for boolean waveform
      Waveform(float incomingX, float incomingY, float incomingZ) {
        x = incomingX;
        y = incomingY;
        z = incomingZ;
      }
    
      void update1() {  //plot boolean waveform
        plotB();
      }
    
      void plotB() {
        for (int i = 0; i < fftLog1.avgSize(); i++) {
          int w = int(width / fftLog1.avgSize());
          x = i * w - 1050;  //adjust the x position of the waveform here
          y = frameCount*5;
          z = height / 4 - fftLog1.getAvg(i) * 10;
          stroke(0);
          point(x, y, z);
          pts1[i] = new PVector(x, y, z);
          //increase size of array trace by length+1
          trace1 = (PVector[]) expand(trace1, trace1.length+1);
          //always get the next to last
          trace1[trace1.length-1] = new PVector(pts1[i].x, pts1[i].y, pts1[i].z);
        }
      }
    
      void plotBoolean() {
        stroke(255, 80);
        int inc = (fftLog1.avgSize() + fftLog2.avgSize())/2;
        for (int i=1; i < (trace1.length+trace2.length)/2-inc; i++) {
          if (i % inc != 0) {
            beginShape(TRIANGLE_STRIP);
            float value = (trace1[i].z*100);
            float m = map(value, -500, 20000, 0, 255);
            fill(m*2, 125, -m*2, 140);
            int threshold = 15;
            if (trace1[i].z < threshold || trace2[i].z < threshold) {
              vertex(trace1[i].x, trace1[i].y, (max(trace1[i].z, trace2[i].z))+(min(trace1[i].z, trace2[i].z)));
              vertex(trace1[i-1].x, trace1[i-1].y, (max(trace1[i-1].z, trace2[i-1].z))+(min(trace1[i-1].z, trace2[i-1].z)));
              vertex(trace1[i+inc].x, trace1[i+inc].y, (max(trace1[i+inc].z, trace2[i+inc].z))+(min(trace1[i+inc].z, trace2[i+inc].z)));
              vertex(trace1[i-1+inc].x, trace1[i-1+inc].y, (max(trace1[i-1+inc].z, trace2[i-1+inc].z))+(min(trace1[i-1+inc].z, trace2[i-1+inc].z)));
              endShape(CLOSE);
            }
          }
        }
      }
    
      void update3() { // plot first song's waveform
        plot1();
      }
    
      void plot1() {
        for (int i = 0; i < fftLog1.avgSize(); i++) {
          int w = int(width/fftLog1.avgSize());
          x = -2500 + i * w;  //adjust the x position of the waveform here
          y = frameCount * 5;
          z = height/4 - fftLog1.getAvg(i)*10;
          stroke(0);
          point(x, y, z);
          pts3[i] = new PVector(x, y, z);
          //increase size of array trace by length+1
          trace3 = (PVector[]) expand(trace3, trace3.length+1);
          //always get the next to last
          trace3[trace3.length-1] = new PVector(pts3[i].x, pts3[i].y, pts3[i].z);
        }
      }
    
      void textdraw1() {  //plot first song's z height waveform
        for (int i = 0; i < fftLog1.avgSize(); i++) {    
          textMode(SCREEN);
          textFont(font, 10);
          float theX = screenX(pts3[i].x+5, pts3[i].y+5, pts3[i].z+5);
          float theY = screenY(pts3[i].x+5, pts3[i].y+5, pts3[i].z+5);
          fill(255);
          text(round(fftLog1.getAvg(i)*100), theX, theY, 0);
          if (frameCount > 220) {
            textFont(fontoutline, 24);
            fill(155);
            text("wagner", 200, 500, 0);
            text("iggy", 900, 500, 0);
            text("max(iggy-wagner)", 500, 500, 0);
          }
        }
      }
    
      void plotTrace1() {
        stroke(255, 80);
        int inc = fftLog1.avgSize();
        for (int i=1; i < trace3.length-inc; i++) {
          if (i % inc != 0) {
            beginShape(TRIANGLE_STRIP);
            float value = (trace3[i].z*100);
            float m = map(value, -500, 20000, 0, 255);
            fill(m*2, 125, -m*2, 140);
            vertex(trace3[i].x, trace3[i].y, trace3[i].z);
            vertex(trace3[i-1].x, trace3[i-1].y, trace3[i-1].z);
            vertex(trace3[i+inc].x, trace3[i+inc].y, trace3[i+inc].z);
            vertex(trace3[i-1+inc].x, trace3[i-1+inc].y, trace3[i-1+inc].z);
            endShape(CLOSE);
          }
        }
      }
    
      void update2() {  //plot second song's waveform
        plot2();
      }
    
      void plot2() {
        for (int i = 0; i < fftLog2.avgSize(); i++) {
          int w = int(width / fftLog2.avgSize());
          x = i * w;  //adjust the x position of the waveform here
          y = frameCount*5;
          z = height / 4 - fftLog2.getAvg(i) * 10;
          stroke(0);
          point(x, y, z);
          pts2[i] = new PVector(x, y, z);
          //increase size of array trace by length+1
          trace2 = (PVector[]) expand(trace2, trace2.length+1);
          //always get the next to last
          trace2[trace2.length-1] = new PVector(pts2[i].x, pts2[i].y, pts2[i].z);
        }
      }
    
      void textdraw2() {
        for (int i = 0; i < fftLog2.avgSize(); i++) {    
          textFont(font);
          float theX = screenX(pts2[i].x+5, pts2[i].y+5, pts2[i].z+5);
          float theY = screenY(pts2[i].x+5, pts2[i].y+5, pts2[i].z+5);
          fill(255);
          text(round(fftLog2.getAvg(i)*100), theX, theY, 0);
        }
      }
    
      void plotTrace2() {
        stroke(255, 80);
        int inc = fftLog2.avgSize();
        for (int i = 1; i < trace2.length-inc; i++) {
          if (i % inc != 0) {
            beginShape(TRIANGLE_STRIP);
            float value = (trace2[i].z*100);
            float m = map(value, -500, 20000, 0, 255);
            fill(m * 2, 125, -m * 2, 140);
            vertex(trace2[i].x, trace2[i].y, trace2[i].z);
            vertex(trace2[i-1].x, trace2[i-1].y, trace2[i-1].z);
            vertex(trace2[i+inc].x, trace2[i+inc].y, trace2[i+inc].z);
            vertex(trace2[i-1+inc].x, trace2[i-1+inc].y, trace2[i-1+inc].z);
            endShape(CLOSE);
          }
        }
      }
    }
    
    void keyPressed() {
      // use a key press so that it doesn't make a million files
      if (key == 'r') record = true;
    }
    
  • you'll need the minim and dxf libraries. the two fonts that he mentions (or similar) and a couple of suitable mp3s.

  • dxf libraries, what are they or how can I get them to add to minim? Also, I'm just wondering how the images are produced, I seem to have loads and loads of files in my sketch folder which I'm constantly having to delete. Thanks, I will try that code out shortly and let you know how I get on.

  • loads and loads of files

    again, please be more precise.

    dxf appears to be creating high quality vector output, you don't really need it if all you're interested in is the onscreen display. and it will only happen if you press 'r' and then only to one file called output.dxf.

    i can't see anything else creating files

  • I'm not at home to try the one you posted, but yeah I seem to have lots of files in my sketches folder which don't really need to be there, they were probably created when I first started to test out Minim and different codes.

  • Ok I got this error: java.lang.NullPointerException at java.io.DataInputStream.readInt(DataInputStream.java:387) at processing.core.PFont.(PFont.java:339) at processing.core.PApplet.loadFont(PApplet.java:6594) at sketch_141114a.setup(sketch_141114a.java:47) at processing.core.PApplet.handleDraw(PApplet.java:2361) at processing.opengl.PJOGL$PGLListener.display(PJOGL.java:862) at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:665) at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:649) at javax.media.opengl.awt.GLCanvas$10.run(GLCanvas.java:1289) at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1119) at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:994) at javax.media.opengl.awt.GLCanvas$11.run(GLCanvas.java:1300) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:302) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733) at java.awt.EventQueue.access$200(EventQueue.java:103) at java.awt.EventQueue$3.run(EventQueue.java:694) at java.awt.EventQueue$3.run(EventQueue.java:692) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.awt.EventQueue.dispatchEvent(EventQueue.java:703) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138) at java.awt.EventDispatchThread.run(EventDispatchThread.java:91) java.lang.RuntimeException: java.lang.RuntimeException: Could not load font HelveticaNeueLT-Bold-18.vlw. Make sure that the font has been copied to the data folder of your sketch. at com.jogamp.common.util.awt.AWTEDTExecutor.invoke(AWTEDTExecutor.java:58) at jogamp.opengl.awt.AWTThreadingPlugin.invokeOnOpenGLThread(AWTThreadingPlugin.java:103) at jogamp.opengl.ThreadingImpl.invokeOnOpenGLThread(ThreadingImpl.java:206) at javax.media.opengl.Threading.invokeOnOpenGLThread(Threading.java:172) at javax.media.opengl.Threading.invoke(Threading.java:191) at javax.media.opengl.awt.GLCanvas.display(GLCanvas.java:541) at processing.opengl.PJOGL.requestDraw(PJOGL.java:688) at processing.opengl.PGraphicsOpenGL.requestDraw(PGraphicsOpenGL.java:1651) at processing.core.PApplet.run(PApplet.java:2256) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.RuntimeException: Could not load font HelveticaNeueLT-Bold-18.vlw. Make sure that the font has been copied to the data folder of your sketch. at processing.core.PApplet.die(PApplet.java:4058) at processing.core.PApplet.die(PApplet.java:4067) at processing.core.PApplet.loadFont(PApplet.java:6597) at sketch_141114a.setup(sketch_141114a.java:47) at processing.core.PApplet.handleDraw(PApplet.java:2361) at processing.opengl.PJOGL$PGLListener.display(PJOGL.java:862) at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:665) at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:649) at javax.media.opengl.awt.GLCanvas$10.run(GLCanvas.java:1289) at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1119) at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:994) at javax.media.opengl.awt.GLCanvas$11.run(GLCanvas.java:1300) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:302) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733) at java.awt.EventQueue.access$200(EventQueue.java:103) at java.awt.EventQueue$3.run(EventQueue.java:694) at java.awt.EventQueue$3.run(EventQueue.java:692) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.awt.EventQueue.dispatchEvent(EventQueue.java:703) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138) at java.awt.EventDispatchThread.run(EventDispatchThread.java:91) Could not run the sketch (Target VM failed to initialize).

    If I download the font, how to I make it a .vlw file or can I just insert the font as Sketch>Add File ?

Sign In or Register to comment.