import ddf.minim.*; import ddf.minim.signals.*; Minim minim; MyOscillator wav, wav2; AudioOutput out; int cx1 = 200, cx2 = 600, cy1 = 210, cy2 = 210; int numPoints = 24; int[] p1 = new int[numPoints]; int[] p2 = new int[numPoints]; float s1 = 0, s2 = 0; int pt1 = 0, pt2 = 0, pt1b = numPoints / 2, pt2b = numPoints / 2, stPt1 = 0, stPt2 = 0, stMs1 = 0, stMs2 = 0; float cFq1, cFq2; boolean isPlaying = false; int bottom = 12; float[] chrom = new float[108]; float[] freq = new float[36 - bottom]; int[] chromatic = {1}; int[] major = {2,2,1,2,2,2,1}; int[] minor = {2,1,2,2,1,2,2}; int[] majPenta = {2,2,3,2,3}; int[] minPenta = {3,2,2,3,2}; int[] wholetone = {2,2,2,2,2,2}; int[] conDim = {1,2,1,2,1,2,1,2}; int[] spanish = {1,2,1,1,2,1,2,2}; int[] ryukyu = {4,1,2,4,1}; String sName = "Chromatic"; float[] tcos = new float[numPoints]; float[] tsin = new float[numPoints]; PFont myFont; void setup() { frameRate(60); size(800,400); background(255,255,0); smooth(); for (int i = 0; i < numPoints; i ++) { p1[i] = 0; p2[i] = 12; } for (int i = 0; i < 108; i ++) { chrom[i] = pow(2, (float) i / 12) * 110; print(i + ":" + chrom[i] + "/\n"); } initFreq(chromatic); createTrigBuff(); //TEXT //String[] fontList = PFont.list(); //println(fontList); myFont = createFont("HelveticaNeue-Bold", 12); textFont(myFont); //MINIM minim = new Minim(this); // get a line out from Minim, default bufferSize is 1024, default sample rate is 44100, bit depth is 16 out = minim.getLineOut(Minim.STEREO); // create a wav wave Oscillator, set to 440 Hz, at 0.5 amplitude, sample rate from line out wav = new MyOscillator(220, 0.5, out.sampleRate()); wav2 = new MyOscillator(220, 0.5, out.sampleRate()); // set the portamento speed on the oscillator to 200 milliseconds wav.portamento(30); wav2.portamento(30); // add the oscillator to the line out out.addSignal(wav); out.addSignal(wav2); wav.setAmp(0); wav2.setAmp(0); wav.setFreq(freq[p1[0]]); wav2.setFreq(freq[p1[0]]); } void initFreq(int[] arr) { int idx1 = 0, idx2 = 0; for (int i = 0; i < freq.length; i ++) { freq[i] = chrom[idx2]; idx1 ++; if (idx1 >= arr.length) { idx1 = 0; } idx2 += arr[idx1]; } } /********************************************************************/ void draw() { background(255,255,0); updatePt(); updateCircle(); updateLine(); updateUI(); updateScale(); if (cFq1 != freq[p1[pt1]]) { cFq1 = freq[p1[pt1]]; wav.setFreq(freq[p1[pt1]]); } if (cFq2 != freq[p1[pt1b]]) { cFq2 = freq[p1[pt1b]]; wav2.setFreq(freq[p1[pt1b]]); } if (isPlaying) { wav.setAmp(((float) p2[pt2]) / (36 - bottom)); wav2.setAmp(((float) p2[pt2b]) / (36 - bottom)); } else { wav.setAmp(0); wav2.setAmp(0); } } /********************************************************************/ void stop() { out.close(); minim.stop(); super.stop(); } void mouseDragged() { checkMousePos(); } void mouseClicked() { checkMousePos(); if (mouseY >= 30 && mouseY <= 60) { if(mouseX > 360 && mouseX < 390) { startf(); } if (mouseX > 410 && mouseX < 440) { stopf(); } } } void checkMousePos() { float d; if (mouseX < 400) { d = getDistance(cx1, cy1); if (d < 180) { p1[getIndex(cx1, cy1)] = (int) max(0, (d / 180 * 36) - bottom); } } else { d = getDistance(cx2, cy2); if (d < 180) { p2[getIndex(cx2, cy2)] = (int) max(0, (d / 180 * 36) - bottom); } } if (mouseY <= 20) { if(mouseX > 140 && mouseX < 260) { s1 = constrain(mouseX - 145, 0, 100); stPt1 = pt1; stMs1 = millis(); } if(mouseX > 540 && mouseX < 660) { s2 = constrain(mouseX - 545, 0, 100); stPt2 = pt2; stMs2 = millis(); } } } float getDistance(int cx, int cy) { return sqrt((mouseX - cx) * (mouseX - cx) + (mouseY - cy) * (mouseY - cy)); } int getIndex(int cx, int cy) { double ang = atan2(mouseX - cx, cy - mouseY); double i = ( ang / PI / 2 * numPoints) + 0.5; if (i < 0) { i = numPoints + i; } return (int)i; } void keyPressed() { println(keyCode); switch (keyCode) { case 49: case 97: initFreq(chromatic); sName = "Chromatic"; break; case 50: case 98: initFreq(major); sName = "Major"; break; case 51: case 99: initFreq(minor); sName = "Minor"; break; case 52: case 100: initFreq(majPenta); sName = "Major Pentatonic"; break; case 53: case 101: initFreq(minPenta); sName = "Minor Pentatonic"; break; case 54: case 102: initFreq(wholetone); sName = "Whole Tone"; break; case 55: case 103: initFreq(conDim); sName = "Combination of Diminished"; break; case 56: case 104: initFreq(spanish); sName = "Spanish"; break; case 57: case 105: initFreq(ryukyu); sName = "Ryukyu"; break; } } void startf() { if(!isPlaying) { isPlaying = true; pt1 = pt2 = 0; stPt1 = stPt2 = 0; stMs1 = stMs2 = millis(); } } void stopf() { if(isPlaying) { isPlaying = false; } } /* ****************************************************************** */ void updatePt() { if (isPlaying) { int ms = millis(); int offset1 = (int)((ms - stMs1) / (300 - s1 * 2)); int offset2 = (int)((ms - stMs2) / (300 - s2 * 2)); pt1 = (stPt1 + offset1) % numPoints; pt2 = (stPt2 + offset2) % numPoints; pt1b = (stPt1 + numPoints / 2 + offset1) % numPoints; pt2b = (stPt2 + numPoints / 2 + offset2) % numPoints; } } void updateScale() { fill(100); textAlign(CENTER); text("Scale[key 1-9]", 400, 340); text(sName, 400, 360); } void updateCircle() { noStroke(); fill(255); ellipse(cx1,cy1,360,360); ellipse(cx2,cy2,360,360); fill(255,200,200); beginShape(); for (int i = 0; i < numPoints; i ++) { vertex(cx1 + tsin[i] * (p1[i] + bottom) * 180 / 36, cy1 - tcos[i] * (p1[i] + bottom) * 180 / 36); } vertex(cx1 + tsin[0] * (p1[0] + bottom) * 180 / 36, cy1 - tcos[0] * (p1[0] + bottom) * 180 / 36); endShape(); fill(200,200,255); beginShape(); for (int i = 0; i < numPoints; i ++) { vertex(cx2 + tsin[i] * (p2[i] + bottom) * 180 / 36, cy2 - tcos[i] * (p2[i] + bottom) * 180 / 36); } vertex(cx2 + tsin[0] * (p2[0] + bottom) * 180 / 36, cy2 - tcos[0] * (p2[0] + bottom) * 180 / 36); endShape(); fill(255); ellipse(cx1,cy1,50,50); ellipse(cx2,cy2,50,50); } void updateLine() { stroke(255); line(cx1, cy1, cx1 + tsin[pt1] * 180, cy1 - tcos[pt1] * 180); line(cx2, cy2, cx2 + tsin[pt2] * 180, cy2 - tcos[pt2] * 180); line(cx1, cy1, cx1 + tsin[pt1b] * 180, cy1 - tcos[pt1b] * 180); line(cx2, cy2, cx2 + tsin[pt2b] * 180, cy2 - tcos[pt2b] * 180); } void updateUI() { noStroke(); fill(255); rect(140,0,120,20); rect(540,0,120,20); fill(200); rect(s1 + 140, 0, 20,20); rect(s2 + 540, 0, 20,20); if (isPlaying) { fill(0,255,0); } else { fill(200); } rect (360,20, 30,30); if (!isPlaying) { fill(255,100,0); } else { fill(200); } rect (410,20, 30,30); fill (255); beginShape(); vertex(370,30); vertex(382,35); vertex(370,40); endShape(); rect(420,30,10,10); } void createTrigBuff() { for (int i = 0; i < numPoints; i ++) { tcos[i] = cos(PI * 2 / numPoints * i); tsin[i] = sin(PI * 2 / numPoints * i); } }