// reKontakt.ck // Luke Dahl, 5/25/08 // see http://ccrma.stanford.edu/~lukedahl/ for instructions on usage. // Open Devices =========================================================> // number of the device to open (see: chuck --probe) 0 => int device; if( me.args() ) me.arg(0) => Std.atoi => device; // open midi event and message MidiIn min; MidiMsg msg; if( !min.open( device ) ) me.exit(); <<< "MIDI device:", min.num(), " -> ", min.name() >>>; // Classes ==============================================================> class kontakteBuff { 6 => int numVcs; // number of buffers (voices) within each object (used to avoid clicking) 0 => int curVc; // current buffer voice false => int rept; // repeat note, y or n? 0 => int lastRow; // last row hit 127 => int lastSlidrVal; SndBuf bufr[numVcs]; Gain g; Event padDown; 0 => int col; 1. => float gain; 1. => float gainMult; 1. => float nomRate; // the nominal rate before modification by pad pressure .5::second => dur T => dur nomT; fun Gain out(){return g;} fun void setup(int num, string fname) { for(0 => int i; i < numVcs; i++) { bufr[i]=>g; fname => bufr[i].read; bufr[i].samples() => bufr[i].pos; // avoid initial bonk } num => col; } fun void setRate(float rt) { for(0 => int i; i < numVcs; i++) { rt => bufr[i].rate; } } fun void trig() { ++curVc % numVcs => curVc; 0 => bufr[curVc].pos; } fun void noteProc(int row, int dat) { if( dat ) { if( row == lastRow) // if same pad, pick a new rate { Std.rand2f(Math.pow(2,col-1),Math.pow(2,col)) => nomRate => setRate; // 8ve range based on column } row => lastRow; if(row == 0) // top row of pads: one hit { false => rept; 1. => gain; padDown.broadcast(); } else if(row == 1) // decaying repetitions { 1. => gain; .85 => gainMult; 100::ms - (dat/127.) * 60::ms => T; true => rept; padDown.broadcast(); } else if(row == 2) // sustained rhythmic { 70::ms => T => nomT; 1. => gain; 1. => gainMult; true => rept; padDown.broadcast(); } else if(row == 3) // bottom row of pads: repeat { slidrProc(lastSlidrVal); 1. => gain; 1. => gainMult; true => rept; padDown.broadcast(); } } else // note off { if(lastRow == 2) { 0.7 => gainMult; } if(lastRow == 3) { 0.95 => gainMult; } else { false => rept;// note off } } } fun void ccProc(int row, int dat) // process aftertouch pressure { if(row == 0) // top row of pads: one hit { } else if(row == 1 || row == 3) // 2nd and 4th row: modulate rate { if( dat > 15) { (1. + .5*(dat - 15)/112.)*nomRate => setRate; } } else if(row == 2) // 3rd row: modulate T { if (dat > 15) { (1. - .8*(dat - 15)/112.)*nomT => T; } } // else if(row == 3) // bottom row //{ //} } fun void slidrProc(int dat) { dat => lastSlidrVal; dat / 128. => float rate; Math.pow(rate,0.125) => rate; (1. - rate)*250::ms + 15::ms => T; } fun void bufCtl() { while( 1 ) { padDown => now; gain => g.gain; trig(); while( rept) { trig(); T => now; gain * gainMult => gain => g.gain; } } } } // Global Variables =====================================================> // Control numbers for trigger finger int midiMsg1[44]; int midiMsg2[44]; initMidiMsg(); // other vars "pulse1.wav" => string filename; kontakteBuff bufP[4]; Pan2 pans[4]; TriOsc lfo[4]; 0. => float panAmount; 0. => float panSpeed; calcLFOspeed(); int i; // Audio Signal Path =====================================================> NRev r => dac; for(0 => i; i < 4; i++) { bufP[i].setup(i, filename); bufP[i].out() => pans[i] => dac; bufP[i].out() => r; lfo[i] => blackhole; } 0 => r.gain; // Do that stuff! =========================================================> spork ~ midiCtl(); spork ~ bufP[0].bufCtl(); spork ~ bufP[1].bufCtl(); spork ~ bufP[2].bufCtl(); spork ~ bufP[3].bufCtl(); // make time pass, and control pan w LFOs int j; while( 1 ) { for(0 => j; j < 4; j++) { lfo[j].last() * panAmount=> pans[j].pan; } 5::ms => now; } // Shred & function defs====================================================> // func to calc lfo speeds fun void calcLFOspeed() { for(0 => int i; i < 4; i++) { panSpeed*(i+3)*.9 + 0.05 => lfo[i].freq; } } // midi-control shred - deal with incoming messages fun void midiCtl() { float tempf, rate; while( true ) { // wait on the event 'min' min => now; // get the message(s) while( min.recv(msg) ) { // slider f1 => sound 1 repeat rate if( msg.data1 == midiMsg1[0] && msg.data2 == midiMsg2[0] ) { bufP[0].slidrProc(msg.data3); <<< "Sound1 speed = ", msg.data3 >>>; } // slider f2 => sound 2 repeat rate else if( msg.data1 == midiMsg1[1] && msg.data2 == midiMsg2[1] ) { bufP[1].slidrProc(msg.data3); <<< "Sound2 speed = ", msg.data3 >>>; } // slider f3 => sound 3 repeat rate else if( msg.data1 == midiMsg1[2] && msg.data2 == midiMsg2[2] ) { bufP[2].slidrProc(msg.data3); <<< "Sound3 speed = ", msg.data3 >>>; } // slider f4 => sound 4 repeat rate else if( msg.data1 == midiMsg1[3] && msg.data2 == midiMsg2[3] ) { bufP[3].slidrProc(msg.data3); <<< "Sound4 speed = ", msg.data3 >>>; } // KNOBS else if( msg.data1 == midiMsg1[4] && msg.data2 == midiMsg2[4] ) { <<< "Knob C1 = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[5] && msg.data2 == midiMsg2[5] ) { <<< "Knob C2 = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[6] && msg.data2 == midiMsg2[6] ) { <<< "Knob C3 = ", msg.data3 >>>; } // knob C5 => dry gain else if( msg.data1 == midiMsg1[7] && msg.data2 == midiMsg2[7] ) { Math.exp(3*msg.data3/127.)/20.1 - 0.0497 => float z; for(0 => int i; i < 4; i++) { z => pans[i].gain; } <<< "dry gain = ", z >>>; } // knob C5 => pan amount else if( msg.data1 == midiMsg1[8] && msg.data2 == midiMsg2[8] ) { msg.data3/127. => panAmount; <<< "Pan Amount = ", msg.data3/127. >>>; } // knob C6 => pan rate else if( msg.data1 == midiMsg1[9] && msg.data2 == midiMsg2[9] ) { msg.data3/127. => panSpeed; calcLFOspeed(); <<< "panSpeed = ", panSpeed >>>; } else if( msg.data1 == midiMsg1[10] && msg.data2 == midiMsg2[10] ) { <<< "Knob C7 = ", msg.data3 >>>; } // knob C8 => reverb gain else if( msg.data1 == midiMsg1[11] && msg.data2 == midiMsg2[11] ) { Math.exp(3*msg.data3/127.)/20.1 - 0.0497 => r.gain; // msg.data3/300. => r.gain; <<< "reverb gain = ", msg.data3/150. >>>; } // PADS else if( msg.data1 == midiMsg1[12] && msg.data2 == midiMsg2[12] ) { bufP[0].noteProc(3, msg.data3); <<< "Pad P1 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[13] && msg.data2 == midiMsg2[13] ) { bufP[0].ccProc(3, msg.data3); <<< "Pad P1 aftertouch = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[14] && msg.data2 == midiMsg2[14] ) { bufP[1].noteProc(3, msg.data3); <<< "Pad P2 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[15] && msg.data2 == midiMsg2[15] ) { bufP[1].ccProc(3, msg.data3); <<< "Pad P2 aftertouch = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[16] && msg.data2 == midiMsg2[16] ) { bufP[2].noteProc(3, msg.data3); <<< "Pad P3 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[17] && msg.data2 == midiMsg2[17] ) { bufP[2].ccProc(3, msg.data3); <<< "Pad P3 aftertouch = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[18] && msg.data2 == midiMsg2[18] ) { bufP[3].noteProc(3, msg.data3); <<< "Pad P4 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[19] && msg.data2 == midiMsg2[19] ) { bufP[3].ccProc(3, msg.data3); <<< "Pad P4 aftertouch = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[20] && msg.data2 == midiMsg2[20] ) { bufP[0].noteProc(2, msg.data3); <<< "Pad P5 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[21] && msg.data2 == midiMsg2[21] ) { bufP[0].ccProc(2, msg.data3); <<< "Pad P5 aftertouch = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[22] && msg.data2 == midiMsg2[22] ) { bufP[1].noteProc(2, msg.data3); <<< "Pad P6 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[23] && msg.data2 == midiMsg2[23] ) { bufP[1].ccProc(2, msg.data3); <<< "Pad P6 aftertouch = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[24] && msg.data2 == midiMsg2[24] ) { bufP[2].noteProc(2, msg.data3); <<< "Pad P7 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[25] && msg.data2 == midiMsg2[25] ) { bufP[2].ccProc(2, msg.data3); <<< "Pad P7 aftertouch = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[26] && msg.data2 == midiMsg2[26] ) { bufP[3].noteProc(2, msg.data3); <<< "Pad P8 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[27] && msg.data2 == midiMsg2[27] ) { bufP[3].ccProc(2, msg.data3); <<< "Pad P8 aftertouch = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[28] && msg.data2 == midiMsg2[28] ) { bufP[0].noteProc(1, msg.data3); <<< "Pad P9 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[29] && msg.data2 == midiMsg2[29] ) { bufP[0].ccProc(1, msg.data3); <<< "Pad P9 aftertouch = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[30] && msg.data2 == midiMsg2[30] ) { bufP[1].noteProc(1, msg.data3); <<< "Pad P10 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[31] && msg.data2 == midiMsg2[31] ) { bufP[1].ccProc(1, msg.data3); <<< "Pad P10 aftertouch = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[32] && msg.data2 == midiMsg2[32] ) { bufP[2].noteProc(1, msg.data3); <<< "Pad P11 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[33] && msg.data2 == midiMsg2[33] ) { bufP[2].ccProc(1, msg.data3); <<< "Pad P11 aftertouch = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[34] && msg.data2 == midiMsg2[34] ) { bufP[3].noteProc(1, msg.data3); <<< "Pad P12 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[35] && msg.data2 == midiMsg2[35] ) { bufP[3].ccProc(1, msg.data3); <<< "Pad P12 aftertouch = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[36] && msg.data2 == midiMsg2[36] ) { bufP[0].noteProc(0, msg.data3); <<< "Pad P13 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[37] && msg.data2 == midiMsg2[37] ) { bufP[0].ccProc(0, msg.data3); <<< "Pad P13 aftertouch = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[38] && msg.data2 == midiMsg2[38] ) { bufP[1].noteProc(0, msg.data3); <<< "Pad P14 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[39] && msg.data2 == midiMsg2[39] ) { bufP[1].ccProc(0, msg.data3); <<< "Pad P14 aftertouch = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[40] && msg.data2 == midiMsg2[40] ) { bufP[2].noteProc(0, msg.data3); <<< "Pad P15 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[41] && msg.data2 == midiMsg2[41] ) { bufP[2].ccProc(0, msg.data3); <<< "Pad P15 aftertouch = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[42] && msg.data2 == midiMsg2[42] ) { bufP[3].noteProc(0, msg.data3); <<< "Pad P16 note = ", msg.data3 >>>; } else if( msg.data1 == midiMsg1[43] && msg.data2 == midiMsg2[43] ) { bufP[3].ccProc(0, msg.data3); <<< "Pad P16 aftertouch = ", msg.data3 >>>; } else { <<< "unassigned midi message: ", msg.data1, msg.data2, msg.data3 >>>; } } } } // setup midimessagevalues: map midi message number from trigger finger to an array fun void initMidiMsg() { 224 => midiMsg1[0]; 0 => midiMsg2[0]; // F1 slider 176 => midiMsg1[1]; 1 => midiMsg2[1]; // F2 slider 176 => midiMsg1[2]; 7 => midiMsg2[2]; // F3 slider 176 => midiMsg1[3]; 8 => midiMsg2[3]; // F4 slider 176 => midiMsg1[4]; 9 => midiMsg2[4]; // C1 knob 176 => midiMsg1[5]; 10 => midiMsg2[5]; // C2 knob 176 => midiMsg1[6]; 11 => midiMsg2[6]; // C3 knob 176 => midiMsg1[7]; 12 => midiMsg2[7]; // C4 knob 176 => midiMsg1[8]; 13 => midiMsg2[8]; // C5 knob 176 => midiMsg1[9]; 14 => midiMsg2[9]; // C6 knob 176 => midiMsg1[10]; 15 => midiMsg2[10]; // C7 knob 176 => midiMsg1[11]; 16 => midiMsg2[11]; // C8 knob 144 => midiMsg1[12]; 36 => midiMsg2[12]; // P1 pad, note 176 => midiMsg1[13]; 100 => midiMsg2[13]; // P1 pad, aftertouch //176 => midiMsg1[13]; 119 => midiMsg2[13]; // P1 pad, aftertouch 144 => midiMsg1[14]; 38 => midiMsg2[14]; // P2 pad, note 176 => midiMsg1[15]; 101 => midiMsg2[15]; // P2 pad, aftertouch 144 => midiMsg1[16]; 40 => midiMsg2[16]; // P3 pad, note 176 => midiMsg1[17]; 102 => midiMsg2[17]; // P3 pad, aftertouch 144 => midiMsg1[18]; 41 => midiMsg2[18]; // P4 pad, note 176 => midiMsg1[19]; 103 => midiMsg2[19]; // P4 pad, aftertouch 144 => midiMsg1[20]; 43 => midiMsg2[20]; // P5 pad, note 176 => midiMsg1[21]; 104 => midiMsg2[21]; // P5 pad, aftertouch 144 => midiMsg1[22]; 45 => midiMsg2[22]; // P6 pad, note 176 => midiMsg1[23]; 105 => midiMsg2[23]; // P6 pad, aftertouch 144 => midiMsg1[24]; 47 => midiMsg2[24]; // P7 pad, note 176 => midiMsg1[25]; 106 => midiMsg2[25]; // P7 pad, aftertouch 144 => midiMsg1[26]; 48 => midiMsg2[26]; // P8 pad, note 176 => midiMsg1[27]; 107 => midiMsg2[27]; // P8 pad, aftertouch 144 => midiMsg1[28]; 50 => midiMsg2[28]; // P9 pad, note 176 => midiMsg1[29]; 108 => midiMsg2[29]; // P9 pad, aftertouch 144 => midiMsg1[30]; 52 => midiMsg2[30]; // P10 pad, note 176 => midiMsg1[31]; 109 => midiMsg2[31]; // P10 pad, aftertouch 144 => midiMsg1[32]; 53 => midiMsg2[32]; // P11 pad, note 176 => midiMsg1[33]; 110 => midiMsg2[33]; // P11 pad, aftertouch 144 => midiMsg1[34]; 55 => midiMsg2[34]; // P12 pad, note 176 => midiMsg1[35]; 111 => midiMsg2[35]; // P12 pad, aftertouch 144 => midiMsg1[36]; 57 => midiMsg2[36]; // P13 pad, note 176 => midiMsg1[37]; 112 => midiMsg2[37]; // 13 pad, aftertouch 144 => midiMsg1[38]; 59 => midiMsg2[38]; // P14 pad, note 176 => midiMsg1[39]; 113 => midiMsg2[39]; // P14 pad, aftertouch 144 => midiMsg1[40]; 60 => midiMsg2[40]; // P15 pad, note 176 => midiMsg1[41]; 114 => midiMsg2[41]; // P15 pad, aftertouch 144 => midiMsg1[42]; 62 => midiMsg2[42]; // P16 pad, note 176 => midiMsg1[43]; 115 => midiMsg2[43]; // P16 pad, aftertouch }