// Channel 4 chuck code // This chuck code modifies the midi timbre that will be send // from Finale notation software. // This code is written based on the midi input example code // posted on Chuck documentation webpage. // Thanks for Romain for contributing NLFfm filter // (used as an unit generator in this code) // so I can possibly come up with a desired timbre for // channel 4 for my piece, “Somewhere In Between”. // May 29, 2014 // Shu Yu Lin // 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 => LPF lpf => Envelope adsr => JCRev r => dac; .5 => g.gain; .1 => r.mix; //adsr.set(40::ms, 3::ms, .2, 5::ms); //.8 => r.gain; // handler shred for a single voice fun void handler() { NLFfm c; 0 => c.ModulationType; 0.9 => c.gain; // => c.Modulation_Frequency; 1 => c.VibratoFreq; 0.01 => c.Vibrato_Gain; 0.1 => c.VibEnvelopeRelease; 800 => c.Modulation_Frequency; Event off; int note; 0.4 => c.Nonlinearity; 0.3 => c.NonlinearityAttack; while (true) { on => now; on.note => note; adsr.keyOn(); //Std.mtof(note+1) + 800 => c.Modulation_Frequency; Std.mtof(note-1) => lpf.freq; c => g; // connect to gain Std.mtof(note) => c.freq; .4 + on.velocity / 128.0 * .6 => c.gain; 1 => c.gate; off @=> us[note]; off => now; 0 => c.gate; null @=> us[note]; adsr.keyOff(); 30::ms => now; c =< g; } } // spork handlers, one for each voice for (0 => int i; i < 20; i++) spork ~ handler(); while (true) { min => now; <<< "MIDI device:" >>>; // get the midimsg while (min.recv(msg)) { //<<< "MIDI device:" >>>; // catch only noteon if (msg.data1 != 144) continue; // 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(); } } }