-
Notifications
You must be signed in to change notification settings - Fork 18
Implement proper ADSR envelope. #7
Comments
Just thought I'd share the technique I used to handle releases in my ADSRs. When I evaluate the ADSR at time (Since I'm using floats, I could have used ¹ using the same curves you do, I cribbed off this project to implement them because mine were klunky. ;) I switched my project to OCaml because DSP is all math and OCaml makes that easy (and super composable.) I may port it back to Rust when I have it working. Anyway, hopefully you can get the gist of it. This code isn't quite finished, but it does the job: let rec adsr ?(curves=(0.,0.,0.)) at dt sl rt =
let (ac, dc, rc) = curves in
fun tr t ->
let mul = match tr with
| Some tr -> (* release case *)
let self = adsr ~curves:curves at dt sl rt in (* get a copy of this ADSR *)
let delt = t -. tr in (* delt = t_now - t_release *)
if delt < 0. then self None t (* relase is in the future; evaluate up to t_now without release *)
else if delt > rt then 0. (* release is over, output 0.0 *)
else
let level = self None tr in
curve rc level 0. (delt /. rt) (* compute the curve *)
| None ->
if t < at then curve ac 0. 1. (t /. at)
else if t < dt +. at
then
let delt = t -. at in
curve dc 1. sl (delt /. dt)
else sl
in mul Some plots with curves=(1.0,1.0,1.0) and varying t_release to test the different phases: Looking at that last plot I just realized there's a bug. The falloff isn't immediately exponential. (Frustratingly, the previous version I wrote accounted for this and did it right.) Anyway, I updated the code above and here's a new plot: I hope this helps if you need any help for the design. You might want to consider state instead for performance. I didn't bother because I would have to recurse the first time anyway to create the state and this thing is aready running quite fast even when supersampled at 16x and with a dumb plotting frontend attached to it. There is a foible. The function blindly returns a value when the release is over so there's no indication that the note is finished. I thought about making it an Peace. |
Thanks a lot for this! Will have a proper read through it soon 👍 |
Np. And yeah... sorry about the length. When I started I didn't think I'd go on so much. |
@smosher Impressive! |
http://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope
Might be best to create an adsr_envelope abstraction in a separate crate.
The text was updated successfully, but these errors were encountered: