Hello to somebody that reads this.
I made a small plugin to take a measurement of RMS intensity.
Finally it does the same thing than vu-meter does in real time, exept that you can get the value written and modulate measurement duration. So very simple idea, but maybe to simple to be thought…
I needed it because my purpose was to evaluate the loudness of a compression effect (or limiter) that make the sound louder in RMS, or/and compare it with some professionnal mixed tracks to understand how they work, if i used it to much or not, etc…
It would be fine to integrate this functionnality in audacity (developer if you read this)
;nyquist plug-in
;version 3
;type analyze
;name "measure RMS Level"
;action "Track RMS Level measurement"
;info "Can be helpfull to manage compression, Limiting (like how many i made my soud louder with the same peak, etc...), by Gabriel D. (France)"
; Mono mode
(defun monomes (signal)
(setq smplrate *sound-srate*)
(setq mono-nb-sample-tot (snd-length signal (* 44100 1200))) ; use snd-length function wich return sample number
(setq mono-lenght-tot (/ (float mono-nb-sample-tot) smplrate) ) ; my variable names are confusing because it
; look like function name (i comment)
(setq mono-avg2 0)
(setq mono-s2 (rms signal)) ; using rms function wich return a sound containing
(setq mono-nb-sample (snd-length mono-s2 (* 44100 1200))) ; rms values
(setq mono-lenght (/ (float mono-nb-sample) smplrate) ) ; number of samples in the sound generated by rms
; function
(setq count 2 ) ; initialize counter of while
(setq mono-sample (snd-fetch mono-s2) )
(setq mono-sample2 (snd-fetch mono-s2) ) ; initialize variables of while
(setq mono-sample3 (snd-fetch mono-s2) ) ; accessing sound samples with snd-fetch function
(setq mono-sample4 (snd-fetch mono-s2) )
(setq mono-sample5 (snd-fetch mono-s2) )
(setq mono-avg2 (/ (+ mono-sample4 mono-sample5) 2)) ; pour initialiser mono-avg2
(while (< count (- (/ mono-nb-sample 3) 1) ) ; calculate a mean value of all rms samples values
; previously outputed.
; it's correct to do this way because rms is an
; absolute value of an average, so not usefull to
(setq mono-avg1 (/ (+ mono-sample mono-sample2 mono-sample3) 3)) ; calculate root and square if already absolute
(setq mono-avg2 (/ (+ mono-avg1 mono-avg2) 2))
(setq mono-sample (snd-fetch mono-s2) ) ; take 3 samples at a step of count
(setq mono-sample2 (snd-fetch mono-s2) ) ; and then calculate average at the beginning while
(setq mono-sample3 (snd-fetch mono-s2) ) ; then 2nd mean calculation with a "remaining"
; variable
; mono-avg2 that contain final value (linear)
(setq count (+ count 1) )
)
(setq db-mono-avg2 (linear-to-db mono-avg2 )) ; using linear-to-db function to convert in dB.
; formula is 20*log(x), not 10*log(x)
(setq meslimit (truncate (/ (* 275 44100) smplrate)) ) ; set limit to big: 12127500 sample max
(setq minlim (truncate (/ meslimit 60)) ) ; can't explain why it go crazy uper
(setq seclim (- meslimit (* minlim 60)) ) ; convert in time
(if (> mono-lenght-tot meslimit) ; display error to big
(format nil "Selection must be less than ~amin ~as~% (or ~a sec), ~%for ~a Hz sample rate. ~%~%Please, take smaller selection." minlim seclim meslimit smplrate)
(format nil ; display result
"RMS INTENSITY LEVEL MESURE
(Mono Mode)~%~%
Track selection RMS Level: ~%~a dB ~%
Time lenght of the selection: ~%~a secondes
Number of samples in selection: ~%~a ~%
Normal values should be between 0 and -50 dB. " db-mono-avg2 mono-lenght-tot mono-nb-sample-tot) )
)
; Stereo mode
(defun stereomes (signal)
;; Left Channel part of stereo mode --------------------------------
(setq left-signal (aref signal 0)) ; loading left channel (stereo sound is an array)
(setq smplrate *sound-srate*)
(setq left-nb-sample-tot (snd-length left-signal (* 44100 1200))) ; in a sound variable using aref. left indice=0
(setq left-lenght1 (/ (float left-nb-sample-tot) smplrate) ) ; use snd-length function wich return sample number
(setq left-avg2 0)
(setq left-s2 (rms left-signal)) ; using rms function wich return a sound containing
(setq left-nb-sample (snd-length left-s2 (* 44100 1200))) ; rms values
(setq leftplouf (/ (float left-nb-sample) smplrate) ) ; number of samples in the sound
; previously generated by rms function
(setq left-count 2 ) ; initialize counter of while
(setq left-sample (snd-fetch left-s2) )
(setq left-sample2 (snd-fetch left-s2) ) ; initialize variables of while
(setq left-sample3 (snd-fetch left-s2) ) ; accessing sound samples with
; snd-fetch function
(setq left-sample4 (snd-fetch left-s2) )
(setq left-sample5 (snd-fetch left-s2) )
(setq left-avg2 (/ (+ left-sample4 left-sample5) 2)) ; pour initialiser left-avg2
(while (< left-count (- (/ left-nb-sample 3) 1) ) ; calculate a mean value of all rms samples value
; previously outputed.
; it's correct to do this way because rms is an
; absolute value of an average, so not usefull to
(setq left-avg1 (/ (+ left-sample left-sample2 left-sample3) 3)) ; calculate root and square if already absolute
(setq left-avg2 (/ (+ left-avg1 left-avg2) 2))
(setq left-sample (snd-fetch left-s2) ) ; take 3 samples at a step of left-count
(setq left-sample2 (snd-fetch left-s2) ) ; and then calculate average at the beginning while
(setq left-sample3 (snd-fetch left-s2) ) ; then 2nd mean calculation with a "remaining"
; variable
; left-avg2 that contain final value (linear)
(setq left-count (+ left-count 1) )
)
(setq left-db-avg2 (linear-to-db left-avg2 )) ; using linear-to-db function to convert in dB.
; formula is 20*log(x), not 10*log(x)
;; Right Channel part of stereo mode --------------------------------
(setq right-signal (aref signal 1)) ; loading left channel (stereo sound is an array)
(setq right-nb-sample-tot (snd-length right-signal (* 44100 1200))) ; in a sound variable using aref. right indice=1
(setq right-lenght1 (/ (float right-nb-sample-tot) smplrate) ) ; use snd-length function wich return sample
; number
(setq right-avg2 0)
(setq right-s2 (rms right-signal)) ; using rms function wich return a sound
(setq right-nb-sample (snd-length right-s2 (* 44100 1200))) ; containing rms values
(setq rightplouf (/ (float right-nb-sample) smplrate) ) ; number of samples in the sound
; previously generated by rms function
(setq right-count 2 ) ; initialize counter of while
(setq right-sample (snd-fetch right-s2) )
(setq right-sample2 (snd-fetch right-s2) ) ; initialize variables of while
(setq right-sample3 (snd-fetch right-s2) ) ; accessing sound samples with
; snd-fetch function
(setq right-sample4 (snd-fetch right-s2) )
(setq right-sample5 (snd-fetch right-s2) )
(setq right-avg2 (/ (+ right-sample4 right-sample5) 2)) ; pour initialiser right-avg2
(while (< right-count (- (/ right-nb-sample 3) 1) ) ; calculate a mean value of all rms samples value
; previously outputed.
; it's correct to do this way because rms is an
; absolute value of an average, so not usefull to
(setq right-avg1 (/ (+ right-sample right-sample2 right-sample3) 3)) ; calculate root and square if already absolute
(setq right-avg2 (/ (+ right-avg1 right-avg2) 2))
(setq right-sample (snd-fetch right-s2) ) ; take 3 samples at a step of right-count
(setq right-sample2 (snd-fetch right-s2) ) ; and then calculate average at the beginning while
(setq right-sample3 (snd-fetch right-s2) ) ; then 2nd mean calculation with a "remaining"
; variable
; right-avg2 that contain final value (linear)
(setq right-count (+ right-count 1) )
)
(setq right-db-avg2 (linear-to-db right-avg2 )) ; using linear-to-db function to convert in dB.
; formula is 20*log(x), not 10*log(x)
(setq meslimit (truncate (/ (* 275 44100) smplrate)) ) ; set limit to big: 12127500 sample max
(setq minlim (truncate (/ meslimit 60)) ) ; can't explain why it go crazy uper
(setq seclim (- meslimit (* minlim 60)) )
(if (> right-lenght1 meslimit) ; display error to big
(format nil "Selection must be less than ~amin ~as~% (or ~a sec), ~%for ~a Hz sample rate. ~%~%Please, take smaller selection." minlim seclim meslimit smplrate)
(format nil ; display stereo result
"RMS INTENSITY LEVEL MESURE
(Stereo Mode)~%~%
Left Channel selection RMS Level: ~%~a dB ~%
Right Channel selection RMS Level: ~%~a dB ~%
Time lenght of the selection: ~%~a secondes
Number of samples in selection: ~%~a ~%
Normal values should be between 0 and -50 dB. " left-db-avg2 right-db-avg2 right-lenght1 right-nb-sample-tot) )
)
; Main program ----------------------------------
(if (arrayp s) ; test if sound is stereo or mono
; (Is it an array?)
(setq nbch 2) ; if stereo nbch=2
(setq nbch 1) ) ; if mono nbch=1
; Apply functions previously defined
(if (= nbch 1)
(monomes s)
(stereomes s)
)