{"id":191,"date":"2013-06-03T00:24:35","date_gmt":"2013-06-03T07:24:35","guid":{"rendered":"http:\/\/www.earlevel.com\/main\/?p=191"},"modified":"2017-01-07T12:10:04","modified_gmt":"2017-01-07T20:10:04","slug":"envelope-generators-adsr-code","status":"publish","type":"post","link":"https:\/\/www.earlevel.com\/main\/2013\/06\/03\/envelope-generators-adsr-code\/","title":{"rendered":"Envelope generators\u2014ADSR code"},"content":{"rendered":"<p>First, a brief example of how to use the ADSR code:<\/p>\n<pre>\r\n\/\/ create ADSR env\r\nADSR *env = new ADSR();\r\n\r\n\/\/ initialize settings\r\nenv->setAttackRate(.1 * sampleRate);  \/\/ .1 second\r\nenv->setDecayRate(.3 * sampleRate);\r\nenv->setReleaseRate(5 * sampleRate);\r\nenv->setSustainLevel(.8);\r\n\u2026\r\n\/\/ at some point, by MIDI perhaps, the envelope is gated \"on\"\r\nenv->gate(true);\r\n\u2026\r\n\/\/ and some time later, it's gated \"off\"\r\nenv->gate(false);\r\n<\/pre>\n<p>In your &#8220;real-time&#8221; thread, where you fill audio buffers for output, you&#8217;d use the process command to generate and return the next ADSR output:<\/p>\n<pre>\r\n\/\/ env->process() to generate and return the ADSR output...\r\noutBuf[idx] = filter->process(osc->getOutput()) * env->process();\r\n<\/pre>\n<h3>Functions<\/h3>\n<p>Create and destroy:<\/p>\n<pre>\r\nADSR(void);\r\n~ADSR(void);\r\n<\/pre>\n<p>Call the <em>process<\/em> function at the control rate (which might be once per sample period, or a lower rate if you&#8217;ve implemented a lower control sampling rate); it returns the current envelope output. The <em>getOutput<\/em> function returns the current output only, for convenience:<\/p>\n<pre>\r\nfloat process(void);\r\nfloat getOutput(void);\r\n<\/pre>\n<p>Set the gate state on (true) or off (false):<\/p>\n<pre>\r\nvoid gate(int on);\r\n<\/pre>\n<p>Set the Attack, Decay, and Release rates (in samples\u2014you can multiply time in seconds by the sample rate), and the sustain level (0.0-1.0); call these when settings change, not at the sample rate:<\/p>\n<pre>\r\nvoid setAttackRate(float rate);\r\nvoid setDecayRate(float rate);\r\nvoid setReleaseRate(float rate);\r\nvoid setSustainLevel(float level);\r\n<\/pre>\n<p>Adjust the curves of the Attack, or Decay and Release segments, from the initial default values (small number such as 0.0001 to 0.01 for mostly-exponential, large numbers like 100 for virtually linear):<\/p>\n<pre>\r\nvoid setTargetRatioA(float targetRatio);\r\nvoid setTargetRatioDR(float targetRatio);\r\n<\/pre>\n<p>Reset the envelope generator:<\/p>\n<pre>\r\nvoid reset(void);\r\n<\/pre>\n<p>It may be useful to know what state an envelope generator is in, for sophisticated control applications (typically, though, you won&#8217;t need this); a state enum is defined for convenience (for example, ADSR::env_sustain is equivalent to the value 3, and indicates that the current state is Sustain):<\/p>\n<pre>\r\nint getState(void);\r\n    env_idle = 0, env_attack, env_decay, env_sustain, env_release\r\n<\/pre>\n<h3>Code<\/h3>\n<p>Calculations that are done in the \u201creal time\u201d thread are written as inline code in the header file. Calculations that are done asynchronously, at \u201csetup time\u201d (which include patch recall and \u201cknob twiddling\u201d), are in the cpp file functions; this includes sub-calculations of the real-time math that are dependent only on setup-time parameters.<\/p>\n<p><a href=\"\/main\/wp-content\/uploads\/2013\/06\/ADSR.zip\" title=\"Download ADSR source code\">Download ADSR source code<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>First, a brief example of how to use the ADSR code: \/\/ create ADSR env ADSR *env = new ADSR(); \/\/ initialize settings env->setAttackRate(.1 * sampleRate); \/\/ .1 second env->setDecayRate(.3 * sampleRate); env->setReleaseRate(5 * sampleRate); env->setSustainLevel(.8); \u2026 \/\/ at some &hellip; <a href=\"https:\/\/www.earlevel.com\/main\/2013\/06\/03\/envelope-generators-adsr-code\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[25,26,23],"tags":[],"_links":{"self":[{"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/posts\/191"}],"collection":[{"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/comments?post=191"}],"version-history":[{"count":2,"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/posts\/191\/revisions"}],"predecessor-version":[{"id":598,"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/posts\/191\/revisions\/598"}],"wp:attachment":[{"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/media?parent=191"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/categories?post=191"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.earlevel.com\/main\/wp-json\/wp\/v2\/tags?post=191"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}