mirror of
https://github.com/cookiengineer/audacity
synced 2026-04-25 23:44:13 +02:00
Add Limiter and Crossfade Clips effects.
This commit is contained in:
@@ -62,10 +62,12 @@ nobase_dist_pkgdata_DATA = \
|
|||||||
plug-ins/beat.ny \
|
plug-ins/beat.ny \
|
||||||
plug-ins/clicktrack.ny \
|
plug-ins/clicktrack.ny \
|
||||||
plug-ins/clipfix.ny \
|
plug-ins/clipfix.ny \
|
||||||
|
plug-ins/crossfadeclips.ny \
|
||||||
plug-ins/crossfadetracks.ny \
|
plug-ins/crossfadetracks.ny \
|
||||||
plug-ins/delay.ny \
|
plug-ins/delay.ny \
|
||||||
plug-ins/equalabel.ny \
|
plug-ins/equalabel.ny \
|
||||||
plug-ins/highpass.ny \
|
plug-ins/highpass.ny \
|
||||||
|
plug-ins/limiter.ny \
|
||||||
plug-ins/lowpass.ny \
|
plug-ins/lowpass.ny \
|
||||||
plug-ins/notch.ny \
|
plug-ins/notch.ny \
|
||||||
plug-ins/pluck.ny \
|
plug-ins/pluck.ny \
|
||||||
|
|||||||
130
plug-ins/crossfadeclips.ny
Normal file
130
plug-ins/crossfadeclips.ny
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
;nyquist plugin
|
||||||
|
;version 4
|
||||||
|
;type process
|
||||||
|
;mergeclips 1
|
||||||
|
;restoresplits 0
|
||||||
|
;name "Crossfade Clips"
|
||||||
|
;action "Crossfading..."
|
||||||
|
;author "Steve Daulton"
|
||||||
|
;copyright "Released under terms of the GNU General Public License version 2"
|
||||||
|
|
||||||
|
|
||||||
|
;; crossfadeclips.ny by Steve Daulton Dec 2014.
|
||||||
|
;; Released under terms of the GNU General Public License version 2:
|
||||||
|
;; http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
|
||||||
|
;; Instructions:
|
||||||
|
;; Place two audio clips into the same track.
|
||||||
|
;; Select (approximately) the same amount of audio from the
|
||||||
|
;; end of one clip and the start of the other.
|
||||||
|
;; Apply the effect.
|
||||||
|
;; The selected regions will be crossfaded.
|
||||||
|
;;
|
||||||
|
;; Note, the audio clips do not need to be touching. Any
|
||||||
|
;; white-space between the clips is ignored.
|
||||||
|
;;
|
||||||
|
;; If the selected region is continuous audio (no splits),
|
||||||
|
;; the the first and last halves of the selected audio
|
||||||
|
;; will be crossfaded.
|
||||||
|
;;
|
||||||
|
;; Advanced Tip:
|
||||||
|
;; A discontinuity in a waveform may be smoothed by applying
|
||||||
|
;; a short crossfade across the glitch.
|
||||||
|
|
||||||
|
;; Limitations (should not occur in normal usage).
|
||||||
|
;; 1) There may be no more than two clips selected in each channel.
|
||||||
|
;; 2) The selection may not start or end in white-space.
|
||||||
|
|
||||||
|
|
||||||
|
(setf err1 "Error.\nInvalid selection.\nMore than 2 audio clips selected.")
|
||||||
|
(setf err2 "Error.\nInvalid selection.\nEmpty space at start/ end of the selection.")
|
||||||
|
|
||||||
|
|
||||||
|
(defun find-ends (T0 T1 clips)
|
||||||
|
"Look for a split or gap within the selection, or return the mid-point"
|
||||||
|
(let ((trk-ends ()) ;starts of clips
|
||||||
|
(trk-starts ())) ;ends of clips
|
||||||
|
(dolist (clip clips)
|
||||||
|
;; look for clip enclosing the selection.
|
||||||
|
(when (and (>= (second clip) T1) (<= (first clip) T0))
|
||||||
|
(psetq trk-ends (list (/ (+ T0 T1) 2))
|
||||||
|
trk-starts (list (/ (+ T0 T1) 2)))
|
||||||
|
(return))
|
||||||
|
;; look for track starts.
|
||||||
|
(when (and (> (first clip) T0) (< (first clip) T1))
|
||||||
|
(push (first clip) trk-starts))
|
||||||
|
;; look for track ends.
|
||||||
|
(when (and (> (second clip) T0) (< (second clip) T1))
|
||||||
|
(push (second clip) trk-ends))
|
||||||
|
; stop looking when we have passed end of selection.
|
||||||
|
(when (> (first clip) T1) (return)))
|
||||||
|
;; if exactly one split position for crossfading,
|
||||||
|
;; return clip positions, else error.
|
||||||
|
(cond
|
||||||
|
((and (= (length trk-ends) 1)
|
||||||
|
(= (length trk-starts) 1)
|
||||||
|
(<= (car trk-ends) (car trk-starts)))
|
||||||
|
(list (car trk-ends)(car trk-starts)))
|
||||||
|
((or (> (length trk-ends) 1)
|
||||||
|
(> (length trk-starts) 1))
|
||||||
|
(throw 'error err1))
|
||||||
|
(T (throw 'error err2)))))
|
||||||
|
|
||||||
|
(defun crossfade (sig out-end in-start end)
|
||||||
|
"Do the crossfade"
|
||||||
|
(abs-env
|
||||||
|
(control-srate-abs *sound-srate*
|
||||||
|
(let* ((fade-out (mult sig (env out-end 0)))
|
||||||
|
(cflen (max out-end (- end in-start))) ;crossfade length
|
||||||
|
(finstart (max (- out-end (- end in-start)) 0))
|
||||||
|
(fade-in (mult (extract (- end cflen) end sig)
|
||||||
|
(env (- cflen finstart) 1 finstart))))
|
||||||
|
(sim fade-out fade-in)))))
|
||||||
|
|
||||||
|
(defun env (dur direction &optional (offset 0))
|
||||||
|
"Generate envelope for crossfade"
|
||||||
|
(abs-env
|
||||||
|
(if (< dur 0.01) ;make it linear
|
||||||
|
(control-srate-abs *sound-srate*
|
||||||
|
(if (= direction 0)
|
||||||
|
(pwlv 1 dur 0) ;fade out
|
||||||
|
(pwlv 0 offset 0 (+ offset dur) 1))) ;fade in
|
||||||
|
(if (= direction 0) ;cosine curve
|
||||||
|
(cos-curve dur 0)
|
||||||
|
(seq (s-rest offset)
|
||||||
|
(cos-curve dur 1))))))
|
||||||
|
|
||||||
|
(defun cos-curve (dur direction)
|
||||||
|
"Generate cosine curve"
|
||||||
|
(if (= direction 0) ;fade out
|
||||||
|
(osc (hz-to-step (/ 0.25 dur)) dur *sine-table* 90)
|
||||||
|
(osc (hz-to-step (/ 0.25 dur)) dur *sine-table* 0)))
|
||||||
|
|
||||||
|
(defun process (sig t0 t1 clips)
|
||||||
|
"Find the split positions and crossfade"
|
||||||
|
(setf fadeclips
|
||||||
|
(multichan-expand #'find-ends t0 t1 clips))
|
||||||
|
(if (arrayp fadeclips)
|
||||||
|
(prog ((fade-out-end (min (first (aref fadeclips 0))
|
||||||
|
(first (aref fadeclips 1))))
|
||||||
|
(fade-in-start (max (second (aref fadeclips 0))
|
||||||
|
(second (aref fadeclips 1)))))
|
||||||
|
(return
|
||||||
|
(multichan-expand #'crossfade sig
|
||||||
|
(- fade-out-end t0)
|
||||||
|
(- fade-in-start t0)
|
||||||
|
(- t1 t0))))
|
||||||
|
(crossfade sig
|
||||||
|
(- (first fadeclips) t0)
|
||||||
|
(- (second fadeclips) t0)
|
||||||
|
(- t1 t0))))
|
||||||
|
|
||||||
|
|
||||||
|
;;; Run the program.
|
||||||
|
(if (= (length (get '*selection* 'tracks)) 1)
|
||||||
|
(catch 'error
|
||||||
|
(process *track*
|
||||||
|
(get '*selection* 'start)
|
||||||
|
(get '*selection* 'end)
|
||||||
|
(get '*track* 'clips)))
|
||||||
|
"Error.\nCrossfade Clips may only be applied to one track.")
|
||||||
134
plug-ins/limiter.ny
Normal file
134
plug-ins/limiter.ny
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
;nyquist plug-in
|
||||||
|
;version 4
|
||||||
|
;type process
|
||||||
|
;categories "http://lv2plug.in/ns/lv2core/#DynamicsPlugin"
|
||||||
|
;name "Limiter..."
|
||||||
|
;action "Limiting..."
|
||||||
|
;preview enabled
|
||||||
|
;author "Steve Daulton"
|
||||||
|
;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:
|
||||||
|
;; http://wiki.audacityteam.org/wiki/Nyquist_Plug-ins_Reference
|
||||||
|
|
||||||
|
;control type "Type" choice "Soft Limit,Hard Limit,Soft Clip,Hard Clip" 0
|
||||||
|
;control gain-L "Input Gain (dB)\nmono/Left" real "" 0 0 10
|
||||||
|
;control gain-R "Input Gain (dB)\nRight 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 smaples
|
||||||
|
(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
|
||||||
|
(Control-srate-abs *sound-srate*
|
||||||
|
(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))))
|
||||||
Reference in New Issue
Block a user