float[][] freqs = { { 130.81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 261.63, 246.94, 233.08, 220.00, 207.65, 196.00, 185.00, 174.61, 164.81, 155.56, 145.83, 138.59 },
{ 392.00, 369.99, 349.23, 329.63, 311.13, 293.66, 277.18, 0, 0, 0, 0, 0 },
{ 523.25, 493.88, 466.16, 440.00, 415.30, 0, 0, 0, 0, 0, 0, 0 },
{ 649.23, 622.23, 587.33, 554.37, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 783.99, 739.99, 698.46, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 932.33, 880.00, 860.61, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1046.50, 987.77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
int len = 512;
float global_freq, phase, phaseAdder, vol;
Overtone[] ot = new Overtone[8];
float ox = 22.5, oy = 77.5, w = 13.83, h = 200;
boolean global_over = false;
boolean start = false;
float emouseX, vs = 0;
BImage labels, cover;
void setup()
{
size(600,300);
Sonia.start(this, 22048);
LiveOutput.start(len, len*2);
LiveOutput.setSleep(5);
LiveOutput.startStream();
ot[0] = new Overtone(ox, oy, w*4, h, freqs[0], color(255,128,128), 1);
ot[1] = new Overtone(ox+w*4, oy, w, h, freqs[1], color(255,128,0), 12);
ot[2] = new Overtone(ox+w*16, oy, w, h, freqs[2], color(255,255,128), 7);
ot[3] = new Overtone(ox+w*23, oy, w, h, freqs[3], color(0,255,128), 5);
ot[4] = new Overtone(ox+w*28, oy, w, h, freqs[4], color(128,255,255), 4);
ot[5] = new Overtone(ox+w*32, oy, w, h, freqs[5], color(0,128,255), 3);
ot[6] = new Overtone(ox+w*35, oy, w, h, freqs[6], color(128,128,255), 3);
ot[7] = new Overtone(ox+w*38, oy, w, h, freqs[7], color(255,128,255), 2);
labels = loadImage("labels.gif");
cover = loadImage("cover.jpg");
}
void loop()
{
background(0);
draw_bg(color(128,192,255), color(255,255,255));
if (!start) {
image(cover, 0, 0);
} else {
display();
play_with_it();
}
}
void display()
{
for (int i = 0; i < ot.length; i++)
ot[i].draw();
stroke(0);
for (int i=0; i < len-1; i++) {
float dx = lerp(0,555,1/512);
line(44 + i, LiveOutput.data[i]*30 + oy/2, 44 + (i+1), LiveOutput.data[(i+1)]*30 + oy/2);
}
image(labels, ox+w*4+w/2, oy+2);
}
void play_with_it()
{
global_over = (mouseX >= ox && mouseY >= oy && mouseX <= ox+(w*40) && mouseY <= oy+h) ? true : false;
set_vol();
set_emouseX();
}
void draw_bg(color a, color b)
{
beginShape(POLYGON);
fill(a);
vertex(0,0);
vertex(width, 0);
fill(b);
vertex(width, height);
vertex(0, height);
endShape();
}
void set_emouseX()
{
float M = 0.8;
float K = 0.2;
float D = 0.70;
float f,as;
f = -K * (emouseX - mouseX);
as = constrain(f / M, -17, 17);
vs = D * (vs + as);
emouseX = emouseX + vs;
if (global_over)
rect(emouseX - 5, mouseY -5, 10, 10);
}
void liveOutputEvent(){
if(mousePressed && global_over){
phaseAdder = global_freq/11025f;
for (int i = 0; i < len; i++) {
phase += phaseAdder;
if (phase > 1f) phase -= 2f;
LiveOutput.data[i] = vol*sin(phase*PI);
}
}else {
for (int i=0; i < len; i++) {
LiveOutput.data[i] = 0;
}
}
}
void set_vol()
{
vol = 0.8 - lerp(0.1, 0.8, (float)mouseY/height);
}
class Overtone
{
float x,y,w,h;
float[] freqs;
color c;
int num;
float noteW, noteH;
float a;
int currentKey = -1;
int valveDiff = 0;
Overtone(float $x, float $y, float $w, float $h, float[] $freq, color $c, int $num)
{
x = $x; y = $y; w = $w*$num; h = $h;
freqs = $freq;
c = $c;
num = $num;
noteW = $w;
noteH = h;
}
void draw()
{
if (over()) {
work_valves();
set_freq(freqs[valveDiff]);
a = 0;
} else {
a = 64;
}
fill(c);
noStroke();
rect(x,y,w,h);
for (int i = 0; i < num; i++) {
if (over() && currentKey == i) {
fill(255,215);
} else if (over() && currentKey == -1 && i == num-1) {
fill(255,235);
} else {
fill(lerp(128,255,(float)i/num) , lerp(0,192,(float)i/num));
}
rect(x+(i*noteW), y, noteW, noteH);
}
label();
fill(0,a);
rect(x,y,w,h);
}
void work_valves()
{
int[] keys = { 48,57,56,55,54,53,52,51,50,49,96 };
if (keyPressed) {
for (int i = keys.length-1; i >= 0; i--) {
if (keys[i] == key) {
currentKey = num-2-i;
valveDiff = i+1;
}
}
} else {
currentKey = -1;
valveDiff = 0;
}
}
void label()
{
/**String s;
for (int i = 0; i < 11; i++) {
s = (i == 0) ? "`" : "";
s = (i == 1) ? "1" : "";
s = (i == 2) ? "2" : "";
s = (i == 3) ? "3" : "";
s = (i == 4) ? "4" : "";
s = (i == 5) ? "5" : "";
s = (i == 6) ? "6" : "";
s = (i == 7) ? "7" : "";
s = (i == 8) ? "8" : "";
s = (i == 9) ? "9" : "";
s = (i == 10) ? "0" : "";
fill(0);
text(s, x+i*noteW - noteW/2, y+10);
}**/
}
boolean over()
{
return (emouseX >= x && emouseX <= x+w && mouseY >= y && mouseY <= y+h) ? true : false;
}
}
void set_freq(float freq)
{
global_freq = freq;
}
float lerp(float mn, float mx, float d)
{
return (mx - mn)*d + mn;
}
float powlerp(float mn, float mx, float d)
{
return mn + pow((mx - mn)*-d,2)/mx;
}
float cubic_lerp(float t, float b, float c, float d) {
return -c * (t/=d)*(t-2) + b;
}
public void stop() {
Sonia.stop();
super.stop();
}
void mousePressed()
{
if (!start) start = true;
}