mirror of
https://github.com/cookiengineer/audacity
synced 2025-04-29 15:19:44 +02:00
150 lines
4.6 KiB
Common Lisp
150 lines
4.6 KiB
Common Lisp
$nyquist plug-in
|
|
$version 4
|
|
$type process
|
|
$name (_ "Limiter")
|
|
$manpage "Limiter"
|
|
$debugbutton false
|
|
$action (_ "Limiting...")
|
|
$preview enabled
|
|
$author (_ "Steve Daulton")
|
|
$release 2.3.0
|
|
$copyright (_ "Released under terms of the GNU General Public License version 2")
|
|
|
|
;; limiter.ny by Steve Daulton November 2011, updated May 2015.
|
|
|
|
;; Released under terms of the GNU General Public License version 2:
|
|
;; http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
;;
|
|
;; For information about writing and modifying Nyquist plug-ins:
|
|
;; https://wiki.audacityteam.org/wiki/Nyquist_Plug-ins_Reference
|
|
|
|
$control type (_ "Type") choice (
|
|
("SoftLimit" (_ "Soft Limit"))
|
|
("HardLimit" (_ "Hard Limit"))
|
|
;i18n-hint: clipping of wave peaks and troughs, not division of a track into clips
|
|
("SoftClip" (_ "Soft Clip"))
|
|
("HardClip" (_ "Hard Clip"))
|
|
) 0
|
|
$control gain-L (_ "Input Gain (dB)
|
|
mono/Left") real "" 0 0 10
|
|
$control gain-R (_ "Input Gain (dB)
|
|
Right channel") real "" 0 0 10
|
|
$control thresh (_ "Limit to (dB)") real "" -3 -10 0
|
|
$control hold (_ "Hold (ms)") real "" 10 1 50
|
|
$control makeup (_ "Apply Make-up Gain") choice (
|
|
(_ "No")
|
|
(_ "Yes")
|
|
) 0
|
|
|
|
(if (not (boundp 'type))
|
|
(setf type 0))
|
|
|
|
(if (boundp 'gain-L)
|
|
(setf gain-L (db-to-linear gain-L))
|
|
(setf gain-L 1))
|
|
|
|
(if (boundp 'gain-R)
|
|
(setf gain-R (db-to-linear gain-R))
|
|
(setf gain-R 1))
|
|
|
|
(if (boundp 'thresh)
|
|
(setf thresh (db-to-linear thresh))
|
|
(setf thresh (db-to-linear -3.0)))
|
|
|
|
(if (not (boundp 'hold))
|
|
(setf hold 10.0))
|
|
|
|
(if (boundp 'makeup)
|
|
(if (= makeup 1) (setf makeup T) (setf makeup nil))
|
|
(setf makeup nil))
|
|
|
|
;;; brick wall limiter
|
|
(defun hardlimit (sig limit hld)
|
|
(let* ((time (/ hld 3000.0)) ; lookahead time (seconds)
|
|
(samples (round (* time *sound-srate*))) ; lookahead in samples
|
|
(peak-env (get-env sig samples time limit)))
|
|
(mult sig
|
|
(snd-exp
|
|
(mult -1 (snd-log peak-env))))))
|
|
|
|
;;; Envelope follower for brick wall limiter
|
|
(defun get-env (sig step lookahead limit)
|
|
(let* ((sig (mult (/ limit) sig))
|
|
(pad-time (* 3 lookahead)) ; padding required at start (seconds)
|
|
(pad-s (* 3 step)) ; padding samples
|
|
(padding (snd-const (peak sig pad-s) 0 *sound-srate* pad-time))
|
|
(peak-env (snd-avg sig (* 4 step) step OP-PEAK)))
|
|
(extract 0 1
|
|
(s-max 1
|
|
(sim padding
|
|
(at-abs pad-time (cue peak-env)))))))
|
|
|
|
(defun softlimit (sig thresh hld)
|
|
(let* ((sig (hardlimit sig 1 hold))
|
|
(step (truncate (* (/ hld 3000.0) *sound-srate*)))
|
|
(waveshape (snd-avg sig (* 4 step) step op-peak))
|
|
(env (sum thresh (mult thresh (diff 1 waveshape))))
|
|
(env (clip env 1))
|
|
(offset (/ (* 3 step) *sound-srate*))
|
|
(initial (peak sig (* 2 step)))
|
|
(pause-lev (sum thresh (mult thresh (diff 1 initial))))
|
|
(pause-lev (clip pause-lev 0.9))
|
|
(pause (snd-const pause-lev 0 *sound-srate* offset)))
|
|
(setf env
|
|
(sim
|
|
pause
|
|
(at-abs offset (cue env))))
|
|
(mult sig env)))
|
|
|
|
|
|
(defun soft-clip-table ()
|
|
"Lookup table for soft clipping wave-shaper"
|
|
(abs-env
|
|
(sound-srate-abs 44100
|
|
(Control-srate-abs 44100
|
|
(let* ((knee (- 1 (/ 1.0 pi)))
|
|
(kcurve (mult knee (osc (hz-to-step (/ (* 4 knee))) knee)))
|
|
(ikcurve (mult knee (osc (hz-to-step (/ (* 4 knee))) knee *sine-table* -90)))
|
|
(lin (pwlv -0.5 knee -0.5
|
|
(+ knee (/ 2.0 pi)) 0.5
|
|
2.0 0.5
|
|
2.0 (+ 0.5 knee)
|
|
2.1 (+ 0.5 knee))))
|
|
(mult (/ 2.0 pi)
|
|
(sim
|
|
(at-abs 0 (cue ikcurve))
|
|
(at-abs 0 (cue lin))
|
|
(at-abs (+ knee (/ 2.0 pi)) (cue kcurve)))))))))
|
|
|
|
(defun soft-clip (sig)
|
|
(let* ((knee (- 1 (/ 1.0 pi)))
|
|
(clip-level (* (+ 0.5 knee)(/ 2.0 pi)))
|
|
(sig (mult clip-level (/ thresh) sig)))
|
|
(if makeup
|
|
(mult 0.999
|
|
(/ clip-level)
|
|
(shape sig (soft-clip-table) 1.0))
|
|
(mult thresh
|
|
(/ clip-level)
|
|
(shape sig (soft-clip-table) 1.0)))))
|
|
|
|
|
|
(defun makupgain (sig)
|
|
(if makeup
|
|
(mult (/ 0.999 thresh) sig) ;keep below 0dB
|
|
sig))
|
|
|
|
;; Pre-gain
|
|
(setf *track*
|
|
(if (arrayp *track*)
|
|
(vector (mult (aref *track* 0) gain-L)
|
|
(mult (aref *track* 1) gain-R))
|
|
(mult *track* gain-L)))
|
|
|
|
|
|
(case type
|
|
(0 (makupgain (multichan-expand #'softlimit *track* thresh hold)))
|
|
(1 (makupgain (multichan-expand #'hardlimit *track* thresh hold)))
|
|
(2 (soft-clip *track*))
|
|
(T (makupgain (clip *track* thresh))))
|