public class gaussian_env { // members vars Envelope line; 5::second => line.duration; // 10::second from -1 to 1 gain g; //constants math.sqrt(2.) => float sqrt2; -1. => float init_val; 5.*sqrt2 => float k; // sets the width of the peak line.value( init_val ); line.target( 1 ); fun void keyOn() { line.value( -1 ); line.target( 1 ); line.keyOn; } fun void keyOff() { line.value( 1 ); line.target( -1 ); line.keyOff; } fun void gauss_bell( float x ){ math.exp( -k*x*x) => g.gain; } // note that line goes from -1 to 1, instead of 0 to 1. For this reason when // setting duration of the gaussian envelope we must divide by two. On the other // hand, when retrieving duration we must multiply by two. // The reason might be that "Envelope" ugen sets duration from 0 to target value // and not from value to target. fun void duration( dur t ){ line.duration( 0.5*t ); } // set duration fun dur get_duration(){ return line.duration()*2; } // get duration // changing k will affect the shape of the bell, and thus you will have to define // new line.value and line.target accordingly fun void bell_width( float n ){ n*sqrt2 => k; } fun void connect( UGen from, UGen to ) { line => blackhole; from => g => to; } fun void thread() { while( true ) { gauss_bell( line.value() ); 1::samp => now; if( line.value() >= 1 ) keyOff(); else if( line.value() <= -1 ) keyOn(); // <<< line.value(), g.gain(), now/second >>>; } } } // how to use it: sinosc sine; sinosc sine2; .5 => sine.gain => sine2.gain; sine.freq( 1000. ); sine2.freq( 1150. ); gaussian_env gauss; gauss.connect( sine, dac ); gauss.connect( sine2, dac ); gauss.duration( 30::second ); spork ~ gauss.thread(); while( true ) { <<< now/second, gauss.line.value(), gauss.g.gain() >>>; 1::second => now; // <<>>; }