env4.lsp Version 1.00 05 April 2005 Author Steven Jones Contact jones57@swbell.net include the word "nyquist" in subject line The contents of this file are released under the terms of the GNU General Public License. See the file LICENSE.txt Implements DX7 style envelope; 4 levels, 4 rates.
class
A 4-level, 4-rates envelope
method
(send env4:class :new gate lev1 lev2 lev3 lev4 time1 time2 time3 time4) Construct new env4:class object. See function env4 for arguments.
function
(env4 gate lev1 lev2 lev3 lev4 time1 time2 time3 time4) A DX7 style envelope. The envelope has 4-levels and 4-rates. Initially the output is at lev4 and immediately moves to lev1 over time1 seconds. After time1 the output moves to lev2 in time2 seconds. Similarly the output moves from lev2 to lev3 over the next time3 seconds. The output is static at lev3 for as long as the key is held down (key depression time is represented by the gate argument) After the key is released the output moves from lev3 to lev4 over time4 seconds. If the key is released prior to the sustain stage the output immediately starts to move towards lev4. gate - Flonum. The "key down" time in seconds. lev1 - Flonum. Output level after time1 seconds. lev2 - Flonum. Output level after time1+time2 seconds lev3 - Flonum. Output level after time1+time2+time3 seconds lev4 - Flonum. Initial and final output level time1 - Flonum. Interval in seconds between lev0 and lev1. Note lev0 is the same as lev4 time2 - Flonum. Interval in seconds between lev1 and lev2. time3 - Flonum. Interval in seconds between lev2 and lev3. time4 - Flonum. Decay time in seconds. There is always a decay stage. The other stages may be terminated by the gate time. return - Sound. The total duration of the resault is gate+time4.
;; env4.lsp ;; Version 1.00 05 April 2005 ;; Author Steven Jones ;; ;; Contact jones57@swbell.net include the word "nyquist" in subject line ;; ;; The contents of this file are released under the terms of the GNU General ;; Public License. See the file LICENSE.txt ;; ;; Implements DX7 style envelope; 4 levels, 4 rates. ;; (provide 'env4) (current-file "env4") ;; @doc class env4:class ;; A 4-level, 4-rates envelope ;; (setf env4:class (send class :new '(.out ;Current output level. .delta-1 ;Increment stage 1-4. .delta-2 .delta-3 .delta-4 .lev-4 ;Amplitude of level 4. .events-1 ;Number of samples/stage 1-4. .events-2 .events-3 .events-4 .events-g ;Number of samples while key-down. .temp ;Temporary variable. ))) ;; @doc method env4:class :new ;; (send env4:class :new gate lev1 lev2 lev3 lev4 time1 time2 time3 time4) ;; Construct new env4:class object. ;; See function env4 for arguments. ;; (send env4:class :answer :isnew '(gate lev1 lev2 lev3 lev4 time1 time2 time3 time4) '( (setf .out lev4) (setf .events-1 (truncate (* time1 *control-srate*))) (setf .events-2 (truncate (* time2 *control-srate*))) (setf .events-3 (truncate (* time3 *control-srate*))) (setf .events-4 (truncate (* time4 *control-srate*))) (setf .events-g (truncate (* gate *control-srate*))) (setf .delta-1 (if (zerop .events-1) 0 (/ (float (- lev1 lev4)) .events-1))) (setf .delta-2 (if (zerop .events-2) 0 (/ (float (- lev2 lev1)) .events-2))) (setf .delta-3 (if (zerop .events-3) 0 (/ (float (- lev3 lev2)) .events-3))) ;; We don't know initial amplitude of stage 4 yet, ;; defer calculation of delta-4. (setf .delta-4 nil) (setf .lev-4 lev4) )) ;; @method env4:class :next ;; (send /env4:class/ :next) ;; Sequentially return envelope values. After returning final envelope sample ;; the next call to :next returns nil. ;; (send env4:class :answer :next '() '( ;(display "" .out .events-g .events-1 .events-2 .events-3) (if (plusp .events-g) ;; Stages 1 - 3 (cond ((plusp .events-1) ;(display "attack" .out .events-g .events-1 .events-2 .events-3) (setf .temp .out) (setf .out (+ .out .delta-1)) (setf .events-1 (1- .events-1)) (setf .events-g (1- .events-g)) .out) ((plusp .events-2) (setf .temp .out) (setf .out (+ .out .delta-2)) (setf .events-2 (1- .events-2)) (setf .events-g (1- .events-g)) .out) ((plusp .events-3) (setf .temp .out) (setf .out (+ .out .delta-3)) (setf .events-3 (1- .events-3)) (setf .events-g (1- .events-g)) .out) ;; sustain stage (t (setf .events-g (1- .events-g)) .out)) ;; Decay stage 4 (progn (if (null .delta-4) (setf .delta-4 (if (zerop .events-4) 0 (/ (float (- .lev-4 .out)) .events-4)))) (if (plusp .events-4) (progn ;(display "decay" .out .delta-4 .events-4 .events-g) (setf .temp .out) (setf .out (+ .out .delta-4)) (setf .events-4 (1- .events-4)) .out) nil)) ))) ;; @doc function env4 ;; (env4 gate lev1 lev2 lev3 lev4 time1 time2 time3 time4) ;; A DX7 style envelope. ;; ;; The envelope has 4-levels and 4-rates. Initially the output is at lev4 and ;; immediately moves to lev1 over time1 seconds. After time1 the output moves ;; to lev2 in time2 seconds. Similarly the output moves from lev2 to lev3 over ;; the next time3 seconds. The output is static at lev3 for as long as the key ;; is held down (key depression time is represented by the gate argument) ;; After the key is released the output moves from lev3 to lev4 over time4 ;; seconds. If the key is released prior to the sustain stage the output ;; immediately starts to move towards lev4. ;; ;; gate - Flonum. The "key down" time in seconds. ;; lev1 - Flonum. Output level after time1 seconds. ;; lev2 - Flonum. Output level after time1+time2 seconds ;; lev3 - Flonum. Output level after time1+time2+time3 seconds ;; lev4 - Flonum. Initial and final output level ;; time1 - Flonum. Interval in seconds between lev0 and lev1. ;; Note lev0 is the same as lev4 ;; time2 - Flonum. Interval in seconds between lev1 and lev2. ;; time3 - Flonum. Interval in seconds between lev2 and lev3. ;; time4 - Flonum. Decay time in seconds. There is always a decay stage. ;; The other stages may be terminated by the gate time. ;; return - Sound. The total duration of the resault is gate+time4. ;; (defun env4 (gate lev1 lev2 lev3 lev4 time1 time2 time3 time4) ;(display "env4" gate lev1 lev2 lev3 lev4 time1 time2 time3 time4) (let (obj) (setf gate (max gate (min-control-time))) (setf obj (send env4:class :new gate lev1 lev2 lev3 lev4 (max (min-control-time) time1) time2 time3 time4)) (snd-fromobject (local-to-global 0) *control-srate* obj)))