How to find where RMS drops 10 dB Audacity 3.2.1

Greetings!

I’m using Audacity 3.2.1 with Windows 10. Hoping someone can teach me how to determine where/when a signal drops 10 dB RMS.
I’m doing a study on note sustain in bass guitars and I want to determine how long it takes each note to drop 10 dB e.g. initial RMS is -2.3 dB, I want to quickly find where the signal drops to -12.3 dB.

So far the only way I can see is display the wave in dB rather than linear, use the Contrast tool to measure the note at its start, and then hunt for the spot where it’s 10 dB less - a VERY SLOW process :unamused: !!!

Any help would be much appreciated :smiley:.

Joe

Try applying this code in the Nyquist Prompt effect:
(Works with mono tracks only)

;type analyze

(setf drop 10)  ; dB drop
(setf *float-format* "%.2f")

(let ((rms (rms *track*))
      target time srate)
  (setf *track* nil)
  (setf srate (snd-srate rms))
  (do ((val (snd-fetch rms) (snd-fetch rms))
       (count 0 (1+ count)))
      ((not val)
       (format nil "Failed.\nSound did not drop by ~a dB." drop))
    (setf val (linear-to-db val))
    (when (= count 0)
      (setf target (- val drop)))
    (when (<= val target)
      (setf time (/ count srate))
      (return (list (list 0 0 (format nil "~a dB" (+ target drop)))
                    (list time time (format nil "~a dB" val)))))))

If the RMS level drops by 10dB from the start of the selected audio, labels are added that indicate the RMS level at the start of the selection, and a second label at the point where the RMS level is 10 dB lower.

Note that as RMS is a kind of “average” the sound has to be repeatedly measured in chunks. The above code measures in chunks of 0.01 seconds, so the second label indicates the first chunk that is 10 dB below the RMS level of the first chunk. In the example below, the first chunk is -20.77 dB RMS, and the first chunk that has a level that is 10 dB below that has a level of -31.03 dB (the previous chunk has a level of -30.44 dB, which is only 9.67 dB below the initial RMS). The label is placed at the start of the chunk to which it relates.

Be aware that measuring RMS with a 0.01 s window (“chunk” size) won’t be very accurate with the lower strings because the fundamental frequency is so low. The bottom E of a bass guitar is normally tuned to 82 Hz, which means that one full cycle takes 1/82 seconds, which is about 0.0122 seconds, so each chunk is a bit less than one full cycle. Nevertheless the dB measurement should be accurate to within 1.5 dB as the worst case.

The dB accuracy could be improved by using a larger “chunk” size (technically called the “window size”), but then the time measurements are less precise.

This problem is rather like measuring reverb time

https://en.wikipedia.org/wiki/Reverberation#/media/File:RT60_measurement.jpg

for accuracy’s sake don’t start measuring too close to pluck.

Here’s a more complex version that may give more accurate measurements.
In this version there are two controls:

  1. “Note frequency: … Hz”
    Set this to the frequency that the string is tuned to.
  2. “Locate drop of: … dB”
    The decrease in dB RMS that you are looking for.


;type analyze

;control hz "Note frequency" int "Hz" 82 20 400
;control drop "Locate drop of" int "dB" 10 1 60

;; Print one decimal place.
(setf *float-format* "%.1f")


(defun rms(sig)
  (let* ((sig (mult sig sig))
         (step (round (/ *sound-srate* hz)))
         (block (* 2 step)))
    (s-sqrt (s-avg sig block step op-average))))


(let ((rms (rms *track*))
      target time srate)
  (setf *track* nil)
  (setf srate (snd-srate rms))
  (do ((val (snd-fetch rms) (snd-fetch rms))
       (count 0 (1+ count)))
      ((not val)
       (format nil "Failed.\
Sound did not by ~a dB." drop))
    (setf val (linear-to-db val))
    (when (= count 0)
      (setf target (- val drop)))
    (when (<= val target)
      (setf time (/ count srate))
      (return (list (list 0 0 (format nil "~a dB" (+ target drop)))
                    (list time time (format nil "~a dB" val)))))))

In this version, the window size is set according to the frequency selected. For example, if the frequency is set to 82 Hz, then the audio is analyzed in chunks that are 2/82 seconds long (two full cycles of an 82 Hz wave). To improve time accuracy, the RMS measurement steps through the audio in steps of “half a chunk”, which in this example is 1/82 seconds (about 0.0122 seconds).

For higher frequencies it may be best to set the Frequency control to half the string frequency. For example, for the G string tuned to 196 Hz, you could set the Frequency control to 98 Hz. The effect will then step through the selected audio in steps of 0.0102, where each chunk is about 0.02 seconds (4 full cycles).

Note that for accurate results, the actual string frequency needs to be an exact multiple of the Frequency setting, so it is important that the bass guitar is tuned as accurately as possible.

Steve, Trebor,

Thanks so much for your help and input! I really appreciate it :smiley:
I’ve never used the Nyquist prompt before but I’m going to give this a try and I’ll report back.

Steve,
That first Nyquist prompt you wrote for me works great :smiley: !! Thanks so much for doing that.

It’s been decades since I’ve done any programming :unamused: so I have to ask: how to modify your code to do the same thing looking for a 20 dB drop?
I tried changing the line
(setf drop 10) ; dB drop
to
(setf drop 20) ; dB drop
but it didn’t fly.

Here’s my project: exposing dead spots on bass guitars that are found on 90% of the usual scale/size bass on the G string. To demonstrate this I want to show for each note from frets 1-12 how long it takes each to drop 10 dB (half initial volume) and 20 dB (1/4 initial volume). It’s disconcerting but common for a $1000 bass to have a dead spot that drops 10 dB in less than 1 second!

As always thanks for your help.

Joe

Steve,

My mistake :unamused: ! I retried changing the “10” to “20” and it worked perfectly.

Thanks again :slight_smile:

Joe

20 dB => factor of 10 , (rather than “1/4 initial”)

Decibels are extremely confusing :confused: because they’re a log function. A change of 20 dB represents a 10x change in VOLTAGE, but a 4x change in LOUDNESS.

http://www.sengpielaudio.com/calculator-levelchange.htm

https://www.gcaudio.com/tips-tricks/the-relationship-of-voltage-loudness-power-and-decibels/

Steve,

I know I’m pushing my luck here, but is there a way to tweak your original prompt to also give the time interval?

Thanks a lot,

Joe