
Dear Chuckists, With the exception of a protracted discussion about garbage collection (of which I have yet to read the conclusion), things have been generally "all quiet on the ChucKian front" this summer. Nevertheless, I know that there are those of you who are still busy digging into this and that project with ChucK. I myself have been working (predictably, doggedly, stubbornly) on more granular synthesis stuff and wanted to share some recent classes that I find helpful to me in general (i.e. not just for granular synthesis). Part 1: INPUT I find that environments like Processing, SC, etc have very easy-to-use input calls like MouseX.kr etc, that easily bring the ability to add some interaction to your code, without having to set up a HidMsg, Hid pair and an event responder. Sometimes you just want mouse input and want it right now. I wanted to automate the process a little so that I could save some time by just telling ChucK to add the boiler plate listener for the mouse, keyboard, or a joystick in a separate thread and make the data available. With the MouseInput class, for instance, you can just do this: MouseInput mi; spork ~ mi.listen(); me.yield(); while(true) { mi => now; <<< mi.deltaX, mi.deltaY, mi.wheelDeltaX, mi.wheelDeltaY, mi.buttonDown, mi.buttonUp >>>; me.yield(); } I find this easier to use. Maybe you will too. There's one for Keyboard input and joystick input too. I'm sure they can be improved, so please share any ideas you have. Part 2: WAVETABLES AS ENVELOPES Concept: A positive, unipolar wavetable can be used as a cheap, flexible alternative to envelope UGens by driving it with a Phasor and multiplying its output with your signal. The CurveEnvelope class: // // CurveTable Envelope // class CurveEnvelope { // members and default params Phasor drive => CurveTable curvetable => Gain multiplier; 3 => multiplier.op; // this is what makes the CurveTable an envelope! 0. => multiplier.gain; // we use this to gait the output, so start at 0. UGen source, out; 0 => drive.op; // stop the driver for now dac @=> out; 1. => float gain; 1::second => dur length; [0., 0., 0., 1., 1., 0., 2., 0.] => curvetable.coefs; // triangle window // methods fun void setEnvelopeCoefs( float _coefs[] ) { _coefs => curvetable.coefs; } fun void connectSource( UGen src ) { src @=> source; } fun void connectOutput( UGen destination ) { destination @=> out; } fun void trigger() { source => multiplier => out; // connect things gain => multiplier.gain; // open gait 1 => drive.op; 0. => drive.phase; // reset driver to beginning of envelope curve 1. / (length / second) => drive.freq; // calculate speed of driver in Hz length => now; // let it happen... 0. => multiplier.gain; // close gait 0 => drive.op; source =< multiplier =< out; // disconnect things } } USAGE: CurveEnvelope ce; SinOsc s; ce.connectSource( s ); ce.connectOutput( dac ); ce.trigger(); TriOsc t; ce.connectSource( t ); ce.connectOutput( dac ); ce.trigger(); <<< "done" >>>; -- http://michaelclemow.com http://semiotech.org