//------------------------------------------------ // name: polyfony2.ck // desc: polyfonic clarinet model with midi input // // authors: Ananya Misra and Ge Wang // send all complaints to prc@cs.princeton.edu //-------------------------------------------- // device to open 0 => int device; // get from command line if( me.args() ) me.arg(0) => Std.atoi => device; MidiIn min; MidiMsg msg; // try to open MIDI port (see chuck --probe for available devices) if( !min.open( device ) ) me.exit(); // print out device that was opened <<< "MIDI device:", min.num(), " -> ", min.name() >>>; // make our own event class NoteEvent extends Event { int note; int velocity; } // the event NoteEvent on; // array of ugen's handling each note Event @ us[128]; // the base patch Gain g => JCRev r => dac; .1 => g.gain; .2 => r.mix; // handler shred for a single voice fun void handler() { // don't connect to dac until we need it Clarinet c; Event off; int note; // inifinite time loop while( true ) { on => now; on.note => note; // dynamically repatch c => g; Std.mtof( note ) => c.freq; .4 + on.velocity / 128.0 * .6 => c.startBlowing; off @=> us[note]; off => now; c.stopBlowing( 10.0 ); null @=> us[note]; 100::ms => now; c =< g; } } // spork handlers, one for each voice for( 0 => int i; i < 20; i++ ) spork ~ handler(); // infinite time loop while( true ) { // wait on midi event min => now; // get the midimsg while( min.recv( msg ) ) { // catch only noteon if( (msg.data1 & 0xf0) == 0x90 ) { // check velocity if( msg.data3 > 0 ) { // store midi note number msg.data2 => on.note; // store velocity msg.data3 => on.velocity; // signal the event on.signal(); // yield without advancing time to allow shred to run me.yield(); } else { if( us[msg.data2] != null ) us[msg.data2].signal(); } } else if( (msg.data1 & 0xf0) == 0x80 ) { us[msg.data2].signal(); } } }