Today I am working with a visual idea that I want to turn into music. I have a blurry scene where the action moves up and a sine wave moves down. It is a start.
I am using a stack blur from quasimondo. It is super fast and it looks ok. Not quite as pleasurable as a gaussian but way faster. I also got bit on a pointer reference thing when converting a PGraphics to a PImage. Be careful! PGraphics is a subclass of PImage and you can assign one to the other thanks to inheritance but to copy the actual image from one to the other you have to use the get() method and then things will behave like you expect. Thanks to the javadocs for Processing.
I have linked code at the bottom.


import javax.media.opengl.*;
import processing.opengl.*;
import ddf.minim.*;
import ddf.minim.signals.*;
Minim minim;
AudioOutput out;
SineWave sine;
PGraphics graph;
PImage img;
int r;
boolean mybool;
float[] points;
int x;
void setup()
{
size(720,480,P2D);
graph = createGraphics(720,480,P2D);
img = createImage(720,480, RGB);
points = new float[400];
for ( int i = 0 ; i < 100; i++)
{
points[i] = width/2 + random(-width/2, width/2) ;
points[i+100] = height/2 + random(-height/2, height/2) ;
points[i+200] = width/2 + random(-width/2, width/2) ;
points[i+300] = height/2 + random(-height/2, height/2) ;
}
smooth();
minim = new Minim(this);
out = minim.getLineOut(Minim.STEREO);
sine = new SineWave(440, 0.5, out.sampleRate());
sine.portamento(200);
out.addSignal(sine);
}
void draw()
{
graph.beginDraw();
graph.background(0);
graph.noStroke();
graph.fill(255);
graph.rect(0,0,width,height/2 + x--);
for (int i = 0; i < points.length ; i++)
points[i] += random(-2,2);
graph.stroke(255);
graph.strokeWeight(1.4);
for ( int i = 0 ; i < 100; i++)
graph.line( points[i] , points[i+100], points[i+200], points[i+300] );
graph.endDraw();
img = graph.get();
fastBlur(img, 10);
img.filter(POSTERIZE,3);
fastBlur(img,4);
image(img,0,0);
sine.setFreq(440 + x);
}
void keyPressed()
{
if (key == ' ')
saveFrame();
}
View this code on GitHub
void fastBlur(PImage img, int radius){
if (radius<1){
return;
}
int w=img.width;
int h=img.height;
int wm=w-1;
int hm=h-1;
int wh=w*h;
int div=radius+radius+1;
int a[]=new int[wh];
int r[]=new int[wh];
int g[]=new int[wh];
int b[]=new int[wh];
int asum,rsum,gsum,bsum,x,y,i,p,p1,p2,yp,yi,yw;
int vmin[] = new int[max(w,h)];
int vmax[] = new int[max(w,h)];
int[] pix=img.pixels;
int dv[]=new int[256*div];
for (i=0;i<256*div;i++){
dv[i]=(i/div);
}
yw=yi=0;
for (y=0;y<h;y++){
asum=rsum=gsum=bsum=0;
for(i=-radius;i<=radius;i++){
p=pix[yi+min(wm,max(i,0))];
asum+=(p>>24) & 0xff;
rsum+=(p & 0xff0000)>>16;
gsum+=(p & 0x00ff00)>>8;
bsum+= p & 0x0000ff;
}
for (x=0;x<w;x++){
a[yi]=dv[asum];
r[yi]=dv[rsum];
g[yi]=dv[gsum];
b[yi]=dv[bsum];
if(y==0){
vmin[x]=min(x+radius+1,wm);
vmax[x]=max(x-radius,0);
}
p1=pix[yw+vmin[x]];
p2=pix[yw+vmax[x]];
asum+=((p1>>24) & 0xff)-((p2>>24) & 0xff);
rsum+=((p1 & 0xff0000)-(p2 & 0xff0000))>>16;
gsum+=((p1 & 0x00ff00)-(p2 & 0x00ff00))>>8;
bsum+= (p1 & 0x0000ff)-(p2 & 0x0000ff);
yi++;
}
yw+=w;
}
for (x=0;x<w;x++){
asum=rsum=gsum=bsum=0;
yp=-radius*w;
for(i=-radius;i<=radius;i++){
yi=max(0,yp)+x;
asum+=a[yi];
rsum+=r[yi];
gsum+=g[yi];
bsum+=b[yi];
yp+=w;
}
yi=x;
for (y=0;y<h;y++){
pix[yi] = (dv[asum]<<24) | (dv[rsum]<<16) | (dv[gsum]<<8) | dv[bsum];
if(x==0){
vmin[y]=min(y+radius+1,hm)*w;
vmax[y]=max(y-radius,0)*w;
}
p1=x+vmin[y];
p2=x+vmax[y];
asum+=a[p1]-a[p2];
rsum+=r[p1]-r[p2];
gsum+=g[p1]-g[p2];
bsum+=b[p1]-b[p2];
yi+=w;
}
}
}
View this code on GitHub
I was again playing with GLGraphics and had a happy accident. I added some more shaders to a sketch and got these swirling worlds. I think this is something I am going to keep. I did something I thought I understood and came up with these great visuals for some reason. This illustrates to me that I need a little more theory before I dig deeper with shaders. Some other time.
My big problem is that I haven’t added audio so I am diverting a bit from my original idea at the beginning of the month. Tomorrow I will refocus.


import javax.media.opengl.*;
import processing.opengl.*;
import codeanticode.glgraphics.*;
GLSLShader shader;
GLModel model;
int numPoints = 1024;
int r;
float[] coords;
float[] colors;
boolean mybool = true;
float denominator = 4000;
void setup()
{
size(720, 480, GLConstants.GLGRAPHICS);
hint( DISABLE_OPENGL_2X_SMOOTH );
hint( ENABLE_OPENGL_4X_SMOOTH );
model = new GLModel(this, numPoints, GLModel.QUAD_STRIP, GLModel.DYNAMIC);
model.initColors();
coords = new float[4 * numPoints];
colors = new float[4 * numPoints];
for (int i = 0; i < numPoints; i++)
{
for (int j = 0; j < 3; j++)
coords[4 * i + j] = height * random(-1, 1);
coords[4 * i + 3] = 1.0;
for (int j = 0; j < 3; j++)
colors[4 * i + j] = random(0, 1);
colors[4 * i + 3] = 0.9;
}
model.updateVertices(coords);
model.updateColors(colors);
shader = new GLSLShader(this, "fishvert.glsl", "fishfrag.glsl");
}
void draw()
{
GLGraphics renderer = (GLGraphics)g;
renderer.beginGL();
translate(width/2, height/2);
background(160);
if (mybool)
{
rotateY((float)r++/denominator);
rotateX((float)r/denominator);
}
else
{
rotateY( (float)r/denominator - PI) ;
rotateX( (float)r/denominator - PI) ;
}
shader.start();
model.render();
shader.stop();
renderer.endGL();
}
void keyPressed()
{
if (key == ' ')
saveFrame();
}
void mousePressed()
{
mybool = !mybool;
}
View this code on GitHub
Today was a bit of a bust. I tried writing some GLSL shaders using GLGraphics and didn’t have much luck. I have been wanting to dig into the library for awhile but haven’t had time, so today was the day. I was able to get some simple frag shaders going but blurs weren’t working. I upgraded to the new version only to find new functionality came with a new API. The patch I made works but crashes after 10 seconds or so. When I have more time I will look further into the issue or post it on the forums but for now I just have a day to make something.

import javax.media.opengl.*;
import processing.opengl.*;
import codeanticode.glgraphics.*;
GLSLShader shader;
GLModel myshape;
int r;
void setup()
{
size(640, 480, GLConstants.GLGRAPHICS);
shader = new GLSLShader(this, "toonvert.glsl", "Pixelate.glsl");
}
void draw()
{
myshape = newmodel();
GLGraphics renderer = (GLGraphics)g;
renderer.beginGL();
translate(width/2, height/2);
background(180);
rotateY((float)r/100);
renderer.model(myshape);
renderer.endGL();
}
void keyPressed()
{
if (key == ' ')
saveFrame();
}
void mousePressed()
{
r++;
}
GLModel newmodel ( )
{
ArrayList vertices = new ArrayList();
for (int i = 0; i < 400; i++)
{
vertices.add(new PVector(random(width)-width/2,random(height)-height/2, random(width)-width/2));
}
GLModel model = new GLModel(this, vertices.size() , LINES, GLModel.DYNAMIC );
model.updateVertices(vertices);
return model;
}
View this code on GitHub
GLModel createTorus(float outerRad, float innerRad, int numc, int numt, int r, int g, int b, int a, String texName) {
GLModel model;
GLTexture tex;
ArrayList vertices = new ArrayList();
ArrayList normals = new ArrayList();
ArrayList texcoords = new ArrayList();
float x, y, z, s, t, u, v;
float nx, ny, nz;
float a1, a2;
int idx = 0;
for (int i = 0; i < numc; i++) {
for (int j = 0; j <= numt; j++) {
for (int k = 1; k >= 0; k--) {
s = (i + k) % numc + 0.5;
t = j % numt;
u = s / numc;
v = t / numt;
a1 = s * TWO_PI / numc;
a2 = t * TWO_PI / numt;
x = (outerRad + innerRad * cos(a1)) * cos(a2);
y = (outerRad + innerRad * cos(a1)) * sin(a2);
z = innerRad * sin(a1);
nx = cos(a1) * cos(a2);
ny = cos(a1) * sin(a2);
nz = sin(a1);
vertices.add(new PVector(x, y, z));
normals.add(new PVector(nx, ny, nz));
texcoords.add(new PVector(u, v));
}
}
}
model = new GLModel(this, vertices.size(), QUAD_STRIP, GLModel.STATIC);
model.updateVertices(vertices);
if (texName != null && !texName.equals("")) {
tex = new GLTexture(this, texName);
model.initTextures(1);
model.setTexture(0, tex);
model.updateTexCoords(0, texcoords);
}
model.initNormals();
model.updateNormals(normals);
model.initColors();
model.setColors(r, g, b, a);
return model;
}
View this code on GitHub
I went out tonight to three art openings around town and I was totally jazzed from seeing art. So I have come home and tried to do something before I go to sleep. This is my first sketch that is a continuation of the day before.
I was looking at things and thinking about in-between. I have made a simple patch that takes yesterday’s patch but adds a cloud of random points and I can do linear interpolation between the two. It is crude right now but there are some very interesting intermediate states between objects that arrive. I have also properly implemented the Dan Shiffman sugar from his space junk sketch so I get some more variation from frame to frame.
Again, OPENGL so code will follow the image, now animated.

import ddf.minim.*;
import ddf.minim.analysis.*;
import processing.opengl.*;
import javax.media.opengl.*;
Minim minim;
AudioInput input;
int Segments = 21;
float[][] mylines = new float[Segments*Segments][3];
float[][] myrandomlines = new float[Segments*Segments][3];
float theta;
float phi;
float scalething = 200;
int r = 1;
int p;
color c1 = color(240,0,0);
color c2 = color (20,150,150);
void setup()
{
size(640,480, OPENGL);
minim = new Minim(this);
input = minim.getLineIn(Minim.STEREO, 512);
for(int i=0;i<Segments;++i)
{
theta = (float)i/Segments * 2 * PI;
for(int j=0;j<Segments;++j)
{
phi = (float)j/Segments * PI;
mylines[i*Segments+j][0] = sin(theta)*cos(phi)*scalething;
mylines[i*Segments+j][1] = sin(theta)*sin(phi)*scalething;
mylines[i*Segments+j][2] = cos(theta)*scalething;
myrandomlines[i*Segments+j][0] = random(0,scalething) - scalething/2;
myrandomlines[i*Segments+j][1] = random(0,scalething) - scalething/2;
myrandomlines[i*Segments+j][2] = random(0,scalething) - scalething/2;
}
}
}
void draw()
{
background(200);
translate(width/2, height/2);
float audiolevel = input.mix.level();
strokeWeight(audiolevel*100);
c1 = color(audiolevel*2100,80,audiolevel*1400);
rotateY((float)p/200);
rotateZ((float)p/123);
for(int i = 1 ; i < Segments * Segments; i++)
{
rotate(random(200));
beginShape(LINES);
stroke(c1);
vertex(mylines[i][0] * (1.0 - 1.0/r) + myrandomlines[i][0] * (1.0/r),
mylines[i][1] * (1.0 - 1.0/r) + myrandomlines[i][1] * (1.0/r),
mylines[i][2] * (1.0 - 1.0/r) + myrandomlines[i][2] * (1.0/r));
stroke(c2);
vertex(mylines[i-1][0] * (1.0 - 1.0/r) + myrandomlines[i-1][0] * (1.0/r),
mylines[i-1][1] * (1.0 - 1.0/r) + myrandomlines[i-1][1] * (1.0/r),
mylines[i-1][2]* (1.0 - 1.0/r) + myrandomlines[i-1][2] * (1.0/r) );
endShape();
}
}
void keyPressed()
{
if (key == ' ')
{
saveFrame();
}
}
void mouseClicked(){
r++;
}
void stop()
{
input.close();
minim.stop();
super.stop();
}
View this code on GitHub
I made a bad VJ patch today. I have a rotating sphere made from a series of line strips with colour gradients. The patch pulses with size and colour to volume. Maybe soon I will put that feature extraction from the other day to use and make something a little more sophisticated.
It is made with OPENGL again so I have included the code below.


import ddf.minim.*;
import ddf.minim.analysis.*;
import processing.opengl.*;
import javax.media.opengl.*;
Minim minim;
AudioInput input;
int Segments = 21;
float[][] mylines = new float[Segments*Segments][3];
float theta;
float phi;
float scalething = 200;
int r;
color c1 = color(240,0,0);
color c2 = color (200,150,150);
void setup()
{
size(640,480, OPENGL);
minim = new Minim(this);
input = minim.getLineIn(Minim.STEREO, 512);
for(int i=0;i<Segments;++i)
{
theta = (float)i/Segments * 2 * PI;
for(int j=0;j<Segments;++j)
{
phi = (float)j/Segments * PI;
mylines[i*Segments+j][0] = sin(theta)*cos(phi)*scalething;
mylines[i*Segments+j][1] = sin(theta)*sin(phi)*scalething;
mylines[i*Segments+j][2] = cos(theta)*scalething;
}
}
}
void draw()
{
translate(width/2, height/2);
float audiolevel = input.mix.level();
strokeWeight(audiolevel*100);
c1 = color(audiolevel*2100,0,0);
rotateX((float)r++/800);
rotateY((float)r/200);
rotateZ((float)r/80);
background(90);
for(int i = 1 ; i < Segments * Segments; i++)
{
beginShape(LINES);
stroke(c1); vertex(mylines[i][0], mylines[i][1], mylines[i][2] );
stroke(200, 150, 150); vertex(mylines[i-1][0], mylines[i-1][1],mylines[i-1][2]);
endShape();
}
}
void keyPressed()
{
if (key == ' ')
{
saveFrame();
}
}
void stop()
{
input.close();
minim.stop();
super.stop();
}
View this code on GitHub
Another audio analysis simple patch for today. I looked into the BeatDetect object in MINIM and found that yesterday’s code could be done even simpler by using the built in detector. It isn’t very good but it works. I didn’t do much tweaking on it but I bet with some massaging I could get it to detect my signals a little bit better.
So today’s patch is a bit of a homage to Dan Shiffman’s space junk patch. The patch has three magic lines that make it look great. The last three valid lines are rotatings in x,y,z. What makes it special is that those lines are repeated multiple times in each frame and a translate is performed afterwards with no pushMatrix() or popMatrix(). So the reference is moved about the sketch multiple times so that there is some interesting placement of objects about the space.
This patch uses the detected volume and onset information to draw a set of shapes around the screen with varying rotation based upon the detected parameters. On my machine the frames show up for a very short amount of time and often aren’t drawn fully so it looks quite glitchy and nice. When I render it out to screenshots the image is preserved. Try squinting and covering half the image in a weird way and you will see what I see when it is running, or run the code yourself.


import ddf.minim.*;
import ddf.minim.analysis.*;
import processing.opengl.*;
import javax.media.opengl.*;
Minim minim;
AudioInput input;
BeatDetect detectorGadget;
void setup(){
size(640,480,OPENGL);
minim = new Minim(this);
input = minim.getLineIn(Minim.STEREO, 512);
detectorGadget = new BeatDetect();
stroke(255, 255, 150);
fill(3,190,129);
}
void draw(){
background(30);
float audiolevel = input.mix.level();
detectorGadget.detect(input.mix);
translate (width/2, height/2,200);
if(detectorGadget.isOnset())
{
for (int i = 0 ; i < 100; i++)
{
ellipse(0,0, 1000*audiolevel,1000*audiolevel);
box(10,10,100);
rotate(audiolevel);
translate(log(audiolevel),0);
}
}
}
void keyPressed()
{
if (key == ' ')
{
saveFrame();
}
}
void stop()
{
input.close();
minim.stop();
super.stop();
}
View this code on GitHub
Today’s sketch is a take on the mouse controlled ball that you can rotate and throw. I have a sphere here that is rotated by making a loud sound. I have done a rather crude thresholding but I discovered that MINIM has a nice level() call on audiobuffers that return the RMS. Hooray!
I also discovered that on a mac when you export your patch to the web it doesn’t work well if you are using OPENGL. I have included the code inline with the blog, which I don’t like so much but it will get the idea to you.
Like I predicted this is a much shorter sketch than on the weekends. This is going to be the way of it until I get more efficient at my changing weeks.

import ddf.minim.*;
import processing.opengl.*;
import javax.media.opengl.*;
Minim minim;
AudioInput input;
float r;
float inc;
void setup(){
size(screen.width, screen.height, OPENGL);
hint(ENABLE_OPENGL_4X_SMOOTH);
minim = new Minim(this);
input = minim.getLineIn(Minim.STEREO, 512);
stroke(255, 255, 150);
noFill();
}
void draw(){
background(30);
float audiolevel = input.mix.level();
if (audiolevel > 0.01)
inc++;
r = r + inc;
inc = inc * 0.85;
translate (width/2, height/2,mouseX);
rotateY(r);
sphere(200 + audiolevel*1000);
}
void keyPressed()
{
if (key == ' ')
{
saveFrame();
}
}
void stop()
{
input.close();
minim.stop();
super.stop();
}
View this code on GitHub
Last night I finished watching the first season of The Wire. I have been watching it on DVD and the splash screen and the opening scene of the show has all of these signal displays. So, I dusted off my trigonometry skills and started making some sine waves dance on my screen.
I have some ideas about how to tweak this a bit more by casting the shapes to PImages and then applying filters but I have a busy day, so that will happen another time. I expect that the sketches during the week will be shorter than the weekend ones. I think that is just how it goes.


Today’s Code:
float amp1;
float inc;
float tri;
boolean up;
float downer;
void setup(){
size(400,300);
amp1 = height/2;
fill(255);
smooth();
}
void draw(){
noStroke();
fill(0,15);
rect(0,0,width,height);
stroke(40,197,90);
fill(255);
amp1 = pow (10, -tri/10);
if (up)
downer = -1;
else
downer = 1;
for (int i = 0 ; i < width; i++)
{
point (i, sin(float(i)/width * TWO_PI + frameCount/PI)*downer * -1 *amp1*height/2 + height/2 - amp1*50) ;
point (i, sin(float(i)/width * TWO_PI *2 - frameCount/(3*PI))* downer * amp1*height/4 + height/4) ;
point (i, sin(float(i)/width * TWO_PI *20 - frameCount/(9*PI))* downer * amp1*height*.23 + height*.8 + amp1*30) ;
}
if ( tri >= 20)
{
inc = -.2;
up = !up;
}
if ( tri <= 0)
inc = .16;
tri = tri + inc;
}
void keyPressed(){
if (key == ' ')
saveFrame();
}
View this code on GitHub
Today I was working with analysis. This patch doesn’t have a lot of good looks but I have implemented a zero crossing rate function, an rms function for time domain analysis, spectral centroid, spectral rolloff, and spectral compactness. I coded up a spectral flatness measure but I keep getting zero as the output. I haven’t done thorough debugging job because I was trying to make sure I have something done for today!
I started out hoping that I could implement both the spectral features and time domain features as an AudioListener object but the FFT object doesn’t work that way. So, I made a method that is called every draw loop. This isn’t the nicest solution but it works. I am dreaming up a link between jAudio and MINIM. If I’m not careful I might be putting another thing on my plate :)
Today’s patch is really just an extension of MINIM’s spectral display patch but an overlay of the feature extraction output. My hope is to eventually do a MINIM version of sndpeek. Maybe tomorrow there will be text and waterfall plots... maybe.


import ddf.minim.analysis.*;
import ddf.minim.*;
Minim minim;
AudioPlayer jingle;
FFT fft;
DrawTime dt;
int w;
float[] myspectrum;
void setup()
{
size(512, 200, P3D);
minim = new Minim(this);
jingle = minim.loadFile("jingle.mp3", 2048);
jingle.loop();
fft = new FFT(jingle.bufferSize(), jingle.sampleRate());
fft.logAverages(22, 3);
dt = new DrawTime();
jingle.addListener(dt);
myspectrum = new float[ jingle.bufferSize() ];
rectMode(CORNERS);
}
void draw()
{
background(0);
fill(255);
stroke(0);
fft.forward(jingle.mix);
w = int(width/fft.avgSize());
for(int i = 0; i < fft.avgSize(); i++)
{
rect(i*w, height, i*w + w, height - fft.getAvg(i)*5);
}
for(int i= 0; i < jingle.bufferSize(); i++)
myspectrum[i] = fft.getBand(i);
dt.draw();
drawSpectral(myspectrum);
}
void keyPressed(){
if (key == ' ')
saveFrame();
}
void stop()
{
jingle.close();
minim.stop();
super.stop();
}
View this code on GitHub
void drawSpectral(float[] spec)
{
float m1 = 0;
float m0 = 0;
for (int i = 0; i < spec.length; i++){
m1 += i * spec[i];
m0 += spec[i];
}
float centroid = 0.5;
if (m0 != 0.0)
{
centroid = (m1 / m0) / (float) spec.length ;
}
pushStyle();
stroke(90,255,90);
strokeWeight(3);
line(centroid * width, 0 , centroid * width, height);
popStyle();
float perc = 0.8;
float[] sumWindow = new float [ spec.length ];
float total = 0;
float sum = 0;
float specRolloff = 0;
boolean specdone = false;
for( int i = 0; i< spec.length; i++)
{
sum += spec[i];
sumWindow[i] = sum;
}
total = sumWindow[spec.length-1];
for ( int i = spec.length-1; i > 1 ; i--){
if (sumWindow[i] < 0.8 * total)
{
specRolloff = (float) i;
specdone = true;
break;
}
}
if ( !specdone )
specRolloff = float(spec.length - 1);
specRolloff /= spec.length;
pushStyle();
stroke(89, 169, 210);
line( specRolloff * width, 0, specRolloff * width, height);
popStyle();
float[] mag_spec = new float[ spec.length ];
for (int i = 0; i < spec.length; i++)
{
mag_spec[i] = abs( spec[i] );
}
double compactness = 0.0;
for (int i = 1; i < mag_spec.length - 1; i++) {
if ((mag_spec[i - 1] > 0.0) && (mag_spec[i] > 0.0) && (mag_spec[i + 1] > 0.0))
{
compactness += Math .abs(
20.0 * Math.log(mag_spec[i])
- 20.0 * (Math.log(mag_spec[i - 1])
+ Math.log(mag_spec[i])
+ Math .log(mag_spec[i + 1]))
/ 3.0);
}
}
pushStyle();
stroke(12,48, 96);
line ( (float)compactness / 10000 * width, 0, (float)compactness / 10000 * width , height);
popStyle();
float flatness = 0;
double geometricMean = spec[0];
float arithmeticMean = sum;
for ( int i = 1; i < spec.length; i++)
{
geometricMean *= (double) spec[i];
if (spec[i] == 0.0)
{
println("WARNING: ZERO DETECTED " +frameCount);
}
}
geometricMean = Math.pow(geometricMean , (1.0f / spec.length) );
arithmeticMean /= spec.length;
flatness = (float)geometricMean / arithmeticMean ;
println(flatness);
}
View this code on GitHub
class DrawTime implements AudioListener
{
private float[] left;
private float[] right;
synchronized void samples(float[] samp)
{
left = samp;
}
synchronized void samples(float[] sampL, float[] sampR)
{
left = sampL;
right = sampR;
}
synchronized void draw()
{
if (left != null && left.length > 0)
{
float rms = 0.0;
for (int i = 0; i < left.length; i++)
rms += (left[i] * left[i] );
if (rms!= 0.0)
{
rms /= left.length;
rms = sqrt(rms);
}
pushStyle();
noFill();
stroke (255, 90,90);
line(0, height - rms*height, width, height - rms*height);
popStyle();
float zcr = 0;
for (int i = 0; i < left.length - 1; i++)
{
if (left[i] > 0.0 && left[i + 1] < 0.0)
zcr++;
else if (left[i] < 0.0 && left[i + 1] > 0.0)
zcr++;
else if (left[i] == 0.0 && left[i + 1] != 0.0)
zcr++;
}
zcr = zcr / (float) left.length;
pushStyle();
noFill();
stroke (90, 90,255);
line(0, height - zcr*height, width, height - zcr*height);
popStyle();
}
}
}
View this code on GitHub
This one has been in the works for awhile. I have been looking at the minim BETA for a few days and now I feel like I am getting my head around it. Today I made my first UGen. I think I am going to submit it to the distribution. It is a byte swapping algorithm inspired by swap~ in zexy for PD. This is one of my favourite distortions. Very loud and very nasty. You’ve been warned.
Today I also finally delved into Processing’s method for exporting applets. So, I am not going to dump a whole lot of code in this post. If you want to see the code follow the links below.
The audio display is rendered as points. This is inspired by something I saw at MUTEK this year and is also the flavour of the visual material for Frank Bretschneider’s EXP. http://www.frankbretschneider.de/Web-Site/exp.html


import ddf.minim.*;
import ddf.minim.ugens.*;
Minim minim;
LiveInput in;
AudioOutput out;
Swap fx1;
DrawWave renderer;
void setup(){
size(400, 200);
smooth();
minim = new Minim(this);
out = minim.getLineOut();
in = new LiveInput( minim.getInputStream(out.getFormat().getChannels(), out.bufferSize(), out.sampleRate(), out.getFormat().getSampleSizeInBits()) );
fx1 = new Swap();
in.patch(fx1).patch(out);
renderer = new DrawWave(0,0, width, height);
out.addListener(renderer);
}
void draw(){
noStroke();
fill(0, 40);
rect(0,0,width,height);
renderer.draw();
}
void keyPressed(){
if (key == ' ')
saveFrame();
}
void stop()
{
in.close();
out.close();
minim.stop();
super.stop();
}
View this code on GitHub
public class Swap extends UGen{
public UGenInput audio;
Swap()
{
audio = new UGenInput(InputType.AUDIO);
}
@Override
protected void uGenerate (float[] channels)
{
if ( audio.isPatched() )
{
for (int i = 0; i < channels.length; i++){
short temp = (short)( audio.getLastValues()[i] * 32768.);
int b1 = temp & 0xff;
int b2 = (temp >> 8) & 0xff;
temp = (short)(b1 << 8 | b2 << 0);
channels[i] = temp * (1. / 32768.);
}
}
}
}
View this code on GitHub
class DrawWave implements AudioListener
{
private float[] left;
private float[] right;
private int x;
private int y;
private int width;
private int height;
private color c;
private color bg;
private boolean drawbackground;
DrawWave(int xx, int yy, int ww, int hh)
{
left = null;
right = null;
this.x = xx;
this.y = yy;
this.width = ww;
this.height = hh;
c = color (255);
bg = color (30, 189, 210);
drawbackground = false;
}
synchronized void samples(float[] samp)
{
left = samp;
}
synchronized void samples(float[] sampL, float[] sampR)
{
left = sampL;
right = sampR;
}
synchronized void draw()
{
if ( left != null && right != null )
{
pushStyle();
stroke(c);
if (drawbackground)
{
fill (bg);
rect(this.x, this.y, this.width-1, this.height);
}
noFill();
float inc = (float)this.width / left.length;
float quarterheight = this.height / 4;
float threequarterheight = quarterheight * 3;
beginShape(POINTS);
for (int step=0;step<left.length;step++) {
vertex ( (inc*step) + this.x, left[step]* quarterheight + this.y + quarterheight);
}
endShape();
beginShape(POINTS);
for (int step=0;step<right.length;step++) {
vertex ( (inc*step) + this.x, right[step]* quarterheight + this.y + threequarterheight);
}
endShape();
popStyle();
}
}
public void setColour(color cc)
{
c = cc;
}
public void background(boolean b)
{
drawbackground = b;
}
public void setBackgroundColour(color cc)
{
bg = cc;
}
}
View this code on GitHub
← newer
::
older →