Some years ago on the mailing list I made some analysis plugins based on Mikael O’s A weighting plugin. But I’ve lost them and I’m recreating them from old emails…
But this base plugin that started it all no longer works - it should return two labels with Leq and LMax, but instead it applies the a-weighting filter to the audio. I’ve been through it line by line with a two channel version that works, but I can’t work out what’s going on.
If you’ve set “type analyze:” it shouldn’t return audio at all anyway, should it? Can anyone help me?
;nyquist plug-in
;version 1
;type analyze
;name "Equivalent and maximum dB(A)..."
;action "Calc. A-weighted equivalent level (LAeq) and maximum level with time weighting FAST (LAFmax)..."
; Mikael Ogren, mr.ogren@...
; 2007-01-12
; Licensed under GPL, no warranty, use at your own risk...
; Calibration so that a 1000 Hz tone with amplitude 1.0 gives 94 dB
(setq calibration (+ 94 28.2))
; A-weighting by Edgar (thanks!)
(setq sa (lp (lp (hp (hp (hp (hp s 20.6) 20.6) 107.7) 737.9) 12200) 12200) )
; Exponential time-weighting filter FAST (125 ms)
; snd-avg is used to downsample to 100 Hz (by averaging over 441 samples)
; This only works for 44.1 kHz sampling frequency, perhaps someone can help out here
; by making a more general approach that works for all sampl. frq?
; The filtering part is OK for all frequencies, but the "441" constant is not.
; -
; The constant 0.000001 is to avoid clipping at filtered squared pressure > 1.0
(setq saf2(mult 0.000001(snd-avg (snd-biquad (mult sa sa ) 1 0 0 (exp (/ 1 (mult (snd-srate sa) - 0.125))) 0 0 0) 441 441 OP-AVERAGE)))
; Length of the downsampled pressure squared signal
(setq mlength(snd-length saf2 99999999999))
; Calc. the equivalent level
(setq leq(+ calibration (* 0.5 (linear-to-db (snd-maxsamp (snd-avg saf2 mlength mlength OP-AVERAGE) )))));
; Calc. the maximum level
(setq lmax
(+ calibration (* 0.5 (linear-to-db (snd-maxsamp saf2)))));
; Set the output format to 3 digits (example: 53.3 dB)
(setq *float-format* "%#3.3g");
; Output result as a label track (or append into existing label track)
(setq u (format NIL "LAeq= ~A LAFmax= ~A" leq lmax))
(list (list 0.0 u))
(there should be no space between the “-” and “0.125”)
That particular expression would be better written as:
(exp (/ (* -0.125 (snd-srate sa))))
It’s really quite bad style to write huge long lines like that which then require a paragraph of explanation, and, as you’ve found, it makes the code difficult to debug.
;nyquist plug-in
;version 1
;type analyze
;name "Equivalent and maximum dB(A)..."
;action "Calc. A-weighted equivalent level (LAeq) and maximum level with time weighting FAST (LAFmax)..."
; Mikael Ogren, mr.ogren@...
; 2007-01-12
; Licensed under GPL, no warranty, use at your own risk...
;
; Set the output format to 3 digits (example: 53.3 dB)
(setq *float-format* "%#3.3g");
; A-Weighting Filter
(defun cascade (s freqs &aux (f (car freqs)))
(cond
((null f) s)
((minusp f) (cascade (lp s (- f)) (cdr freqs)))
(t (cascade (hp s f) (cdr freqs)))))
;;
;; Main
(let* (
; Calibration so that a 1000 Hz tone with amplitude 1.0
; gives 94 dB
(calibration (+ 94 28.2))
; A-weighting frequencies by Edgar (thanks!)
(freqs '(20.6 20.6 107.7 737.9 -12200 -12200))
(sa (cascade s freqs))
(step (round (/ *sound-srate* 100.0)))
(saf2 (snd-avg (biquad (prod sa sa)
1e-6 0 0 1 (exp (/ -8 (snd-srate sa))) 0)
step step OP-AVERAGE))
; Length of the downsampled pressure squared signal
(mlength(snd-length saf2 ny:all))
; Calc. the equivalent level
(leq (+ calibration (* 0.5 (linear-to-db (snd-maxsamp (snd-avg saf2 mlength mlength OP-AVERAGE))))))
; Calc. the maximum level
(lmax (+ calibration (* 0.5 (linear-to-db (snd-maxsamp saf2)))));
; Output result as a label track (or append into existing label track)
(u (format nil "LAeq= ~A LAFmax= ~A" leq lmax)))
u; Sends output to message box if next is commented out
; (list (list 0.0 u))
); end let*
The 0.000001 gain is completely in the biquad section and the exp term is also simplified.
The filtering is “out-sourced”.
Is the filter correct, has any one checked against all frequencies?
(lp and hp are not “normal” filter types)
I think mlength can get too high for long audio and snd-avg won’t therefore return a valuable result for LAeq.
Also to mention, it helps a lot if variable names are meaningful. For example, what are “SA” and “SAF2”?
It is good to keep variable names reasonably brief, but sufficiently long to be clear what they are.
I’ve previously checked the A-weighting filter from Edgar-rft and it is a reasonably close approximation. I’ve not checked the biquad expression.
Just a brief note that I have checked the code vs a class 1 professional analyzer, with results within +/- 0.1 dB, for sampling frequencies 44.1 and 48 kHz.
sa - the variable name is from the fact that Nyquist uses “s” as variable name for the sound. “sa” - A-weighted sound, “saf” - A-weighted with time weighting FAST.