Hid hi; HidMsg msg; Inst1 synth; Inst2 kick; Inst3 snare; Inst4 drone; Inst5 vinyl; Inst6 beat; Inst7 beat2; Inst8 beat3; Inst0 auxSynth; synth.init(); kick.init(); snare.init(); drone.init(); auxSynth.init(); vinyl.init(); beat.init(); beat2.init(); beat3.init(); // which keyboard 0 => int device; // get from command line if( me.args() ) me.arg(0) => Std.atoi => device; <<< device >>>; // open keyboard (get device number from command line) if( !hi.openKeyboard( device ) ) me.exit(); if(hi.name() != "Keychron K6" && hi.name() != "Apple Internal Keyboard / Trackpad") me.exit(); <<< "keyboard '" + hi.name() + "' ready", "" >>>; fun void printLog() { while(true) { <<< "Inst 1:", synth.printGain(), "Inst 2:", kick.printGain(), "Inst 3:", snare.printGain(), "Inst 4:", drone.printGain(), "Inst 5:", vinyl.printGain(), "Inst 6:", beat.printGain(), "Inst 7:", beat2.printGain(), "Inst 8:", beat3.printGain(), "Inst 0:", auxSynth.printGain() >>>; 500::ms => now; } } spork ~ printLog(); // infinite event loop while( true ) { // wait on event hi => now; // get one or more messages while( hi.recv( msg ) ) { if(msg.isButtonDown()) { // <<< "type: down", msg.which, "(code)", msg.key, "(usb key)", msg.ascii, "(ascii)" >>>; if(msg.ascii == 81) me.exit(); // 1 (Synth) if(msg.ascii == 49) { while(true) { <<< "Inst 1: [SELECTED]" >>>; // wait on event hi => now; hi.recv(msg); if(msg.ascii == 80) { <<< "MAIN MENU [SELECTED]" >>>; break; } if(msg.ascii == 81) me.exit(); msg.ascii => synth.ascii; // synth.print_ascii(); 100::ms => now; } } // 2 (Kick Drum) if(msg.ascii == 50) { while(true) { <<< "Inst 2: [SELECTED]" >>>; // wait on event hi => now; hi.recv(msg); if(msg.ascii == 80) { <<< "MAIN MENU [SELECTED]" >>>; break; } if(msg.ascii == 81) me.exit(); msg.ascii => kick.ascii; // kick.print_ascii(); 100::ms => now; } } // 3 (Snare Drum) if(msg.ascii == 51) { while(true) { <<< "Inst 3: [SELECTED]" >>>; // wait on event hi => now; hi.recv(msg); if(msg.ascii == 80) { <<< "MAIN MENU [SELECTED]" >>>; break; } if(msg.ascii == 81) me.exit(); msg.ascii => snare.ascii; // snare.print_ascii(); 100::ms => now; } } // 4 (Drone) if(msg.ascii == 52) { while(true) { <<< "Inst 4: [SELECTED]" >>>; // wait on event hi => now; hi.recv(msg); if(msg.ascii == 80) { <<< "MAIN MENU [SELECTED]" >>>; break; } if(msg.ascii == 81) me.exit(); msg.ascii => drone.ascii; // drone.print_ascii(); 100::ms => now; } } // 5 (Vinyl) if(msg.ascii == 53) { while(true) { <<< "Inst 5: [SELECTED]" >>>; // wait on event hi => now; hi.recv(msg); if(msg.ascii == 80) { <<< "MAIN MENU [SELECTED]" >>>; break; } if(msg.ascii == 81) me.exit(); msg.ascii => vinyl.ascii; // vinyl.print_ascii(); 100::ms => now; } } // 6 (Beat 1) if(msg.ascii == 54) { while(true) { <<< "Inst 6: [SELECTED]" >>>; // wait on event hi => now; hi.recv(msg); if(msg.ascii == 80) { <<< "MAIN MENU [SELECTED]" >>>; break; } if(msg.ascii == 81) me.exit(); msg.ascii => beat.ascii; // beat.print_ascii(); 100::ms => now; } } // 7 (Beat 2) if(msg.ascii == 55) { while(true) { <<< "Inst 7: [SELECTED]" >>>; // wait on event hi => now; hi.recv(msg); if(msg.ascii == 80) { <<< "MAIN MENU [SELECTED]" >>>; break; } if(msg.ascii == 81) me.exit(); msg.ascii => beat2.ascii; // beat.print_ascii(); 100::ms => now; } } // 8 (Beat 3) if(msg.ascii == 56) { while(true) { <<< "Inst 8: [SELECTED]" >>>; // wait on event hi => now; hi.recv(msg); if(msg.ascii == 80) { <<< "MAIN MENU [SELECTED]" >>>; break; } if(msg.ascii == 81) me.exit(); msg.ascii => beat3.ascii; // beat.print_ascii(); 100::ms => now; } } // 0 (Aux Synth) if(msg.ascii == 48) { while(true) { <<< "Inst 0: [SELECTED]" >>>; // wait on event hi => now; hi.recv(msg); if(msg.ascii == 80) { <<< "MAIN MENU [SELECTED]" >>>; break; } if(msg.ascii == 81) me.exit(); msg.ascii => auxSynth.ascii; // auxSynth.print_ascii(); 100::ms => now; } } } } } class Inst1 { // construct patch TriOsc tri => ADSR e => LPF low => DelayL delay => PRCRev rev => Pan2 pan => dac; // array of possible frequencies 12 => int offset; [ 60+offset, 64+offset, 64-offset, 67+offset, 48+offset ] @=> int scale[]; [ 60+offset, 63+offset, 63-offset, 72+offset, 67+offset ] @=> int scaleMinor[]; // set parameters for UGens 0 => tri.gain; 0 => pan.pan; 1 => low.Q; 1000 => low.freq; 500::ms => delay.max => delay.delay; .4 => rev.mix; e.set( 80::ms, 50::ms, .2, 100::ms ); // class variable to keep track of keypresses int ascii; 0 => int minor; fun void gainController() { while(true) { while(ascii == 85) { tri.gain() + .02 => tri.gain; // <<< "Inst1:", tri.gain() >>>; 100::ms => now; } while(ascii == 68) { if(tri.gain() > 0.02) { tri.gain() - .02 => tri.gain; // <<< "Inst1:", tri.gain() >>>; } 100::ms => now; } while(ascii == 32) { tri.gain() => tri.gain; // <<< "Inst1:", tri.gain() >>>; 100::ms => now; } if(ascii == 77) { // <<< "[Inst 1] Minor Mode Activated" >>>; 1 => minor; } if(ascii == 0) { // <<< "[Inst 1] Minor Mode Activated" >>>; 0 => minor; } 1::ms => now; } } fun void modulatePan() { 10::ms => dur T; 0.0 => float t; while(true) { Math.sin(t) => pan.pan; T / second * 2.5 +=> t; T => now; Math.random2(0, 15)::ms => now; } } fun void start() { while(true) { if(minor) { Std.mtof(scaleMinor[Math.random2(0, 4)]) => tri.freq; } else { Std.mtof(scale[ Math.random2(0,4) ]) => tri.freq; } e.keyOn(); 200::ms => now; e.keyOff(); e.releaseTime() => now; 20::ms => now; } } fun void init() { spork ~ start(); spork ~ gainController(); spork ~ modulatePan(); } fun void print_ascii() { <<< "Inst1:", ascii >>>; } fun float printGain() { return tri.gain(); } } class Inst2 { // construct the patch SndBuf buf => LPF low => Gain g => dac; int ascii; 1 => low.Q; 1000 => low.freq; fun void start() { // start with kick drum muted 0 => g.gain; // this synchronizes to period 1::second => dur T; T - (now % T) => now; // read in the file me.dir() + "data/kick.wav" => buf.read; // time loop while( true ) { // set the play position to beginning 0 => buf.pos; // randomize gain a bit // Math.random2f(.8,.9) => buf.gain; // advance time 1.5::T => now; 0 => buf.pos; .5::T => now; 0 => buf.pos; 2::T => now; } } fun void gainController() { while(true) { while(ascii == 85) { g.gain() + .02 => g.gain; // <<< "Inst2:", g.gain() >>>; 100::ms => now; } while(ascii == 68) { if(g.gain() > 0.02) { g.gain() - .02 => g.gain; // <<< "Inst2:", g.gain() >>>; } 100::ms => now; } while(ascii == 32) { g.gain() => g.gain; // <<< "Inst2:", g.gain() >>>; 100::ms => now; } 1::ms => now; } } fun void print_ascii() { <<< "Inst2:", ascii >>>; } fun void init() { spork ~ start(); spork ~ gainController(); } fun float printGain() { return g.gain(); } } class Inst3 { // construct the patch SndBuf buf => Gain g => dac; int ascii; // where we actually want to start (in # of sample frames) 100 => int where; fun void start() { // start with kick drum muted 0 => g.gain; // this synchronizes to period 1::second => dur T; T - (now % T) => now; // read in the file me.dir() + "data/snare-hop.wav" => buf.read; // time loop while( true ) { // note: Math.randomf() returns value between 0 and 1 if( Math.randomf() > .25 ) { // set play position to 'where' where => buf.pos; // advance time 2::T => now; } else { where => buf.pos; .75::T => now; .8 => buf.gain; where => buf.pos; 1.25::T => now; } } } fun void gainController() { while(true) { while(ascii == 85) { g.gain() + .02 => g.gain; // <<< "Inst3:", g.gain() >>>; 100::ms => now; } while(ascii == 68) { if(g.gain() > 0.02) { g.gain() - .02 => g.gain; // <<< "Inst3:", g.gain() >>>; } 100::ms => now; } while(ascii == 32) { g.gain() => g.gain; // <<< "Inst3:", g.gain() >>>; 100::ms => now; } 1::ms => now; } } fun void print_ascii() { <<< "Inst3:", ascii >>>; } fun void init() { spork ~ start(); spork ~ gainController(); } fun float printGain() { return g.gain(); } } class Inst4 { // construct patch SawOsc root => ADSR e => LPF low => DelayL delay => PRCRev rev => Pan2 pan => dac; SawOsc third => e; // array of possible frequencies 12 => int offset; [ 60+offset, 72+offset, 55+offset, 67+offset, 48+offset ] @=> int scale[]; [ 63+offset, 63-offset, 63+(2 * offset), 55+offset, 67+offset ] @=> int scaleMinor[]; [ 64+offset, 64-offset, 64+(2 * offset), 55+offset, 67+offset ] @=> int scaleMajor[]; // set parameters for UGens 0 => root.gain; 0 => third.gain; 0 => pan.pan; 1 => low.Q; 1000 => low.freq; 1200::ms => delay.max => delay.delay; .6 => rev.mix; e.set( 100::ms, 800::ms, .8, 2100::ms ); // class variable to keep track of keypresses int ascii; 0 => int minor; fun void gainController() { while(true) { while(ascii == 85) { root.gain() + .02 => root.gain; third.gain() + .02 => third.gain; // <<< "Inst4:", root.gain() >>>; 100::ms => now; } while(ascii == 68) { if(root.gain() > 0.02 && third.gain() > 0.02) { root.gain() - .02 => root.gain; third.gain() - .02 => third.gain; // <<< "Inst4:", root.gain() >>>; } 100::ms => now; } while(ascii == 32) { root.gain() => root.gain; third.gain() => third.gain; // <<< "Inst4:", root.gain() >>>; 100::ms => now; } if(ascii == 77) { // <<< "[Inst 4] Minor Mode Activated" >>>; 1 => minor; } if(ascii == 0) { // <<< "[Inst 4] Minor Mode Activated" >>>; 0 => minor; } 1::ms => now; } } fun void modulatePan() { 10::ms => dur T; 0.0 => float t; while(true) { Math.sin(t) => pan.pan; T / second * 2.5 +=> t; T => now; Math.random2(0, 15)::ms => now; } } fun void start() { while(true) { if(minor) { Std.mtof(scale[ Math.random2(0,4) ]) => root.freq; Std.mtof(scaleMinor[ Math.random2(0,4) ]) => third.freq; } else { Std.mtof(scale[ Math.random2(0,4) ]) => root.freq; Std.mtof(scaleMajor[ Math.random2(0,4) ]) => third.freq; } e.keyOn(); 900::ms => now; e.keyOff(); e.releaseTime() => now; if(Math.random2(0, 1)) { 1000::ms => now; } else { 250::ms => now; } } } fun void init() { spork ~ start(); spork ~ gainController(); //spork ~ modulatePan(); } fun void print_ascii() { <<< "Inst4:", ascii >>>; } fun float printGain() { return root.gain(); } } class Inst5 { // construct patch SndBuf record => PRCRev rev => dac; SndBuf super8 => rev; // set parameters for UGens 0 => record.gain; 0 => super8.gain; me.dir() + "data/vinyl.wav" => record.read; me.dir() + "data/film.wav" => super8.read; 1 => record.rate; 1 => super8.rate; .08 => rev.mix; // class variable to keep track of keypresses int ascii; fun void gainController() { while(true) { while(ascii == 85) { record.gain() + .1 => record.gain; super8.gain() + .02 => super8.gain; // <<< "Inst5:", record.gain() >>>; 100::ms => now; } while(ascii == 68) { if(record.gain() > 0.1 && super8.gain() > 0.02) { record.gain() - .1 => record.gain; super8.gain() - .02 => super8.gain; // <<< "Inst5:", record.gain() >>>; } 100::ms => now; } while(ascii == 32) { record.gain() => record.gain; super8.gain() => super8.gain; // <<< "Inst5:", record.gain() >>>; 100::ms => now; } 1::ms => now; } } fun void startRecord() { while(true) { 0 => record.pos; record.length() => now; } } fun void startSuper8() { while(true) { 0 => super8.pos; super8.length() => now; } } fun void init() { spork ~ startRecord(); spork ~ startSuper8(); spork ~ gainController(); } fun void print_ascii() { <<< "Inst5:", ascii >>>; } fun float printGain() { return record.gain(); } } class Inst6 { // construct patch SndBuf buffy => dac; // set parameters for UGens 0 => buffy.gain; me.dir() + "data/voice.wav" => buffy.read; 1 => buffy.rate; // class variable to keep track of keypresses int ascii; // this synchronizes to period 1::second => dur T; T - (now % T) => now; fun void gainController() { while(true) { while(ascii == 85) { buffy.gain() + .02 => buffy.gain; 100::ms => now; } while(ascii == 68) { if(buffy.gain() > 0.02) { buffy.gain() - .1 => buffy.gain; } 100::ms => now; } while(ascii == 32) { buffy.gain() => buffy.gain; 100::ms => now; } 1::ms => now; } } fun void start() { while(true) { 1.5::T => now; 0 => buffy.pos; // advance time 1.5::T => now; // vocalBeat.length() => now; } } fun void init() { spork ~ start(); spork ~ gainController(); } fun void print_ascii() { <<< "Inst6:", ascii >>>; } fun float printGain() { return buffy.gain(); } } class Inst7 { // construct patch SndBuf buffy => dac; // set parameters for UGens 0 => buffy.gain; me.dir() + "data/snare1.wav" => buffy.read; 1 => buffy.rate; // class variable to keep track of keypresses int ascii; // this synchronizes to period 1::second => dur T; T - (now % T) => now; fun void gainController() { while(true) { while(ascii == 85) { buffy.gain() + .02 => buffy.gain; 100::ms => now; } while(ascii == 68) { if(buffy.gain() > 0.02) { buffy.gain() - .1 => buffy.gain; } 100::ms => now; } while(ascii == 32) { buffy.gain() => buffy.gain; 100::ms => now; } 1::ms => now; } } fun void start() { while(true) { 0 => buffy.pos; // advance time 1::T => now; // vocalBeat.length() => now; } } fun void init() { spork ~ start(); spork ~ gainController(); } fun void print_ascii() { <<< "Inst7:", ascii >>>; } fun float printGain() { return buffy.gain(); } } class Inst8 { // construct patch SndBuf buffy => dac; // set parameters for UGens 0 => buffy.gain; me.dir() + "data/snare2.wav" => buffy.read; 1 => buffy.rate; // class variable to keep track of keypresses int ascii; // this synchronizes to period 1::second => dur T; T - (now % T) => now; fun void gainController() { while(true) { while(ascii == 85) { buffy.gain() + .02 => buffy.gain; 100::ms => now; } while(ascii == 68) { if(buffy.gain() > 0.02) { buffy.gain() - .1 => buffy.gain; } 100::ms => now; } while(ascii == 32) { buffy.gain() => buffy.gain; 100::ms => now; } 1::ms => now; } } fun void start() { while(true) { .75::T => now; 0 => buffy.pos; // advance time 1.25::T => now; // vocalBeat.length() => now; } } fun void init() { spork ~ start(); spork ~ gainController(); } fun void print_ascii() { <<< "Inst8:", ascii >>>; } fun float printGain() { return buffy.gain(); } } class Inst0 { // construct patch SawOsc tri => ADSR e => LPF low => DelayL delay => PRCRev rev => Pan2 pan => dac; // array of possible frequencies 12 => int offset; [ 60+offset, 64+offset, 64-offset, 67+offset, 48+offset ] @=> int scale[]; [ 60+offset, 63+offset, 63-offset, 72+offset, 67+offset ] @=> int scaleMinor[]; // set parameters for UGens 0 => tri.gain; 0 => pan.pan; 1 => low.Q; 1000 => low.freq; 500::ms => delay.max => delay.delay; .4 => rev.mix; e.set( 80::ms, 50::ms, .2, 100::ms ); // class variable to keep track of keypresses int ascii; 0 => int minor; fun void gainController() { while(true) { while(ascii == 85) { tri.gain() + .02 => tri.gain; // <<< "Inst0:", tri.gain() >>>; 100::ms => now; } while(ascii == 68) { if(tri.gain() > 0.02) { tri.gain() - .02 => tri.gain; // <<< "Inst0:", tri.gain() >>>; } 100::ms => now; } while(ascii == 32) { tri.gain() => tri.gain; // <<< "Inst0:", tri.gain() >>>; 100::ms => now; } if(ascii == 77) { // <<< "[Inst 0] Minor Mode Activated" >>>; 1 => minor; } if(ascii == 0) { // <<< "[Inst 0] Minor Mode Activated" >>>; 0 => minor; } 1::ms => now; } } fun void modulatePan() { 10::ms => dur T; 0.0 => float t; while(true) { Math.sin(t) => pan.pan; T / second * 2.5 +=> t; T => now; Math.random2(0, 15)::ms => now; } } fun void start() { while(true) { if(minor) { Std.mtof(scaleMinor[Math.random2(0, 4)]) => tri.freq; } else { Std.mtof(scale[ Math.random2(0,4) ]) => tri.freq; } e.keyOn(); 200::ms => now; e.keyOff(); e.releaseTime() => now; 20::ms => now; } } fun void init() { spork ~ start(); spork ~ gainController(); spork ~ modulatePan(); } fun void print_ascii() { <<< "Inst0:", ascii >>>; } fun float printGain() { return tri.gain(); } }