mirror of
https://github.com/cookiengineer/audacity
synced 2026-04-26 07:53:42 +02:00
Add Limiter and Crossfade Clips effects.
This commit is contained in:
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.")
|
||||
Reference in New Issue
Block a user