a collection of creative code samples

github

constructed criticism

info

Constructed Criticism is an artificial intelligence programmed to deliver "thoughtful" critique and feedback for your artistic endeavors.criticism’s from the internet’s most vocal critics, Constructed Criticism produces thoughtfully constructed criticism based on what it has heard on the internet.classic echo chamber fashion, this AI creates “new” critiques using patterns and habits present in critiques it has read. -- made with Node.js

gridGen -- grid

info

a series of audio generated grid patterns to relax the mind and release the voice -- made with Processing

code snippet

import ddf.minim.*;  //Includes the minim library for audioinput
import codeanticode.syphon.*;

Minim minim;
AudioInput in;
AudioPlayer player;
SyphonServer server;

float x, y;
float gridSize = 32; //Set at 32 for 1024 BufferSize (multiples of this number work nice)
float xGrid, yGrid;

void settings(){
  size(500, 500, P3D);
  PJOGL.profile=1;
}

void setup(){

  //fullScreen();
  background(255);
  smooth();
  noStroke();

  minim = new Minim(this); //creates new Minim object
  in = minim.getLineIn();  //defines minim objects getLineIn as variable in
  //player = minim.loadFile("Aphex Twin - Xtal.mp3");
  server= new SyphonServer(this, "GridGen");

  //Sets and adjusts the rectangles to gridSize
  xGrid = width/gridSize;
  yGrid = height/gridSize;

  //player.play();

}

void draw(){

  background(255);
  int bufferCapture = 0;
  //itterates through a column, then all rows (based on gridSize)
  //until the specified gridSize is reached
  for(y = 0; y < height; y += yGrid){
    for(x = 0; x < width; x += xGrid){

      bwColor(in.mix.get(bufferCapture), 0.2);
      rect(x, y, xGrid, yGrid);
      bufferCapture++;
      bufferCapture %= in.bufferSize();

    }
  }
  server.sendScreen();

}

//Sets the color of the rectangle to black or white based on
//the wave value (between -1 and 1) and a given sensitivy (usually between 0 and 1)
void bwColor(float wave, float sensitivity){

  if(wave >= sensitivity || wave <= -(sensitivity)){
    fill(255);
    noStroke();
  }else{
    fill(0);
    stroke(0);
  }

paint.IR

info

By hacking a common tool and medium, paint.IR allows the user to explore the art of spray painting with a new-media twist. Featured at Portland's Winter Light Festival, visitors were invited to spray paint light onto OMSI walls, exploring their creativity, collaborating with others, and contributing their work to the wonderful collection presented in the festival.made with OpenFrameworks -- made with OpenFrameworks

code snippet

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){

    kinect.init(true); //sets the kinect to IR mode
    kinect.open(); //opens the first availble kinect

    // print the intrinsic IR sensor values
    if(kinect.isConnected()) {
        ofLogNotice() << "sensor-emitter dist: " << kinect.getSensorEmitterDistance() << "cm";
        ofLogNotice() << "sensor-camera dist:  " << kinect.getSensorCameraDistance() << "cm";
        ofLogNotice() << "zero plane pixel size: " << kinect.getZeroPlanePixelSize() << "mm";
        ofLogNotice() << "zero plane dist: " << kinect.getZeroPlaneDistance() << "mm";
    }

    //setting up openCV
    grayImage.allocate(kinect.width, kinect.height);

    threshold = 80;
    lineWidth = 1;

    hue = 0;
    lineColor.setHsb(hue, 255, 255);

    for (int i = 0; i <= kinect.width; i++){
        int addValue = ofGetWidth()/kinect.width;
        xMap.push_back(addValue * i);
    }
    for (int i = 0; i <= kinect.height; i++){
        int addValue = ofGetHeight()/kinect.height;
        yMap.push_back(addValue * i);
    }

    ofSetFrameRate(60);
    ofBackground(0, 0, 0);

    //Syphon settings
    bSmooth = false;
    ofSetWindowTitle("winter-lights-festival");

    mainOutputSyphonServer.setName("Screen Output");

}

//--------------------------------------------------------------
void ofApp::update(){

    //ofSetLineWidth(lineWidth);

    //ofBackground(100, 100, 100);

    //Updating the kinect
    kinect.update();

    //Checks tos ee if there is a new frame from the kinect, applies that image to the OpenCV
    if(kinect.isFrameNew()){
        grayImage.setFromPixels(kinect.getPixels());
        grayImage.threshold(threshold);

        grayImage.flagImageChanged();

        contourFinder.findContours(grayImage, 5, (kinect.width*kinect.height)/2, 5, false);
    }

    //Updates the ofPoints class and Line class with data from the IR light for drawing
    if(contourFinder.nBlobs > 0){

        //resets the elapsed time everytime a 'blob' is detected//a line is made
        ofResetElapsedTimeCounter();

        int x = ofGetWidth()-xMap[contourFinder.blobs[0].centroid.x];
        int y = yMap[contourFinder.blobs[0].centroid.y];

        for (auto point : drawnPoints){
            ofPoint mouse;
            mouse.set(x, y);
            float dist = (mouse - point).length();
            if (dist < 30){
                Line lineTemp;
                lineTemp.a = mouse;
                lineTemp.b = point;
                lines.push_back(lineTemp);
            }
        }
        drawnPoints.push_back(ofPoint(x, y));
    }

    //Cycles the HUE of the lineColor ofColor
    /*hue += 1;
    if(hue > 255){hue = 0;};
    lineColor.setHsb(hue, 100, 255);
    */

    //Checks the ammount of time since a line was added, if its over X seconds
    //then the vectors are cleared and the elapsed time is reset
    if(ofGetElapsedTimef() > 10){
        drawnPoints.clear();
        lines.clear();
        ofResetElapsedTimeCounter();
    }




}

//--------------------------------------------------------------
void ofApp::draw(){

    //clears the background for compositing later if you so choose
    //glClearColor(0.0, 0.0, 0.0, 0.0);
    //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    /*
    //draw the kinect image
    kinect.draw(0, 0, kinect.width, kinect.height);

    //draw the openCV Grayscale Image, and then draw the Countour on top of it
    grayImage.draw(kinect.width, 0, kinect.width, kinect.height);
    contourFinder.draw(kinect.width, 0, kinect.width, kinect.height);
     */

    //ofEnableAntiAliasing();
    ofEnableAlphaBlending();
    ofSetColor(lineColor);

    //Draw the lines on the screen as stored in the Line class 'lines'
    for (auto line : lines){
        ofDrawLine(line.a, line.b);
    }

    mainOutputSyphonServer.publishScreen();

    /*
     ofNoFill();
    ofSetColor(0, 0, 0, 30);
    ofDrawRectangle(0, 0, kinect.width, kinect.height);
     */

    //Report information about the kinect onto the screen
    stringstream reportBlobPos;
    for (int i = 0; i < contourFinder.nBlobs; i++){

        int blobX = contourFinder.blobs[i].centroid.x;
        int blobY = contourFinder.blobs[i].centroid.y;

        //ofSetColor(255, 0, 0);
        //ofFill();
        //ofDrawCircle(blobX, blobY, 5);

        reportBlobPos << "x of blob_" << i << " " << blobX << " y of blob_" << i << " " << blobY << endl;
    }
    ofSetHexColor(0xffffff);
    stringstream reportStr;
    reportStr << "threshold " << threshold << " (press: +/-)" << endl << "line width " << lineWidth << " (press: l/k)" << endl
    << "num blobs found " << contourFinder.nBlobs << ", fps: " << ofGetFrameRate() << endl << reportBlobPos.str();
    ofDrawBitmapString(reportStr.str(), 20, kinect.height + 50);

}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

    switch (key){
        case '+':
            threshold ++;
            if (threshold > 255) threshold = 255;
            break;
        case '-':
            threshold --;
            if (threshold < 0) threshold = 0;
            break;
        case 'r':
            lines.clear();
            drawnPoints.clear();
            break;
        case 'l':
            lineWidth++;
            break;
        case 'k':
            lineWidth--;
            break;
        case 's':
            bSmooth = !bSmooth;
            break;
    }


}

gridGen -- lines

info

a series of audio generated grid patterns to relax the mind and release the voice -- made with Processing

code snippet

/*
MAJOR CHANGES: REDACTED FRAMERATE FOR BETTER INPUT
ADDED bwColor FUNCTION
*/
import ddf.minim.*;  //Includes the minim library for audioinput
import codeanticode.syphon.*;

Minim minim;
AudioInput in;
AudioPlayer player;

//SyphonServer server;


int x, y;
float gridSize = 10;
float xGrid, yGrid, xAdj;

void settings(){
  size(1080, 1080, P3D);
  PJOGL.profile=1;
}

void setup(){


  //fullScreen();
  background(255);
  smooth();
  frameRate(29.97);

  minim = new Minim(this);

  in = minim.getLineIn(); // defines the getLineIn method of Minim to get audioInput
  player = minim.loadFile("noise_wav.wav");
  //server = new SyphonServer(this, "BarGraph");

  xGrid = width/in.bufferSize();

}

void draw(){

  background(0);
  y = 0;
  xAdj = 0;

  for(x = 0; x <= in.bufferSize() - 1; x++){

    bwColor(in.mix.get(x), 0.15);
    rect(x, y, xGrid, height);
  }
  //server.sendScreen();

}

//Sets the color of the rectangle to black or white based on
//the wave value (between -1 and 1) and a given sensitivy (usually between 0 and 1)
void bwColor(float wave, float sensitivity){

  if(wave >= sensitivity){
    fill(255);
    noStroke();
  }else if(wave < -sensitivity){
    fill(255);
    noStroke();
  }else{
    fill(0);
    stroke(0);
  }

}

void keyPressed() {
  if(key == 'p' || key == 'P') {
    player.play();
  }
}
Contact GitHub API Training Shop Blog About

turntable sequencer

info

The Interactive Turntable Sequencer is a concept piece that engages audiences of all ages, forcing them to question recorded audio, engage with taboo objects, and explore music composition through play. The piece is designed to be welcoming to non-musicians and musicians alike, and evens the playing field trough experimental applications. -- made with Processing

gridGen -- ellipse

info

a series of audio generated grid patterns to relax the mind and release the voice -- made with Processing

code snippet

import ddf.minim.*;
import codeanticode.syphon.*;

Minim minim;
AudioInput in;
SyphonServer server;

PShape ring;

void settings(){
  size(1080, 1080, P3D);
  PJOGL.profile=1;
}

void setup()
{
  minim = new Minim(this);

  // use the getLineIn method of the Minim object to get an AudioInput
  in = minim.getLineIn();
  server = new SyphonServer(this, "AudioRing");
}

void draw()
{
  background(0);
  stroke(255);
  strokeWeight(3);
  ring = createShape();

  float radius = 300;
  int centX = width/2;
  int centY = height/2;
  float x, y;
  float radVariance, thisRadius, rad;

  ring.beginShape();
  fill(20, 50, 70, 50);

  // draw the waveforms so we can see what we are monitoring
  for(int ang = 0; ang < 360; ang++)
  {
    radVariance = 600 * in.mix.get(int(ang));
    thisRadius = radius + radVariance;
    rad = radians(ang);

    x = centX + (thisRadius * cos(rad));
    y = centY + (thisRadius * sin(rad));

    ring.curveVertex(x, y);
  }
  ring.endShape();

  shape(ring);
  String monitoringState = in.isMonitoring() ? "enabled" : "disabled";
  text( "Input monitoring is currently " + monitoringState + ".", 5, 15 );

  server.sendScreen();
}

void keyPressed()
{
  if ( key == 'm' || key == 'M' )
  {
    if ( in.isMonitoring() )
    {
      in.disableMonitoring();
    }
    else
    {
      in.enableMonitoring();
    }
  }
}