For a pre-determined (1) threshold RMS value (2) Segment length: Possible?- Nyquist interface to select the "minimum RMS value" segment for an audio file?

I found an apparently similar topic in Is it possible to create audio map of volume? but from the post 11 onwards it seems that data is returned to a list, which with the debug option could be written to a file.

However, I need a band (say, of 300ms) of lowest amplitude peak range (assuming that the baseline zero RMS for my purpose is -33 dB, but it could be changed) to be selected on the very audacity waveform window itself for an already opened audio file.

I tried:

;; Define function to convert dB to linear scale
(defun db-to-linear (db)
(exp (* 0.11512925464970229 db)))

;; Set parameters
(setq base-threshold -33) ; Base RMS threshold in dB
(setq min-band-duration 0.3) ; Minimum RMS band duration in seconds

;; Calculate linear-scale threshold from dB
(setq threshold (db-to-linear base-threshold))

;; Calculate Nyquist step size
(setq step (truncate (* min-band-duration sound-srate)))

;; Get RMS values for each segment
(setq rms-values (snd-avg track step step op-rms))

;; Find segments above threshold
(setq segments ())
(do ((rms (snd-fetch rms-values) (snd-fetch rms-values))
(start 0 (+ start step)))
((not rms))
(if (> rms threshold)
(setq segments (cons (list start (+ start min-band-duration)) segments))))

;; Find segment with minimum duration above threshold
(setq min-segment (car (sort segments #‘< :key #’(lambda (x) (- (cadr x) (car x))))))

;; Convert segment start and end time to hour, minute, second, millisecond format
(setq start-time (format nil “~2,'0d:~2,'0d:~2,'0d.~3,'0d”
(truncate (/ (car min-segment) 3600))
(truncate (mod (/ (car min-segment) 60) 60))
(truncate (mod (/ (car min-segment) 60) 60))
(truncate (* (mod (car min-segment) 1) 1000))))
(setq end-time (format nil “~2,'0d:~2,'0d:~2,'0d.~3,'0d”
(truncate (/ (cadr min-segment) 3600))
(truncate (mod (/ (cadr min-segment) 60) 60))
(truncate (mod (/ (cadr min-segment) 60) 60))
(truncate (* (mod (cadr min-segment) 1) 1000))))

;; Output the selected segment
(format nil “Selected segment: ~a - ~a” start-time end-time)

Leaders and senior members may please note that this is a children level code and doesn’t work as intended. I have very fuzzy idea of accessing the native audacity script framework using the Nyquist Prompt.

I also would like to have the active window automatically be shifted to have the selected band centred within that window.

No need to write a db-to-linear function. See: Nyquist Functions

;; Calculate Nyquist step size
(setq step (truncate (* min-band-duration sound-srate)))

Probably just an error caused by the forum software, but that should be:

;; Calculate Nyquist step size
(setq step (truncate (* min-band-duration *sound-srate*)))

;; Get RMS values for each segment
(setq rms-values (snd-avg track step step op-rms))

This is not valid code. The operation parameter for snd-avg must be either OP-AVERAGE or OP-PEAK.

Also, it is recommended to use s-avg rather than snd-avg.

See: Nyquist Functions
and: Nyquist Functions

If you want RMS, there is a separate function: Nyquist Functions

(setq min-segment (car (sort segments #‘< :key #’(lambda (x) (- (cadr x) (car x))))))

I’d recommend avoiding complex lines like this. Writing it as separate operations makes it easier to read an, if necessary, easier to debug.

;; Find segment with minimum duration above threshold
(setf sorted-segments (sort segments #‘< :key #’(lambda (x) (- (cadr x) (car x)))))
(setq min-segment (car sorted-segments))

Then you can test each part, for example, testing your sort expression:

; List of lists to sort.
(setf segments (list (list 1 2) (list 5 8) (list 6 4)))

; Sort the list.
(setf sorted-segments (sort segments #'< :key #'(lambda (x) (- (cadr x) (car x)))))

; Print the result.
(print sorted-segments)

gives the error:

error: too many arguments
Function: #<Subr-SORT: #0x55eb26903f10>
  ((1 2) (5 8) (6 4))
  #<Subr-<: #0x55eb2690aae8>
  #<Closure: #0x55eb26940758>
Function: #<FSubr-SETF: #0x55eb26902278>

I’m not sure what you are trying to do here, but referring to the documentation (Appendix 3: XLISP: An Object-oriented Lisp) we can see that your syntax is wrong for the sort function.

Maybe you meant:

;; Find segment with minimum duration above threshold
(setf sorted-segments (sort segments #'(lambda (x y) (< (car x) (car y)))))
(setq min-segment (car sorted-segments))

Mr. Steve, please ignore my codes. I know that they are all wrong, because I can’t get the intended result.
I have already informed that they are children codes.
Please don’t look into my codes. Please don’t try to correct them. They are too complicated to be corrected. Ignore them.
Rather, please look at my objective from the Question, the inputs, etc., from the Bird’s Eye View.
I want to reach to the minimum RMS segment above (1) the threshold of -33dB and (2) time-band of 300ms and have that minimum RMS volume audio segment selected from the Nyquist prompt.
Then suggest a working solution please.

It is reasonable to ask for help on this forum. That’s what the forum is for. It is a place where Audacity users can help each other learn how to use Audacity effectively.

It is not reasonable to expect others to do your work for you.

Yes, of course, Mr. Steve.
My 2nd post was to deter you from making the unnecessary effort of correcting the incorrigible codes.
I don’t have a clue on how to approach the problem. There are two variables. Which is creating the problem for me. RMS part is easy. But how to grow the segment from 300ms, that is the main issue. Can’t solve presently.

The “Label Sounds” plug-in looks pretty close to what you want.

Mr. Steve, mine is an old version 2.4.2. label-sounds.ny isn’t present. Could I safely use the version from here?
Thank you for understanding my issue, Mr. Steve.
Now, regarding my need: I need to identify bands of minimum sounds just above a certain threshold.
Whereas, label-sounds.ny deals with labeling “… the audio level in the selected track(s). When the track level exceeds a specified threshold level, the audio is considered to be “sound”, and when below the level it is considered to be “silence” …”.
Doesn’t appear to “… identify bands of minimum sounds just above a certain threshold …”.
Any input or advice, Mr. Steve, in this regard please?

In Audacity 2.4.2 you could use “Sound Finder”.

“Label Sounds” should also work. The official version is here: (Use “File Save” in your web browser and it should save the page as label-sounds.ny)

1 Like

Yes, Mr. Daulton. Works. Absolutely works. Thank you indeed. Even deleting the silences work as intended if the either of the tracks are selected while using Truncate Silence.
I request you to please look from my POV and remember that we all work collaboratively to achieve objectives. Even if I want to, I won’t be able to solve most of the difficulties I need solved. My intent was not about asking someone to do my work for me. I can never be a programmer. “Developer” isn’t even imagined. My skill sets, though different, are also dedicated for my fellow humankind, my papers and patent would testify.

This topic was automatically closed after 31 days. New replies are no longer allowed.