*Selection* Variable Not Updating While Nyquist Plugin Is Running


I’m trying to write a program that selects a specific portion of a track then appends the RMS to the track name. Here’s what I have for code:

;nyquist plug-in
;version 4
;type tools
;name "Append RMS"
;;action "Measuring level and appending to name..."
;codetype lisp
;;debugflags trace

(aud-select :track 0 :start 8 :end 18)
(aud-setTrackStatus :name (strcat (get '*track* 'name) (format nil " ~A dB" (linear-to-db (get '*selection* 'rms)))))
(print "Complete!")

I’m getting an issue, however, where the selection variable is using the selection from when before the script started. In other words, if I select from 4 seconds to 8 seconds then run the script, it will give me the RMS of the 4 second long selection instead of the 10 second long selection I want.

The script is properly selecting the part that I want to measure, however, the selection variable doesn’t seem to be updating correctly. I have tried changing the ;type, but it doesn’t seem to help at all. Is there a way to force the variable to update? Or another way to tackle this problem? Eventually I want to set up a loop so that this can go through multiple tracks and append the RMS. Any help would be appreciated!

Yes, that’s how it works.
The “problem” is that Nyquist isn’t really part of Audacity, it’s a separate programming language that has been shoehorned into Audacity.

When a Nyquist plug-in is launched, the process is like this:

  1. Audacity reads the Nyquist script.
  2. The script is parsed.
  3. Header commands are used by Audacity to create the GUI (if any), sets variables (such as track, selection … and their property lists).
  4. If this is the first time Nyquist has been run in this session (since Audacity was launched), Nyquist is initialised.
  5. The Nyquist/LISP part of the script is passed to the Nyquist interpreter, including any variables (such as track, selection … and their property lists)
  6. The Nyquist script may have “side effects”, such as outputting debug messages, sending “aud-do” commands to Audacity, playing sounds…
  7. Nyquist returns a “result” to Audacity
  8. Audacity does something with the result. If the result is a sound, it is returned to an Audacity track. If the result is text, it is printed to a message dialog …

Note that the only time that Nyquist can get information about the project is step 5.
In other words, Nyquist knows quite a lot about the state of the project at the time when the script starts, but there is no opportunity for that information to be updated.

More to follow… There is a way round this.

Audacity’s “Macros” are properly part of Audacity. A macro is a sequence of Audacity commands, that run in strict order.
If for example, you run Macro commands to:

  1. Launch a Nyquist plug-in. Nyquist sees the state of the project at this point in time.
  2. Change the project with a Macro command.
  3. Launch the Nyquist plug-in again. Nyquist now sees the updated version of the project.

Unfortunately, for technical reasons, it is not (currently) possible to launch a Nyquist plug-in from a Macro command in a Nyquist script. However, you can launch a series of Nyquist plug-ins, to run one after another, from a “normal” Audacity Macro.
If you have a (normal) Macro containing two Nyquist scripts, the first will run through steps 1 to 8 (as described in my previous post), then the second one will run through steps 1 to 8.

Hi Steve,

Thanks for the pointer. I have created a Macro that will first select the region I want, then call the Nyquist plugin to perform the analysis. However, I have run into a new problem: I can see that the RMS has been appended to the track name when the “Complete!” message pops up. However, when I close the message, the RMS disappears from the track name. It seems like my changes are being reverted somehow.

Do you have any idea on what might cause this?

Your Macros are stored in simple text files. On Windows 10, the default location is:
(you need to close Audacity to update the Macro file to your latest version)

Find your Macro file, and any .ny files that you are using, and attach them to your reply so I can see what you are doing.

Here are the files I’m using.
RF RMS Append.txt (132 Bytes)
appendRMS.ny (317 Bytes)

This is a bit tricky because of some limitations that are currently applied to Nyquist macros.
To get the RMS value, we want the plug-in to be an Analyze type, but to run the macro commands we want the plug-in to be a Tools type. I’m hoping that this restriction will be loosened in a future version of Audacity, but for now we have to create two Nyquist plug-ins and run them one after the other from the Macro. We can use SCRATCH to pass the result of the first plug-in to the second plug-in.

First plug-in:

;nyquist plug-in
;version 4
;type analyze
;name "Append RMS"

; Use a name that is unlikely to collide with any other plug-in:
(setf key 'appendRMS-get-new-name-14-08-2019)

(let ((db (linear-to-db (get '*selection* 'rms)))
      (oldname (get '*track* 'name)))
  (putprop '*scratch* (format nil "~a ~a dB" oldname db) key)
  "") ;Return a no-op

Second plug-in:

;nyquist plug-in
;version 4
;type tool
;name "Apply Name"


; This key must match appendRMS.ny
(setf key 'appendRMS-get-new-name-14-08-2019)

(let ((name (get '*scratch* key)))
  (aud-setTrackStatus :name name))

(remprop '*scratch* key)  ;Clean up


Select:End="18" Mode="Set" RelativeTo="ProjectStart" Start="8" Track="0" TrackCount="1"

(“Use_Preset=”" is not necessary, because it’s the default)

That works perfectly. Thank you so much for the help!