Nyquist-Macros

From Audacity Development Manual
Jump to: navigation, search
Nyquist is a LISP like language integrated into Audacity. It was originally written to process audio.
  • Nyquist now also has the ability to control Audacity, similar to how Macros work, but with greater flexibility.

Comparison of Macros to Nyquist-Macros

Ordinary Macros execute a fixed sequence of commands in a fixed order.

By contrast, the Nyquist language is a full language from the LISP family. That makes it more powerful and also more complex to use.

  • Nyquist has commands for logic, loops and conditionally executing code.
  • Nyquist supports streams and string formatting functions.
  • Nyquist supports data structures, and is especially strong in handling lists.
  • Nyquist, in Audacity, can prompt for parameters and then use those parameters in its code.

Pros and Cons:

While Nyquist-Macros have many advantages over ordinary Macros, ordinary Macros also have some advantages:

  • There is a graphical interface for creating Macros, whereas Nyquist-Macros are written as a Nyquist plug-in.
  • Macros may include any built-in or plug-in effects, but Nyquist-Macros cannot use Nyquist effects.
  • Macros may include other Macros and Nyquist-Macros, but Nyquist-Macros cannot call other Nyquist-Macros.

Nyquist can be used independently of Audacity. When used from within Audacity, it gains an additional command, AUD-DO.

AUD-DO

AUD-DO is a function that extends Nyquist's capabailities.

AUD-DO makes it possible to use all Audacity Macro scripting commands from within Nyquist. The full list of scripting commands and their parameters is provided at the page Scripting Reference. The scripting commands are passed to AUD-DO as strings.

A very similar approach is used for Audacity Python Scripting. Commands must be created as strings and passed to a function to process. One advantage of Nyquist-Macros over Python Scripting is that Nyquist is already built in to Audacity.

Using AUD-DO

Nyquist-Macros will usually be "type tool".

;type tool

The following command in a Nyquist script would set the first label in a project to 'foo'

(AUD-DO "SetLabel: Text=\"Foo\"")

The text string after AUD-DO is passed to the scripting engine to process.

A complete example of a Nyquist Script using AUD-DO that you can enter at the Tools Nyquist Prompt is given below:

;nyquist plug-in
;version 4
;type tool
;name "Test Me"
;debugbutton false
;action "Applying TestMe..."
;author "Nemo Nemesis"
;release 2.3.0
;copyright "Public Domain"

;; test-me.ny by Nemo Nemesis, August 2018

;; For information about writing and modifying Nyquist plug-ins:
;; https://wiki.audacityteam.org/wiki/Nyquist_Plug-ins_Reference

(AUD-DO "SelectTime: Start=60 End=170")
(AUD-DO "SelectTracks: Track=1 TrackCount=2") 

Possibly the easiest way to find the correct strings to use is to use the Macros command to add commands to a macro and examine the strings added.

Tip The full list of commands available via AUD-DO is given in the Scripting Reference

Differences to Scripting in Nyquist

The ';type' setting in Nyquist sets what capabilities Nyquist will have for that Nyquist script. For example, ;type process and ;type analyze scripts are given the *TRACK* variable. Process scripts, when applied, will be called repeatedly, once for each channel to process.

Another use of the ';type' setting is to set which menu in Audacity a script will be placed in. It can occasionally be useful to place a process, generator or analyze Nyquist script in the tools menu, even though its functionality is one of the other types. To do that you can use two arguments to the ';type' setting.

You can create Nyquist plug-ins with for the Tools menu using any of the following:

;type tool
;type tool process
;type tool generator
;type tool analyze

The first argument to 'type' determines which Audacity menu the plug-in ends up in. All four examples are for the Tools menu. The qualifier process / generator / analyze determines how the plug-in actually behaves. ';type tool' should usually be used with AUD-DO.

Examples

Example Using Parameters

Scripts using AUD-DO can use parameters. Probably the easiest way to pass them to AUD-DO is using the XLISP format command.

;nyquist plug-in
;version 4
;type tool
;name "Test Me2"
;author "A Person"
;release 2.3.3
;copyright "Public Domain"

;control start "Start time" float-text "" 5 0 nil
;control end "End time" float-text "" 15 0 nil

(AUD-DO (format nil "SelectTime: Start=~S End=~S" start end))
(setf reply (AUD-DO (format nil "Message: Text=\"Start was set to ~S End to ~S\"" start end)))

;; "reply" is a list in the form ("quoted message" . T)
(first reply) ;returns the message


Click Removal Example

On the scripting page, for example, the parameters for the click removal command are documented:

int Threshold, (default:200)
int Width, (default:20)

To invoke the same command in Nyquist, you need to pass a string to AUD-DO. For example:

(AUD-DO "ClickRemoval: Threshold=200 Width=25")

Default values do not need to be specified, so a shorter version of the same command would be:

(AUD-DO "ClickRemoval: Width=25")

GetInfo Example

Advice See also AUD-GET-INFO.

The AUD-DO "GetInfo" Scripting commands provide results as strings, and offers three different result formats.

Tip It is usually easiest, in Nyquist, to ask for the results of GetInfo commands as strings in LISP format

The parameters of GetInfo are:

enum Type, (default:0)

  • Commands
  • Menus
  • Preferences
  • Tracks
  • Clips
  • Envelopes
  • Labels
  • Boxes

enum Format, (default:0)

  • JSON
  • LISP
  • Brief

You'd use a command like the following to get a list of labels (as a string).

(AUD-DO "GetInfo: Type=Labels Format=LISP")


AUD-GET-INFO

This function, as with other functions that are prefixed "aud-", is unique to Nyquist in Audacity. It is similar to the AUD-DO "GetInfo" command, but differs in that it returns a Lisp list rather than a string.

Syntax:

  (aud-get-info string)

Valid string parameters are (case insensitive):

  • "Commands"
  • "Menus"
  • "Preferences"
  • "Tracks"
  • "Clips"
  • "Envelopes"
  • "Labels"
  • "Boxes"

Example:

  (aud-get-info "tracks")

If the project contains two mono audio tracks, the return value will be similar to:

  (((NAME "Audio Track") (FOCUSED 1) (SELECTED 1) (KIND "wave") (START 0) (END 30) (PAN 0) (GAIN 1) (CHANNELS 1) (SOLO 0) (MUTE 0) (VZOOMMIN -1) (VZOOMMAX 1))
   ((NAME "Audio Track") (FOCUSED 0) (SELECTED 0) (KIND "wave") (START 0) (END 30) (PAN 0) (GAIN 1) (CHANNELS 1) (SOLO 0) (MUTE 0) (VZOOMMIN -1) (VZOOMMAX 1)))

Information about a specific track can be extracted by looking at the 'nth' list item. For example, information about the first track:

  (nth 0 (aud-get-info "tracks"))

or

  (first (aud-get-info "tracks"))

Because the returned data is a valid list, we can manipulate the data easily with standard Lisp functions. For example, to print the names of all tracks:

  (let ((tracks (aud-get-info "tracks")))
    (dotimes (j (length tracks))
      (setf track (nth j tracks))
      (print (second (assoc 'name track)))))


AUD-DO-COMMAND

"AUD-DO-COMMAND" provides a higher level alternative to "AU-DO".
The first time that AUD-DO-COMMAND runs it may be observed that there is a delay.This is caused by Nyquist building a cache of AUD-DO commands and parameters for fast look-up. Once the cache has been built, AUD-DO-COMMAND commands will be almost as fast as AUD-DO commands.

Usage:

(aud-do-command "command" [[:keyword :argument] ...]) Where "command" is the scripting command to be sent to Audacity.

Unlike AUD-DO the commands are not case sensitive except for enum arguments.

Example:

 (aud-do "Chirp: StartFreq=100 EndFreq=400 StartAmp=1.0 EndAmp=0.5 Waveform=Sawtooth")  ;AUD-DO syntax
 (aud-do-command "chirp" :startfreq 100 :endfreq 400 :startamp 1.0 :endamp 0.5 :waveform "Sawtooth")  ;AUD-DO-COMMAND syntax

Note that in the AUD-DO-COMMAND version, "Sawtooth" is an enum and so is case sensitive.

Advantages to using AUD-DO-COMMAND:

The main advantage is that the syntax is more LISP-like, and this simplifies usage when passing parameters. For example, if we want to generate a Chirp and we want to pass variables for the parameter values:

 (setq start-hz 100)
 (setq end-hz 400)
 (setq start-amp 1.0)
 (setq end-amp 0.5)
 
 ;; Using AUD-DO
 (let (command)
   (setf command
       (format nil "Chirp: StartFreq=~s EndFreq=~s StartAmp=~s EndAmp=~s Waveform=~s"
               start-hz
               end-hz
               start-amp
               end-amp
               "Sawtooth"))
   (aud-do command))


 (setq start-hz 100)
 (setq end-hz 400)
 (setq start-amp 1.0)
 (setq end-amp 0.5)
 
 ;; Using AUD-DO-COMMAND
 (aud-do-command "chirp" :startfreq start-hz :endfreq end-hz :startamp start-amp :endamp end-amp :waveform "Sawtooth")

Another benefit for Nyquist developers is that debug messages are much improved for all commands that are supported by #GetInfo_Example GetInfo:.

Example:

This (invalid) AUD-DO example ignores the invalid "start" parameter, making it difficult to find the error:

 (aud-do "Chirp: start=100")

This (invalid) AUD-DO-COMMAND example returns helpful debug information:

 (aud-do-command "Chirp" :start 100)
 ;;Debug output:
 Invalid key in "Chirp" :START
 Valid keys for Chirp are:
    StartFreq (double) 
    EndFreq (double) 
    StartAmp (double) 
    EndAmp (double) 
    Waveform [Sine Square Sawtooth Square, no alias]
    Interpolation [Linear Logarithmic]
 Too many arguments: "Chirp" :START


Tip For more information about Nyquist and Nyquist-Macro commands, please refer to the documentation on the Audacity wiki