/** * Read about this app at my blog. */ import controlP5.*; import ddf.minim.signals.*; import ddf.minim.*; import ddf.minim.analysis.*; import ddf.minim.effects.*; import ddf.minim.ugens.*; Minim minim; AudioOutput mainOut; Summer melodyBus; Multiplier melodyVolume; Summer bassBus; Multiplier bassVolume; ControlP5 gui; DropdownList melodyWave; DropdownList bassWave; DropdownList currentKey; DropdownList currentScale; public float Tempo = 80; public boolean Kick = true; public boolean Snare = true; public boolean Hat = true; public float MelodyAmp = 0.5f; public float BassAmp = 0.9f; public float Shuffle = 0.f; float[] noteProb = new float[] { 1.0f, 0.2f, 1.0f, 0.5f, 1.0f, 0.3f, 1.0f, 0.33f, 1.0f, 0.25f, 1.0f, 0.22f, 1.0f, 0.27f, 1.0f, 0.4f }; float[] bassProb = new float[] { 1.0f, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f, 0.5f, 0.f, 1.f, 0.f, 0.f, 1.f, 0.f, 1.f, 0.f }; // called when the Randomize! bang is clicked. public void Randomize() { for(int i = 0; i < noteProb.length; ++i) { noteProb[i] = random( 0.f, 1.f ); gui.controller("M" + (i+1)).setValue( noteProb[i] ); bassProb[i] = random( 0.f, 1.f ); gui.controller("B" + (i+1)).setValue( bassProb[i] ); } } // called when any control events are fired. public void controlEvent( ControlEvent theEvent ) { int index = theEvent.controller().id(); String name = theEvent.controller().name(); if ( name.length() <= 3 ) { if ( name.startsWith("M") ) { noteProb[ index ] = theEvent.controller().value(); } else if ( name.startsWith("B") ) { bassProb[ index ] = theEvent.controller().value(); } } } void setup() { size( 1000, 400 ); colorMode(HSB, 360, 1, 1); gui = new ControlP5(this); int sliderHeight = 35; int sliderWidth = 36; int sliderSpacing = 55; int sliderStartY = 75; gui.addTextlabel("mproblabel", "Melody Note Probabilities", 20, 65); gui.addTextlabel("bproblabel", "Bass Note Probabilities", 20, 65 + sliderHeight + 25); int xpos = 0; for(int i = 0; i < noteProb.length; ++i ) { if ( i % 4 == 0 ) xpos += 20; gui.addSlider( "M" + (i + 1), 0.f, 1.f, noteProb[i], xpos, sliderStartY, sliderWidth, sliderHeight ).setId( i ); gui.addSlider( "B" + (i + 1), 0.f, 1.f, bassProb[i], xpos, sliderHeight + 25 + sliderStartY, sliderWidth, sliderHeight ).setId( i ); xpos += sliderSpacing; } xpos = 20; gui.addTextlabel("tlabel", "Tempo", xpos, 20); Numberbox tempoBox = gui.addNumberbox( "Tempo", Tempo, xpos, 30, 30, 15 ); tempoBox.setLabel(""); tempoBox.setMin( 1.f ); tempoBox.setDecimalPrecision( 0 ); tempoBox.setDirection( ControlP5.HORIZONTAL ); //tempoBox.setMax( 400.f ); xpos += 45; gui.addTextlabel("shufflabel", "Shuffle", xpos, 20); gui.addSlider("Shuffle", 0.f, 1.f, Shuffle, xpos, 30, 40, 15).setLabel(""); xpos += 55; gui.addTextlabel("klabel", "Kick", xpos, 20 ); gui.addToggle("Kick", Kick, xpos, 30, 15, 15 ).setLabel(""); xpos += 30; gui.addTextlabel("slabel", "Snare", xpos, 20 ); gui.addToggle("Snare", Snare, xpos, 30, 15, 15 ).setLabel(""); xpos += 30; gui.addTextlabel("hlabel", "Hat", xpos, 20 ); gui.addToggle("Hat", Hat, xpos, 30, 15, 15 ).setLabel(""); xpos += 30; gui.addTextlabel("mwave", "Melody Waveform", xpos, 20); melodyWave = gui.addDropdownList("wave1", xpos, 40, 80, 150); melodyWave.hideScrollbar(); melodyWave.setLabel("Sine"); melodyWave.activateEvent( false ); melodyWave.addItem("Sine", 0); melodyWave.addItem("Triangle", 1); melodyWave.addItem("Saw", 2); melodyWave.addItem("Square", 3); melodyWave.addItem("Pulse", 4); melodyWave.addItem("Wave4", 5); melodyWave.addItem("Wave8", 6); melodyWave.addItem("Wave16", 7); melodyWave.addItem("Wave32", 8); xpos += 100; gui.addTextlabel("bwave", "Bass Waveform", xpos, 20); bassWave = gui.addDropdownList("wave2", xpos, 40, 80, 150); bassWave.hideScrollbar(); bassWave.setLabel("Sine"); bassWave.activateEvent( false ); bassWave.addItem("Sine", 0); bassWave.addItem("Triangle", 1); bassWave.addItem("Saw", 2); bassWave.addItem("Square", 3); bassWave.addItem("Pulse", 4); bassWave.addItem("Wave4", 5); bassWave.addItem("Wave8", 6); bassWave.addItem("Wave16", 7); bassWave.addItem("Wave32", 8); xpos += 100; gui.addTextlabel("mamplabel", "Melody Volume", xpos, 20 ); gui.addSlider("MelodyAmp", 0.f, 1.f, MelodyAmp, xpos, 30, 65, 15).setLabel(""); xpos += 80; gui.addTextlabel("bassamplabel", "Bass Volume", xpos, 20 ); gui.addSlider("BassAmp", 0.f, 1.f, BassAmp, xpos, 30, 65, 15).setLabel(""); xpos += 80; gui.addTextlabel("keylabel", "Key", xpos, 20); currentKey = gui.addDropdownList("KeyList", xpos, 40, 45, 250); currentKey.hideScrollbar(); currentKey.setLabel("C"); currentKey.addItem("C", 0); currentKey.addItem("D-flat", 1); currentKey.addItem("D", 2); currentKey.addItem("E-flat", 3); currentKey.addItem("E", 4); currentKey.addItem("F", 5); currentKey.addItem("G-flat", 6); currentKey.addItem("G", 7); currentKey.addItem("A-flat", 8); currentKey.addItem("A", 9); currentKey.addItem("B-flat", 10); currentKey.addItem("B", 11); xpos += 55; gui.addTextlabel("scalelabel", "Scale", xpos, 20); currentScale = gui.addDropdownList("ScaleList", xpos, 40, 90, 300); currentScale.hideScrollbar(); currentScale.setLabel("Pentatonic"); currentScale.addItem("Pentatonic", 0); currentScale.addItem("Major", 1); currentScale.addItem("Minor Pentatonic", 2); currentScale.addItem("Natural Minor", 3 ); currentScale.addItem("Harmonic Minor", 4); currentScale.addItem("Blues", 5); xpos += 105; gui.addTextlabel("rlabel", "Randomize Probabilities", xpos, 20); gui.addBang("Randomize", xpos, 30, 15, 15).setLabel(""); minim = new Minim(this); mainOut = minim.getLineOut(); melodyBus = new Summer(); melodyVolume = new Multiplier( MelodyAmp ); melodyBus.patch( melodyVolume ).patch( mainOut ); bassBus = new Summer(); bassVolume = new Multiplier( BassAmp ); bassBus.patch( bassVolume ).patch( mainOut ); // start the loop mainOut.pauseNotes(); mainOut.setTempo( Tempo ); mainOut.playNote( 0.f, 4.0f, new Looper() ); mainOut.resumeNotes(); } ////////////////////////////////////////////////// // // DRAWING DOWN HERE // float waveSize = 50; float centerY = 275; float hueForSample( float sample ) { return map( abs(sample), 0, 1, 120, 450 ); } // draw is run many times void draw() { melodyVolume.setValue( MelodyAmp ); bassVolume.setValue( BassAmp ); // erase the window to black background( 0 ); // draw using a white stroke stroke( 255 ); // draw the waveforms for( int i = 0; i < mainOut.bufferSize() - 1; i++ ) { // find the x position of each buffer value float x1 = map( i, 0, mainOut.bufferSize(), 0, width ); float x2 = map( i+1, 0, mainOut.bufferSize(), 0, width ); // draw a line from one buffer position to the next for both channels stroke( hueForSample(mainOut.left.get(i)), 1, 1 ); line( x1, centerY - waveSize + mainOut.left.get(i)*waveSize, x2, centerY - waveSize + mainOut.left.get(i+1)*waveSize); stroke( hueForSample(mainOut.right.get(i)), 1, 1 ); line( x1, centerY + waveSize + mainOut.right.get(i)*waveSize, x2, centerY + waveSize + mainOut.right.get(i+1)*waveSize); } } // stop is run when the user presses stop void stop() { // close the AudioOutput mainOut.close(); // stop the minim object minim.stop(); super.stop(); }