//----------------------------------------------------------------------------- /* Copyright (c) 2007 Dan Trueman. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. ----------------------------------------------------------------------------- Example of using the Cyclotron with a simple filtered click to execute: > ./chuck SpokeEvent_class.ck Cyclotron_class.ck simpleClicker.ck */ //----------------------------------------------------------------------------- //instantiate a Cyclotron engine Cyclotron mycycler; //set up clik listener with engine, so we can hear when the spokes click SpokeEvent clikMsg; mycycler.setEvent(clikMsg); //set up port for OSC communications to a GUI (unique to this Cyclotron) Std.rand2(200, 20000) => int newPort; //generate a port number randomly for (0=>int i; i < me.args(); i++) { Std.atoi(me.arg(i)) => newPort; //or specify with argument } //we do this so we can open up multiple pairs of these simultaneously without //duplicating OSC ports. kludge. //open GUI, so we can manipulate the spokes //optional args to cyc1.jar are sendPort, filename (for loading cycler), framerate (to control CPU load of GUI) "java -jar cyc1.jar " + newPort + " &" @=> string guicmd; Std.system(guicmd); //<<>>; 3.5::second => now; //wait for the GUI to open mycycler.setPort(newPort); //use this val in the system call below; can instantiate //multiple cyclers with different ports, as long as their //port numbers are not consecutive numbers (Cyclotron uses //two ports....) //start cycler engine spork ~ mycycler.go(); //listen for cliks spork ~ clik_receive(); //count the days.... while(true) {1::day => now;} //----------------------------------------------------------------------------- /*** Listen ***/ //click listener function fun void clik_receive() { me.yield(); float spoke[]; int spokeNum; float spokeTime, spokeNextTime; float spokeLen; float spokeCapsize; float spokeInc; while(true) { clikMsg => now; //get spoke data mycycler.getSpoke(clikMsg.spoke) @=> spoke; clikMsg.spoke => spokeNum; spoke[1] => spokeTime; spoke[2] => spokeLen; spoke[3] => spokeCapsize; spoke[4] => spokeInc; spoke[5] => spokeNextTime; if(spokeNum == 0) { //can do things at the top of the cycle, like reverse the cycler, change the warping, etc... //mycycler.reverse(); //1./mycycler.phaseWarp => mycycler.setPhaseWarp; } //pitched click spokeLen * 48. + 28. => Std.mtof => float currentFreq; 0.5 * (0.1 + spokeCapsize * 2.) => float currentGain; //spork a click spork ~ click(currentFreq, currentGain, 0.9999, 0::ms, 0::ms, 1., 250::ms); } } fun void click(float freq, float gain, float radius, dur atk, dur dec, float sus, dur rel) { //me.yield(); Impulse clik => BiQuad f => ADSR e => dac; 0.2 => clik.gain; freq => f.pfreq => float currentFreq; gain => e.gain; radius => f.prad; 1 => f.eqzs; e.set(atk, dec, sus, rel); clik.next(1); e.keyOn(); 2::ms => now; e.keyOff(); rel => now; } //-----------------------------------------------------------------------------