├── MIDI.pde ├── OSC.pde ├── Processing_Resolume_FFT.pde ├── README.md ├── controlP5.pde ├── gifs └── code_gui.gif └── minim.pde /MIDI.pde: -------------------------------------------------------------------------------- 1 | void midiBusSetup() { 2 | MidiBus.list(); // List all available Midi devices on STDOUT. This will show each device's index and name. 3 | myBus = new MidiBus(this, 3, 3); // Create a new MidiBus with the right input and output to match AKAI APC40 4 | } 5 | 6 | 7 | //Simples MIDI Recieve Functions. Perhaps also worth checking out the classBased ones? 8 | 9 | void noteOn(int channel, int pitch, int velocity) { 10 | // Receive a noteOn 11 | println(); 12 | println("Note On:"); 13 | println("--------"); 14 | println("Channel:"+channel); 15 | println("Pitch:"+pitch); 16 | println("Velocity:"+velocity); 17 | 18 | //if (channel == 7 && pitch == 57 && velocity == 127) { 19 | // bang(); 20 | //} 21 | } 22 | 23 | void noteOff(int channel, int pitch, int velocity) { 24 | // Receive a noteOff 25 | println(); 26 | println("Note Off:"); 27 | println("--------"); 28 | println("Channel:"+channel); 29 | println("Pitch:"+pitch); 30 | println("Velocity:"+velocity); 31 | } 32 | 33 | void controllerChange(int channel, int number, int value) { 34 | // Receive a controllerChange 35 | println(); 36 | println("Controller Change:"); 37 | println("--------"); 38 | println("Channel:"+channel); 39 | println("Number:"+number); 40 | println("Value:"+value); 41 | 42 | //Base MIDI Controlls 43 | //Still to do: How to control radiobuttons? How to set ranges? 44 | 45 | 46 | 47 | if (channel == 0 && number == 48) { 48 | cp5.get("base").setValue(int(map(value, 0, 127, baseMin, baseMax))); 49 | } else if (channel == 0 && number == 49) { 50 | cp5.get("baseThreshold").setValue(int(map(value, 0, 127, 100, 1))); 51 | } else if (channel == 0 && number == 50) { 52 | cp5.get("baseTimerThreshold").setValue(int(map(value, 0, 127, 0, 1000))); 53 | } else if (channel == 0 && number == 51) { 54 | baseClipsColumnsEffect.activate(round(map(value, 0, 127, 0, 2))); 55 | } 56 | //else if (channel == 0 && number == 52) { 57 | // cp5.get("baseClipOrColumn").setValue(round(map(value, 0, 127, 1, 8))); 58 | //} 59 | 60 | //Snare MIDI Controls 61 | else if (channel == 0 && number == 52) { 62 | cp5.get("snare").setValue(int(map(value, 0, 127, snareMin, snareMax))); 63 | } else if (channel == 0 && number == 53) { 64 | cp5.get("snareThreshold").setValue(int(map(value, 0, 127, 100, 1))); 65 | } else if (channel == 0 && number == 54) { 66 | cp5.get("snareTimerThreshold").setValue(int(map(value, 0, 127, 0, 1000))); 67 | } else if (channel == 0 && number == 55) { 68 | snareClipsColumnsEffect.activate(round(map(value, 0, 127, 0, 2))); 69 | } 70 | //else if (channel == 0 && number == 20) { 71 | // snareOscRange.setLowValue(map(value, 0, 127, 1, snareOscRange.getHighValue())); 72 | //} else if (channel == 0 && number == 21) { 73 | // snareOscRange.setHighValue(map(value, 0, 127, snareOscRange.getLowValue(), 6)); 74 | //} 75 | } -------------------------------------------------------------------------------- /OSC.pde: -------------------------------------------------------------------------------- 1 | void oscSetup() { 2 | oscP5 = new OscP5(this, portToListenTo); 3 | myRemoteLocation = new NetAddress(ipAddressToSendTo, portToSendTo); 4 | myMessage = new OscMessage("/"); 5 | } -------------------------------------------------------------------------------- /Processing_Resolume_FFT.pde: -------------------------------------------------------------------------------- 1 | //YellowClaw Master: MIDI, OSC, controlP5, Minim 2 | 3 | //OSC 4 | import oscP5.*; 5 | import netP5.*; 6 | 7 | //controlP5 8 | import controlP5.*; 9 | 10 | // Minim 11 | import ddf.minim.*; 12 | import ddf.minim.analysis.*; 13 | 14 | //MidiBus 15 | import themidibus.*; 16 | MidiBus myBus; 17 | 18 | 19 | //Minim 20 | Minim minim; 21 | AudioInput myAudio; 22 | 23 | FFT myAudioFFT; 24 | 25 | int myAudioRange = 11; 26 | int myAudioMax = 100; 27 | 28 | float myAudioAmp = 6500.0; 29 | float myAudioIndex = 0.2; 30 | float myAudioIndexAmp = myAudioIndex; 31 | float myAudioIndexStep = 0.5; 32 | 33 | int base = 0; 34 | int snare = 5; 35 | 36 | int baseMin = 0; 37 | int baseMax = 10; 38 | 39 | int snareMin = 0; 40 | int snareMax = 10; 41 | 42 | // ************************************************************************************ 43 | 44 | //Visualization constants 45 | 46 | int rectSize = 70; 47 | 48 | int stageMargin = 100; 49 | int stageWidth = (myAudioRange * rectSize) + (stageMargin * 2); 50 | int stageHeight = 300; 51 | 52 | float xStart = stageMargin; 53 | float yStart = stageMargin; 54 | int xSpacing = rectSize; 55 | 56 | color bgColor = #333333; 57 | color snareColor = #00FFFD; 58 | color baseColor = #FA00FF; 59 | 60 | // ************************************************************************************ 61 | 62 | //OSC config 63 | int portToListenTo = 12000; 64 | int portToSendTo = 7000; 65 | String ipAddressToSendTo = "localhost"; 66 | 67 | OscP5 oscP5; 68 | NetAddress myRemoteLocation; 69 | OscBundle myBundle; 70 | OscMessage myMessage; 71 | 72 | //Control p5 73 | ControlP5 cp5; 74 | RadioButton fftWindow; 75 | RadioButton snareClipsColumnsEffect; 76 | RadioButton baseClipsColumnsEffect; 77 | RadioButton sequentialOrRandom; 78 | 79 | RadioButton baseSequentialOrRandom; 80 | 81 | RadioButton baseLayerClips; 82 | RadioButton baseOverUnder; 83 | 84 | CheckBox snareLayers; 85 | CheckBox baseLayers; 86 | 87 | Range snareOscRange; 88 | 89 | Range baseOscRange; 90 | 91 | boolean snareOscToggle = true; 92 | boolean baseOscToggle = true; 93 | 94 | //Shared timer GUI variable 95 | int timerWidth = 275; 96 | 97 | //Timer variables (base) 98 | int baseTimer = 0; 99 | int baseLastTimer = 0; 100 | int baseTimerThreshold; 101 | 102 | //Timer variables (snare) 103 | int snareTimer = 0; 104 | int snareLastTimer = 0; 105 | int snareTimerThreshold; 106 | 107 | 108 | //Threshold variables 109 | int baseThreshold; 110 | int snareThreshold; 111 | 112 | 113 | //Clip/column for the base to trigg 114 | int baseClipOrColumn; 115 | 116 | //Variables for range of clips/columns being triggered 117 | int snareMinRange = 1; 118 | int snareMaxRange = 7; 119 | 120 | int baseMinRange = 1; 121 | int baseMaxRange = 7; 122 | 123 | //Variables for random number 124 | int randNum; 125 | int prevRandNum; 126 | 127 | //Variables for sequential numbers 128 | int seqNum = 1; 129 | int prevSeqNum=1; 130 | 131 | 132 | //Experiments 133 | int snareClipNumber; 134 | int baseClipNumber; 135 | 136 | int snarePianoClip; 137 | int basePianoClip; 138 | 139 | boolean snarePeakToggle = true; 140 | boolean basePeakToggle = true; 141 | 142 | 143 | 144 | // ************************************************************************************ 145 | 146 | void setup() { 147 | 148 | size(1000, 750); 149 | //pixelDensity(2); //Uncomment this line if running on a Retina display 150 | background(bgColor); 151 | 152 | //minim setup 153 | minimSetup(); 154 | 155 | //osc setup 156 | oscSetup(); 157 | 158 | //controlP5 setup 159 | controlP5Setup(); 160 | 161 | //midiBusSetup 162 | midiBusSetup(); 163 | 164 | 165 | PFont pfont = createFont("Helvetica", 32, true); 166 | textFont(pfont, 12); 167 | } 168 | 169 | void draw() { 170 | background(bgColor); 171 | 172 | minimSetWindow(); 173 | 174 | myAudioFFT.forward(myAudio.mix); 175 | 176 | for (int i = 0; i < myAudioRange; ++i) { 177 | stroke(0); 178 | strokeWeight(1); 179 | if (i == snare && i ==base) fill(lerpColor(baseColor, snareColor, .5)); // others 180 | else if (i==base) fill(baseColor); // base 181 | else if (i==snare) fill(snareColor); // snare 182 | else fill(#CCCCCC); // others 183 | 184 | float tempIndexAvg = (myAudioFFT.getAvg(i) * myAudioAmp) * myAudioIndexAmp; 185 | float tempIndexCon = constrain(tempIndexAvg, 0, myAudioMax); 186 | rect( xStart + (i*xSpacing), yStart, rectSize, tempIndexCon); 187 | 188 | // visualize the number data for range item 189 | fill(200); 190 | text(str((int)tempIndexCon), xStart + (i*xSpacing) + 10, stageMargin+myAudioMax+(stageMargin/2)); 191 | 192 | //SNARE 193 | if (i==snare && snareOscToggle==true) { 194 | 195 | if (snareClipsColumnsEffect.getValue() == 2 ) { 196 | OscMessage myMessage = new OscMessage(cp5.get(Textfield.class, "SnareOscAdress").getText()); 197 | myMessage.add((myAudioFFT.getAvg(snare) * myAudioAmp) * myAudioIndexAmp / 100); /* add an int to the osc message */ 198 | oscP5.send(myMessage, myRemoteLocation); 199 | } 200 | //If volume exceeds threshold 201 | if ((myAudioFFT.getAvg(snare) * myAudioAmp) * myAudioIndexAmp > snareThreshold && snareTimer > snareTimerThreshold && snareOscToggle==true && snarePeakToggle == true) { 202 | if (snareTimer > snareTimerThreshold) { 203 | if (snareClipsColumnsEffect.getValue() == 0) { // Trig clips (not columns) 204 | for (int j=0; j snareMaxRange) { 218 | prevSeqNum = snareMinRange; 219 | } 220 | } else if (snareClipsColumnsEffect.getValue() == 1 ) { //Trig entire columns 221 | 222 | if (sequentialOrRandom.getValue() == 0) { 223 | snareClipNumber = sequentialOrder(prevSeqNum); 224 | } else if (sequentialOrRandom.getValue() == 1) { 225 | snareClipNumber = randomNoDublicates(snareMinRange, snareMaxRange, prevRandNum); 226 | } 227 | 228 | OscMessage myMessage = new OscMessage("/track" + snareClipNumber + "/connect"); 229 | myMessage.add(1); /* add an int to the osc message */ 230 | oscP5.send(myMessage, myRemoteLocation); 231 | prevSeqNum++; 232 | 233 | if (prevSeqNum > snareMaxRange) { 234 | prevSeqNum = snareMinRange; 235 | } 236 | } 237 | } 238 | prevRandNum = randNum; 239 | snareLastTimer = millis(); 240 | } 241 | 242 | //If volume is BELOW threshold 243 | if ((myAudioFFT.getAvg(snare) * myAudioAmp) * myAudioIndexAmp < snareThreshold && snareTimer > snareTimerThreshold && snareOscToggle==true && snarePeakToggle == false) { 244 | if (snareTimer > snareTimerThreshold) { 245 | if (snareClipsColumnsEffect.getValue() == 0) { // Trig clips (not columns) 246 | for (int j=0; j snareMaxRange) { 260 | prevSeqNum = snareMinRange; 261 | } 262 | } else if (snareClipsColumnsEffect.getValue() == 1 ) { //Trig entire columns 263 | 264 | if (sequentialOrRandom.getValue() == 0) { 265 | snareClipNumber = sequentialOrder(prevSeqNum); 266 | } else if (sequentialOrRandom.getValue() == 1) { 267 | snareClipNumber = randomNoDublicates(snareMinRange, snareMaxRange, prevRandNum); 268 | } 269 | 270 | OscMessage myMessage = new OscMessage("/track" + snareClipNumber + "/connect"); 271 | myMessage.add(1); /* add an int to the osc message */ 272 | oscP5.send(myMessage, myRemoteLocation); 273 | prevSeqNum++; 274 | 275 | if (prevSeqNum > snareMaxRange) { 276 | prevSeqNum = snareMinRange; 277 | } 278 | } 279 | } 280 | prevRandNum = randNum; 281 | snareLastTimer = millis(); 282 | } 283 | 284 | 285 | //BASE 286 | } else if (i ==base && baseOscToggle==true) { 287 | if (baseClipsColumnsEffect.getValue() == 2 ) { 288 | OscMessage myMessage = new OscMessage(cp5.get(Textfield.class, "BaseOscAdress").getText()); 289 | myMessage.add((myAudioFFT.getAvg(base) * myAudioAmp) * myAudioIndexAmp / 100); /* add an int to the osc message */ 290 | oscP5.send(myMessage, myRemoteLocation); 291 | } 292 | //If volume exceeds threshold 293 | if ((myAudioFFT.getAvg(base) * myAudioAmp) * myAudioIndexAmp > baseThreshold && baseTimer > baseTimerThreshold && baseOscToggle==true && basePeakToggle == true) { 294 | if (baseTimer > baseTimerThreshold) { 295 | if (baseClipsColumnsEffect.getValue() == 0) { // Trig clips (not columns) 296 | for (int j=0; j baseMaxRange) { 310 | prevSeqNum = baseMinRange; 311 | } 312 | } else if (baseClipsColumnsEffect.getValue() == 1 ) { //Trig entire columns 313 | 314 | if (baseSequentialOrRandom.getValue() == 0) { 315 | baseClipNumber = sequentialOrder(prevSeqNum); 316 | } else if (baseSequentialOrRandom.getValue() == 1) { 317 | baseClipNumber = randomNoDublicates(baseMinRange, baseMaxRange, prevRandNum); 318 | } 319 | 320 | OscMessage myMessage = new OscMessage("/track" + baseClipNumber + "/connect"); 321 | myMessage.add(1); /* add an int to the osc message */ 322 | oscP5.send(myMessage, myRemoteLocation); 323 | prevSeqNum++; 324 | 325 | if (prevSeqNum > baseMaxRange) { 326 | prevSeqNum = baseMinRange; 327 | } 328 | } 329 | } 330 | prevRandNum = randNum; 331 | baseLastTimer = millis(); 332 | } 333 | 334 | //If volume is BELOW threshold 335 | if ((myAudioFFT.getAvg(base) * myAudioAmp) * myAudioIndexAmp < baseThreshold && baseTimer > baseTimerThreshold && baseOscToggle==true && basePeakToggle == false) { 336 | if (baseTimer > baseTimerThreshold) { 337 | if (baseClipsColumnsEffect.getValue() == 0) { // Trig clips (not columns) 338 | for (int j=0; j baseMaxRange) { 352 | prevSeqNum = baseMinRange; 353 | } 354 | } else if (baseClipsColumnsEffect.getValue() == 1 ) { //Trig entire columns 355 | 356 | if (baseSequentialOrRandom.getValue() == 0) { 357 | baseClipNumber = sequentialOrder(prevSeqNum); 358 | } else if (baseSequentialOrRandom.getValue() == 1) { 359 | baseClipNumber = randomNoDublicates(baseMinRange, baseMaxRange, prevRandNum); 360 | } 361 | 362 | OscMessage myMessage = new OscMessage("/track" + baseClipNumber + "/connect"); 363 | myMessage.add(1); /* add an int to the osc message */ 364 | oscP5.send(myMessage, myRemoteLocation); 365 | prevSeqNum++; 366 | 367 | if (prevSeqNum > baseMaxRange) { 368 | prevSeqNum = baseMinRange; 369 | } 370 | } 371 | } 372 | prevRandNum = randNum; 373 | baseLastTimer = millis(); 374 | } 375 | } 376 | myAudioIndexAmp+=myAudioIndexStep; 377 | } 378 | myAudioIndexAmp = myAudioIndex; 379 | 380 | //Audio max line 381 | stroke(#FF3300); 382 | noFill(); 383 | line(stageMargin, stageMargin+myAudioMax, stageMargin + rectSize*snareMax + rectSize, stageMargin+myAudioMax); 384 | 385 | //baseThreshold line 386 | strokeWeight(4); 387 | stroke(baseColor, 122); 388 | line(stageMargin + rectSize*baseMin, 100+baseThreshold, stageMargin + rectSize*baseMax+rectSize, 100+baseThreshold); 389 | 390 | //snareThreshold line 391 | stroke(snareColor, 122); 392 | line(stageMargin + rectSize*snareMin, 100+snareThreshold, stageMargin + rectSize*snareMax + rectSize, 100+snareThreshold); 393 | 394 | drawTimer(width/2-75, 300, snareTimer, snareTimerThreshold, "READY TO TRIG"); //Draw snareTimer 395 | drawTimer(0, 300, baseTimer, baseTimerThreshold, "READY TO TRIG"); //Draw baseTimer 396 | snareTimer = millis() - snareLastTimer; 397 | baseTimer = millis() - baseLastTimer; 398 | 399 | 400 | //Warning text 401 | if (snareOscToggle && baseOscToggle && (baseClipsColumnsEffect.getValue() == 1) && (snareClipsColumnsEffect.getValue() == 1)) { 402 | fill(255, 0, 0); 403 | text("Warning! Both snare and base \nare set to control columns... ", width/2 +100, height-100); 404 | } 405 | 406 | if (frameCount % 30 == 0) { 407 | println("snarePianoClip: " + snarePianoClip); 408 | println("basePianoClip: " + basePianoClip); 409 | } 410 | 411 | 412 | //PianoTrigs 413 | if (baseClipsColumnsEffect.getValue() == 3 ) pianoTrig(1, basePianoClip, baseTimerThreshold, 0); 414 | if (snareClipsColumnsEffect.getValue() == 3 ) pianoTrig(1, snarePianoClip, snareTimerThreshold, 1); 415 | } 416 | 417 | void drawTimer(int posX, int posY, int instrumentTimer, int instrumentTimerThreshold, String message) { 418 | 419 | pushMatrix(); 420 | translate(posX, posY); 421 | pushStyle(); 422 | strokeWeight(1); 423 | //Draw a small bar that indicates when you can retrig 424 | if (instrumentTimer < instrumentTimerThreshold) { 425 | fill(255, 0, 0); 426 | } else { 427 | fill(0, 255, 0); 428 | } 429 | 430 | rect(stageMargin, 0, constrain(map(instrumentTimer, 0, instrumentTimerThreshold, 0, timerWidth), 0, timerWidth), 10); 431 | stroke(255); 432 | line(stageMargin, -10, stageMargin, 20); 433 | line(stageMargin + timerWidth, -10, stageMargin + timerWidth, 20); 434 | fill(255); 435 | 436 | //textAlign(CENTER); 437 | //fill(255); 438 | //textSize(16); 439 | //text("Timer: " + instrumentTimerThreshold, (stageMargin + timerWidth)/2 + timerWidth/2, 0.5*stageMargin); 440 | 441 | textAlign(LEFT); 442 | textSize(16); 443 | if (instrumentTimer >instrumentTimerThreshold) { 444 | text(message, stageMargin, -25); 445 | } else { 446 | text("ON HOLD...", stageMargin, -25); 447 | } 448 | popStyle(); 449 | popMatrix(); 450 | } 451 | 452 | int randomNoDublicates (int min, int max, int prevRandNum) { 453 | 454 | if (min == max) { 455 | return min; 456 | } else { 457 | 458 | randNum = ceil(random(min, max)); 459 | while (randNum == prevRandNum) { 460 | randNum = int(random(min, max)); 461 | } 462 | return randNum; 463 | } 464 | } 465 | 466 | int sequentialOrder (int prevSeqNum) { 467 | int seqNum = prevSeqNum; 468 | return seqNum; 469 | } 470 | 471 | 472 | 473 | void pianoTrig(int layer, int clip, int timerThreshold, int baseOrSnare) { 474 | 475 | if (baseOrSnare == 0) { 476 | if (baseTimer < timerThreshold) { 477 | OscMessage myMessage = new OscMessage("/layer" + layer + "/clip" + clip + "/connect"); 478 | myMessage.add(1); 479 | oscP5.send(myMessage, myRemoteLocation); 480 | } else if (baseTimer >timerThreshold) { //else if (counter >frames) { 481 | OscMessage myMessage = new OscMessage("/layer" + layer + "/clip" + clip + "/connect"); 482 | myMessage.add(0); 483 | oscP5.send(myMessage, myRemoteLocation); 484 | } 485 | } else if (baseOrSnare == 1) { 486 | if (snareTimer < timerThreshold) { 487 | OscMessage myMessage = new OscMessage("/layer" + layer + "/clip" + clip + "/connect"); 488 | myMessage.add(1); 489 | oscP5.send(myMessage, myRemoteLocation); 490 | } else if (snareTimer >timerThreshold) { //else if (counter >frames) { 491 | OscMessage myMessage = new OscMessage("/layer" + layer + "/clip" + clip + "/connect"); 492 | myMessage.add(0); 493 | oscP5.send(myMessage, myRemoteLocation); 494 | } 495 | } 496 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Processing_Resolume_FFT 2 | Automatic VJ interface for FFT powered communication between Processing, Resolume Arena and a MIDI controller 3 | 4 | 5 | ![alt text](https://github.com/AndreasRef/Processing_Resolume_FFT/blob/master/gifs/code_gui.gif "GIF!") 6 | 7 | ## Tested with: 8 | Processing 3.0.1 9 | Processing 3.0.2 10 | & 11 | Resolume Arena 5.0.1 12 | 13 | Current prototype uses soundFlower to analyse internal audio playing on the computer. To react to sound files placed on your computers local disk simply change from AudioInput to Audioplayer and from minim.getLineIn(Minim.MONO) to minim.loadFile(“yourMusicFile”) like so 14 | 15 | 16 | **Global variable** 17 | AudioPlayer myAudio; 18 | //AudioInput myAudio; 19 | 20 | 21 | **Setup in minim.pde** 22 | myAudio = minim.loadFile(“yourMusicFile”); 23 | //myAudio = minim.getLineIn(Minim.MONO); 24 | 25 | 26 | ## OSC Adresses 27 | Make sure you type in the complete correct adress including slashes (e.g. */composition/link1/values*). Only works with parameters that accepts floats between 0.0-1.0 28 | 29 | 30 | ###Made by: 31 | Andreas Refsgaard for Circus Family 2016 32 | 33 | -------------------------------------------------------------------------------- /controlP5.pde: -------------------------------------------------------------------------------- 1 | void controlP5Setup() { 2 | 3 | cp5 = new ControlP5(this); 4 | 5 | PFont pfont = createFont("Helvetica", 32, true); // use true/false for smooth/no-smooth 6 | ControlFont font = new ControlFont(pfont, 14); 7 | cp5.setFont(font); 8 | //Controllers are organized from the top and down and left to right 9 | 10 | cp5.addSlider("base") 11 | .setPosition(stageMargin+35 + 50*baseMin, 40) 12 | .setWidth(rectSize*(baseMax-baseMin)) 13 | .setHeight(20) 14 | .setRange(baseMin, baseMax) 15 | .setValue(0) 16 | .setNumberOfTickMarks(baseMax-baseMin + 1) 17 | .setSliderMode(Slider.FLEXIBLE) 18 | .setColorActive(baseColor) 19 | .setColorForeground(baseColor) 20 | .setColorLabel(baseColor) 21 | ; 22 | 23 | cp5.addSlider("snare") 24 | .setPosition(stageMargin+35+50*snareMin, 70) 25 | .setWidth(rectSize*(snareMax-snareMin)) 26 | .setHeight(20) 27 | .setRange(snareMin, snareMax) 28 | .setValue(5) 29 | .setNumberOfTickMarks(snareMax-snareMin + 1) 30 | .setSliderMode(Slider.FLEXIBLE) 31 | .setColorActive(snareColor) 32 | .setColorForeground(snareColor) 33 | .setColorLabel(snareColor) 34 | ; 35 | 36 | 37 | cp5.addSlider("baseThreshold").setPosition(65, 100).setSize(20, 100).setColorForeground(baseColor).setColorActive(baseColor).setRange(100, 0).setValue(50).setColorLabel(baseColor); 38 | cp5.getController("baseThreshold").getValueLabel(); 39 | cp5.getController("baseThreshold").getCaptionLabel().align(ControlP5.CENTER, ControlP5.BOTTOM_OUTSIDE).setPaddingY(10); 40 | 41 | cp5.addSlider("snareThreshold").setPosition(width-110, 100).setSize(20, 100).setColorForeground(snareColor).setColorActive(snareColor).setRange(100, 0).setValue(50).setColorLabel(snareColor); 42 | cp5.getController("snareThreshold").getValueLabel(); 43 | cp5.getController("snareThreshold").getCaptionLabel().align(ControlP5.CENTER, ControlP5.BOTTOM_OUTSIDE).setPaddingY(10); 44 | 45 | cp5.addKnob("baseTimerThreshold").setPosition(width/2-75, 275).setRadius(25).setColorForeground(baseColor).setColorActive(baseColor).setRange(1, 1000).setValue(50).setColorLabel(baseColor); 46 | cp5.getController("baseTimerThreshold").getValueLabel().align(ControlP5.RIGHT, ControlP5.BOTTOM_OUTSIDE).setPaddingX(0); 47 | cp5.getController("baseTimerThreshold").getCaptionLabel().align(ControlP5.CENTER, ControlP5.BOTTOM_OUTSIDE).setPaddingX(0); 48 | 49 | 50 | cp5.addKnob("snareTimerThreshold").setPosition(width - stageMargin- 50, 275).setRadius(25).setColorForeground(snareColor).setColorActive(snareColor).setRange(1, 1000).setValue(50).setColorLabel(snareColor); 51 | cp5.getController("snareTimerThreshold").getValueLabel().align(ControlP5.RIGHT, ControlP5.BOTTOM_OUTSIDE).setPaddingX(0); 52 | cp5.getController("snareTimerThreshold").getCaptionLabel().align(ControlP5.CENTER, ControlP5.BOTTOM_OUTSIDE).setPaddingX(0); 53 | 54 | 55 | Group BASEOSC = cp5.addGroup("BASEOSC") 56 | .setPosition(stageMargin-25, 400) 57 | .setBarHeight(18) 58 | .setSize(350, 200) 59 | .activateEvent(true) 60 | .setColorBackground(0) 61 | .setColorLabel(snareColor) 62 | //.setColorForeground(snareColor) 63 | .setBackgroundColor(color(255, 80)) 64 | //.setBackgroundHeight(100) 65 | .setLabel("BASE OSC Controls") 66 | ; 67 | 68 | baseClipsColumnsEffect = cp5.addRadioButton("baseClipsColumnsEffect") 69 | .setPosition(10, 10) 70 | .setSize(20, 15) 71 | .setColorForeground(color(120)) 72 | .setColorActive(color(255)) 73 | .setColorLabel(color(255)) 74 | .addItem("Clips", 0) 75 | .addItem("Columns", 1) 76 | .addItem("Effect", 2) 77 | .addItem("Pianop", 3) 78 | .setNoneSelectedAllowed(false) 79 | .activate(0) 80 | .setGroup(BASEOSC) 81 | ; 82 | 83 | 84 | baseLayers = cp5.addCheckBox("baseLayers") 85 | .setPosition(250, 10) 86 | .setSize(20, 15) 87 | .setColorForeground(color(120)) 88 | .setColorActive(color(255)) 89 | .setColorLabel(color(255)) 90 | .addItem("Layer3", 3) 91 | .addItem("Layer2", 2) 92 | .addItem("Layer1", 1) 93 | .setNoneSelectedAllowed(false) 94 | .activate(2) 95 | .setGroup(BASEOSC) 96 | ; 97 | 98 | 99 | 100 | baseOscRange = cp5.addRange("baseRange") 101 | // disable broadcasting since setRange and setRangeValues will trigger an event 102 | .setBroadcast(false) 103 | .setPosition(10, 85) 104 | .setSize(215, 10) 105 | .setHandleSize(20) 106 | .setRange(1, 6) 107 | .setDecimalPrecision(0) 108 | // after the initialization we turn broadcast back on again 109 | .setBroadcast(true) 110 | .setLowValue(1) 111 | .setHighValue(6) 112 | .setGroup(BASEOSC) 113 | ; 114 | 115 | 116 | 117 | baseSequentialOrRandom = cp5.addRadioButton("baseSequentialOrRandom") 118 | .setPosition(125, 10) 119 | .setSize(20, 15) 120 | .setColorForeground(color(120)) 121 | .setColorActive(color(255)) 122 | .setColorLabel(color(255)) 123 | .addItem("_Sequential", 0) 124 | .addItem("_Random", 1) 125 | .setNoneSelectedAllowed(false) 126 | .activate(1) 127 | .setGroup(BASEOSC) 128 | ; 129 | 130 | 131 | 132 | 133 | cp5.addTextfield("BaseOscAdress") 134 | .setPosition(10, 110) 135 | .setSize(215, 30) 136 | .setFocus(false) 137 | .setLabel("OSC Effect Adress") 138 | .setGroup(BASEOSC) 139 | ; 140 | 141 | 142 | cp5.addToggle("basePeakToggle") 143 | .setPosition(235, 110) 144 | .setSize(30, 20) 145 | .setGroup(BASEOSC) 146 | .setLabel("Peak") 147 | ; 148 | 149 | 150 | cp5.addToggle("baseOscToggle") 151 | .setPosition(280, 110) 152 | .setSize(30, 20) 153 | .setGroup(BASEOSC) 154 | .setLabel("On/Off") 155 | ; 156 | 157 | 158 | cp5.addSlider("basePianoClip") 159 | .setPosition(10, 170) 160 | .setSize(212, 10) 161 | .setRange(1, 6) // values can range from big to small as well 162 | .setValue(1) 163 | .setNumberOfTickMarks(6) 164 | .setSliderMode(Slider.FLEXIBLE) 165 | .setGroup(BASEOSC) 166 | ; 167 | 168 | 169 | 170 | Group SNAREOSC = cp5.addGroup("SNAREOSC") 171 | .setPosition(width/2+25, 400) 172 | .setBarHeight(18) 173 | .setSize(350, 200) 174 | .activateEvent(true) 175 | .setColorBackground(0) 176 | .setColorLabel(snareColor) 177 | //.setColorForeground(snareColor) 178 | .setBackgroundColor(color(255, 80)) 179 | //.setBackgroundHeight(100) 180 | .setLabel("SNARE OSC Controls") 181 | ; 182 | 183 | snareClipsColumnsEffect = cp5.addRadioButton("snareClipsColumnsEffect") 184 | .setPosition(10, 10) 185 | .setSize(20, 15) 186 | .setColorForeground(color(120)) 187 | .setColorActive(color(255)) 188 | .setColorLabel(color(255)) 189 | .addItem("CLIPS", 0) 190 | .addItem("COLUMNS", 1) 191 | .addItem("EFFECT", 2) 192 | .addItem("PIANO", 3) 193 | .setNoneSelectedAllowed(false) 194 | .activate(0) 195 | .setGroup(SNAREOSC) 196 | ; 197 | 198 | sequentialOrRandom = cp5.addRadioButton("sequentialOrRandom") 199 | .setPosition(125, 10) 200 | .setSize(20, 15) 201 | .setColorForeground(color(120)) 202 | .setColorActive(color(255)) 203 | .setColorLabel(color(255)) 204 | .addItem("Sequential", 0) 205 | .addItem("Random", 1) 206 | .setNoneSelectedAllowed(false) 207 | .activate(1) 208 | .setGroup(SNAREOSC) 209 | ; 210 | 211 | snareLayers = cp5.addCheckBox("snareLayers") 212 | .setPosition(250, 10) 213 | .setSize(20, 15) 214 | .setColorForeground(color(120)) 215 | .setColorActive(color(255)) 216 | .setColorLabel(color(255)) 217 | .addItem("Layer 3", 3) 218 | .addItem("Layer 2", 2) 219 | .addItem("Layer 1", 1) 220 | .setNoneSelectedAllowed(false) 221 | .activate(2) 222 | .setGroup(SNAREOSC) 223 | ; 224 | 225 | 226 | snareOscRange = cp5.addRange("snareRange") 227 | // disable broadcasting since setRange and setRangeValues will trigger an event 228 | .setBroadcast(false) 229 | .setPosition(10, 85) 230 | .setSize(215, 10) 231 | .setHandleSize(20) 232 | .setRange(1, 6) 233 | .setDecimalPrecision(0) 234 | // after the initialization we turn broadcast back on again 235 | .setBroadcast(true) 236 | .setLowValue(1) 237 | .setHighValue(6) 238 | //.snapToTickMarks(true) 239 | //.setColorForeground(snareColor) 240 | //.setColorBackground(0) 241 | .setGroup(SNAREOSC) 242 | ; 243 | 244 | 245 | cp5.addTextfield("SnareOscAdress") 246 | .setPosition(10, 110) 247 | .setSize(215, 30) 248 | //.setFont() 249 | .setFocus(false) 250 | //.setColor(color(255,0,0)) 251 | //.setFont(createFont("arial",14)) 252 | .setLabel("OSC Effect Adress") 253 | .setGroup(SNAREOSC) 254 | ; 255 | 256 | 257 | cp5.addToggle("snarePeakToggle") 258 | .setPosition(245, 110) 259 | .setSize(30, 20) 260 | .setGroup(SNAREOSC) 261 | .setLabel("Peak") 262 | ; 263 | 264 | 265 | cp5.addToggle("snareOscToggle") 266 | .setPosition(295, 110) 267 | .setSize(30, 20) 268 | .setGroup(SNAREOSC) 269 | .setLabel("On/Off") 270 | ; 271 | 272 | cp5.addSlider("snarePianoClip") 273 | .setPosition(10, 170) 274 | .setSize(212, 10) 275 | .setRange(1, 6) // values can range from big to small as well 276 | .setValue(1) 277 | .setNumberOfTickMarks(6) 278 | .setSliderMode(Slider.FLEXIBLE) 279 | .setGroup(SNAREOSC) 280 | ; 281 | 282 | 283 | Group FFT = cp5.addGroup("FFT") 284 | .setPosition(stageMargin-25, 625) 285 | .setBarHeight(18) 286 | .setWidth(350) 287 | .activateEvent(true) 288 | .setBackgroundColor(color(255, 80)) 289 | .setBackgroundHeight(100) 290 | .setLabel("FFT Variables") 291 | ; 292 | 293 | 294 | int fftOffsetX = 150; 295 | 296 | cp5.addSlider("myAudioAmp").setPosition(fftOffsetX, 10).setSize(175, 10).setRange(0, 15000).setValue(6500).setGroup(FFT); 297 | cp5.getController("myAudioAmp").getValueLabel().align(ControlP5.RIGHT, ControlP5.BOTTOM_OUTSIDE).setPaddingX(0); 298 | cp5.getController("myAudioAmp").getCaptionLabel().align(ControlP5.LEFT, ControlP5.BOTTOM_OUTSIDE).setPaddingX(0); 299 | 300 | cp5.addSlider("myAudioIndex").setPosition(fftOffsetX, 40).setSize(175, 10).setRange(0.0, 1.0).setValue(0.2).setGroup(FFT); 301 | cp5.getController("myAudioIndex").getValueLabel().align(ControlP5.RIGHT, ControlP5.BOTTOM_OUTSIDE).setPaddingX(0); 302 | cp5.getController("myAudioIndex").getCaptionLabel().align(ControlP5.LEFT, ControlP5.BOTTOM_OUTSIDE).setPaddingX(0); 303 | 304 | cp5.addSlider("myAudioIndexStep").setPosition(fftOffsetX, 70).setSize(175, 10).setRange(0.0, 1.0).setValue(0.5).setGroup(FFT); 305 | cp5.getController("myAudioIndexStep").getValueLabel().align(ControlP5.RIGHT, ControlP5.BOTTOM_OUTSIDE).setPaddingX(0); 306 | cp5.getController("myAudioIndexStep").getCaptionLabel().align(ControlP5.LEFT, ControlP5.BOTTOM_OUTSIDE).setPaddingX(0); 307 | 308 | 309 | fftWindow = cp5.addRadioButton("fftWindow") 310 | .setPosition(10, 10) 311 | .setSize(20, 15) 312 | .setColorForeground(color(120)) 313 | .setColorActive(color(255)) 314 | .setColorLabel(color(255)) 315 | .addItem("NONE", 0) 316 | .addItem("BARTLETT", 1) 317 | .addItem("BARTLETTHANN", 2) 318 | .addItem("BLACKMAN", 3) 319 | .addItem("GAUSS", 4) 320 | .setNoneSelectedAllowed(false) 321 | .setCaptionLabel("FFT Window Type") 322 | .activate(0) 323 | .setGroup(FFT) 324 | ; 325 | 326 | cp5.addBang("bang").setPosition(width-75, height-75).setSize(40, 40).setLabel("reset"); 327 | cp5.getController("bang").getCaptionLabel().align(ControlP5.CENTER, ControlP5.BOTTOM_OUTSIDE); 328 | } 329 | 330 | 331 | public void bang() { 332 | //This is not updated right now... 333 | cp5.get("myAudioAmp").setValue(65); 334 | cp5.get("snareThreshold").setValue(50); 335 | cp5.get("snareTimerThreshold").setValue(50); 336 | cp5.get("myAudioIndex").setValue(0.2); 337 | cp5.get("myAudioIndexStep").setValue(0.5); 338 | cp5.get("fftWindow").setValue(4); 339 | snare = 5; 340 | fftWindow.activate(4); 341 | } 342 | 343 | 344 | void controlEvent(ControlEvent theEvent) { 345 | if (theEvent.isFrom(snareLayers)) { 346 | 347 | print("got an event from "+snareLayers.getName()+"\t\n"); 348 | // checkbox uses arrayValue to store the state of 349 | // individual checkbox-items. usage: 350 | println(snareLayers.getArrayValue()); 351 | int col = 0; 352 | 353 | for (int i=0; i