import pitaru.sonia_v2_9.*; SoundStroke s; int soundCount = 0; float h; LinkedList beingDrawn; class XY{ float x; float y; XY(float x, float y){ this.x = x; this.y = y; } } class SoundStroke{ float[] x; float[] y; float[] data; SoundStroke(LinkedList l){ //initialize float[]s x = new float[l.size()]; y = new float[l.size()]; data = new float[l.size()]; XY current; float startX = ((XY)(l.getFirst())).x; float startY = ((XY)(l.getFirst())).y; float endX = ((XY)(l.getLast())).x; float endY = ((XY)(l.getLast())).y; // fill the floats ListIterator iter = l.listIterator(); int i = 0; while(iter.hasNext()){ current = (XY)(iter.next()); x[i] = current.x; y[i] = current.y; data[i] = distanceToLine(current.x, current.y, startX, startY, endX, endY); i++; } //Some futzing to keep the waveform from being too loud and getting hard-limited. //There must be a more efficient way. float least = data[0]; float greatest = data[0]; for(int j = 0; j < data.length; j++){ if(data[j] < least) least = data[j]; if(data[j] > greatest) greatest = data[j]; } if (abs(least) > greatest) greatest = abs(least); float scaleLimit = h; if (greatest > h) scaleLimit = greatest; //scale it down to below one. for(int j = 0; j < data.length; j++){ data[j] = data[j] / scaleLimit; } } } float distanceToLine(float aX, float aY, float startX, float startY, float endX, float endY){ float lineDX = endX - startX; float lineDY = endY - startY; return (lineDX*(startY - aY) - (startX - aX)*lineDY) / sqrt(lineDX*lineDX + lineDY*lineDY); } void setup(){ int streamSize = 1024; Sonia.start(this, 44100); LiveOutput.start(streamSize,streamSize*2); // Start LiveOutput with a buffer. LiveOutput.startStream(); // Start the liveOutput stream, and activate the liveOutputEvent(){} size(600, 500); h = 500; noFill(); LinkedList init = new LinkedList(); init.add(new XY(0.0, 0.0)); s = new SoundStroke(init); beingDrawn = new LinkedList(); } boolean drawing = false; void draw(){ background(70, 40, 20); if(drawing){ beingDrawn.add(new XY(mouseX, mouseY)); //** //this next line below make the sound play as you're drawing it //this means that the sound starts extremely high, since the //line you draw is very short to begin with, //and then the sound gets lower the longer you draw. //you can also play with the angle that the sound is taken from the //mark by drawing around the starting point of the line. s = new SoundStroke(beingDrawn); //** if(beingDrawn.size() > 0){ stroke(255, 255, 100); ListIterator iter = beingDrawn.listIterator(); XY last = (XY)(iter.next()); XY current; // this second drawing check in the while statement seems to avoid a // ConcurrentModification error, although I don't know why. while(iter.hasNext() && drawing){ current = (XY)(iter.next()); line(last.x, last.y, current.x, current.y); last = current; } } } else { stroke(100, 255, 255); for(int i = 0; i < s.x.length - 1; i++){ line(s.x[i], s.y[i], s.x[i + 1], s.y[i + 1]); line(i, height-50, i, height-50+(s.data[i]*50.0)); } } } void mousePressed(){ drawing = true; } void mouseReleased(){ drawing = false; s = new SoundStroke(beingDrawn); beingDrawn.clear(); } void liveOutputEvent(){ float toSave; if(s.data.length > 0) { for(int i = 0; i < LiveOutput.data.length; i++){ toSave = s.data[soundCount %= s.data.length]; LiveOutput.data[i] = toSave; soundCount++; } } else { for(int i = 0; i < LiveOutput.data.length; i++){ LiveOutput.data[i] = 0; } } } public void stop(){ Sonia.stop(); super.stop(); }