Code
This a drawing tool that takes your basic line
drawings and changes them into
sine/cosine/tangent waves.
The panels on the left change the thickness of your line
(and how loud the sound is) and the panel on the right
changes the type of wave generated.
To see this applet you will have to download the JSyn plugin that you can find here:
http://www.softsynth.com/jsyn/plugins/
Sample soundChannel = null;
ArrayList pointList = null;
WaveDisplay viewWave = null;
ColorSquare[] squares = new ColorSquare[6];
WaveformButton[] formButtons = null;
float[] toReturn = new float[15000];
boolean mouseDragging = false;
boolean arrayPopulated = false;
int currentWaveForm = 0;
int pointCounter = 0;
int currentStroke = 255;
int panelWidth;
int panelHeight;
int panelX;
int panelY;
void setup(){
Sonia.start(this);
size(700,600);
panelWidth = 500;
panelHeight = 500;
panelX = 100;
panelY = 0;
soundChannel = new Sample(15000,15000);
pointList = new ArrayList(500);
viewWave = new WaveDisplay(toReturn, 100,500);
formButtons = new WaveformButton[3];
background(100,100,100);
for(int i = 0; i < 6; i++){
squares[i] = new ColorSquare(255 - (i*42), 0, 100 * i, 100);
squares[i].draw();
}
for(int i = 0; i < 3; i++){
formButtons[i] = new WaveformButton(i,600,i*100 + (i*3),100,100);
formButtons[i].draw();
}
currentStroke = 0;
}
void loop(){
strokeWeight(3);
stroke(0);
fill(255,255,255);
strokeWeight(1);
rect(panelX, panelY, panelWidth, panelHeight);
drawPointList();
viewWave.drawWave();
if(arrayPopulated ){
if(!mousePressed){
warpPoints();
}
parseArray();
soundChannel.play();
}
if(currentStroke == 255){
for(int i = 0; i < pointList.size(); i++){
((PointHolder) pointList.get(i)).x = 0;
((PointHolder) pointList.get(i)).y = 0;
arrayPopulated = false;
}
}
}
void keyPressed(){
switch(key){
case '1':
currentStroke = squares[0].fillcolor;
break;
case '2':
currentStroke = squares[1].fillcolor;
break;
case '3':
currentStroke = squares[2].fillcolor;
break;
case '4':
currentStroke = squares[3].fillcolor;
break;
case '5':
currentStroke = squares[4].fillcolor;
break;
case '6':
currentStroke = squares[5].fillcolor;
break;
}
}
void mouseReleased(){
mouseDragging = false;
if(pointCounter > 0){
arrayPopulated = true;
}
}
void mouseDragged(){
if(mouseX > 100 && mouseX < 600){
if(pointCounter == 0){
for(int i = 0; i < pointList.size(); i++){
((PointHolder) pointList.get(i)).x = 0;
((PointHolder) pointList.get(i)).y = 0;
}
}
mouseDragging = true;
if(pointList.size() <= pointCounter){
pointList.add(new PointHolder(mouseX, mouseY));
}
else{
PointHolder temp = (PointHolder) pointList.get(pointCounter);
temp.x = mouseX;
temp.y = mouseY;
}
pointCounter++;
}
}
void mousePressed(){
if(mouseX < 100){
for(int i = 0; i < squares.length; i++){
if(mouseX > 0){
if(mouseY > squares[i].y && mouseY < squares[i].y + 100){
currentStroke = squares[i].fillcolor;
}
}
}
}
else if(mouseX > 600){
for(int i = 0; i < formButtons.length; i++){
if(mouseX> 0){
if(mouseY > formButtons[i].y && mouseY < formButtons[i].y + 100){
currentWaveForm = formButtons[i].type;
}
}
}
}
else{
pointCounter = 0;
}
}
public void warpPoints(){
currentStroke += 1;
for(int i = 0; i < pointCounter; i++){
PointHolder current = (PointHolder) pointList.get(i);
if(current.x < width /2){
current.x--;
}
else{
current.x++;
}
}
}
public void parseArray(){
int[] maxes = findMaxes(pointList);
int[] mins = findMins(pointList);
float waveAmplitude = maxAmp(maxes,mins,pointList);
float waveFrequency = findFreq(maxes, mins, pointList);
viewWave.myFreq = waveFrequency;
populateSample(waveAmplitude, waveFrequency);
}
public void populateSample(float waveAmplitude, float waveFrequency){
for(int i = 0; i < toReturn.length; i++){
//**********************************************
//THIS IS THE MOST IMPORTANT LINE IN THE PROGRAM
//**********************************************
if(currentWaveForm == 0){
toReturn[i] = sin(i * waveFrequency);
}else if(currentWaveForm == 1){
toReturn[i] = cos(i * waveFrequency);
}else{
toReturn[i] = tan(i * waveFrequency);
}
}
while(waveAmplitude > 1){
waveAmplitude = waveAmplitude / 10;
}
soundChannel.write(toReturn);
soundChannel.setVolume(waveAmplitude);
}
public int[] findMaxes(ArrayList pointList){
ArrayList toReturn = new ArrayList();
for(int i = 0; i < pointList.size(); i++){
if(i > 0 && i < pointList.size() - 1){
PointHolder previous = (PointHolder) pointList.get(i - 1);
PointHolder current = (PointHolder) pointList.get(i);
PointHolder next = (PointHolder) pointList.get(i+1);
if (previous.y < current.y && next.y < current.y){
toReturn.add(new Integer(i));
}
}
else if(i == 0){
PointHolder current = (PointHolder) pointList.get(i);
PointHolder next = (PointHolder) pointList.get(i+1);
if(current.y > next.y){
toReturn.add(new Integer(i));
}
}
else if(i == pointList.size() - 1){
PointHolder previous = (PointHolder) pointList.get(i - 1);
PointHolder current = (PointHolder) pointList.get(i);
if(current.y > previous.y){
toReturn.add(new Integer(i));
}
}
}
int[] returnArray = new int[toReturn.size()];
for(int i = 0; i < toReturn.size(); i++){
returnArray[i] = ((Integer) toReturn.get(i)).intValue();
}
return returnArray;
}
public int[] findMins(ArrayList pointList){
ArrayList toReturn = new ArrayList();
for(int i = 0; i < pointList.size(); i++){
if(i > 0 && i < pointList.size() - 1){
PointHolder previous = (PointHolder) pointList.get(i - 1);
PointHolder current = (PointHolder) pointList.get(i);
PointHolder next = (PointHolder) pointList.get(i+1);
if (previous.y > current.y && next.y > current.y){
toReturn.add(new Integer(i));
}
}
else if(i == 0){
PointHolder current = (PointHolder) pointList.get(i);
PointHolder next = (PointHolder) pointList.get(i+1);
if(current.y < next.y){
toReturn.add(new Integer(i));
}
}
else if(i == pointList.size() - 1){
PointHolder previous = (PointHolder) pointList.get(i - 1);
PointHolder current = (PointHolder) pointList.get(i);
if(current.y < previous.y){
toReturn.add(new Integer(i));
}
}
}
int[] returnArray = new int[toReturn.size()];
for(int i = 0; i < toReturn.size(); i++){
returnArray[i] = ((Integer) toReturn.get(i)).intValue();
}
return returnArray;
}
public float maxAmp(int[] maxes, int[] mins, ArrayList pointList){
if(maxes.length == 0 || mins.length == 0){
return 0.0;
}
float[] differences = null;
if(maxes.length > mins.length){
differences = new float[mins.length];
}
else{
differences = new float[maxes.length];
}
for(int i = 0; i < differences.length; i++){
differences[i] = abs(((PointHolder) pointList.get(maxes[i])).y - ((PointHolder) pointList.get(mins[i])).y);
}
float maxFloat = differences[0];
for(int i = 0; i < differences.length; i++){
if(differences[i] > maxFloat){
maxFloat = differences[i];
}
}
return maxFloat;
}
public float findFreq(int[] maxes, int[] mins, ArrayList pointList){
float arrayWidth = findWidth(pointList);
float toReturn = max((maxes.length/(arrayWidth/100)), (mins.length/(arrayWidth/100)));
return toReturn;
}
public float findWidth(ArrayList pointList){
float minX = ((PointHolder) pointList.get(0)).x;
float maxX = ((PointHolder) pointList.get(0)).x;
for(int i = 0; i < pointList.size(); i++){
PointHolder current = ((PointHolder) pointList.get(i));
if(minX > current.x){
minX = current.x;
}
if(maxX < current.x){
maxX = current.x;
}
}
return abs(maxX - minX);
}
public void drawPointList(){
stroke(currentStroke);
beginShape(LINE_STRIP);
for(int i = 0; i < pointCounter; i++){
PointHolder cPoint = (PointHolder) pointList.get(i);
int tempX = cPoint.x;
int tempY = cPoint.y;
if(cPoint.x < panelX){
tempX = panelX;
}
if(cPoint.x > panelX + panelWidth){
tempX = panelX + panelWidth;
}
if(cPoint.y > panelHeight){
tempY = panelHeight;
}
vertex(tempX, tempY);
}
endShape();
}
public class PointHolder{
int x;
int y;
public PointHolder(int x, int y){
this.x = x;
this.y = y;
}
}
public class ColorSquare{
int fillcolor;
int x;
int y;
int size;
public ColorSquare(int fillcolor, int x, int y, int size){
this.fillcolor = fillcolor;
this.x = x;
this.y = y;
this.size = size;
}
public void draw(){
stroke(0);
fill(fillcolor,fillcolor,fillcolor);
rect(x,y,size,size);
}
}
public class WaveDisplay{
float[] myWave;
float myFreq;
int backgroundColor;
int x;
int y;
int width;
int height;
float period;
public WaveDisplay(float[] myWave, int x, int y){
this.myWave = myWave;
this.backgroundColor = 0;
this.x = x;
this.y = y;
width = 500;
height = 100;
}
public void updateArray(float[] myWave){
this.myWave = myWave;
}
public void drawWave(){
fill(backgroundColor);
stroke(backgroundColor);
rect(x,y,width,height);
fill(0,255,0);
stroke(0,255,0);
line(x,y+height/2, x+width, y+height/2);
line(x+(width/2), y, x+(width/2), y+height);
fill(255,0,0);
stroke(255,0,0);
float[] temp = new float [width];
int counter = 0;
for(float i = -5.0; counter < 500; i+= (10.0/width)){
if(currentWaveForm == 0){
temp[counter] = sin(i*myFreq) * (height/2);
}else if(currentWaveForm == 1){
temp[counter] = cos(i*myFreq) * (height/2);
}
else{
temp[counter] = tan(i*myFreq) * (height/2);
}
counter++;
}
for(int i = 0; i < temp.length; i++){
if((y+height/2) + temp[i] > y){
point(x+i,(y+height/2) + temp[i]);
}
}
}
}
public class WaveformButton{
//0 = sin, 1 = cos, 2 = tan
int type;
int x;
int y;
int width;
int height;
public WaveformButton(int type, int x, int y, int width, int height){
this.type= type;
this.x = x;
this.y = y;
this. width = width;
this.height = height;
}
public void draw(){
stroke(0);
strokeWeight(3);
fill(150,150,150);
rect(x,y,width,height);
strokeWeight(1);
int counter = 0;
float[] temp = new float[100];
switch(type){
case 0:
for(float i = -5.0; counter < 100; i+= (10.0/width)){
temp[counter] = sin(i) * (height/2);
counter++;
}
break;
case 1:
for(float i = -5.0; counter < 100; i+= (10.0/width)){
temp[counter] = -1 * (cos(i) * (height/2));
counter++;
}
break;
case 2:
for(float i = -5.0; counter < 100; i+= (10.0/width)){
temp[counter] = -1 * (tan(i) * (height/2));
counter++;
}
break;
}
beginShape(LINE_STRIP);
for(int i = 0; i < temp.length; i++){
if((y+height/2) + temp[i] > y+ height){
vertex(x+i,y+height);
}
else if(y+height/2 + temp[i] < y){
vertex(x+i, y);
}
else{
vertex(x+i,(y+height/2) + temp[i]);
}
}
endShape();
}
}
Project 2: Create your own drawing tool, emphasizing algorithmic generation/modification/manipulation.
Statement:The contemporary computer scene is dominated by the graphical user interface (GUI). For almost every task, from manipulating text, imagery, sound, video, to configuring a computer's operating system (e.g. control panels), from searching for and organizing information (e.g. the web), to the process of programming (e.g. integrated development environments), there are special purpose GUI tools supporting the task through analogies to embodied interaction with physical objects. But no tool is neutral; every tool bears the marks of the historical process of its creation, literally encoding the biases, dreams, and political realities of its creators, offering affordances for some interactions while making other interactions difficult or impossible to perform or even conceive. While the ability to program does not bring absolute freedom (you can never step outside of culture, and of course programming languages are themselves tools embedded in culture), it does open up a region of free play, allowing the artist to climb up and down the dizzying tower of abstraction and encode her own biases, dreams and political realities. What graphical tools would you create? Create your own drawing tool, emphasizing algorithmic generation/modification/manipulation. Explore the balance of control between the tool and the person using the tool. The tool should do something different when moving vs. dragging (moving with the mouse button down). The code for your tool should use at least one class.
To see this applet you will have to download the JSyn plugin that you can find here:
http://www.softsynth.com/jsyn/plugins/
Changes drawn lines into sound waves on the fly. No wave files here, just big arrays of floating point numbers.
It doesn't seem to like to run in a browser, however. For some reason it doesn't see ArrayList.