Silence Marker Plus
Marks silence in more ways than default Silence Finder
;nyquist plug-in
;version 1
;type analyze
;categories "http://lv2plug.in/ns/lv2core#AnalyserPlugin"
;name "Silence Marker Plus..."
;action "Marking silence in various ways..."
;info "Adds labels in various points of silence according to the specified level and duration of silence.\nIf too many silences are detected, increase the silence level and/or duration;\nif too few are detected, reduce the level and/or duration.\nThe more samples per second checked, the more precisely the program can place the silence labels, but the longer it takes."
;author "uvhwpevx"
;copyright "Released under terms of the GNU General Public License version 2"
;; by uvhwpevx
;; Based on Silence Finder by Alex S. Brown, PMP (http://www.alexsbrown.com)
;; Released under terms of the GNU General Public License version 2:
;; http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
;control sil-lev "Treat audio below this level as silence, -dB" real "" 26 0 100
;control sil-dur "Minimum duration of silence, seconds" real "" 0.25 0.01 60
;control per-sec "Analyze samples per second" int "" 1000 1 16000
;control labeltype "Label placement" choice "Silence midpoint,At % of silence time,All silence (T1...T2),At T1 seconds after silence begins,At T2 seconds before silence ends" 0
;control labelatdur "Label at % of silence time (if selected)" real "" 33.333 0.0 100.0
;control labelafterdur "Padding T1 after silence begins, seconds" real "" 0.0 0.0 60.0
;control labelbeforedur "Padding T2 before silence ends, seconds" real "" 0.0 0.0 60.0
;control labeltext "Label text" string "" "" ""
;Create a function to make the sum the two channels if they are stereo
(defun mono-s (s-in) (if (arrayp s-in) (snd-add (aref s-in 0) (aref s-in 1)) s-in))
;Create a function to reduce the sample rate and prepare the signal for
;analysis. RMS is good to monitor volume the way humans hear it, but is not
;available in Audacity. Used a peak-calculating function instead.
;NOTE: this is the place to add any processing to improve the quality of the
;signal. Noise filters could improve the quality of matches for noisy signals.
;PERFORMANCE vs. ACCURACY
;Reducing the samples per second should improve the performance and decrease
;the accuracy of the labels. Increasing the samples per second will do the
;opposite. The more samples checked, the longer it takes. The more samples
;checked, the more precisely the program can place the silence labels.
;my-srate-ratio determines the number of samples in my-s.
(defun my-s (s-in)
(setq my-srate-ratio (truncate (/ (snd-srate (mono-s s-in)) per-sec)))
(snd-avg (mono-s s-in) my-srate-ratio my-srate-ratio OP-PEAK)
)
;Set the silence threshold level (convert it to a linear form)
(setq thres (db-to-linear (* -1 sil-lev)))
;Store the sample rate of the sound
(setq s1-srate (snd-srate (my-s s)))
;Initialize the variable that will hold the length of the sound.
;Do not calculate it now with snd-length, because it would waste memory.
;We will calculate it later.
(setq s1-length 0)
;Initialize the silence counter and the labels variable
(setq sil-c 0)
(setq l NIL)
;Convert the silence duration in seconds to a length in samples
(setq sil-length (* sil-dur s1-srate))
;Define a function to add new items to the list of labels
(defun add-label (l-time l-text)
(setq l (cons (list l-time l-text) l))
)
(defun add-range-label (l-starttime l-endtime l-text)
(setq l (cons (list l-starttime l-endtime l-text) l))
)
;The main working part of the program, it counts
;the number of sequential samples with volume under
;the threshold. It adds to a list of markers ever time
;there is a longer period of silence than the silence
;duration amount.
;It runs through a loop, adding to the list of markers (l) each time it finds silence.
(let (s1) ;Define s1 as a local variable to allow efficient memory use
; Get the sample into s1, then free s to save memory
(setq s1 (my-s s))
(setq s nil)
;Capture the result of this "do" loop, because we need the sountd's legnth in samples.
(setq s1-length
;Keep repeating, incrementing the counter and getting another sample each time through the loop.
(do ((n 1 (+ n 1)) (v (snd-fetch s1) (setq v (snd-fetch s1))))
;Exit when we run out of samples (v is nil) and return the number of samples processed (n)
((not v) n)
;Start the execution part of the do loop
;if found silence, increment the silence counter
(if (< v thres) (setq sil-c (+ sil-c 1)))
;If this sample is NOT silent and the previous samples were silent then mark the passage.
(if (and (> v thres) (> sil-c sil-length))
(case labeltype
(0 (add-label (/ (- n (/ sil-c 2)) s1-srate) labeltext)) ;At midpoint
(1 (add-label (/ (- n (* sil-c (- 1.0 (/ labelatdur 100.0)))) s1-srate) labeltext)) ; At % of silence time
(2 (if (>= (/ sil-c s1-srate) (+ labelafterdur labelbeforedur)) ;All silence (T1...T2)
(add-range-label (+ (/ (- n sil-c) s1-srate) labelafterdur) (- (/ n s1-srate) labelbeforedur) labeltext)))
(3 (if (>= (/ sil-c s1-srate) labelafterdur) ;At T1 seconds after silence begins
(add-label (+ (/ (- n sil-c) s1-srate) labelafterdur) labeltext)))
(4 (if (>= (/ sil-c s1-srate) labelbeforedur) ;At T2 seconds before silence ends
(add-label (- (/ n s1-srate) labelbeforedur) labeltext)))
)
)
;If this sample is NOT silent, then reset the silence counter
(if (> v thres)
(setq sil-c 0)
)
)
)
)
;Check for a long period of silence at the end of the sample. If so, then mark it.
(if (> sil-c sil-length)
;If found, add a label
;Label time is the time the silence began plus the silence duration target
;amount. We calculate the time the silence began as the end-time minus the
;final value of the silence counter
(add-label (+ (/ (- s1-length sil-c) s1-srate) sil-dur) labeltext)
)
;If no silence markers were found, return a message
(if (null l)
(setq l "No silences found.\nTry reducing the silence level\nand/or minimum silence duration.")
)
l
Unfortunately, moderators still are suspecting me of something hideous and disabled BBCode and all stuff in my messages…