mirror of
				https://github.com/cookiengineer/audacity
				synced 2025-10-31 14:13:50 +01: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/clicktrack.ny \ | ||||
|    plug-ins/clipfix.ny \ | ||||
|    plug-ins/crossfadeclips.ny \ | ||||
|    plug-ins/crossfadetracks.ny \ | ||||
|    plug-ins/delay.ny \ | ||||
|    plug-ins/equalabel.ny \ | ||||
|    plug-ins/highpass.ny \ | ||||
|    plug-ins/limiter.ny \ | ||||
|    plug-ins/lowpass.ny \ | ||||
|    plug-ins/notch.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