Audacity Support Forum / Audacity and Nyquist / Nyquist Reference Manual / Nyquist Examples and Tutorials


Audacity and Nyquist 2009


  1. Nyquist Plugin Header
  2. Nyquist Plugin Widgets
  3. Nyquist Variables
  4. Stereo Tracks
  5. Return Values
  6. Math Functions
  7. Nyquist Workbench
  8. Apropos Plugin

The Audacity Nyquist Interface is implemented in the following files in the Audacity source code:

Note: All [comments] and [explanations] on this page are written in square brackets, so they cannot be confused with (Lisp code).


Nyquist Plugin Header


Important: In the Nyquist plugin header there must be only one single semicolon at the beginning of each line because these lines are parsed by Audacity.

The Nyquist Lisp interpreter as well as the Nyquist SAL compiler in contrast recognize everything after the first semicolon up to the end of the line as a comment and just simply ignores it. So in the Nyquist code, below the plugin header, comments can also be started with several semicolons in a row.

;nyquist plug-in
;version version
;type type
;name "name"
;action "text"
;categories "text"
;info "text"
;control parameters
;codetype type
;debugflags flags

The 'categories', 'info', 'control', 'codetype', and 'debugflags' lines are optional and can be omitted.

Required plugin header lines:

;nyquist plug-in
  -  tells Audacity 'this is a Nyquist plugin'.
 
;version 1
  -  only the Slider widget is supported.
;version 2
  -  the Text input widget was added in Audacity 1.2.
;version 3
  -  the multiple-Choice widget was added in Audacity 1.3.
 
Only one ';version' line is needed. If you don't know which one to choose use the version with the highest number. The version line is only needed to prevent Audacity from raising errors in case a user comes to the idea to apply a plugin with a brand-new feature in a very old Audacity program.
 
;type generate
  -  plugin appears in the Audacity 'Generate' menu.
;type process
  -  plugin appears in the Audacity 'Effect' menu.
;type analyze
  -  plugin appears in the Audacity 'Analyze' menu.
 
Only one ';type' line is needed. A plugin cannot appear in several Audacity menus at the same time. But it is possible to write several plugins with the same name but with different ';type' lines, which then will appear under the same name in different Audacity menus. But please do this only if you really need it.
 
;name "name"
  -  name of the plugin how it will appear in the Audacity menu.
;action "text"
  -  text to be displayed while the plugin is working.
 
Optional plugin header lines:
 
;categories "text"
  -  LV2 categories, see Categories below.
;info "text"
  -  text to be displayed at the top border of the plugin window.
 
A character sequence '\n' within 'text' causes a line break. It is not possible to 'quote' a line break in the plugin code with a backslash '\' at the end of the line. In the plugin header, the 'text' in the 'action' und 'info' lines must be written in one single line.
 
;control parameters
  -  defines a Plugin Widget. There can be several 'control' lines in the plugin header.
 
;codetype lisp
  -  the syntax of the plugin is Lisp. This is the default if the 'codetype' line is missing.
;codetype sal
  -  the syntax of the plugin is SAL. The default is 'lisp'.
 
;debugflags flags
  -  see Internal Debug Options below.

Categories  [Audacity 1.3.9, November 2009]

LV2 categories had been introduced in Audacity as part of 'Google Summer of Code 2008':

The categories were tried out in the 1.3.6 Beta version of Audacity, but it was unpopular with the majority of users because of the extra navigation involved to reach the effects. Categories will not be re-introduced until it is provided with a way by which the user can turn the grouping on and off in the interface.

The 'categories' header line is currently optional.

Internal Debug Options

There is an optional 'debugflags' line available, which skips the plugin window and directly executes the plugin code, so if a 'debugflags' line is found in the plugin header no user-interaction is possible.

;debugflags trace
  -  sets *tracenable* to 'true'. The plugin behaves as if the 'Debug' button was clicked by the user. This is the default.
;debugflags notrace
  -  sets *tracenable* to 'false'. The plugin behaves as if the 'OK' button was clicked by the user.
;debugflags compiler
  -  sets *sal-compiler-debug* to 'true'.
;debugflags nocompiler
  -  sets *sal-compiler-debug* to 'false'. This is the default.

In the Nyquist Workbench, the 'compiler' and 'nocompiler' debugflags control whether the generated Lisp code from the SAL compiler will be sent to 'stdout' or to the output window in the Nyquist Workbench.

  Back to top


Nyquist Plugin Widgets


Every ';control' line gets parsed by Audacity into several tokens, where each token is separated by one or several whitespaces:

  tokens[0]   tokens[1]   tokens[2]   tokens[3]   tokens[4]   tokens[5]   tokens[6]   tokens[7]
  ;control   var-name   "text-left"   widget-type   "text-right"   initial-value   minimum   maximum   -  plugin template
 
  ;control   symbol   "string"   int   "string"   integer   integer   integer   -  integer Slider widget
  ;control   symbol   "string"   real   "string"   float   float   float   -  floating-point Slider widget
  ;control   symbol   "string"   string   "string"   "string"   [space]   [space]   -  Text input widget
  ;control   symbol   "string"   choice   "string"   integer   [space]   [space]   -  multiple-Choice widget

Blue words represent data types. Because tokens are separated by whitepace, strings containing whitespace must be written in-between quotation marks. Do not try to memorize this table, use it as a reference. The detailed syntax for each widget type is described in the following sections below.

  Back to top


Slider Widget


 [Slider Widget]

Slider widgets are supported in all Audacity Nyquist plugin versions.

;control variable-name "text-left" variable-type "text-right" initial-value minimum maximum

variable-name
  -  a Lisp symbol.
variable-type
  -  a 'number' type:
int
  -  integer [FIXNUM, a XLISP number without a dot]
real
  -  floating point [FLONUM, a XLISP number with a dot]
"text-left"
  -  text that will appear to the left of the slider
"text-right"
  -  text that will appear to the right of the slider
initial-value
  -  variable value [and slider position] at the first start of the plugin
minimum
  -  variable value when the slider is moved to the left border
maximum
  -  variable value when the slider is moved to the right border

The variable value [the slider position] can be referenced by the variable name in the plugin code.

In more recent versions of Audacity there appears a text input box beside the slider, where the user can type in a variable value via the keyboard. Note that it's up to the plugin programmer to catch undesired variable values typed in by the user.

  Back to top


Text Input Widget


  [Text Input Widget]

The text input widget is supported in plugins version 2 or above, it will not work in Audacity 1.1 and below.

;control variable-name "text-left" string "text-right" "initial-string"

variable-name
  -  a Lisp symbol.
"text-left"
  -  text that will appear to the left of the text input field.
"text-right"
  -  text that will appear to the right of the text input field.
"initial-string"
  -  the string will appear inside the text field.

The text typed in by the user in the text field of the plugin window can be referred as a string variable from within the plugin code.

Examples how to use the 'text input' widget can be found in the source code of the Apropos plugin.

  Back to top


Multiple-Choice Widget


 [Multiple-Choice Widget]

The choice widget is supported in plugins version 3 or above, it will not work in Audacity 1.2 or below.

;control variable-name "text-left" choice "string-1,string-2,..." initial-value

variable-name
  -  a Lisp symbol.
"text-left"
  -  text that will appear to the left of the multiple-choice list.
"string-1,..."
  -  for every string an entry in a list to choose from will be produced.
initial-value
  -  the number of the list entry, that will be displayed as the default choice at the first start of the plugin.

The list entries 'string-1', 'string-2', etc. are internally represented by integer numbers. The first, top most list entry 'string-1' will be represented by the number 0. The list entry choosen by the user can be determined by the integer value of the variable from within the plugin code.

Examples how to use the 'choice' widget can be found in the source code of the Apropos plugin.

  Back to Top


Nyquist Variables


The variables given from Audacity to Nyquist are defined in the file 'audacity/lib-src/libnyquist/nyx/nyx.c' in the Audacity source code.

The following variables are given from Audacity to Nyquist:

s
  -  the Audacity sound [the selected part of the Audacity audio track]
len
  -  the number of samples contained in 's'
*sound-srate*
  -  the sample frequency of the Audacity track
*warp*
  -  a list of three values:
time-offset
  -  in Audacity always 0.
time-stretch
  -  the length in seconds of the selected part of the Audacity audio track.
continuous-time-warp
  -  in Audacity always NIL.

The length of the sound in seconds can be computed one of the following ways:

(/ len *sound-srate*)
  -  divide the number of samples by the sample frequency
(get-duration 1)
  -  get the 'time-stretch' value from the *warp* variable

Roger Dannenberg writes:

The details of *warp* are part of the Nyquist internal implementation, and one should not write code that accesses *warp* directly. To get the duration of an Audacity selection, call the Nyquist function:

(get-duration 1)

This function answers the question: "If a behavior has a nominal duration of 1, how long will it be after warping it according to the Nyquist environment?" Since many built-in behaviors like OSC and LFO have nominal durations of 1, Audacity sets up the environment to stretch them by the selection's duration. Otherwise, if you wrote (OSC C4), the result would have a duration of one second instead of the duration of the selection.

  Back to top


The *scratch* Symbol


Since Audacity 1.3.9, there is a new global symbol *scratch*, which is not deleted in-between plugin runs.

Roger Dannenberg writes:

The point of *scratch* is to provide some way for information to survive from one invocation of a plug-in to the next. There should probably be some recommended protocols for dealing with *scratch* since it is sort of a bottleneck for passing data among plug-ins. I would recommend not setting *scratch* as a variable but using it as a holder of property lists. That way, you get a whole name space rather than a single variable name.

To pass data from plugin 'effectX-partA' to 'effectX-partB':

1. Assign a property name based on the effect name, e.g.:

'EFFECTX

2. 'effectX-partA' should delete any old property value:

remprop(quote(*scratch*), quote(effectx))

3. 'effectX-partA' should compute a new property value 'v' and save it:

putprop(quote(*scratch*), v, quote(effectx))

4. 'effectX-partB' should access the property using:

get(quote(*scratch*), quote(effectx))

5. When 'effectX-partB' finishes, it should remove the property:

remprop(quote(*scratch*), quote(effectx)), ...

But there may be cases where you do some analysis and want to use the analysis data multiple times. You might even have multiple analysis plugins operating on different inputs to collect data to feed into a plugin with multiple inputs. In this case, which might be quite common, you should not call 'remprop()', but this has the problem of leaving data on the *scratch* property list indefinitely, so ...

In cases where *scratch* data is not deleted immediately after use, there should be another effect, e.g. 'effectX-partCleanup', that simply calls:

remprop(quote(*scratch*), quote(effectx))

allowing the user to explicitly free up any data stored on the 'EFFECTX property. It would be reasonable to omit the 'effectX-partCleanup' effect if the data stored on the property list has a maximum size of, say, 10KB. The problem we want to avoid is properties with unbounded size getting left in the heap until Audacity is restarted.

  Back to Top


Stereo Tracks


If a sound from an Audacity stereo track was given to Nyquist, the 's' variable contains an array of sounds. Because all Nyquist 'snd-...' low-level functions only can process mono signals, to use such a function, the 's' array first must be split into single mono signals and afterwards being re-combined into an array before it is given back to Audacity.

(if (arrayp s)
    (vector
      (snd-function (aref s 0))   ; left stereo channel
      (snd-function (aref s 1)))  ; right stereo channel
  (snd-function s))               ; mono signal

(arrayp s)
  -  tests if 's' is an array
(vector ... )
  -  re-combines the two mono signals into a stereo signal, a 'vector' is an one-dimensional array
(aref s 0)
  -  the left stereo channel [the 0-th slot of the array]
(aref s 1)
  -  the right stereo channel [the 1-st slot of the array]

Important: The Nyquist interface within Audacity can handle a maximum of two channels simultaneously [Audacity stereo tracks]. If in Audacity more than one audio track were selected, each of the selected tracks will be given sequencially, one after the other, with a maximum of two channels simultaneously [stereo] to Nyquist for processing. It is not possible with Nyquist in Audacity e.g. to copy audio signals from one Audacity track into another track [Audacity 1.3.9, November 2009].

multichan-expand

In the 'nyquist.lsp' file in the Audacity 'nyquist' sub-directory there is a function 'multichan-expand' defined that simplifies the handling of multi-channel sounds [e.g. stereo tracks]:

(multichan-expand function &rest arguments)

So the 'arrayp' constuct from above can also be written:

(multichan-expand #'snd-function s)

This looks a bit more cryptic and reads less intelligibly [arrording to my opinion], but it can help to clean up the code in long-winded audio processing functions.

  Back to Top


Return Values


The result of the last computation within the plugin code will be given back from Nyquist to Audacity. According to the data type of the Nyquist return value one of the following actions will be invoked in Audacity:

sound
  -  the sound will be re-inserted into the selected part of the Audacity track. If the returned sound is shorter or longer than the original sound, the selection will be reduced or augmented. If a mono sound is returned to a stereo track, so in both channels of the stereo track the same mono sound will be inserted. If a stereo sound is returned to a mono track, an error message will be displayed.
string
  -  a dialog window will appear with the string being displayed as text.
list
  -  if a specially formatted list [see below] will be given back to Audacity, a label track will be created below the audio track[s].

The list to create a label track must have the following format:

((int-or-float "string") (int-or-float "string") ... )

int-or-float
  -  the time in seconds from the beginning of the Audacity selection, where the label will appear.
"string"
  -  a string to be displayed in the label's text field.

  Back to top


Math Functions


n-th power of x:

(exp (* (log x-number) n-number))

n-th root of a number:

(exp (/ (log x-number) n-number))

n-th root of a sound:

(s-exp (mult (s-log x-sound) (/ 1.0 n-number)))

n-th root with two sounds:

(s-exp (mult (s-log x-sound) (s-recip n-sound)))

  Back to top


Nyquist Workbench


The Nyquist Workbench gives the ability to run arbitrary Nyquist code in Audacity from a graphical IDE.

  [Nyquist Workbench]

The Nyquist Workbench is an Audacity module, which currently [Audacity 1.3.9, November 2009] is no official part of the Audacity distribution. The source code can be downloaded from:

Download the 'NyqBench' zip-archive from the URL above and unpack it on your harddisk. In the 'Readme.txt' file in the Nyquist Workbench source code directory you will find instructions how to compile the Nyquist Workbench on your operation system.

Here is how it works on Linux:

1. First type './configure' in the Audacity source code directory:

sh:~/downloads/audacity$ ./configure

After 'configure' has finished, do not type 'make', you first need to compile the Nyquist Workbench.

2. Open the Makefile in the Nyquist Workbench directory and make the AUDACITY_DIR variable at the top of the Makefile point to the base of the Audacity source code directory:

AUDACITY_DIR ?= /home/edgar/downloads/audacity

Of course you need to replace '/home/edgar/downloads/audacity' with the Audacity source code directory on your harddisk.

3. After saving the changes in the Makefile, compile the Nyquist Workbench. In the Nyquist Workbench directory type:

sh:~/downloads/nyqbench$ make

After 'make' has finished you shold see a message like:

NyqBench.so has been copied to /home/edgar/downloads/audacity/modules

4. Now compile Audacity. In the Audacity source code directory type:

sh:~/downloads/audacity$ make

5. If 'make' has finished successfully, still in the Audacity source code directory, type:

sh:~/downloads/audacity$ sudo make install

6. Currently [Audacity 1.3.10-alpha, November 2009] the Audacity 'make install' does not copy the 'modules' directory, so type:

sh:~/downloads/audacity$ sudo cp -r modules /usr/local/share/audacity

This copies the 'modules' directory including everything inside from the Audacity source code directory to '/usr/local/share/audacity/modules'.

7. After the next start of Audacity, you should have an additional Audacity 'Tools' menu with a 'Nyquist Workbench' entry inside.

Tested with Audacity 1.3.10-alpha CVS HEAD, November 23. 2009, on Ubuntu 9.10.

  Back to Top


Nyquist Apropos Plugin


Because not all functions, documented in the Nyquist manual, are implemented in Audacity and also not even all Nyquist functions are documented in the Nyquist manual [Lisp is a 'programmable programming language', only functions which are considered as stable are documented], it is often helpful to have a tool to find out wether a particular Nyquist function is implemented or not.

Basically only Nyquist functions beginning with 'snd-...' are implemented in C within the Nyquist interpreter [in the Nyquist manual they are called 'low-level' functions], while all other Nyquist functions are implemented in the Lisp files within the Audacity 'nyquist' sub-directory and can be changed, improved and extended with no need to re-compile Audacity [as long as no C-implemented Nyquist 'low-level' function is needed which is not included with Nyquist in Audacity].

All Nyquist/XLISP symbols [e.g. all variable and function names] are stored in the XLISP *obarray*. To find out from within Audacity, wether a particular function is implemented or not, you can e.g. first create and select a 'dummy' audio track with any generator from the Audacity 'Generate' menu, then open the 'Nyquist Prompt' from the Audacity 'Effect' menu [doesn't work without a selected audio track] and copy the following line into the 'Nyquist Prompt' text input field:

(print (fboundp 'snd-abs))

Important: now please klick 'Debug' instead of the 'OK' button.

First a dialog appears telling you: 'Nyquist did not return audio' [or similar]. In this dialog, klick the 'OK' button. Then another dialog 'Nyquist output' appears with the result of the 'print' function:

T
  -  meaning 'true', function is implemented
NIL
  -  meaning 'false', function is not implemented

I had typed this so often in the past that I have written an Audacity Nyquist 'Apropos' plugin:

Download:  Apropos-Plugin

Right-Click on the plugin link, choose 'save target as', and save the file 'apropos.ny' file in the Audacity 'Plug-Ins' sub-directory. After a re-start of Audacity you can find the 'Apropos' plugin in the 'Generate' menu, the only menu that works without a 'dummy' audio track.

The 'Apropos' plugin offers a pattern search through the Nyquist/XLISP *obarray*. You can also choose between 'Functions only', 'Variables only' and 'All symbols':

  [Apropos Plugin Window]

Note: with no search pattern [empty field], the plugin matches all symbol names.

Important: As written in the plugin window, please press 'Debug' instead of the 'OK' button, otherwise you will not see the results.

First appears a dialog that reminds me that I have forgotten to press the 'Debug' button:

  [Apropos Plugin Message]

In the first dialog above, just klick the 'OK' button. Afterwards, but only if you have clicked the 'Debug' button in the plugin window, appears the window with the results, sorted in alphabetical order:

  [Apropos Plugin Output]

  Back to Top


Audacity Support Forum / Audacity and Nyquist / Nyquist Reference Manual / Nyquist Examples and Tutorials