//-- // name: PushPulse.ck // desc: interactive process for loudspeakers, directional mic and // optional MIDI keyboard // // relies on Tracking.ck (Ge Wang + Rebecca Fiebrink, 2007) // // author: Andy Stuhl // date: 2011 //-- //MIDI F1-8 fader assignments //1) gain //2) reverb //3) velocity fluctuation //4) decay rate //5) restore rate //6) tracking sensitivity //7) base pulse duration //8) base gap duration 4 => int nChans; 0.5::second => dur startPLength; 0.2::second => dur startGLength; 0.99 => float startDecay; 0.001 => float decayInc; 0.015 => float restoreFac; dur pulseLength[nChans]; dur gapLength[nChans]; float decayFac[nChans]; 0.2 => float gainVal; 0.02 => float revVal; 15.0 => float trackSen; 0.1 => float velFac; int notes[nChans]; 62 => notes[0]; 66 => notes[1]; 69 => notes[2]; 73 => notes[3]; Clarinet s[nChans]; NRev r[nChans]; noteAssign(); for(0 => int i; i < nChans; i++) { s[i] => r[i] => dac.chan(i); r[i].mix(revVal); <<>>; startPLength => pulseLength[i]; startGLength => gapLength[i]; startDecay => decayFac[i]; 0 => s[i].vibratoFreq; 0 => s[i].vibratoGain; Std.rand2f(0.0, 0.5) => s[i].reed; Std.rand2f(0.5, 1) => s[i].noiseGain; Std.rand2f(0.0, 1) => s[i].pressure; } fun void noteAssign() { for(0 => int m; m < nChans; m++) s[m].freq(Std.mtof(notes[m])); } fun void pulsePattern(int chanID) { while(true) { s[chanID].gain(gainVal); 0.5 + velFac * Std.rand2f(-0.5, 0.5) => s[chanID].noteOn; pulseLength[chanID] => now; s[chanID].gain(0); gapLength[chanID] => now; } } fun void paramChange(int pID, int val) { if(pID < 12 || pID > 19) me.exit(); 11 -=> pID; val => float scaledVal; scaledVal / 127.0 => scaledVal; if(pID == 1) { 0.0 + scaledVal * 0.5 => gainVal; for(0 => int c; c < nChans; c++) s[c].gain(gainVal); } else if(pID == 2) { 0.0 + scaledVal * 0.1 => revVal; for(0 => int c; c < nChans; c++) r[c].mix(revVal); } else if(pID == 3) { scaledVal => velFac; } else if(pID == 4) { 0.0 + scaledVal * 0.003 => decayInc; } else if(pID == 5) { 0.0 + scaledVal * 0.03 => restoreFac; } else if(pID == 6) { 15.0 + scaledVal * 30.0 => trackSen; } else if(pID == 7) { 0.2::second + scaledVal::second * 0.8 => startPLength; } else if(pID == 8) { 0.05::second + scaledVal::second * 0.5 => startGLength; } } fun void chordChanger() { 0 => int device; MidiIn min; MidiMsg msg; if( !min.open( device ) ) me.exit(); <<< "MIDI device:", min.num(), " -> ", min.name() >>>; int newNotes[nChans]; 0 => int changeCount; while(true) { min => now; while( min.recv( msg ) ) { <<< msg.data1, msg.data2, msg.data3 >>>; if ( msg.data1 == 176 ) { paramChange( msg.data2, msg.data3); continue; } if ( msg.data1 != 144 ) continue; if ( msg.data3 > 0 ) { msg.data2 => notes[changeCount]; s[changeCount].freq(Std.mtof(notes[changeCount])); changeCount ++; if (changeCount >= nChans) 0 => changeCount; } } } } for (0 => int j; j < nChans; j++) { spork ~ pulsePattern(j); } spork ~ chordChanger(); while( true ) { Tracking.the_event => now; for(0 => int k; k < nChans; k++) { if(Std.mtof(notes[k]) > Tracking.the_freq - trackSen && Std.mtof(notes[k]) < Tracking.the_freq + trackSen) { //decay pulseLength[k] * decayFac[k] => pulseLength[k]; gapLength[k] * decayFac[k] => gapLength[k]; decayFac[k] - decayInc => decayFac[k]; } else { //restore pulseLength[k] + (startPLength - pulseLength[k]) * restoreFac => pulseLength[k]; gapLength[k] + (startGLength - gapLength[k]) * restoreFac => gapLength[k]; decayFac[k] + (startDecay - decayFac[k]) * restoreFac => decayFac[k]; } } 50::ms => now; } 1::day => now;