You can find out more about Chuck at http://chuck.cs.princeton.edu/.
More about me at www.scotthewitt.co.uk and about my PhD.
Send comments to @scotthewitt.
More about ChucK Instrument Processing (CIP) here.
As always an immediately unintended outcome is that I ended up writing a php syntax highlight for Chuck which I will use on this page.
/*Number 1 Chuck a day 2009 by Scott Hewitt www.ablelemon.co.uk/chuckaday */ //Build DSP SinOsc s => dac; 440 => s.freq; //Declare int i; //Loop while (i < 50) { //Random frequency Std.rand2f(200, 500) => s.freq; //Random duration to pass Std.rand2f(10, 500)*1::ms => now; //Increment Loop i++; }
ChucK file 1.ck
If you remove the // on the print lines <<< you can see f's value change over time.
//Number 2 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //Declare int k; //int used to track if shreds are running int f; //main function fun void valueshift() { //Build DSP SinOsc s => dac; //declare freq 440 => s.freq; int i; f++; //<<< f >>>; while (i < 50) { //Random frequency Std.rand2f(200, 1000) => s.freq; //Random duration to pass Std.rand2f(10, 500)*1::ms => now; //Increment Loop i++; } f--; //<<< f >>>; } //sporks shreds off while (k < 6) { spork~ valueshift(); 2000::ms => now; k++; } //loop time until all shreds are dead while (f > 0 ) { 500::ms => now; //<<< "waiting on" >>>; //<<< f >>>; }
ChucK file 2.ck
The sonic material is contained within the function build() while the score is the the list of function calls separated by lengths of time.
Could not find away to manipulate dsp control parameters outside of there if statements so will revisit that.
//Number 3 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //function holds 'instrument' function void build(int d, dur e){ 0 => int b; 0 => int a; while (b < d){ Std.rand2(1,4) => a; <<< a >>>; if (a == 1) { SinOsc s => dac; 0.3 => s.gain; Std.rand2f(440, 800) => s.freq; }else{ TriOsc f => dac; 0.3 => f.gain; Std.rand2f(440, 800) => f.freq; } b++; e => now; } } //a score? build(2, 100::ms); 2000::ms => now; build(2, 400::ms); 4000::ms => now; build(2, 10::ms); 1000::ms => now; build(2, 999::ms); 1000::ms => now;
ChucK file 3.ck
The event communication seams a great way to communicate between the parent and children shreds and I imagine waiting for something to happen rather than querying to see if it has is more efficient coding.
//Number 4 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //Events for note on/off Event e; Event f; Event g; Event h; //int represents how many voices are sounding 0 => int stop; //signals score progression Event i; //synth function int set frequency, responds to event function void synthee (Event event, int xx){ SawOsc s => Envelope env => Pan2 p => dac; 0.3 => s.gain; 100::ms => env.duration; xx => s.freq; <<< xx >>>; while (true){ event => now; 0.8 => env.target; Std.rand2f(-1.0, 1.0) => p.pan; 1 => env.keyOn; stop++; <<< stop >>>; event => now; 0 => env.target; 1 => env.keyOff; stop--; } } //signal events function void control () { while (true){ if (maybe){ g.signal(); Std.rand2f(100, 800) * 1::ms => now; } if (maybe){ h.signal(); Std.rand2f(100, 800) * 1::ms => now; } if (maybe){ e.signal(); Std.rand2f(100, 800) * 1::ms => now; } if (maybe){ f.signal(); Std.rand2f(100, 800) * 1::ms => now; } } 1::ms => now; } //counts 20 seconds and then moves on score function void timer () { 20::second => now; i.signal(); } //create multiple voices using sporking spork ~ synthee(e, 500); spork ~ synthee(f, 800); spork ~ synthee(g, 1000); spork ~ synthee(h, 600); //Score ?? //counts 20 seconds spork ~ timer(); //changes synthee values spork ~ control(); //awaits signal to start end i => now; <<< "to end" >>> ; //waits for all notes to be off and ends while (stop != 0){ 1::ms => now; } //allows final envelope to end 101::ms => now;
ChucK file 4.ck
I can see this dynamic parameter change being useful in FM synthesis and for other stuff.
If your running this code please send me comments or follow me on twitter @scotthewitt.
//Number 5 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //dsp chain SinOsc n => HPF biq => dac; //randoms and then sweeps freq value function void freqsweep () { while (true){ 0 => int dd; Std.rand2f(0, 1) => biq.freq; while (dd < 10 ) { 1000::ms => now; biq.freq() - 0.1 => biq.freq; dd++; } Std.rand2f(10, 100) * 1::ms => now; } } //randoms and then sweeps q value function void qsweep () { while (true){ 0 => int cc; Std.rand2f(0, 1) + 0.1 => biq.Q; while (cc < 10 ) { 1000::ms => now; biq.Q() - 0.01 => biq.Q; cc++; } Std.rand2f(10, 100) * 1::ms => now; } } //changes frequency and sweeps spork ~ freqsweep(); //changes q and sweeps spork ~ qsweep(); //run for 60 seconds 60::second => now;
ChucK file 5.ck
Also used the Echo Ugen to fill out the sitar sound.
Used the zero values in the arrays to introduce shape to the lines, as they cause a break to occur, though had to add additional if statements looking for them, otherwise they just cause errors.
Any ideas for day 7? @scotthewitt
//Number 6 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //Today we play with arrays [440,400,300,0,600,590,550,520,420] @=> int tune[]; [200,220,210,180,300,240,0,310,200] @=> int tuneb[]; [210,350,400,260,200,320,310] @=> int tunec[]; Event enew; Event eenew; Event eeenew; //DSP (maybe there is a better way of dong this) Sitar sit => Echo e => dac; Sitar sitb => Echo ee => dac; Sitar sitc => Echo eee => dac; 1000::ms => e.max => ee.max => eee.max; 0.1 => e.mix => ee.mix => eee.mix; //play array function void mel (){ for (0 => int i; i < tune.cap(); i++){ if(tune[i] != 0){ tune[i] => sit.freq; Std.rand2f(0, 1) => sit.pluck; 0.9 => sit.noteOn; 200::ms => now; 0.0 => sit.noteOff; 200::ms => now; enew.signal(); }else{ 400::ms => now; } } } function void accop () { for (0 => int i; i < tuneb.cap(); i++){ if(tuneb[i] != 0){ tuneb[i] => sitb.freq; Std.rand2f(0, 1) => sitb.pluck; 0.9 => sitb.noteOn; 200::ms => now; 0.0 => sitb.noteOff; 200::ms => now; eenew.signal(); }else{ 400::ms => now; } } } function void melb (){ int kk; for (0 => int i; i < tunec.cap(); i++){ Std.rand2(1, (tunec.cap() -1)) => kk; if(tune[kk] != 0){ tunec[kk] => sitc.freq; Std.rand2f(0, 1) => sitc.pluck; 0.9 => sitc.noteOn; 200::ms => now; 0.0 => sitc.noteOff; 200::ms => now; eeenew.signal(); }else{ 400::ms => now; } } } //create echo values function void echoer (){ while (true){ enew => now; Std.rand2(100, 900) * 1::ms => e.delay; } } function void echoerb (){ while (true){ eenew => now; Std.rand2(100, 1000) * 1::ms => ee.delay; } } function void echoerc (){ while (true){ eeenew => now; Std.rand2(100, 700) * 1::ms => eee.delay; } } //spork shreds spork~ echoer(); spork~ echoerb(); spork~ echoerc(); spork~ mel(); spork~ melb(); spork~ accop(); //keep parent alive so children complete 4::second => now;
ChucK file 6.ck
Has more complicated Ugen network with some Ugens feeding back into each other.
I am finding that 'spork~ing' things is the easiest way to modulate multiple parameters.
As always and ideas are welcome @scotthewitt.
//Number 7 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //DSP adc => Delay del => dac; del => Delay delb => dac; delb => del; //Control Envelope env => blackhole; Envelope envb => blackhole; SinOsc s => blackhole; //Preset values 1000 => s.freq; 0.5 => delb.gain; 5000::ms => del.max; 1000::ms => del.delay; 5000::ms => delb.max; 1000::ms => delb.delay; //amplitude modulation function void feedbackamp (){ while (true){ s.last() => delb.gain; //<<< s.last() >>>; <<< delb.gain() >>>; 21::ms => now; } } //change delay value delb function void delaa (){ while (true){ env.value() * 1::ms => delb.delay; 100::ms => now; } } //change delay value del function void delbb (){ while (true){ envb.value() * 0.7::ms => del.delay; 100::ms => now; } } //envelope control function void envbcontrol() { while (true){ Std.rand2(10, 4500) => envb.value; Std.rand2(10, 4500) => envb.target; Std.rand2(10, 4500) => envb.time; envb.keyOn; envb.time() * 1::ms => now; } } spork ~ feedbackamp(); spork ~ delaa(); spork ~ delbb(); spork ~ envbcontrol(); //main loop while (true) { 1000::ms => now; Std.rand2(10, 1500) => env.value; Std.rand2(10, 1500) => env.target; Std.rand2(10, 4500) => env.time; env.keyOn; env.time() * 1::ms => now; }
ChucK file 7.ck
This code sort of does it. Pitches are created based on random choice between movments allowed. The available movments are hardcoded as a percentage of the length of score.
Sort of works - one thing I am sure of is that ChucK seames to handle this kind of thing quite well.
As always any comments to @scotthewitt.
//Number 8 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday int scorelength; Std.rand2(10, 30) => scorelength; int score[scorelength]; float beat[scorelength]; int ups; int downs; int change; int extra; int doublebar; float f; scorelength / 4 $ int => doublebar; //layout picths steps <<< "scorelength", scorelength >>>; scorelength * 0.4 => f; f $ int => ups; <<< "ups", ups >>>; scorelength * 0.4 => f; f $ int => downs; <<< "downs", downs >>>; scorelength * 0.2 => f; f $ int => change; <<< "change", change >>>; scorelength - ups - downs - change => extra; change + extra => change; <<< "change + extra", change >>>; int i; int control; 0 => int shift; //functions handle pitch steps function void upper(int move){ score[i-1] + move + shift => score[i]; ups--; } function void downer(int move){ score[i-1] - move + shift => score[i]; downs--; } function void changer(int move){ score[i-1] + move + shift => score[i]; change--; } //tempo score function void rythmscore(){ <<< "rythm" >>>; int kk; for (1 => int ii; ii < scorelength; ii++) { 1 => beat[ii]; kk++; if (kk == 3){ if (maybe){ 0.7 => beat[ii]; } else 1.3 => beat[ii]; } if (kk > doublebar){ 0 => kk; if (maybe){ 2.54 => beat[ii]; } else 4.56 => beat[ii]; } } } //creates score using pitch step values function void makescore() { <<< "score" >>>; 1 => score[0]; for (1 => i; i < scorelength; i++) { if (score[i-1] == 7) { 8 => shift; // 4 => beat[i-1]; //1 => beat[i]; } if (shift == 8){ if (score[i-1] == 11){ 0 => shift; // 4 => beat[i-1]; // 1 => beat[i]; } } 0 => control; <<< "shift", shift >>>; if (ups > 0) { control + 1 => control; } if (downs > 0) { control + 2 => control; } if (change > 0){ control + 4 => control; } <<< "control" , control >>>; if (control == 0){ Std.rand2(0,2) => int choice; <<< "choice", choice >>>; if (choice == 0){ upper(4); } if (choice == 1){ downer(4); } if (choice == 2){ changer(-8); } } if (control == 1){ upper(2); } if (control == 2){ downer(2); } if (control == 3){ if (maybe){ upper(3); }else downer(3); } if (control == 4){ changer(5); } if (control == 5){ if (maybe){ upper(5); }else changer(6); } if (control == 6){ if (maybe){ downer(3); }else changer(3); } if (control == 7){ Std.rand2(0,2) => int choice; <<< "choice", choice >>>; if (choice == 0){ upper(4); } if (choice == 1){ downer(2); } if (choice == 2){ changer(5); } } } } //creats pitch score makescore(); rythmscore(); SinOsc s => Envelope env => dac; 1 => env.value; 0.1 => s.gain; //plays score while (true){ int j; for (1 => j; j < scorelength; j++) { <<< "score: ", score[j] >>>; if (Std.mtof(score[j] + 69.0) > 100){ if (Std.mtof(score[j] + 69.0) < 2000){ Std.mtof(score[j] + 69.0) => s.freq; } } <<< "freq: ",s.freq() >>>; 130::ms => env.duration; 1.0 => env.target; 1 => env.keyOn; 100::ms => now; beat[j] * 500::ms => now; 130::ms => env.duration; 0.0 => env.target; 1 => env.keyOn; 400::ms => now; <<< "beat: ", beat[j] >>>; } makescore(); rythmscore(); <<< "next score" >>>; 150::ms => env.duration; 0.0 => env.target; 1 => env.keyOn; 1000::ms => now; 0 => env.keyOff; 1 => env.value; }
ChucK file 8.ck
As always any comments to @scotthewitt.
//Number 9 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday Impulse x => Pan2 b => dac;while(10::ms=>now) x.next(0.9/(Std.randf()))=>b.pan;
ChucK file 9.ck
Killing the sporks off by using a global int as the control for the while loops works well.
As always any comments to @scotthewitt.
//Number 10 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday SinOsc s => dac; SinOsc d => blackhole; SinOsc f => blackhole; TriOsc tri => blackhole; 1000 => f.freq; 90 => tri.freq; 200 => d.freq; 11 => float m; 400 => float depth; 8.01 => float ma; 10.01 => float deptha; 1 => int mbcontrol; 1 => int scontrol; function void modderb (){ while(mbcontrol){ ma + (deptha * f.last()) => d.freq; //<<< s.freq() >>>; 1::samp => now; } } function void modder (){ while(true){ m + (depth * d.last()) => s.freq; //<<< s.freq() >>>; 1::samp => now; } } function void sweep () { while (scontrol){ depth + (tri.last() * 3.0) => depth; //<<< tri.last() >>>; 1::samp => now; } } 3000::ms => dur dd; spork ~ modder(); dd => now; spork ~ modderb(); dd => now; spork ~ sweep(); dd => now; //end sporks 0 => mbcontrol; dd => now; //end sporks 0 => scontrol; dd => now;
ChucK file 10.ck
Would be cool to make some some of drum machine using ChucK, however tomorrow I think I might do some poly rhythms.
As always any comments to @scotthewitt.
//Number 11 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //main called function function void drum (dur beat, int max, float dec){ Shakers s => dac; Std.rand2(0, 128) => s.objects; dec => s.decay; <<< s.objects() >>>; for (0 => int i; i < max; i++){ 1 => s.noteOn; beat => now; 0 => s.noteOff; <<< me.id() >>>; } } 0.5 => float decc; 500::ms => dur gap; 5 => int hits; spork ~ drum(gap, hits, decc); gap * hits => now; 400::ms => gap; 5 => hits; spork ~ drum(gap, hits, decc); spork ~ drum(500::ms, 24, decc); gap * hits => now; 300::ms => gap; 5 => hits; spork ~ drum(gap, hits, decc); gap * hits => now; 200::ms => gap; 10 => hits; spork ~ drum(gap, hits, decc); gap * hits => now; 100::ms => gap; 10 => hits; spork ~ drum(gap, hits, decc); 1000::ms => now; 0.6 => decc; 1764::ms => gap; 10 => hits; spork ~ drum(gap, hits, decc); spork ~ drum(0.5 * gap, hits, decc); spork ~ drum(0.7 * gap, hits, 0.4); 500::ms => gap; 10 => hits; spork ~ drum(gap, hits, decc); gap * hits => now; 0.7 => decc; 400::ms => gap; spork ~ drum(gap, hits, decc); gap * hits => now; 300::ms => gap; spork ~ drum(gap, hits, decc); gap * hits => now; 0.8 => decc; 200::ms => gap; spork ~ drum(gap, hits, decc); gap * hits => now; 5000::ms => now;
ChucK file 11.ck
Will revisit this as a more extended work.
As always any comments to @scotthewitt.
//Number 12 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //main called function function void drum (dur beat, int max, float dec){ Shakers s => dac; 11 => s.objects; dec => s.decay; <<< s.objects() >>>; for (0 => int i; i < max; i++){ 1 => s.noteOn; beat => now; 0 => s.noteOff; <<< now, me.id() >>>; } } 0.5 => float decc; 1100::ms => dur gap; 11 => int hits; spork ~ drum(gap, hits, decc); 1000::ms => gap; 12 => hits; spork ~ drum(gap, hits, decc); gap * hits => now;
ChucK file 12.ck
As always any comments to @scotthewitt.
//Number 13 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday 0 => int control; function void audio (int hz, dur length, dur hold, dur rel){ control++; <<< control >>>; SinOsc s => Envelope e => dac; 0.0 => e.value; hz => s.freq; length => e.duration; 1 => e.target; 1 => e.keyOn; length => now; hold => now; length => e.duration; 0 => e.keyOff; 0 => e.target; rel => now; control--; } spork ~ audio(440, 2500::ms, 2500::ms, 2500::ms); 2500::ms => now; spork ~ audio(441, 2500::ms, 2500::ms, 2500::ms); 2500::ms => now; spork ~ audio(442, 2500::ms, 2500::ms, 2500::ms); 2500::ms => now; spork ~ audio(443, 2500::ms, 2500::ms, 2500::ms); 2500::ms => now; 3000::ms => now; spork ~ audio(442, 500::ms, 500::ms, 500::ms); spork ~ audio(441, 500::ms, 500::ms, 500::ms); spork ~ audio(440, 500::ms, 500::ms, 500::ms); //2000::ms => now; spork ~ audio(440, 500::ms, 500::ms, 500::ms); 10::ms => now; spork ~ audio(440, 500::ms, 500::ms, 500::ms); 10::ms => now; spork ~ audio(440, 500::ms, 500::ms, 500::ms); //part b spork ~ audio(440, 2500::ms, 2800::ms, 4000::ms); 2000::ms => now; spork ~ audio(441, 2100::ms, 2600::ms, 2500::ms); 2900::ms => now; spork ~ audio(442, 2000::ms, 2500::ms, 2200::ms); 2200::ms => now; spork ~ audio(443, 2300::ms, 2900::ms, 2800::ms); spork ~ audio(443, 500::ms, 100::ms, 500::ms); 10::ms => now; spork ~ audio(444, 500::ms, 100::ms, 500::ms); 10::ms => now; spork ~ audio(445, 500::ms, 100::ms, 500::ms); do{ 1::second => now; <<< control >>>; } while (control > 0);
ChucK file 13.ck
mouse.ck in the examples was invaluable here to handle the mouse interaction
As always any comments to @scotthewitt. #hackpact
//Number 14 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //Human you => you.clickmouse() // make HidIn and HidMsg Hid hi; HidMsg msg; // which mouse 0 => int device; // get from command line if( me.args() ) me.arg(0) => Std.atoi => device; // open mouse 0, exit on fail if( !hi.openMouse( device ) ) me.exit(); <<< "mouse '" + hi.name() + "' ready", "" >>>; function void buttonstate (){ // infinite event loop while( true ) { // wait on HidIn as event hi => now; // messages received while( hi.recv( msg ) ) { if( msg.isButtonDown() ) { <<< "mouse button", msg.which, "down" >>>; //spork new shred spork ~ sound(); } } } } //generate audio function void sound (){ Shakers s => dac; Std.rand2(0, 128) => s.objects; Std.rand2(1000, 3000) * 1::ms => dur gap; <<< "shaker object:", s.objects(), "gap:", gap >>>; while (true){ 1 => s.noteOn; 100::ms => now; 0 => s.noteOff; gap => now; } } //look for mouse button down spork ~ buttonstate(); 1::minute => now;
ChucK file 14.ck
As always and ideas are welcome @scotthewitt. #hackpact
//Number 15 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday float sinlast; float sinfre; 440 => sinfre; //create dsp function void sour (UGen u){ SinOsc s => u; if (u == dac){ <<< "ok" >>>; while (true){ sinfre => s.freq; 100::ms => now; } } if (u == blackhole){ <<< "blackhole" >>>; while (true){ 44 => s.freq; s.last() => sinlast; 100::ms => now; } } } //modulate function void mod(){ while (true){ (sinlast * 20) + sinfre => sinfre; 100::ms => now; } } //spork shreds spork ~ sour(dac); spork ~ sour(blackhole); spork ~ mod(); 1000::ms => now;
ChucK file 15.ck
Buses idea from here.
As always and ideas are welcome @scotthewitt. #hackpact
//Number 16 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //increase the size of the array to get more channels public class bus { static Gain @ chan[8]; } new Gain[8] @=> bus.chan; function void test(UGen u){ SinOsc s => u; 440 => s.freq; 1000::ms => now; } spork ~ test(bus.chan[1]); bus.chan[1] => dac; 2000::ms => now;
ChucK file 16.ck
The modular design should allow me to post parts as I build them.
As always and ideas are welcome @scotthewitt. #hackpact
//Number 17 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //This does nothing its the first plan for CIP public class bus { static Gain @ chan[8]; } new Gain[8] @=> bus.chan; adc => bus.chan[1]; bus.chan[1] => processing => bus.chan[2]; bus.chan[2] => processing => bus.chan[3]; bus.chan[4] => processing => bus.chan[8]; bus.chan[1] => processing => bus.chan[5]; bus.chan[5] => processing => bus.chan[8]; bus.chan[8] => dac;
ChucK file 17.ck
They are included as one file though they should be broken into three sections. They work best when used multiple times concurrently with altered values.
As always and ideas are welcome @scotthewitt. #hackpact
//Number 18 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //Number 1 adc => Delay a => dac; Delay b => dac; a => b; 1::minute => a.max => b.max; 10::second => a.delay; function void sweep(){ SinOsc s => blackhole; 100 => s.freq; while(true){ s.last() => a.gain; 1::ms => now; } } spork ~ sweep(); while(true){ 1000::ms => now; } //Number 2 function void noiser(){ Noise nn => dac; while(true){ 0.1 ==> nn.gain; Std.rand2(1,50) * 1::ms => now; 0.0 => nn.gain; Std.rand2(100,8000) * 1::ms => now; } } spork ~ noiser(); while(true){ 3000::ms => now; } //Number 3 function void siner(int a, int b){ SinOsc s => Envelope e => dac; b => s.freq; a * 1::ms => dur b; 0.5 => e.target; b => e.duration; 1 => e.keyOn; b => now; 0.0 => e.target; b => e.duration; 1 => e.keyOn; b => now; } function void other(){ while(true){ spork ~ siner(Std.rand2(100,400),Std.rand2(400, 800)); 6000::ms => now; } } spork ~ other(); while(true){ spork ~ siner(Std.rand2(10,100),Std.rand2(200,400)); 4000::ms => now; }
ChucK file 18.ck
This is a continuation of my investigations into dynamically altering the dsp processing.
As always and ideas are welcome @scotthewitt. #hackpact
//Number 19 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //thanks to Kassen for help with this fun void setFreq(UGen u) { Std.rand2f(200,600) => float freq; //Cast resolves issues issue of no .freq in UGen freq => (u $ SinOsc).freq; } TriOsc s => dac; SinOsc k => dac; SawOsc f => dac; setFreq(s); setFreq(k); setFreq(f); 1000::ms => now;
ChucK file 19.ck
This feels much more like compositional approach rather and gives an interesting idea of a score.
As always and ideas are welcome @scotthewitt. #hackpact
//Number 20 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday Impulse imp => Delay dela => dac; imp => Delay delb => dac; imp => Delay delc => dac; 3000::ms => dela.max => delb.max => delc.max; function void fire(dur a){ while(true){ 1.0 => imp.next; a => now; } } spork ~ fire(1000::ms); 3000::ms => now; 500::ms => dela.delay; 700::ms => delb.delay; 3000::ms => now; spork ~ fire(900::ms); 900::ms => delc.delay; 9000::ms => now; delb => Gain g => delc; <<<"stage">>>; 0.5 => g.gain; 9000::ms => now; dela =< dac; dela => delb; spork ~ fire(770::ms); 9000::ms => now; spork ~ fire(200::ms); 9000::ms => now; spork ~ fire(100::ms); 2000::ms => now;
ChucK file 20.ck
As always and ideas are welcome @scotthewitt. #hackpact
//Number 21 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday SinOsc s => dac; //create midi object MidiIn min; MidiMsg msg; //check if midi present if( !min.open(0) ) { me.exit(); } <<< "midi connected" >>>; function void midiinput(){ while(true){ min => now; while( min.recv(msg) ){ <<< msg.data2 >>>; Std.mtof(msg.data2) => s.freq; } } } spork ~ midiinput(); while (true){ 5000::ms => now; }
ChucK file 21.ck
Happy to see how doable this is and think the event signaling is something to be used more often.
As always and ideas are welcome @scotthewitt. #hackpact
//Number 22 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //extend event for noteoffs class Zeroevent extends Event{ int pitch; } Zeroevent noteoff; //create midi object MidiIn min; MidiMsg msg; //check if midi present if( !min.open(0) ) { me.exit(); } <<< "midi connected" >>>; //handle midi input function void midiinput(){ while(true){ min => now; while( min.recv(msg) ){ if(msg.data3 == 0){ //send pitch noteoff to child shreds msg.data2 => noteoff.pitch; noteoff.broadcast(); }else{ //new picth spork shred (voice) spork ~ synth(msg.data2, msg.data3); } } } } //synth function void synth(int a, int b){ //synth dsp SinOsc s => Envelope env => dac; 50::ms => env.duration; 1 => env.keyOn; Std.mtof(a) => s.freq; while(true){ //await noteoff event noteoff => now; //match noteoff if(noteoff.pitch == a){ 1 => env.keyOff; 51::ms => now; me.exit(); } } } spork ~ midiinput(); while (true){ 5000::ms => now; }
ChucK file 22.ck
As always and ideas are welcome @scotthewitt. #hackpact
//Number 23 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //extend event for noteoffs class Zeroevent extends Event{ int pitch; } Zeroevent noteoff; //create midi object MidiIn min; MidiMsg msg; //check if midi present if( !min.open(0) ) { me.exit(); } <<< "midi connected" >>>; //handle midi input function void midiinput(){ while(true){ min => now; while( min.recv(msg) ){ if(msg.data3 == 0){ //send pitch noteoff to child shreds msg.data2 => noteoff.pitch; noteoff.broadcast(); }else{ //new picth spork shred (voice) spork ~ synth(msg.data2, msg.data3); } } } } //synth function void synth(int a, int b){ float kxf; //synth dsp TriOsc s => ResonZ rz => Envelope env => dac; SinOsc sx => blackhole; 10 => sx.freq; (Std.mtof(a) * 2)=> kxf; //play 50::ms => env.duration; 1 => env.keyOn; Std.mtof(a) => s.freq; while(noteoff.pitch != a){ sx.last() * 80 + kxf => rz.freq; 1::ms => now; <<< rz.freq() >>>; } 1 => env.keyOff; 51::ms => now; me.exit(); } spork ~ midiinput(); while (true){ 5000::ms => now; }
ChucK file 23.ck
As always and ideas are welcome @scotthewitt. #hackpact
//Number 24 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday public class bus { static Gain @ chan[8]; } new Gain[8] @=> bus.chan; //labels for sliders ["0","1","2","3","4","5","6","7"] @=> string label[]; MAUI_View bus_view; bus_view.size( 250, 500 ); MAUI_Gauge gauge[8]; MAUI_Slider slider[8]; //setup gauge function void lev_mon (int a){ while (true){ bus.chan[a].last() * 100.0 => gauge[a].value; 20::ms => now; } } //await slider movment function void slid_event (int b){ while (true){ slider[b] => now; slider[b].value() => bus.chan[b].gain; } } //setup interface for each bus for(0 => int i; i < 8; i++ ){ bus_view.addElement (gauge[i]); gauge[i].position(0,(i * 60)); bus_view.addElement (slider[i]); label[i] => slider[i].name; slider[i].position(0,(i * 60)); spork ~ lev_mon(i); spork ~ slid_event(i); 0 => bus.chan[i].gain; } //draw display bus_view.display(); //demo connects adc => bus.chan[0]; adc => bus.chan[4]; bus.chan[0] => dac; bus.chan[4] => dac; while(true) { 5::second => now; }
ChucK file 24.ck
I have developed it on OSX so there maybe some graphic issues on other platforms also you need the miniAudicle for this one.
As always and ideas are welcome @scotthewitt. #hackpact
//Number 25 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //DSP DelayL del[3]; Gain feedback[3]; adc => Gain gmm => Gain gm => del[0] => dac; gm => del[1] => dac; gm => del[2] => dac; del[0] => feedback[0] => gm; del[1] => feedback[1] => gm; del[2] => feedback[2] => gm; 20::second => del[0].max => del[1].max => del[2].max; 0.0 => gmm.gain; 1.0 => gm.gain; 0.0 => feedback[0].gain => feedback[1].gain => feedback[2].gain; 0.0 => del[0].gain => del[1].gain => del[2].gain; Event exitevent; //GUI elements and layout MAUI_View del_view; del_view.size( 800, 250 ); MAUI_Slider slidermaster; MAUI_Gauge gaugemaster; MAUI_Button exitbutton; exitbutton.pushType(); exitbutton.name("Exit"); del_view.addElement (slidermaster); "Input Volume" => slidermaster.name; slidermaster.position(0,0); del_view.addElement (gaugemaster); gaugemaster.position(250,0); del_view.addElement (exitbutton); exitbutton.position(500,0); MAUI_Slider slider[9]; for(0 => int i; i < 3; i++){ del_view.addElement (slider[i]); "Tap "+ Std.itoa(i) + " Gain" => slider[i].name; slider[i].position(0,((i * 60) + 55)); } for(3 => int i; i < 6; i++){ del_view.addElement (slider[i]); slider[i].precision(8); slider[i].range(0, 20000); "Tap "+ Std.itoa((i - 3)) + " Delay" => slider[i].name; slider[i].position(250,(((i - 3) * 60) + 55)); } for(6 => int i; i < 9; i++){ del_view.addElement (slider[i]); "Tap "+ Std.itoa((i - 6)) + " Feedback" => slider[i].name; slider[i].position(500,(((i - 6) * 60)+ 55)); } MAUI_Gauge gauge[3]; for(0 => int i; i < 3; i++){ del_view.addElement (gauge[i]); gauge[i].size(100.0, 50.0); gauge[i].position(710,((i * 60)+ 65)); } del_view.display(); //GUI functions //a much better way to do the monitor outputs function void lev_mon (){ while (true){ del[0].last() * 100.0 => gauge[0].value; del[1].last() * 100.0 => gauge[1].value; del[2].last() * 100.0 => gauge[2].value; gmm.last() * 100.0 => gaugemaster.value; 20::ms => now; } } //exit button event function void exitbutton_event (){ while (true){ exitbutton => now; exitevent.broadcast(); } } //input slider function void slidinput_event (){ while (true){ slidermaster => now; slidermaster.value() => gmm.gain; } } //gain slider function void slid_event (int b){ while (true){ slider[b] => now; slider[b].value() => del[b].gain; } } //delay slider function void sliddel_event (int b){ while (true){ slider[b] => now; slider[b].value() * 1::ms => del[(b - 3)].delay; } } //feedback slider function void slidfb_event (int b){ while (true){ slider[b] => now; slider[b].value() => feedback[(b - 6)].gain; } } //Program //level monitor spork ~ lev_mon(); spork ~ slidinput_event(); spork ~ exitbutton_event(); //gain slider spork ~ slid_event(0); spork ~ slid_event(1); spork ~ slid_event(2); //del slider spork ~ sliddel_event(3); spork ~ sliddel_event(4); spork ~ sliddel_event(5); //fb slider spork ~ slidfb_event(6); spork ~ slidfb_event(7); spork ~ slidfb_event(8); 500::ms => now; exitevent => now; <<<"test">>>; me.exit(); //this does not seam to work del_view.destroy();
ChucK file 25.ck
As always and ideas are welcome @scotthewitt. #hackpact
//Number 26 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //DSP adc => Gain ginput => Chorus c => dac; 0.0 => ginput.gain; 0.0 => c.modFreq; 0.0 => c.modDepth; Event exitevent; //GUI elements and layout MAUI_View cho_view; cho_view.size( 500, 220 ); MAUI_Slider slidermaster; MAUI_Slider slidermix; MAUI_Slider slidermodf; MAUI_Slider slidermodd; MAUI_Gauge gaugemaster; MAUI_Button exitbutton; exitbutton.pushType(); exitbutton.name("Exit"); cho_view.addElement (slidermaster); "Input Volume" => slidermaster.name; slidermaster.position(0,0); cho_view.addElement (slidermodf); "Modulation Freq" => slidermodf.name; slidermodf.precision(3); slidermodf.range(0., 10.0); slidermodf.position(0, 60); cho_view.addElement (slidermodd); "Modulation Depth" => slidermodd.name; slidermodd.precision(3); slidermodd.range(0., 5.0); slidermodd.position(250, 60); cho_view.addElement (slidermix); "Wet/Dry" => slidermix.name; slidermix.position(0, 120); cho_view.addElement (gaugemaster); gaugemaster.position(250,10); cho_view.addElement (exitbutton); exitbutton.position(250, 120); cho_view.display(); //GUI functions //level monitor function void lev_mon(){ while (true){ ginput.last() * 100.0 => gaugemaster.value; 20::ms => now; } } //exit button event function void exitbutton_event (){ while (true){ exitbutton => now; exitevent.broadcast(); } } //input slider function void slidinput_event (){ while (true){ slidermaster => now; slidermaster.value() => ginput.gain; } } //wet dry slider function void slidwetdry_event (){ while (true){ slidermix => now; slidermix.value() => c.mix; } } //mod depth slider function void slidmoddepth_event (){ while (true){ slidermodd => now; slidermodd.value() => c.modDepth; } } //mod freq slider function void slidmodfreq_event (){ while (true){ slidermodf => now; slidermodf.value() => c.modFreq; } } //spork all functions spork ~ lev_mon(); spork ~ exitbutton_event(); spork ~ slidinput_event(); spork ~ slidwetdry_event(); spork ~ slidmoddepth_event(); spork ~ slidmodfreq_event(); exitevent => now; <<<"Chorus Exit">>>; me.exit(); //this does not seam to work cho_view.destroy();
ChucK file 26.ck
As always and ideas are welcome @scotthewitt. #hackpact
//Number 27 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //DSP adc => Gain ginput => PitShift ps => dac; Event exitevent; //GUI MAUI_View pitgui; MAUI_Slider pitshift; MAUI_Slider pitmix; MAUI_Button exitbutton; MAUI_Gauge gaugemaster; pitgui.addElement (gaugemaster); gaugemaster.position(250,10); pitshift.position(0,0); pitmix.position(0,60); exitbutton.position(300,60); exitbutton.pushType(); exitbutton.name("Exit"); pitshift.name("Pitch Shift"); pitshift.range(0.5, 1.5); pitmix.name("Pitch Mix"); pitgui.addElement(exitbutton); pitgui.addElement(pitshift); pitgui.addElement(pitmix); pitgui.size(500, 200); pitgui.display(); //exit button event function void exitbutton_event (){ while (true){ exitbutton => now; exitevent.broadcast(); } } function void shift_event(){ while (true){ pitshift => now; pitshift.value() => ps.shift; } } function void mix_event(){ while (true) { pitmix => now; pitmix.value() => ps.mix; } } function void lev_mon(){ while (true){ ginput.last() * 100.0 => gaugemaster.value; 20::ms => now; } } //sporks spork ~ lev_mon(); spork ~ exitbutton_event(); spork ~ shift_event(); spork ~ mix_event(); exitevent => now; <<<"Pitch Shift Exit">>>; me.exit();
ChucK file 27.ck
You can choose the example sound files included with ChucK. Not sure if I like having standalone buttons or a more polished interface.
As always and ideas are welcome @scotthewitt. #hackpact
//Number 28 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //base tempo 500::ms => dur basetempo; //Sound file player function void player(string file, dur tempo){ SndBuf sf => dac; file => sf.read; while(true){ 0 => sf.pos; 1 => sf.rate; tempo => now; } } //file player gui and playback logic function void fileplay(string file, float subdivision, string name){ MAUI_Button button; button.toggleType(); button.name( name ); button.display(); basetempo * subdivision => dur elementtempo; while(true) { button => now; //this is the key line @=> Shred offspring spork ~ player(file, elementtempo) @=> Shred offspring; button => now; //exit shred identified offspring.exit(); } } //spork kit parts spork ~ fileplay("chuckaday/hihat.wav", 4, "hihat"); spork ~ fileplay("chuckaday/snare-chili.wav", 3, "snare"); while (true){ 1::minute => now; }
ChucK file 28.ck
Changin the fftsize is alot of fun as well.
As always and ideas are welcome @scotthewitt. #hackpact
//Number 29 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday adc => JCRev jrev => FFT fft =>blackhole; TriOsc t => JCRev jrevA => FFT ffta => blackhole; IFFT ifft => dac; 400 => t.freq; 1024 => fft.size => ffta.size => int fftsize; fftsize / 4 => int frame; complex store[fftsize]; complex storeA[fftsize]; complex storeC[fftsize]; while(true){ fft.upchuck(); fft.spectrum(store); ffta.upchuck(); ffta.spectrum(storeA); for(int i; i < fftsize / 2 ; i++){ store[i] * storeA[i] => storeC[i]; } //<<< store[2], storeA[2], storeC[2] >>>; ifft.transform(storeC); ifft.upchuck(); frame::samp => now; }
ChucK file 29.ck
You can download it here.
As always and ideas are welcome @scotthewitt. #hackpact
function void pitchshift(){ CIPps ps; ps.inouta(0,1); ps.go(); } function void delayeffect(){ CIPdel pdel; pdel.inouta(1,2); pdel.go(); } function void chory(){ CIPch pch; pch.inouta(2,3); pch.go(); } spork ~ pitchshift(); spork ~ delayeffect(); spork ~ chory(); while (true){ 1::minute => now;}
ChucK file 30.ck
As always and ideas are welcome @scotthewitt. #hackpact
This is the end of my Chuck A Day, 31 days done, lots of Chuck learnt, CIP project will be ongoing here.
Thanks for everyones help.
Scott
public class XSynth { UGen in; UGen out; int inputbusnum; int outputbusnum; function void inouta(int xx, int zz){ bus.chan[xx] => in; xx => inputbusnum; out => bus.chan[zz]; zz => outputbusnum; } //GUI elements and layout MAUI_View xsynth_view; xsynth_view.name( "xsynth" ); xsynth_view.size( 800, 250 ); //cip interface stuff MAUI_Slider slidermaster; MAUI_Gauge gaugemaster; MAUI_Button exitbutton; exitbutton.pushType(); exitbutton.name("Exit"); xsynth_view.addElement (slidermaster); "Input Volume" => slidermaster.name; slidermaster.position(0,0); xsynth_view.addElement (gaugemaster); gaugemaster.position(250,0); xsynth_view.addElement (exitbutton); exitbutton.position(500,0); //app interface stuff MAUI_Slider fftsizeslider; "FFT size" => fftsizeslider.name; fftsizeslider.precision(8); fftsizeslider.range(4, 1024); xsynth_view.addElement (fftsizeslider); fftsizeslider.position(0,100); xsynth_view.display(); //DSP in => Gain gm => FFT fft =>blackhole; TriOsc t => JCRev jrevA => FFT ffta => blackhole; IFFT ifft => out; int fftsize; //exit button Event exitevent; 400 => t.freq; 80 => fft.size => ffta.size => fftsize; fftsize / 4 => int frame; //exit button event function void exitbutton_event (){ while (true){ exitbutton => now; exitevent.broadcast(); } } function void slidinput_event (){ while (true){ slidermaster => now; slidermaster.value() => gm.gain; } } function void fftsizeslider_event (){ while (true){ fftsizeslider => now; fftsizeslider.value() $ int => fftsize => fft.size => ffta.size; } } function void lev_mon(){ while (true){ gm.last() * 100 => gaugemaster.value; 20::ms => now; } } function void mainfft (){ while(true){ complex store[fftsize]; complex storeA[fftsize]; complex storeC[fftsize]; fft.upchuck(); fft.spectrum(store); ffta.upchuck(); ffta.spectrum(storeA); for(int i; i < fftsize / 2 ; i++){ store[i] * storeA[i] => storeC[i]; } //<<< store[2], storeA[2], storeC[2] >>>; ifft.transform(storeC); ifft.upchuck(); frame::samp => now; } } function void viewtitle(){ xsynth_view.name( "bus.chan["+Std.itoa(inputbusnum)+"] => XSynth => bus.chan[" + Std.itoa(outputbusnum) +"]" ); } function void go(){ viewtitle(); spork ~ lev_mon(); spork ~ slidinput_event(); spork ~ exitbutton_event(); spork ~ mainfft(); spork ~ fftsizeslider_event(); exitevent => now; xsynth_view.name("dead"); <<<"test">>>; me.exit(); //this does not seam to work xsynth_view.destroy(); } }
ChucK file 31.ck
Plan to use this sort of code on Friday at the Leeds Sound and Music Expo.
As always and ideas are welcome @scotthewitt. #hackpact
//Number 32 //Chuck a day 2009 //by Scott Hewitt //www.ablelemon.co.uk/chuckaday //Each section should be added to the ChucK VM in turn //Section 1 //Extend Event Class public class E extends Event{ int value; } //Section 2 //Create VM wide extended event public class F{ static E @ value; } new E @=> F.value; //Section 3 //Send extended events with ints function void s (){ while (true){ Std.rand2(100,300) => F.value.value; F.value.broadcast(); 500::ms => now; <<<"sent">>>; } } //spork ~ r(); spork ~ s(); while (true){ 1::day => now; } //Section 4 //print recieved event int values while (true){ F.value => now; <<>>; <<<"got">>>; }
ChucK file 32.ck