UNPKG

genish.js

Version:
106 lines (81 loc) 3.37 kB
/* * There are a variety of different ways to do enveloping using the ugens in genish.js. * There are two included envelopes found in typical synthesis algorithms ( ad() and adsr() ) * but there are many other ways to envelope. In fact, it is important to note that both ad and * adsr are simple aggreates of other genish.js ugens; you could easily re-create them on your own. * * This tutorial will attempt to look at some of the various options for enveloping in genish.js */ // First, we can create a ascending and descending ramps using accum(). The trick is to wrap the // accum() in miggn() or max() so that they don't go below 0 (for decays) or above 1 (for attacks). // We also need to set the shouldWrap property to be false. Below is a descending ramp, starting // at 1 and traveling downward. { 'use jsdsp' trigger = bang() mydecay = max( accum( -2 / gen.samplerate, trigger, { shouldWrap:false, resetValue:1 }), 0 ) play( cycle(330) * mydecay ) } // re-trigger envelope trigger.trigger() /* * Part II: By using two of these together in an ifelse ugen, we can create a linear attack-decay. * The code below is almost identical to the linear version of the ad() ugen. */ attackTrigger = bang() decayTrigger = bang() attack = gen.samplerate * 2 // two seconds decay = gen.samplerate * 2 // two seconds { 'use jsdsp' // create the attack myattack = accum( 1 / attack, attackTrigger ) // create the decay mydecay = accum( -1 / decay, decayTrigger, { resetValue:1 }) // running phase accumulator to determine currnet envelope stage phase = accum( 1, attackTrigger, { shouldWrap:false } ) myenv = ifelse( // attack... if phase is less than two seconds lt( phase, attack ), myattack, // else if envelope is still supposed to run, decay lt( phase, attack + decay ), mydecay, // else return 0 0 ) play( cycle(330) * myenv * .25 ) } // re-trigger envelope (run both lines at once) attackTrigger.trigger() decayTrigger.trigger() /* * The envelope generated above can also be created simply using ad( 88200, 88200 ), but hopefully * illustrating how the ad() ugen works will give you some ideas for your own envelopes. ad() and * adsr() also use exponential envelopes by default, so they work a little bit better perceptually (you * can change this by adding a { shape:'linear' } properties dictionary to either ugen). * Using the ifelse() ugen, we can make as many stages in our envelope as our heart desires. That's * basically how the adsr() works, simply extending our previous example with a couple of more stages. */ { 'use jsdsp' osc = phasor(330) // attackTime, decayTime, sustainTime, sustainLevel, releaseTime env = adsr( gen.samplerate / 2, gen.samplerate / 2, gen.samplerate, .65, gen.samplerate ) play( osc * env * .15 ) } env.trigger() /* * We can also specify that the release stage of our envelope should be triggered; * until the envelope will remain at the sustainLevel */ { 'use jsdsp' osc = phasor(330) // attackTime, decayTime, sustainTime, sustainLevel, releaseTime env = adsr( gen.samplerate / 2, gen.samplerate / 2, gen.samplerate, .65, gen.samplerate, { triggerRelease:true }) play( osc * env * .15 ) } // trigger env.trigger() // release env.release() // see the adsr documentation for more details.