import controlP5.*; import netP5.*; ControlP5 cp5; // === EQ bands (fixed centers/Q, draggable gains in dB) === float band1Gain = 0; float band2Gain = 0; final float band1Center = 0.3; final float band2Center = 0.7; final float bandQ = 10; boolean draggingBand1 = false; boolean draggingBand2 = false; // === Other effect parameters === float delayTime = 0.5; float delayFeedback = 0.4; float distortionAmount= 0.5; float distortionMix = 0.5; float chorusAmount = 0.5; float chorusDryWet = 0.5; void setup() { size(1680, 780, P3D); // Use orthographic projection to render a perfect cube without perspective distortion ortho(0, width, height, 0, -1000, 1000); frameRate(125); background(21,21,30); noStroke(); surface.setResizable(false); surface.setLocation(100, 100); cp5 = new ControlP5(this); // Envelope knobs cp5.addKnob("AmpAttack").setLabel("Attack").setRange(0,1).setValue(0.4) .setPosition(85,350).setRadius(45).setViewStyle(Knob.ARC) .setColorBackground(color(21,21,30)).setColorForeground(color(255,178,44)) .setColorActive(color(250,170,40)).setFont(createFont("Futura",15)); cp5.addKnob("AmpRelease").setLabel("Release").setRange(0,1).setValue(0.4) .setPosition(215,350).setRadius(45).setViewStyle(Knob.ARC) .setColorBackground(color(21,21,30)).setColorForeground(color(255,178,44)) .setColorActive(color(250,170,40)).setFont(createFont("Futura",15)); cp5.addKnob("FilterAttack").setLabel("Attack").setRange(0,1).setValue(0.4) .setPosition(405,350).setRadius(45).setViewStyle(Knob.ARC) .setColorBackground(color(21,21,30)).setColorForeground(color(255,178,44)) .setColorActive(color(250,170,40)).setFont(createFont("Futura",15)); cp5.addKnob("FilterRelease").setLabel("Release").setRange(0,1).setValue(0.4) .setPosition(535,350).setRadius(45).setViewStyle(Knob.ARC) .setColorBackground(color(21,21,30)).setColorForeground(color(255,178,44)) .setColorActive(color(250,170,40)).setFont(createFont("Futura",15)); cp5.addKnob("PitchAttack").setLabel("Attack").setRange(0,1).setValue(0.4) .setPosition(725,350).setRadius(45).setViewStyle(Knob.ARC) .setColorBackground(color(21,21,30)).setColorForeground(color(255,178,44)) .setColorActive(color(250,170,40)).setFont(createFont("Futura",15)); cp5.addKnob("PitchRelease").setLabel("Release").setRange(0,1).setValue(0.4) .setPosition(855,350).setRadius(45).setViewStyle(Knob.ARC) .setColorBackground(color(21,21,30)).setColorForeground(color(255,178,44)) .setColorActive(color(250,170,40)).setFont(createFont("Futura",15)); // Distortion knobs cp5.addKnob("distortionAmount").setLabel("Amount").setRange(0,1).setValue(distortionAmount) .setPosition(405,550).setRadius(45).setViewStyle(Knob.ARC) .setColorBackground(color(21,21,30)).setColorForeground(color(255,178,44)) .setColorActive(color(250,170,40)).setFont(createFont("Futura",15)); cp5.addKnob("distortionMix").setLabel("Mix").setRange(0,1).setValue(distortionMix) .setPosition(535,550).setRadius(45).setViewStyle(Knob.ARC) .setColorBackground(color(21,21,30)).setColorForeground(color(255,178,44)) .setColorActive(color(250,170,40)).setFont(createFont("Futura",15)); // Chorus knobs cp5.addKnob("chorusAmount").setLabel("Amount").setRange(0,1).setValue(chorusAmount) .setPosition(725,550).setRadius(45).setViewStyle(Knob.ARC) .setColorBackground(color(21,21,30)).setColorForeground(color(255,178,44)) .setColorActive(color(250,170,40)).setFont(createFont("Futura",15)); cp5.addKnob("chorusDryWet").setLabel("Dry/Wet").setRange(0,1).setValue(chorusDryWet) .setPosition(855,550).setRadius(45).setViewStyle(Knob.ARC) .setColorBackground(color(21,21,30)).setColorForeground(color(255,178,44)) .setColorActive(color(250,170,40)).setFont(createFont("Futura",15)); // Delay knobs cp5.addKnob("delayTime").setLabel("Time").setRange(0,1).setValue(delayTime) .setPosition(1045,550).setRadius(45).setViewStyle(Knob.ARC) .setColorBackground(color(21,21,30)).setColorForeground(color(255,178,44)) .setColorActive(color(250,170,40)).setFont(createFont("Futura",15)); cp5.addKnob("delayFeedback").setLabel("Feedback").setRange(0,1).setValue(delayFeedback) .setPosition(1175,550).setRadius(45).setViewStyle(Knob.ARC) .setColorBackground(color(21,21,30)).setColorForeground(color(255,178,44)) .setColorActive(color(250,170,40)).setFont(createFont("Futura",15)); } void draw() { background(21,21,30); // Panels grid stroke(64); fill(12); rect(50,100,300,180,8); rect(370,100,300,180,8); rect(690,100,300,180,8); rect(1010,100,300,180,8); rect(1330,100,300,180,8); rect(50,300,300,180,8); rect(370,300,300,180,8); rect(690,300,300,180,8); rect(50,500,300,180,8); rect(370,500,300,180,8); rect(690,500,300,180,8); rect(1010,500,300,180,8); rect(1330,500,300,180,8); // Labels textAlign(CENTER, TOP); fill(255); textSize(18); text("Oscillator #1", 200, 110); text("Oscillator #2", 520, 110); text("Oscillator #3", 840, 110); text("Filter", 1160,110); text("LFO", 1480,110); text("Amp Env", 200, 330); text("Filter Env", 520, 330); text("Pitch Env", 840, 330); text("EQ", 200, 530); text("Distortion", 520, 530); text("Chorus", 840, 530); text("Delay", 1160, 530); text("Reverb", 1480, 530); // Waveforms & graphs SinWave(); SawtoothWave(); TriangleWave(); drawFilterGraph(); drawLFOWaveform(); drawEQGraph(); // --- Reverb: smaller wireframe cube --- pushMatrix(); translate(1480, 590, 0); rotateX(frameCount * 0.01f); rotateY(frameCount * 0.013f); rotateZ(frameCount * 0.007f); noFill(); stroke(255, 178, 44); strokeWeight(2); float s = 20; // half-edge length = 20 → full cube = 40 // front face (z = +s) line(-s,-s, s, s,-s, s); line( s,-s, s, s, s, s); line( s, s, s, -s, s, s); line(-s, s, s, -s,-s, s); // back face (z = -s) line(-s,-s,-s, s,-s,-s); line( s,-s,-s, s, s,-s); line( s, s,-s, -s, s,-s); line(-s, s,-s, -s,-s,-s); // side edges line(-s,-s, s, -s,-s,-s); line( s,-s, s, s,-s,-s); line( s, s, s, s, s,-s); line(-s, s, s, -s, s,-s); popMatrix(); } void drawEQGraph() { int x0=50, y0=500, w=300, h=180; int midY = y0 + h/2; stroke(64); fill(12); rect(x0,y0,w,h,8); stroke(80); fill(255); textSize(12); textAlign(RIGHT, CENTER); for(int i=0; i<=4; i++){ float db = map(i, 0, 4, +20, -60); float yy = y0 + i*(h/4); line(x0-5, yy, x0, yy); text(nf(db,1,0)+" dB", x0-8, yy); } fill(255,178,44); textSize(14); textAlign(LEFT, BOTTOM); text("Low Band: "+nf(band1Gain,1,1)+" dB", x0+8, y0+h-8); textAlign(RIGHT, BOTTOM); text("High Band: "+nf(band2Gain,1,1)+" dB", x0+w-8, y0+h-8); noFill(); stroke(255,178,44); beginShape(); float g1n = map(band1Gain, -60, 20, -1, 1); float g2n = map(band2Gain, -60, 20, -1, 1); for(int i=0; i<=w; i++){ float norm = i/(float)w; float d1 = g1n * exp(-sq((norm-band1Center)*bandQ)); float d2 = g2n * exp(-sq((norm-band2Center)*bandQ)); float y = midY - (d1 + d2)*(h/2); vertex(x0+i, y); } endShape(); noStroke(); fill(255,178,44); float hx1 = x0 + band1Center*w; float hy1 = midY - map(band1Gain,-60,20,-1,1)*(h/2); ellipse(hx1, hy1, 12, 12); float hx2 = x0 + band2Center*w; float hy2 = midY - map(band2Gain,-60,20,-1,1)*(h/2); ellipse(hx2, hy2, 12, 12); } void mousePressed() { int x0=50, y0=500, w=300, h=180; float hy1 = map(band1Gain, 20, -60, y0, y0+h); float hy2 = map(band2Gain, 20, -60, y0, y0+h); if (dist(mouseX, mouseY, x0+band1Center*w, hy1) < 10) draggingBand1 = true; else if (dist(mouseX, mouseY, x0+band2Center*w, hy2) < 10) draggingBand2 = true; } void mouseDragged() { int y0=500, h=180; if (draggingBand1) { float cy = constrain(mouseY, y0, y0+h); band1Gain = map(cy, y0+h, y0, -60, 20); } if (draggingBand2) { float cy = constrain(mouseY, y0, y0+h); band2Gain = map(cy, y0+h, y0, -60, 20); } } void mouseReleased() { draggingBand1 = draggingBand2 = false; } // ControlP5 callbacks (no-op) void AmpAttack(float v) {} void AmpRelease(float v) {} void FilterAttack(float v) {} void FilterRelease(float v) {} void PitchAttack(float v) {} void PitchRelease(float v) {} void distortionAmount(float v){ distortionAmount = v; } void distortionMix(float v) { distortionMix = v; } void chorusAmount(float v) { chorusAmount = v; } void chorusDryWet(float v) { chorusDryWet = v; } void delayTime(float v) { delayTime = v; } void delayFeedback(float v) { delayFeedback = v; } // Waveform & helpers void SinWave() { stroke(255,178,44); noFill(); float phase = frameCount * 0.025f; int yBase=210, amp=60, x0=70, x1=330; beginShape(); for(int x=x0; x<=x1; x++){ float t = map(x,x0,x1,0,TWO_PI*2); vertex(x,yBase+sin(t+phase)*amp); } endShape(); } void SawtoothWave() { stroke(255,178,44); noFill(); float phase=frameCount*0.025f; int yBase=210, x0=390, x1=650; beginShape(); for(int x=x0; x<=x1; x++){ float t=map(x,x0,x1,0,2)+phase, p=t-floor(t), v=-1+p*2; vertex(x,yBase+v*60); } endShape(); } void TriangleWave() { stroke(255,178,44); noFill(); float phase=frameCount*0.04f; int yBase=210, amp=60, x0=710, x1=970; beginShape(); for(int x=x0; x<=x1; x++){ float t=map(x,x0,x1,0,4)+phase; int s=floor(t); float f=t-s; float v=(s%2==0)?-1+f*2:1-f*2; vertex(x,yBase+v*amp); } endShape(); } void drawFilterGraph() { stroke(255,178,44); noFill(); int x0=1030, y0=140, w=260, h=180; beginShape(); for(int i=0;i<=w;i++){ float n=i/(float)w, m=1/sqrt(1+pow(n/0.5f,2)); vertex(x0+i, y0+(1-m)*h); } endShape(); } void drawLFOWaveform() { stroke(255,178,44); noFill(); int x0=1330, y0=100, w=260, h=180, m=20; float phase=frameCount*0.02f; beginShape(); for(int i=0;i<=w;i++){ float a=map(i,0,w,0,TWO_PI); vertex(x0+m+i, y0+h/2+sin(a)*(h/2-10)); } endShape(); float p=(phase%TWO_PI)/TWO_PI; noStroke(); fill(255,178,44); ellipse(x0+m+p*w, y0+h/2+sin(phase)*(h/2-10), 12,12); }