Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
A Widget is an element of a graphical user interface (GUI), such as a button or slider, which facilitates user interaction. Audacity supplies a number of widget types for Nyquist plug-ins, which are ultimately derived from the WxWidgets toolkit. Fortunately, Nyquist plug-in developers are largely spared from the complexities of WxWidgets, and can simply select which widgets they need by adding the appropriate "header" to the top of the plug-in script.
The layout of a Nyquist plug-in GUI is a simple list of widgets, one above the other.
Slider widgets are supported in all Audacity Nyquist plug-in versions.
variable-name : [symbol] A Lisp symbol.
text-left : [string] Text that will appear to the left of the slider.
variable-type : [keyword] A "number" type, either int, float or real*:
int : integer [FIXNUM, an XLISP whole number]
float (or real*) : floating point [FLONUM, an XLISP number supporting decimal places]
text-right : [string] Text that will appear to the right of the slider.
initial-value : [int / float] Variable value [and slider position] at the first start of the plug-in.
minimum : [int / float] Numeric variable value when the slider is moved to the left border.
maximum : [int / float] Numeric 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 plug-in code.
A text input box to the left of the slider allows the user to type in a value via the keyboard. As of Audacity 2.1.1, input values are validated to only allow input between minimum and maximum values.
The "real" keyword is deprecated. New plug-ins should use "float" as the variable type for floating point input.
The numeric text widget was introduced in Audacity 2.1.2.
variable-name : [symbol] A Lisp symbol.
text-left : [string] Text that will appear to the left of the text box.
variable-type : [keyword] A "number" type, either "int-text" or "float-text":
int-text : Integer [FIXNUM, an XLISP whole number]
float-text : Floating point [FLONUM, an XLISP number supporting decimal places]
text-right : [string] Text that will appear to the right of the text box.
initial-value : [int / float] Variable value at the first start of the plug-in.
minimum : [int / float / NIL] Numeric minimum variable value that will pass validation.
maximum : [int / float / NIL] Numeric maximum variable value that will pass validation.
Minimum and maximum may be numeric values or "NIL". The minimum / maximum is not defined when set as "NIL" and is limited only by the numeric limit for the number type. The valid range for numbers depends on the computer platform. Typically the limits for integers are -2147483648 to 2147483647. The limits for floating point numbers are very large.
Examples of undefined minimum / maximum:
The text input widget ("string widget") is supported in plug-ins version 2 or above.
variable-name : [symbol] A Lisp symbol.
text-left : [string] Text that will appear to the left of the text input field.
variable-type : [keyword] Declares a "string" input type widget.
text-right : [string] Text that will appear to the right of the text input field.
default-string : [string] The string will appear inside the text field.
The text typed in by the user in the text field of the plug-in window can be referred as a string variable from within the plug-in code. All string characters are valid, though care must be taken with escape characters if the string is to be evaluated.
Examples how to use the text input widget can be found in the source code of the Apropos Plug-in.
The multiple choice input widget is supported in plug-ins version 3 or above.
variable-name : [symbol] A Lisp symbol.
text-left : [string] Text that will appear to the left of the multiple-choice list.
variable-type : [keyword] Declares a "Multiple-Choice" type widget.
string-1,... : [string] 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 plug-in.
The list entries string-1, string-2, etc. are comma separated and internally represented by integer numbers. The first, top-most list entry string-1 will be represented by the number 0. The list entry chosen by the user can be determined by the integer value of the variable from within the plug-in code.
An example of the 'choice' widget can be found sample-data-export.ny
Introduced in Audacity 2.3.0.
variable-name : [symbol] A Lisp symbol.
text-left : [string] Text that will appear to the left of the time control.
time : [keyword] A "time" widget.
text-right : [string] Text that will appear to the right of the time control.
initial-value : [int / float] Default value. Number (float or integer) in seconds.
minimum : [number] Minimum numeric value (float or integer) in seconds.
maximum : [number] Maximum numeric value (float or integer) in seconds.
Minimum and maximum may be numeric values or "NIL". The minimum / maximum is not defined when set as "NIL" and is limited to a range of 0 and the maximum supported by the current widget view.
This widget is to input durations. The value set is converted to seconds and assigned as the value of the widget variable.
Example taken from the Pluck effect:
In this example:
variable name is "dur",
text-left is "Duration (60s max)",
text-right is "" (empty string).
initial-value is 1 second.
minimum is 0.0 seconds.
maximum is 60 seconds.
The File Button Widget requires Audacity 2.3.0 or later.
variable-name : [symbol] A Lisp symbol.
text-left : [string] Text that will appear to the left of the file button widget.
variable-type : [keyword] Declares a "File-button" type widget.
button text : [string] Text that appears on the button.
default-file-path : [string] The default file path.
wildcard-filters : [string] File types to show in file browser (based on file extensions).
flags : [string] Option flags, based on wxWidgets File Dialog Styles).
The text widget was introduced in Audacity 2.3.0. Although not actually a "control", it shares similar syntax to all other Nyquist plug-in widgets:
This widget adds a line of text (the "string") to the plug-in GUI.
Best practice: While it may seem convenient to add text to an interface to explain how the plug-in should be used, this widget should be used sparingly. Text descriptions should not be used as a substitute for good design. Plug-in developers should also be aware that it is not currently possible to provide localization (translations) of text in any widgets in third party plug-ins.
Plug-in Headers are specially formatted code comments placed at the top of a Nyquist plug-in script.
Any line beginning with a semi-colon (";") is entirely ignored by Nyquist, but properly formatted "header" comments provide instructions that tell Audacity how to create the plug-in.
Plug-in headers are written as:
where keyword is the header command, and args is a list of values. For most header commands there must be the correct number of arguments.
Important:
Nyquist plug-in headers normally begin with one single semicolon at the beginning of each line.
Headers must be all lower-case except for quoted text (for example: "name") which may include upper-case characters.
Malformed plug-in headers are ignored (treated as normal code comments).
Audacity 2.3.0 adds a new style of header for plug-ins that are shipped with Audacity which provides multi-language translation support.
Translated headers begin with a dollar character ("$") rather than a semi-colon. The string to be translated is double quoted, and appears between (_ and ).
Multi-language support for a plug-in's GUI is available only to plug-ins that are shipped with Audacity, as the translations must be compiled into Audacity's language files.
See also: Plug-in Translations.
Example:
All plug-in headers have the syntax: ;keyword args, where args are the parameters ("arguments") for the header command.
Tells Audacity "this is a Nyquist plug-in". This should normally be the first line as it defines the contents of the file.
Name of the plug-in as it will appear in the Audacity menu:
Note that for plug-ins to be used in Chains, the colon character ":" cannot be used (as it is a special character in the Chain text file).
If the plug-in has an interface, the name should end with three dots so as to indicate that additional user action is required before the plug-in is applied. Plug-ins that act immediately without additional user action should not have dots at the end of the name.
Only one ";type" line should be used.
A plug-in cannot appear in several Audacity menus at the same time, but it is possible to write several plug-ins with the same name and different ";type" lines. Each plug-in will then appear in the appropriate menu. Using the same name for more than one plug-in is not recommended and should generally be avoided.
Tool type plug-ins are typically Nyquist Macros or plug-ins that don't fit well in any of the first three roles. They may also be combined with one of the other types:
Use only one ";version" line.
All new plug-ins should use the most recent version number so that all current features are available. The version line is required to allow Audacity to run the plug-in correctly and prevents plug-ins with new features from being loaded in an old Audacity program that is missing required features.
Name of the plug-in Author. If this line is added, its text will appear in the Audacity Effect Menu when sorted or grouped by "Publisher". The author name string must be quoted.
A short statement of the copyright/license terms. For plug-ins shipped with Audacity, this must be compatible with Audacity's GPL v2 license. The copyright string must be quoted.
Recommended text for GPL v2 license:
;copyright "Released under terms of the GNU General Public License version 2 or later"
Additional copyright details may be included in the plug-in code comments, but must not conflict with the terms declared in the copyright header.
Displays a release version number for the plug-in in the Manage > About menu.
Plug-ins that are shipped with Audacity have a release version number equivalent to the Audacity version at the time that the plug-in was last updated.
Plug-in authors may choose whichever versioning scheme they prefer, but should ensure that later versions of the plug-in always have a later version number. If the version number has spaces, it must be enclosed in double quotes.
Any one of the following are valid (though there should be only ONE release header in a plug-in):
release 1 release 0.0.1 release "1.0" release "3.5 beta"
Declaration of code syntax. May be either lisp or sal (lower case).
For LISP syntax plug-ins this is usually omitted, but it should always be included for SAL syntax plug-ins.
If the code type is not declared in the Nyquist Prompt effect, Audacity attempts to deduce the correct syntax from the code.
The code type can only be Lisp syntax or SAL. It cannot be a mix of both.
Show or hide the Debug button. The default is to show the button, but for plug-ins that are shipped with Audacity, or other plug-ins that are believed to be bug free, the Debug button may be hidden by setting this to "false" or "disabled"
or
These flags may be used in conjunction with the debugbutton header to provide a variety of behaviors.
debugbutton true, debugflags trace: Debug window opens if debug button pressed or if Nyquist printed to the debug window.
debugbutton false, debugflags trace: Debug button disabled, but debug window opens if Nyquist printed to the debug window.
debugbutton true, debugflags notrace: Debug window opens only when Debug button is pressed. If Debug button has NOT been pressed, any error messages that arise are routed to the Audacity log.
debugflags compiler, debugflags trace: (When using SAL syntax) The Debug window always opens to display the output from the SAL compiler.
debugflags compiler, debugflags notrace: (When using SAL syntax) The Debug window only opens to display the output from the SAL compiler if Debug button is clicked, otherwise it is printed to the Audacity log.
debugflags nocompiler, debugflags trace: (When using SAL syntax) The Debug window always opens to display debug and/or error messages. Output from the SAL compiler is suppressed.
A Help button may be added to the plug-in GUI by giving the relative path and name of a help file. As the button can only be created if the plug-in has a GUI, this header should not be used in plug-ins that do not have a GUI.
The file path is relative to the plug-in search path. Normally the help file would be placed in the same location as the plug-in when it is installed. To support HTML files with images and/or media, the help file and its resources may be in a folder, and the folder included in the file path. For example, if the help file is called "my_effect.html" and it includes images, then the html file and images may be placed in a folder called "my_effect_help", and the helpfile header would be:
If the help file is not found, the ? button will not appear.
This is primarily intended for use by plug-ins that are shipped with Audacity. It is similar to the helpfile header, except that it looks for the help file in the search path for Audacity's manual. As with ";helpfile" it should only be used in plug-ins that have a GUI. For more information, see Location of Manual
Specifies the maximum number of samples to be processed in "process" or "analyze" type plug-ins. This can help the progress bar if length that will be processed is determined by the plug-in rather than by the length of selection. It could also be used as a fail-safe for plug-ins that are specifically designed for short selections. This example limits the number of samples to 1 million:
When the MAXLEN header is used, the Nyquist global variable LEN is the maximum of "length of selection in samples" and "value set by MAXLEN".
In "process" type effects, this may cause the selected audio to be truncated to the specified number of samples. In such cases it may be best to throw an error if "maxlen" is exceeded, for example:
Allows Nyquist plug-ins to override Audacity's default "clip merge" behaviour. By default, when effects (including generator effects) are applied across one or more clip boundaries and the returned audio is a different length from the original selection, Audacity will add "split lines" at the ends of the returned audio. In all other cases, the returned audio is "merged" into the current audio.
This option only applies when the plug-in is applied across clip boundaries (including across "split lines").
-1 Automatic clip merge behaviour (default)
0 Don't merge clips. Effects that are applied across clip boundaries will not be merged into the existing audio (there will be split lines at the ends of the returned audio) whether the returned audio is the same length as the original selection or not.
1 Always merge clips. The returned audio will always be merged into the existing audio (no split lines added).
See also "restoresplits".
Provides options for previewing the effect. Multiple preview options may be defined to achieve the desired behaviour.
Preview Options
enabled (default). Preview is enabled.
true Same as "enabled".
disabled Preview is disabled. If Audacity is unable to provide a meaningful preview, then preview should be disabled. This may be required for effects that affect specific time regions within the selection.
false Same as "disabled".
linear Provides an optimisation for previewing multiple tracks by mixing the selected tracks before applying the Nyquist code. This optimisation is disabled by default.
selection When previewing, the Nyquist code is applied to the entire selection (not just the length that will be previewed). Audacity's "Preview" then plays the first few seconds of the processed audio. This may be required for effects that vary over the duration of the selection.
Allows Nyquist plug-ins to override Audacity's default "split restore" behaviour. By default, when effects (including generator effects) are applied across one or more clip boundaries, Audacity will restore "split lines" at the position of the original clip boundaries.
This option only applies when the plug-in is applied across clip boundaries (including across "split lines").
Restore Splits Options
1 Splits at clip boundaries are restored (default)
0 Splits at clip boundaries are not restored (clips are joined).
Note: Nyquist plug-ins are not currently able to distinguish between silence and "empty space" within the selection, so gaps between audio clips will be treated as if the empty space is an additional "silent" audio clip.
See also "mergeclips".
These headers are obsolete and no longer used by Audacity. They should not be used in new plug-ins.
They may still be found in some old plug-ins, but are now treated by Audacity as ordinary "comments" and simply disregarded.
Description shown in progress window.
Specifies an LV2 category for the plug-in.
A single line of text to be displayed at the top border of the plug-in window. For multiple lines of text, a two-character sequence "\n" may be used within "text" to create a line break.
If the plug-in includes at least one properly formed "Control" header, Audacity will launch the plug-in with a GUI.
Each valid "Control" header adds a widget to the GUI. If there are no "Control" headers, Audacity will attempt to run the effect without a GUI.
There can be several "control" lines in the plug-in header. Add one for each widget to appear in the dialog box. The ;control headers should normally be the final headers as they define variables used by the Nyquist code.
This page explains how to use Nyquist to change the volume of Audacity tracks in different ways.
Note: All [comments] and [explanations] are written in square brackets, so they cannot be confused with (Lisp code).
SAL is a new alternative syntax to LISP. Although Nyquist is based on the LISP programming language, you can write almost any Nyquist program in SAL. Most people prefer SAL syntax to LISP syntax because SAL is a bit more like popular programming languages that include Java, C, and Python.
You can only use one or the other in your script.
scale(number, sound)
The "scale" function multiplies the amplitude [volume] of the "sound" by the given "number". A number of 0.5 will make the sound become only half as loud as before, while a number of 2 will make the sound become double as loud as before.
Example:
To run this example in the Nyquist Prompt, ensure that "Use legacy (version 3) syntax" is not selected.
1. Create an audio track with some audio [eg a short recording]
2. Now click Tools > Nyquist Prompt. A window with a text field will appear where you can type in:
Important: Do not forget to type the parentheses. The parentheses are part of the Lisp language Nyquist is based on. Without the parentheses the Nyquist Lisp interpreter will not be able to understand your code.
Important: Do not forget to type the parens and comma. These are part of the SAL language.
After clicking "OK" in the "Nyquist Prompt" window the "scale" function will take the Audacity sound and return a "scaled-down" sound with half the volume to Audacity. The result of the last computation of the Nyquist code always gets automatically returned to Audacity.
If you try "scale" with big numbers you will notice that you can return sounds with volumes taller than the Audacity track which will sound very distorted if you play them afterwards in Audacity. So an important lesson to learn is that Nyquist gives you the freedom to do whatever you want but it's now on you to take care that the result will still sound good afterwards.
MULT may be used with numbers, sounds or multi-channel sounds. When using MULT with a sound and a number, each sample value in the selected sound is multiplied by the number, which is essentially the same as using the SCALE command.
In general terms, a variable is a symbol which contains a value. The symbol can be any valid name, and its value may be changed (hence "variable"). In Nyquist, the value may be of any data type (for example, a number, a character, or even a sound) and may be changed from one data type to another. Unlike some programming languages, variables do not need to be declared before use - they can just be set, and then they exist.
In addition to the value of the variable, one or more "properties" may also be attached to the symbol. Each "property" has a name and a value. The properties are known collectively as the symbol's "property list".
Setting the value of a symbol "binds" the value to the symbol. A symbol that has no value (not even "nil") is said to be "unbound".
In addition to the value of a symbol, we can also attach properties. This is a way of associating a list of items, each with their own value, to a single variable. Each item is called a key or indicator, and we can give each key a value. This list of items is called a "property list" (or plist for short).
To get the value of a property, we use the GET command.
When getting the value of a property, we do NOT want to evaluate either the variable (symbol) or the key symbol, so we must "quote" both symbols to prevent evaluation.
When the type of a plug-in is process or analyze, Audacity sets the value of *TRACK* to the currently selected audio, and sets a lists of properties related to that track. The plug-in processes one track at a time in sequence, and the *TRACK* variable is set each time for the track that is being processed.
The GET command returns the value of the property (the name of the track), which may be assigned to another variable and used elsewhere in the code. For example, to print a pretty message:
For mono tracks, the CLIPS property is a list, containing a two element list for each clip in the selected track. A mono track with two audio clips will look like ((s1 e1)(s2 e2))
where s1 and s2 to are the start times of the two clips, and e1 and e2 are the end times.
This code snippet will print the start and end times of the first audio clip in a mono track:
Fortunately it is easy to find the absolute start time of the selection by using "START" property of the *SELECTION* variable: (get '*selection* 'start)
. We can create a label at an absolute time (relative to Audacity's Timeline) like this:
We can now put this all together and create a label for each audio clip in the selected track:
Just as stereo sounds are represented as an array of sounds, so the track "clip" data for stereo tracks is an array of lists (one list per channel). A stereo track with two audio clips in each channel will look like: #(((s1 e1)(s2 e2))((s3 e3)(s4 e3)))
where s1 to s4 to are the start times, and e1 to e4 are the end times.
This code snippet will print the start and end times of the first audio clip in the left channel of a stereo track:
In a similar manner to the mono example, we can create a label for each clip in a stereo track:
Nyquist-Macros are a special kind of Nyquist plug-in that instruct Audacity to perform tasks using Audacity's scripting interface.
To use this feature effectively, it is necessary to use the correct commands and syntax, and also understand that when Nyquist is used in this way, Nyquist is not allowed, or able, to modify the project. Nyquist-Macros may instruct Audacity to modify the project, but unlike ''ordinary'' Nyquist plug-ins, Nyquist cannot itself modify the project.
Nyquist Macros are a fairly advanced topic, so this tutorial is aimed at users with an intermediate to advanced level of experience with Nyquist programming.
Nyquist Macros are a powerful extension of Audacity's features. With great power comes great responsibility. Nyquist Macros bypass much of Audacity's built-in validation, so it is relatively easy to pass invalid commands that can cause Audacity to crash. Test your Nyquist Macros thoroughly before using them for important production work.
(aud-do "Play")
Some things to note:
The command "Play:" is a string (text).
The Nyquist function is AUD-DO, which like any other Nyquist function is case insensitive, and usually written in lower case in code.
The function AUD-DO takes exactly one parameter, which is the command string.
As Nyquist cannot modify the project when used to send Macro scripting commands, most Nyquist-Macros will be written as "tool" type plug-ins.
As described above, the "AUD-DO" function takes exactly one argument (parameter), which is the command that will be sent to Audacity. However, we may sometimes want to send a command that has multiple parameters. For example, to generate a 10 second, 200 Hz, 0.5 amplitude sine tone, the Macro Scripting command is:
Tone: Frequency=200 Amplitude=0.5 Waveform="Sine"
With AUD-DO we can send the command, including it's parameters, as one string:
(aud-do "Tone: Frequency=200 Amplitude=0.5 Waveform=Sine")
Using the above example, the macro command string could be passed as the value of a variable:
(setf command "Tone: Frequency=200 Amplitude=0.5 Waveform=Sine")
(aud-do command)
Here is a simplified implementation of Audacity's Tone Generator:
Some important things to note in this example Nyquist Macro:
The plug-in type is "tool". If it were set as a "generate" type, running the plug-in without a track would crash because of the duplicate attempt to create a new track (once from the plug-in being a generate type, and again from the Audacity scripting command).
This simplified version does not provide a "Duration" control, so the generated tone will be the length of the selection (if there is a selection), or 30 seconds (default).
In the Scripting command, the Waveform parameter must be quoted because its value may include a space. We therefore use ~S rather than ~A in the FORMAT function.
If you are familiar with Nyquist's LISP syntax, you will have noticed that the syntax described above is not very Lisp-like. The ''magic string'' commands are case sensitive, and constructing the strings is inelegant. However, for many of the scripting commands, a lisp equivalent exists.
Each of these functions have names beginning '''AUD-''', suffixed with the scripting command name. The scripting command parameters are passed as keyword arguments.
There is a small performance penalty when using these LISP syntax commands, so for performance critical applications (such as batch processing many small files), it may be preferred to use the AUD-DO versions.''
In Audacity 2.3.2 and later, the following scripting commands have equivalent LISP functions:
Tip: Remember that Nyquist Macros cannot call Nyquist effects.
Example: The scripting command for Audacity's built-in "Amplify" effect is:
Amplify: Ratio=<number>
The equivalent imported LISP function for Audacity's built-in Amplify effect is:
(aud-amplify :ratio <number>)
In both versions, the ratio is a floating point number representing the gain on a linear scale. If we want to Amplify by -3 dB, we can apply the Amplify effect:
Tip: Although the imported function names, and keys are case insensitive, note that if the keyword value is a string, the value is case sensitive.
In this next code sample, we reproduce the simple "Tone" generator from above, using the imported AUD-TONE function:
One limitation of Nyquist plug-ins that we cannot yet work around, is that the plug-in UI is not dynamic and cannot be changed programmatically. Where as Audacity's built-in Tone generator will automatically show the length of the selected audio, this is not yet possible for Nyquist plug-ins. As a compromise solution, we can:
Add a "Duration" control.
If there is no selection, create a selection of the length specified by the Duration control.
If there is a selection, ignore the Duration control and generate into the selection.
Note: In order to generate audio into a selection, there has to be a ''track'' selection before running the generate command. It is not enough to have a time selection without a track being selected.
As we want to mimic the behaviour of Audacity's Tone generator, we need to handle cases where:
There is a selection in an audio track.
There is a time selection but no track selection.
There is a track selection but no time selection.
In Audacity 2.3.0 and later, there is a "[Nyquist_Plug-ins_Widgets#Time_Widget time widget]", which greatly simplifies handling durations, and is in keeping with Audacity's built-in effects.
;control duration "Duration" time "" 30 0 nil
Then we want to check if an audio track is selected, and if not, add a new track. Note that there isn't a LISP function for adding a new track, so we fall back on AUD-DO instead:
And to handle the time selection:
The completed Nyquist Macro plug-in:
When using built-in effects or "Scriptable" commands, it is recommended to use the optional LISP functions. Not only are they more Lisp-like and convenient to use, they also provide a little more error checking, which can be very helpful when debugging. Note however that there is a small performance penalty when using these LISP syntax commands. For performance critical applications (such as batch processing many small files), it may be preferred to use the AUD-DO versions.
Be flexible in your thinking. Scripting commands are available for many, but not all of Audacity's functions. If you need to do something that appears to be missing from the available commands, consider other ways to achieve the desired result.
See also:
Type header | Features | Typical Role |
---|---|---|
Type header | Features |
---|---|
Version header | Features |
---|---|
debugflags header | Description |
---|---|
You can specify which one you're using with the respective :
To change the volume of an Audacity track with Nyquist, the easiest way is to use the Nyquist function:
See for an explanation how the Nyquist prompt works.
For more information about the *track*** ** keyword, refer to the
An alternative command for amplifying a sound is the command.
The following examples may be run in the .
For a full list of global properties, see the .
The value of *TRACK* provides direct access to the selected audio, and its property list provides access to other properties of the track. The NAME property provides the name of the Audacity track that is currently being processed. To access the value of the NAME property, we use the command.
Although we can change the value of the NAME property (using ), doing so will NOT change the name of the Audacity track. The value of the NAME property is only a copy of the track name, created by Audacity when the plug-in runs. If required, the name of the track could be changed using the scripting command . More generally, modifying a *TRACK* property does not modify the track.
See also in the XLisp manual.
This property contains a list of start and end times of each audio clip in the track. This property is more likely to find uses in than in standard Nyquist plug-ins. Note that this property refers to the entire selected track, and not only the selected portion of the track.
It is important to remember that Nyquist sees the start of the current selection as "time=zero". Thus if we wish to actual track times in Nyquist, we must offset the times by the start time of the current selection. We can create a point label at time=0 with (list (list 0 0 ""))
, but this is relative to the start of the current selection. If we want to create a label at time=zero as shown in the regardless of where the selection starts, then we must offset the label times by the start time of the selection.
Nyquist-Macros are potentially far more powerful than normal in that they may make use of logic, loops and conditionally executing code, rather than only running through a simple list. They can also accept user input via the usual , and most other features of Nyquist plug-ins.
In this tutorial, we will be reimplementing Audacity's generator as a Nyquist Macro. During the course of the tutorial, many of the abilities and core concepts of Nyquist Macros will be discussed, along with tips and potential pitfalls to watch out for in your own programming.
Audacity provides a rich set of scripting commands, which are documented in the section of the Audacity manual. These commands may be sent from Nyquist, to tell Audacity what to do, using the function call "AUD-DO". As a very simple example, Nyquist can tell Audacity to start playing by sending the command "Play:"
The command is case sensitive. It must be capitalized exactly as stated in the .
The examples in this section may be run in the , but ensure that you make a in an audio track first.
As with other Nyquist commands, a string argument does not need to be a , it may be a variable that evaluates to a string.
In this slightly more complex example we use the command to construct the command string. This approach is very useful if scripting command parameters are to be generated programmatically or obtained from user input.
If we incorporate this code in an installable Nyquist Macro, we see that we are getting close to re-implementing Audacity's generator as a Nyquist macro.
effects.
effects.
.
.
Unlike Nyquist's generator functions, Audacity's built-in do not have a parameter for the duration of the sound that is generated. Instead, the duration is set by the length of the track selection. If there is no track selection, then the length defaults to 30 seconds.
While is is possible to find what is selected using the scripting command , a simpler way is to use the Nyquist global property list *SELECTION*.
If you get stuck, ask for help. As with other aspects of Nyquist programming, support requests may be made on the Nyquist board of the .
Required plug-in headers:
These headers are required in all Nyquist plug-ins.
****
Defines the text file as a Nyquist plug-in.
;name "name"
Sets the name of the plug-in.
;type "type"
Specifies the type of plug-in.
;version version
Specifies the Nyquist plug-in version.
Display Headers:
Display additional information about the plug-in. These headers are optional.
;author "text"
Name of plug-in developer. Shown in the "About" section of Manage. Also used when effects are sorted by "Publisher".
;copyright "text"
Copyright / license notice. Shown in the "About" section of Manage.
;release version
Version / release number of the plug-in. Shown in the "About" section of Manage.
Functional Headers:
These headers may be used to provide additional functionality.
;codetype type
Specifies if the Nyquist code uses SAL or LISP syntax.
;debugbutton option
Specifies if the Debug button is visible.
;debugflags flags
Sets the debug message behavior.
;helpfile "path to file"
Displays a Help button that links to a plug-in Help file.
;manpage "URL"
Displays a Help button that links to the plug-in Help page in the Audacity manual.
;maxlen integer
Sets the maximum number of samples to be processed.
;mergeclips integer
Specifies the clip merge behavior.
;preview option
Specifies the plug-in Preview options.
;restoresplits integer
Specifies the clip split behavior.
Obsolete Headers:
These headers are no longer used by current versions of Audacity and are ignored.
;action "text"
Ignored.
;categories "text"
Ignored.
;info "text"
Ignored.
These headers define the plug-in GUI.
;control <args>
The parameters (<args>) specify the type of widget and the widget's required arguments. See also: Nyquist Plug-ins Widgets
;type analyze
Plug-in appears in the Audacity Analyze menu.
Analyzing selected track audio.
Durations are relative to the selection length.
Code iterates through each selected track.
;type generate
Plug-in appears in the Audacity Generate menu.
Generating audio.
Durations are absolute (1 "unit" of time = 1 second).
Code runs once only regardless of number of tracks.
;type process
Plug-in appears in the Audacity Effect menu.
Processing selected track audio.
Durations are relative to the selection length.
Code iterates through each selected track.
;type tool
Plug-in appears in the Audacity Tools menu.
Nyquist Macros / Other.
Nyquist cannot directly modify the project.
;type tool analyze
Appears in the Audacity Tools menu and behaves like an Analyze type.
;type tool generate
Appears in the Audacity Tools menu and behaves like a Generate type.
;type tool process
Appears in the Audacity Tools menu and behaves like a Process type.
;version 1
Slider Widget
;version 2
Text input widget added
;version 3
multiple-Choice widget added
;version 4
Additional global variables to pass additional information from Audacity to Nyquist.
New optional plug-in headers:
;debugflags trace
Sets tracenable (LISP) or sal-traceback (SAL) and displays debug window if there is anything to show.
This may be useful when showing debug info is integral to what the plug-in does, or when debugging a script.
;debugflags notrace
Disables tracenable (LISP) / sal-traceback (SAL). This prevents the debug window from opening on error, unless the Debug button has been pressed.
If the Debug button has not been pressed and there is an error, the error message will be sent to Audacity's log. Note that disabling tracenable limits the debug output to only the error message with little or no additional debugging information.
;debugflags compiler
Set sal-compiler-debug to 'true'.
Output from the SAL compiler is printed to the debug output. This may be viewed in the Debug window if enabled (for example, by clicking the Debug button), otherwise in the Audacity log.
;debugflags nocompiler
Set sal-compiler-debug to 'false'.
Disables compiler messages from SAL. Only debug and error messages are printed to the debug output.
This page explains how to use Nyquist to change the volume of left and right stereo channels independently.
As discussed previously, the audio data <sound>
from an Audacity track is passed to Nyquist in a variable '*track*
'. If the track is mono (just one channel) then the <sound>
is simply the value given to the variable '*track*
'. However, for a stereo track there are two sounds, and these are passed to Nyquist as two elements of an array. The name of the array is '*track*'
.
To access a specific element of an array we use the (aref) command.
As a stereo track has 2 channels, the array '*track*
' has two elements which are numbered 0 and 1. the 0th element is the audio data from the left channel and the other element contains the audio data from the right channel.
To access the audio data from the left channel we can use:
To access the audio data from the right channel we can use:
As described in the previous tutorial we can amplify a sound using the (scale) function. For a mono track if we want to halve the amplitude of the sound we simply type
If we use this instruction on a stereo track the function is applied to each element of '*track*' in turn, so both channels are amplified to half of their original amplitude. However if we want to access the channels individually then we also need to know how to send two different sounds back to the same track in Audacity.
To send two different sounds to a stereo track in Audacity we must create an array with two elements. The first element will contain the <sound>
{=html} for the left channel and the second element will contain the sound for the right channel. The easiest way to do this is to use the vector function.
<left channel>
and <right channel>
will be the sounds that we are sending from Nyquist.
To try this out we will amplify the left channel only of a stereo track.
Open a short stereo track.
From the Effect menu select "Nyquist Prompt" and enter the following code:
Notice that the two elements are within the ellipses of the "vector" function.
The 0th element in this array is the original left channel (aref *track* 0)
that has been scaled [amplified] by 2. This will be the new left channel. The next element in this array is the original right channel (aref *track* 1)
which is sent back unaltered as the new right channel.
Instead of using the function (scale)
we could use the function mult. This is virtually identical to using the function scale except that we do not need to specify the multiplication factor first. (mult 2.0 *track*)
is identical to (mult *track* 2.0)
.
For our second example we will amplify the left channel to half of its original amplitude and the right channel to double its original amplitude:
This page explains how to use Nyquist to add a feedback delay effect in Audacity.
Note: All [comments] and [explanations] are written in square brackets, so they cannot be confused with (Lisp code).
To add a feedback delay effect to an Audacity track with Nyquist, the easiest way is to use the Nyquist "feedback-delay" function:
(feedback-delay sound delay feedback)
The "feedback-delay" function applies feedback delay to sound. The delay must be a number (in seconds). The sample rate is the maximum from sound and feedback (if feedback is also a sound). The amount of feedback should be less than 1 to avoid an exponential increase in amplitude. Also since output is truncated at the stop time of sound, you may want to append some silence to sound to give the filter time to decay.
Example:
1. First either load a sound file into Audacity or record some.
2. Now click Tools -> Nyquist Prompt. A window with a text field will appear where you can type in:
Do not forget to type the parens. The parens are part of the Lisp language Nyquist is based on. Without the parens the Nyquist Lisp interpreter will not be able to understand your code
See Prompt Basics for more info about the prompt.
After clicking "OK" in the "Nyquist Prompt" window the "feedback-delay" function will take the Audacity sound and return a output sound with a feedback delay of 0.7s throughout the sound. The result of the last computation of the Nyquist code always gets automatically returned to Audacity.
The ''*TRACK*''' variable is the Audacity "sound" [the selected part of the Audacity track]. Nyquist in Audacity always understands ''*TRACK*'' as the Audacity sound variable.
Try "feedback-delay" with longer or shorter delay times as well as different sounds for feedback. Nyquist provides many more functions to generate sounds besides the simple "sine" function. Look at Functions: Sound Synthesis for the complete list of these functions.
This tutorial provides a description and examples of how to create and use a File-Button Widget in Nyquist Plugins.
The File-Button Widget provides a means to select one or more files via a graphical file browser.
For some plug-ins it is necessary to read from or write to files. In order to do this, it is necessary to define precisely which file is required, where the file is located, and whether it is required for read access or write access (for read access, the file must exist, whereas for write access this is not always a requirement).
Prior to the availability of the File-Button Widget, file names could be hard coded into the Nyquist script, or a text box could be provided for the user to enter the name of the file. Hard coded file paths lack flexibility, are platform specific (a path starting with "C:\" does not work on Mac or Linux), and may point to locations that do not exist on some machines. While a text box may provide a better solution than hard coding a file path, it remains inconvenient and prone to user error, especially for long file paths. The File-Button Widget was introduced in Audacity 2.3.0 to solve these problems, by providing access to a graphical "file browser window" similar to using File menu > Open or File menu > Save in other applications.
The File-Button Widget, as shown above, has an editable text input field that allows a file path to be typed (or pasted). After the text input field is a button that launches a file browser. Below is an example of the familiar file browser window on Windows 10.
Note that selecting a file in this file browser does NOT open the file.
When a file is selected in the file browser window, the full name and path of the selected file is passed to the Nyquist script as the value of the File-Button Widget variable.
The syntax for creating a File-Button Widget is similar to all other Nyquist Plug-in widgets.
;control : Start of header statement. The leading semicolon ";" (or dollar character "$") tells Nyquist to treat this line as a comment and ignore it. The keyword "control" tells Audacity to create a GUI widget to be used by the Nyquist script.
variable-name : [symbol] The variable name that will be set.
text-left : [string] Text on the left side of the widget.
file : [keyword] Declares a "file" type widget.
button-text : [string] Text on the button. Normally this would be two double quotes (an empty string), which gives the default text: "Select a file"
default-file-path : [string] Default file path for the file browser. This supports keywords to aid cross-platform support.
wildcard-filters : [string] This is a magic "wildcard" string that follows the same syntax as wxFileDialog. The string comprises pairs of "description", pipe symbol ("|"), "file extension(s)". Multiple file extensions may be listed, separated by semi-colons (";").
flags : [string] This is a "magic" string that sets options for the file browser, following the same syntax as wxFileDialog.
The final three arguments, default-file-path, wildcard-filters, and flags, use special keywords that define the behavior of the File-Button Widget and the associated File Browser.
Note that unlike Nyquist symbols, these keywords are case sensitive.
The "Windows", "macOS" and "Linux" examples below refer to standard file paths for modern operating systems, though may be different on some machines.
"<username>" is the name of the computer user's account (log-in name).
"default file path" supports the keywords:
*home*" : The current user's "home" directory.
Windows: C:\Users\<username>
\
macOS: /Users/<username>
/
Linux: /home/<username>
/
~ : An alias for *home*.
*default* : The default "Documents" path.
Windows: C:\Users\<username>
\Documents\Audacity
macOS: /Users/<username>/
Documents/
Linux: /home/<username>
/Documents/
*export* The default "Export" path.
Windows: C:\Users\<username>
\Desktop\
macOS: /Users/<username>
/Documents/
Linux: /home/<username>
/Documents/
*save* The default "Save" path.
Windows: C:\Users\<username>
\Desktop\
macOS: /Users/<username>
/Documents/
Linux: /home/<username>
/Documents/
*config* The default configuration file directory.
Windows: C:\Users\<username>
\AppData\Roaming\audacity\
macOS: /Users/<username>
/Library/Application Support/audacity/
Linux: /home/<username>
/.audacity-data/
These keywords may be combined with a file name to specify which file to open. For example, if you want the default file to be called "sample-data.txt", and you want the default location to be the default "Documents" path, you could write the default file path parameter as: "*default*/sample-data.txt"
.
File paths should be quoted with double quotes, otherwise spaces in file name will fail. If no file path is provided, the default is "default". If no file name is provided, the default file name is "untitled". The default file extension is taken from the wildcard-filters.
The "wildcard-filters" determine which file types are visible in the file browser. An empty string will default to all files types.
This "magic string" follows the same syntax as wxFileDialog. The string comprises pairs of "description" and "file extension(s)", separated by a pipe character ("|"). Multiple file extensions may be listed, separated by semi-colons (";").
Example:
"Text file|*.txt;*.TXT|All files|*.*;*"
In this example we have two pairs:
Text file|*.txt;*.TXT: Description: "Text file" File extension "*.txt" matches: "anything.txt" File extension "*.TXT" matches: "anything.TXT"
All files|*.*;*: Description: "All files" File extension "*.*" matches: "anything.anything" File extension "*" matches: "anything"
The magic "flags" string is similar to the "Styles" options in wxFileDialog. Flags may be an empty string, a single keyword, or a comma separated list of keywords.
Available keywords are:
open : This is a "file open" dialog. Usually this means that the default button's label of the dialog is "Open". Cannot be combined with "save"
save : This is a "file save" dialog. Usually this means that the default button's label of the dialog is "Save". Cannot be combined with "open".
overwrite : For save dialog only: prompt for a confirmation if a file will be overwritten.
exists : For open dialog only: the user may only select files that actually exist
multiple : For open dialog only: allows selecting multiple files.
Example: Open file dialog for one or more files that must exist.
"open,exists,multiple"
Example: Save file dialog with overwrite prompt if file exists.
"save,overwrite"
The File-Button widget attempts to create a valid file path as a string, and assign it to the "variable-name" symbol.
If a single file is selected using the file browser, then the widget text box is updated to show the full path to the selected file.
If multiple files are selected using the file browser (requires "multiple" flag to be set), each file path is enclosed in double quotes. Note: The list of file paths is NOT a LISP list. It is still a string. See example below for how to deal with multiple file paths.
If the file path text box is empty, then the widget variable symbol is set to the default path.
If the file path text box contains only a file name (or any string that is not a path), then it is prepended with the default path and assigned as the value of the widget variable.
In the event of programming or user errors, the File-Button Widget may return an error message. Understanding these messages can be a great help when debugging a new plug-in.
<Path>
is not a valid file path.
****This error occurs if the returned file path is invalid, for example, if the directory does not exist. : This error is most likely to be due to the user manually editing the file path text box with an invalid file path.
Mismatched quotes in <string>
****When the "multiple" flag is set, the file browser returns a list of quoted strings for each path. This error is thrown if the opening quotes do not have matching closing quotes. : This error is most likely to be due to the user manually editing the file path text box and missing one or more quote characters.
Invalid wildcard string in 'path' control. Using empty string instead. ****This error occurs if the 'wildcard' magic string is malformed. : This is a programming error. Check the syntax of your wildcard string.
Simple "Open File" Example
;control var "Select file to open" file "" "" "" ""
In this example. only the variable ("var") and the "text-left" ("Select file to open") are explicitly set. Empty strings are passed to the other parameters, so they will all take default values.
In reverse order: the default "flag" is "open", the default wildcard filter is "All files", the default file path is "*default*", the default file name is "untitled", and the default button text is "Select a file".
Simple "Save File" Example
;control var "Select file to save" file "" "" "" "save"
Very much like the simple "open file" example above, except this one is selecting a file for writing.
Advanced "Open File" Example
;control filename "Select file" file "" "*default*/sample-data.txt" "Text file|*.txt;*.TXT|All files|*.*;*" "open,exists"
Unlike the previous examples, all parameters are explicitly defined. The default file name is "sample-data.txt", and by default the file browser filters the file list to show Text files only (ending in ".txt" or ".TXT"). The file browser also has an option to show all files.
Note that the file browser is created by the underlying operating system, so there are subtle differences across platforms. The "exists" flag is only relevant for file browsers that allow you to type the file name. For a purely graphical browser it is not possible to select a file that does not exist.
Note also that the "exists" flag only affects the file browser - it does not prevent the user typing a non-existent file name in the file path text field. If the plug-in requires the file to exist, then the plug-in code should run a test to ensure that it does. A simple test for the existence of a file, is to try and open it, for example:
Advanced "Save File" Example
;control filename "Export data to" file "Select a file" "*default*/sample-data.txt" "Text file|*.txt;*.TXT|CSV files|*.csv;*.CSV|HTML files|*.html;*.HTML;*.htm;*.HTM|All files|*.*;*" "save,overwrite"
In this example, all parameters are explicitly defined:
variable-name: filename
text-left: "Export data to"
button-text: "Select a file"
default-file-path: "*default*/sample-data.txt"
wildcard-filters: ****Text file|*.txt;*.TXT| CSV files|*.csv;*.CSV| HTML files|*.html;*.HTML;*.htm;*.HTM| All files|*.*;*"
flags : "save,overwrite"
The wildcard filters provide options in the file browser to show either text files (.txt or .TXT), which is the default, or CSV files (.csv pr .CSV), or HTML files (.html, or .HTML, or .htm, or .HTM), or "All files" (any file name).
Note that on Windows, file extensions are not case sensitive, but Linux, and some Mac computers are case sensitive, so for cross-platform portability it is recommended to use both upper and lower case file name extensions.
Open Multiple Files
;control var "Select one or more files" file "Select" "*default*" "Text file|*.txt;*.TXT|All files|*.*;*" "open,multiple"
In this example, the variable that will be set is var
, the default directory is *default*
, and the default file type filter is for text files (with an option to show all files). Unlike the previous versions, the file browser may be used to select multiple files (requires Audacity 2.3.1 or later).
If the users selects one or more files using the file browser, then each file path will be enclosed in double quotes. However, the user could type in the path to a single file without quotes, or, as in this case, the default could be an unquoted single file path, so we should check for and support both versions.
To extract all of the the paths from the returned string, we first need to convert it to a more useful form, such as a LISP list:
(setf path-string
(format nil "(list ~s )" (string-trim "\"" var)))
Here we have stripped the outer double quotes (if present), and then formatted it into a string that describes a LISP list. So, for example, if the selected files were: "C:\first.txt" and "C:\second.txt", then the value of var
would be ""C:\first.txt""C:\second.txt""
, and the value of path-string
would be "(list "C:\first.txt" "C:\second.text")"
.
Important: Note that this is still only a string value, not a LISP list.
To convert this string into a LISP list, we need to evaluate the string as if it were code. Fortunately in Audacity 2.3.1 and later, there is an easy way to do this with the EVAL-STRING
function:
(setf paths (eval-string path-string))
paths
is now a valid LISP list of strings, which we can iterate through like this:
(dolist (p paths)
(print p))
The complete example that can run in the Nyquist Prompt:
These example applications may be run in the Nyquist Prompt, or could be converted to plug-ins by adding full plug-in headers.
These code examples are excessively commented so as to explain what they are doing. For production code, comments should be concise and provide clarification where the intent is not obvious. As far as possible, the code should be self explanatory, but as this is intended for learning purposes, additional explanatory comments are included.
In this example, we use a File-Button widget to specify a file that will be written to. It is important to note that selecting the file does NOT write to the file, it only captures the file path and file name, which we then write to later in the script. The plug-in will get some information about the selected audio, and write (append) it to a file.
First we start with a couple of headers to set the syntax version and plug-in type.
;version 4
;type analyze
Next is our File-Button widget. Note that it has the "save" flag because we are selecting a file to write to.
;control filename "Export to" file "" "data.txt" "Text file|*.txt;*.TXT|All files|*.*;*" "save"
The next three code lines gather the raw information that we will be writing to the file.
When we write to a file with Nyquist, the file is overwritten by the data that we are writing. As we want to append the new data to the file rather than overwriting it, we must first read the existing text from the file and store it in a variable. We can then write the old data, plus the new data back to the file. Here is a function that will read the contents of the file if it exists, and returns the data to the function caller.
As this code is designed to work with text files, we can check that the file name ends with ".txt".
The file name extension is NOT a reliable way to test the file type. In any situation where security is a concern, the file extension must not be relied as an indicator of the file type.
First we assign an empty string as the value of the variable ext
.
If the file name is at least 4 characters long, we extract the last 4 characters and assign it as the value of ext
.
We can then apply a case insensitive string comparison. If ext
is equal to .txt, then we assume it is a plain text file.
So now we can run our main program, which is within a program prog block.
The program block begins by binding a local variable {{inlineCode|data}}
{=mediawiki} to the data returned by the {{inlineCode|read-file}}
{=mediawiki} function (defined above).
Then we open the file for writing.
And then the data can be written to the open file.
After reading or writing to a file, the file should be closed again.
Finally we return an acknowledgment message.
If the file did not end with .txt, we return an error message.
The Complete Code:
This is an advanced example that uses the File-Button widget to read data from one or more text files. Text handling is not one of Nyquist's strengths (Nyquist is primarily designed for handling audio), hence parsing the text file data is quite complex.
In this example, we will import (read) labels from one or more text files.
For simplicity, we will deal only with the basic label format and not support "spectral" labels.
The data format we will use is compatible with exported labels, provided that Spectral Selections are NOT used.
For this plug-in, we will specify that the label data file has one label definition per line, and each label definition has a start time (in seconds), and end time (in seconds) and optional label text. The numbers and optional label text may be separated by spaces or tabs. The data should be saved as plain text, with a ".txt" file extension.
Example Data:
The Complete Code:
This page explains how to use the Audacity Nyquist Prompt to test-run Nyquist code snippets.
The Audacity Nyquist prompt appears in Audacity's "Tools" menu.
For testing generate-type commands in Nyquist, you can use the Generate Prompt plugin instead.
Sound files are imported into Audacity via: File > Import > Audio or the shortcut CTRL + SHIFT + I
.
If you have no pre-existing sound files to work with, you can create your own mono or stereo tracks via the Audacity "Generate" menu.
Select the track(s) and click Tools > Nyquist Prompt.
The Nyquist Prompt appears like this:
Simply enter the code below and press Apply to receive a "hello world" prompt:
The programming language used above is Lisp. The Nyquist prompt automatically assumes you're using Lisp if the first character is an (
. If it isn't, the prompt assumes you are writing SAL, which is more similar to C-like syntax. If you prefer SAL, a "hello world" program looks like this:
The prompt also comes with a debug button. It shows you various warnings and non-fatal errors after the program finished. For example, if you forget the quotation marks around "
hello world
"
, just hitting apply will just do nothing, whereas hitting debug will tell you where you went wrong:
The current Nyquist manual is here: Nyquist Reference Manual.
A useful index of Nyquist commands is here: Nyquist Language reference
Audacity uses the *TRACK* variable to reference the current audio file/selection. Thus, you can use basic commands such as mult or sum with *track* and the Nyquist prompt will replace the file/selection with the result (or as Audacity calls it, "returned audio").
Note: Prior to version 4 syntax, the vaiable S
was used instead of *TRACK*
. You may encounter this in some old plug-ins or old documentation. The old syntax is obsolete and should not be used in new code
Note: These examples are focused upon using Audacity to manipulate digital signals (clearly Audacity is better suited to audio, but features such as Nyquist can open many other uses). For those interested, the signal used is an infra red (IR) sample from a remote control.
Type the following into the Nyquist Prompt (using LISP syntax): (sum *track* 1)
``Or type the following equivalent SAL command: return *track* + 1
The whole signal has now moved up to above zero.
To multiply a signal with a generated carrier signal, you can use the following commands:
The (hzosc 19000) produces 19kHz sine wave carrier.
The (osc-pulse 19000 0)
produces 19kHz square wave carrier (note the 0 is the bias or 50/50 duty cycle, -1 to 1 = 0%-100% pulse-width ). Applying the 19kHz square wave carrier obtains this result.
The top and bottoms of the signal can then be clipped using the Hard Limiter option from the effects menu (0dB limit and Wet level 1) if required.
The above examples show how you can use the many Nyquist commands to perform basic signal processing without using scripts.
Note: Unfortunately, this isn't the end of the road for this sample; it is near, but the curved "head/tail" of the signal causes a problem for the digital signal being produced [and it was also upside-down, too...]. This will hopefully form the basis of some more complex examples, since I shall need to use Nyquist to:
Find the zero crossing points
Then only apply the carrier frequency to those regions above zero. Or find another suitable command...
This page offers a detailed look at the structure and syntax of Nyquist Plug-ins. It is intended for people who wish to write their own plug-ins.
If you are looking for extra Nyquist plug-ins to use, see Nyquist Plug-ins.
If you are especially interested in Nyquist in Audacity, we highly recommend subscribing to our Audacity forum, which has a section specifically for matters relating to Nyquist.
Nyquist is a superset of the XLISP programming language, (a dialect of LISP and supports both a LISP syntax and an alternative syntax called SAL. A general introduction to Nyquist is given on the main Nyquist page.
The Audacity Nyquist Interface is implemented in the following files in the Audacity source code:
audacity/src/effects/nyquist/Nyquist.cpp
audacity/lib-src/libnyquist/nyx.c
Nyquist is in many ways a separate program from Audacity (and is also available as a standalone programming language). Nyquist is embedded in Audacity as a software library that may be called from the main Audacity application to provide additional functionality, most notably as "plug-ins".
When a Nyquist plug-in is selected from one of Audacity's menus, Audacity locates the plug-in script (the ".NY" file), starts a Nyquist session and passes the Nyquist code to be interpreted by the Nyquist library. Nyquist then attempts to run the program. The result of running the Nyquist script is returned to Audacity.
As in most other computer languages, Nyquist supports code comments. Any line beginning with a semi-colon (;) is entirely ignored by Nyquist. Comments may also be placed at the end of a line of code by beginning the comment with a semi-colon. Nyquist ignores everything from the semi-colon to the end of the line.
In Audacity, special comments are used in Nyquist plug-ins to pass information to Audacity. As with other code comments, these are ignored entirely by Nyquist, but provide instructions to tell Audacity how to create the plug-in.
In this example (derived from the High-Pass Filter effect), the first four lines make up the essential headers that are required in all Nyquist plug-ins.
;nyquist plug-in
This header tells Audacity that this file is a Nyquist plug-in.
;version 4
This header specifies that this is a "4th generation" plug-in.
;type process
This header defines the plug-in as a "process" (Effect) type.
;name "High-Pass Filter"
This header tells Audacity the name of the plug-in.
The other headers enable various options and properties, including the plug-in's controls.
Full descriptions of all plug-in headers are provide on the Nyquist Plug-in Headers page.
Nyquist plug-ins support a range of "widgets", which are control elements for a graphical user interface (GUI). These elements are unique to Nyquist in Audacity.
The GUI is created by Audacity when a plug-in contains one or more widget header commands.
As with other plug-in headers, they begin with a semicolon (;) and are ignored by Nyquist, except that the variable name of the widget is initialized with a value and made available to Nyquist. This means that Nyquist can access the value that has been set in the widget as the value of the variable specified in the widget header.
Note: The "Text widget" is an exception to the above at it is for display purposes only and does not set a value.
Each widget begins with ";control", and is followed by a number of parameters, one of which defines the type of widget. There are currently nine widget types, though not all of them are available for old versions of Audacity.
When a plug-in is launched, Audacity searches the plug-in .NY file for valid headers. Every ";control" line that is found gets parsed by Audacity into several tokens, where each token is separated by spaces. If the tokens match one of the defined patterns, then Audacity adds the widget to the GUI, otherwise they are ignored.
Note: "real" (deprecated) is an alternative name for "float" and is provided as legacy support for old plug-ins. It should not be used in new code.
Italic words in the table denote data types. Because tokens are separated by whitepace, strings containing whitespace must be written within quotation marks.
Note: Older versions of Audacity may not support all of these controls, which may lead to an "unbound symbol" error. Plug-in users are encouraged to use the current version of Audacity, to ensure that they can benefit from all of the latest features.
The following code may be run in the Nyquist Prompt of Audacity 2.3.1 or later, and produces the GUI shown above:
The detailed syntax for each widget type is described on the Nyquist Plug-ins Widgets page.
Audacity passes information about the current Audacity session to the Nyquist interpreter, along with the Nyquist code. Typically, when the code runs, it acts on data that has been passed from Audacity, which often includes the selected audio data, and returns data back to Audacity. Here we shall look at the ways that audio data is passed from Audacity to Nyquist, and from Nyquist back to Audacity.
For process and analyze type plug-ins, Nyquist runs the plug-in code on each selected track in turn. The audio data is passed from Audacity to Nyquist as a variable called *TRACK* (the asterisks are part of the name).
For mono tracks, the value of *TRACK* is a "sound" (which is a Nyquist data type).
For stereo tracks, the value of *TRACK* is an "array". An array is a special kind of ordered list. The array has two elements, both of which are "sounds". The first element holds audio data from the left channel, and the second element hold data from the right channel.
The selected audio is only available to "process" and "analyze" type plug-ins (including the compound types "tool process" and "tool analyze").
The way that time and durations are handled depends on the type of plug-in.
For process and analyze type plug-ins, the start time of the selection is seen as "time = 0", and the length of the selection is seen as one unit of time. The absolute length of the sound in seconds can be computed one of the following ways:
NOTE: get-duration 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, In process effects, Audacity sets up the environment (including warp) 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.
In 'generate' effects, this does not happen, so the length specified by the effect is the length that is produced. For example, if you write (OSC C4 3.5), a generate type effect will produce a tone of duration 3.5 seconds.
For generate type plug-ins, the length of the selection (if there is a selection) is usually ignored by Nyquist. However, if for some reason the length of the selection needs to be known, then *SELECTION* START and END properties may be used (version 4 plug-ins or later).
When generating sounds with a 'generate' type plug-in, durations in Nyquist represent seconds. For example, to generate a 2.5 second sine tone, you could write:
but if the same code is used in a 'process' type plug-in, the generated tone will be 2.5 x the duration of the track selection:
If a duration in seconds is required in a 'process' type plug-in, this may be done using the ABS-ENV command:
The above examples may be run in the Nyquist Prompt.
In addition to the standard global variables defined in the Nyquist Reference Manual, Nyquist in Audacity also has global variables that relate specifically to Audacity. Listed here are a few common standard Nyquist globals, and global variables that are relevant to Nyquist in Audacity.
*CONTROL-SRATE* : [float] The sample frequency of the control signals (such as those created by piecewise approximations. By default 1/20 of the sample rate of the track.
*DECIMAL-SEPARATOR* : [char] A comma character (#\') or dot character (#\.) depending on the language selected in Audacity's Preferences.
*FILE-SEPARATOR* : [char] The character that separates directories in a path, e.g. "/" (#\/) for Unix, ":" (#\:) for Mac, and "\" (#\\) for Win32.
LEN : [int] The number of samples contained in the selected Audacity sound.
*LOCALE* : [list] This is variable name is reserved for translation strings.
*PREVIEWP* : [bool] True when previewing an effect, otherwise false.
*RUNTIME-PATH* : [string] Path to Nyquist .lsp files.
*PROJECT* : A variable with a list of properties relating to the current Audacity project.
S (obsolete) : [sound or array of two sounds] Prior to version 4 plug-ins, in process and analyze type plug-ins this was the Audacity sound [the selected part of the Audacity audio track]. In generate type plug-ins "S" is the Adagio notation for a quarter note (float value 0.25).
S : Adagio notation. [float] A quarter note (float value 0.25).
*SCRATCH* : [any] a symbol whose value and property list are preserved from one effect invocation to the next.
*SELECTION* : A variable with a list of properties relating to the current selection.
*SOUND-SRATE* : [float] The sample frequency of the selected track audio.
*SYSTEM-DIR* : A variable with a list of properties relating to the file system.
*SYSTEM-TIME* : A variable with a list of properties relating to the system time/date.
*TRACK* : [sound or array of sounds] The Audacity sound [the selected part of the Audacity audio track]. The *TRACK* variable also has a list of "properties" that pass additional information to Nyquist.
*WARP* : information that communicates start-time and duration to Nyquist functions. In Audacity, the start-time is always considered to be zero (regardless of the actual start time of the selection) and the duration indicates the duration of the selection. *warp* should not normally be accessed directly.
Other global variables provided by Nyquist can be found in the Nyquist manual index.
Property lists are defined for the global variables *AUDACITY*, *PROJECT*, *SELECTION*, *SYSTEM-DIR*, *SYSTEM-TIME*, and *TRACK*.
For examples using property lists, see the Nyquist Property List Tutorial.
This property list was added in Audacity version 2.1.0
Value: Unbound (not defined).
LANGUAGE : [string] The country code for the language set in Audacity Preferences.
Example - when Audacity's locale setting is for English, (print (get '*audacity* 'language))
will print en
.
VERSION : [integer list] A list in the form (Audacity_version Audacity_release Audacity_revision)
Example: Print the full Audacity version for Audacity 2.1.3
(let ((version-list (get '*audacity*' version)))
(format nil "Audacity version ~a.~a.~a" (first version-list)(second version-list)(third version-list)))
Prints: Audacity version 2.1.3
Value: Unbound (not defined).
LABELTRACKS : [integer] The number of label tracks in the project.
MIDITRACKS : [integer] The number of note tracks in the project.
NAME : [string] The name of the current project. A project that has not been named (not yet saved) returns an empty string.
PREVIEW-DURATION : [float] The Effects Preview Length set in Audacity preferences.
PROJECTS : [integer] The number of open projects.
RATE : [integer] The project rate in the project.
TIMETRACKS : [integer] The number of time tracks in the project.
TRACKS : [integer] The number of tracks in the project.
WAVETRACKS : [integer] The number of audio tracks in the project.
Value: Unbound (not defined).
BANDWIDTH : [float] The bandwidth of the frequency selection in octaves (Spectrogram or Spectrogram (log f) track view).
CENTER-HZ : [float] The centre frequency selection in Hz (Spectrogram or Spectrogram (log f) track view).
CHANNELS : [integer] The number of selected audio channels.
END : [float] The end of the selection in seconds.
HIGH-HZ : [float] The high frequency selection Hz (Spectrogram or Spectrogram (log f) track view).
LOW-HZ : [float] The low frequency selection Hz (Spectrogram or Spectrogram (log f) track view).
RMS : [float or array] For mono tracks, the RMS amplitude (linear scale). For stereo tracks, an array containing the RMS for each channel.
PEAK : [float or array] For mono tracks, the absolute peak level (linear scale). For stereo tracks, an array containing the absolute peak level for each channel. Returns 'NIL' if peak level is infinite or NaN.
PEAK-LEVEL : [float] The absolute peak level (linear scale). Returns 'NIL' if peak level is infinite or NaN.
START : [float] The start of the selection in seconds.
TRACKS : [integer list] A list of track numbers of selected audio tracks.
Value: Unbound (not defined).
BASE : [string] The Audacity installation directory.
DATA : [string] The Audacity data directory. This is where the audacity.cfg, plug-inregistry.cfg and EQCurves.xml files are located.
DOCUMENTS [string] The system default documents directory.
HELP : [string] The installation directory for the Audacity Manual (note that the Manual may not exist).
HOME : [string] The current user's "home" directory.
PLUG-IN : [string list] The Nyquist plug-in search path. This includes the directories where Audacity looks for Nyquist plug-ins, and other Nyquist related files. Not all directories are currently used and some are for legacy support only.
SYS-TEMP : [string] The system temp directory.
TEMP : [string] The Audacity temp directory. This is where unsaved project data is temporarily stored.
USER-PLUG-IN : [string] The default path for user plug-ins.
This property list was added in Audacity version 2.1.1.
Value: A list in the form '(year, day, hours, minutes, seconds), where each list item is an integer.
Example: 5 minutes past 2pm January 1st 2022 would be the list: 2022, 1, 14, 5, 0
.
Note that "day" is a number in the range 1 to 366, counted from the start of the year.
This is the time that the Nyquist code is parsed, NOT the time it is executed. It cannot therefore be used for timing events that occur while the code is running. Possible uses for *SYSTEM-TIME* could include automatic naming of files written to disk, or for "seeding" random processes.
DATE : [string] The date formatted according to the current locale. Example: "dd/mm/yy".
DAY : [integer] Day of the month.
DAY-NAME : [string] The name of the day (Example: "Monday").
ISO-DATE : [string] The date represented in the ISO 8601 format "YYYY-MM-DD".
ISO-TIME : [string] The time represented in the ISO 8601 format "HH:MM:SS".
MONTH : [integer] The month (as an integer).
MONTH-NAME : [string] The name of the month (Example: "January").
TIME : [string] The time formatted according to the current locale. Example: "hh:mm:ss".
YEAR : [integer] The year (as an integer).
Value: The sound from a selected mono audio track, or an array of two sounds from a selected stereo track (see the Nyquist Stereo Track Tutorial).
Properties of *TRACK* all relate to the track that is being processed. Currently Nyquist only processes audio tracks. When multiple tracks are selected, Nyquist processes each audio track in turn (top to bottom).
CHANNELS : [integer] The number of channels in the track (mono = 1, stereo = 2).
CLIPS : [list or array] For mono tracks, a list of start and end time of each audio clip. For stereo tracks, an array containing a list of clips for each channel. Due to a limitation in Nyquist, the "clips" property can hold a maximum of 1000 start / end times. If an audio channel contains more than 1000 clips, the first 1000 will be listed, and the 1001th item will be NIL. See AUD-GET-INFO for an alternative way to get clip times that will work with 1000's of clips.
END-TIME : [float] The track end time.
FORMAT : [integer or float] The track sample format. One of (Integer) 16, (Integer) 24, or (float) 32.
GAIN : [float] The value of the track Gain slider.
INDEX : [integer] A counter that increments for each track processed. On processing the first track, the value is "1".
NAME : [string] The name of the track.
PAN : [float] The value of the track Pan slider.
RATE : [float] The track sample rate.
SPECTRAL-EDIT-ENABLED : [bool] Returns 'T' (true) if spectral editing is enabled, otherwise 'NIL'. Note that this is irrespective of the track view and will return 'T' if the spectral editing option for the track is enabled even if the track is not displaying a spectrogram.
START-TIME : [float] The track start time (note that this will often be different from the selection start time.)
TYPE : [string] The type of track. One of: "wave", "midi", "label", "time". Currently only "wave" (audio tracks) are processed by Nyquist plug-ins.
VIEW : [string or list] The track view. Only applies to audio tracks. * A single track view returns one of "Waveform", "Spectrogram" or NIL. Multi-View returns a list of strings or NIL. * Multi-view returns the upper view as the first element, and the lower view as the second (either "Waveform" or "Spectrogram"). Both normal "Waveform" and "Waveform (dB)" return the string "Waveform". * Prior to Audacity 2.4.x : [string] One of: "Waveform", "Waveform (dB)", "Spectrogram" or NIL.
The VIEW property may change in future versions of Audacity, so is not recommended for public release plug-ins. During Preview, audio tracks are copied to temporary tracks which are not visible, so the returned "VIEW" value is NIL.
Nyquist supports many "data types", including "numbers" (integer or floating-point), "characters" (such as the letter "A", the number "4", or any other ASCII character), "strings" (text), "list" (a list of data), "array" (special kind of indexed list), and "sounds" (a sound / digital signal).
The result of the last computation within the plug-in code will be given back from Nyquist to Audacity. According to the data type of the returned value one of the following actions will be invoked in Audacity:
If a "sound" is returned, the sound will be re-inserted into the selected part of the Audacity track, (or a new track for "generate" type plug-ins). 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, the same mono sound will be inserted into both channels of the stereo track.
Nyquist handles multi-channel sounds as an array of sounds. The first element of the array is the left channel, and the second element is the right channel. Audacity currently supports a maximum of two channels in a track (stereo).
Returning an array of sounds to a mono track is an error.To return a stereo sound without error, a stereo track must be selected before running the Nyquist code.
For more information about stereo tracks, see the Nyquist Stereo Track Tutorial.
When the return value is a character or string, a dialog window will appear with the data displayed as text.
A dialog window will appear with the number displayed as text.
If an appropriately formatted list is returned to Audacity, a label track will be created below the audio track(s).
For point labels the format is:
((
number
`` ``"
string
") (
number
`` ``"
string
") ... )
The list to create a label track must contain one or more lists, each of which must have:
number - (an integer or float) is 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.
For region labels, each label list must contain two int-or-float elements, one for the start and one for the end of the label region.
((
number
````
number
`` ``"
string
") (
number
````
number
`` ``"
string
") ... )
Audacity will always place returned audio or labels relative to the start of the selection and not the start of the Timeline.
An empty string may be used as a "null return", which means that the plug-in returns nothing, and no error. An example use would be if you wish to process only the first selected track.
When using the Nyquist Prompt or (most) Nyquist plug-ins that have a GUI, if the plug-in returns a sound, it may be previewed using the Preview
button. In addition to this, it is also possible to play sounds directly from Nyquist, using the PLAY function. The PLAY function will be executed when the plug-in code runs.
The PLAY function is described in the Nyquist manual. The information here describes aspects that are specific to Nyquist in Audacity.
Note that the Nyquist PLAY command does not use Audacity's audio device settings. Nyquist uses the system default device for playback, and has a default buffer of 100 ms. The buffer setting may be changed with the SND-SET-LATENCY command. The actual latency values are dependent on the computer sound system and may differ from those requested by Nyquist.
To see the list of available devices when Nyquist plays, set *snd-list-device* to "true" before the play command, then use Debug
button to see the output.
(setf *snd-list-devices* t)
(play *track*)
To select a specific output device, set *snd-device* to the index number of the device you wish to use (not all devices are valid). For example, if ALSA hw(0,0) is device 0, select it with:
(setf *snd-device* 0)
(setf *snd-list-devices* t)
(play *track*)
It is not possible to interrupt Nyquist playback. The sound will continue playing until it reaches the end, and other Audacity functions are disabled until Nyquist playback has finished.
To limit the amount of audio that will play, the length of the sound must be defined before starting playback. For example, to play the first 1 second of a selection, you could write (LISP syntax):
Note also that if a plug-in uses Nyquist PLAY command, using Preview
will cause an error on some machines because Audacity may not be able to access the audio device while it is being used by Nyquist. For "own use" plug-ins, if you have more than one sound card, a possible workaround to enable Preview and Nyquist PLAY simultaneously, is to set the Nyquist playback device to a different device to that which Audacity uses. For public release plug-ins the Preview
button should normally be disabled if Nyquist PLAY is used.
Nyquist plug-ins provide two mechanisms for translation into the language specified in Audacity's preferences.
One method is exclusively for plug-ins that are shipped by default with Audacity and requires compiling Audacity from source, plus several other steps involving gettext. Unfortunately this method is not documented, so only a brief description is provided here.
The other method may be used by plug-in developers for their "third party" plug-ins, but can be used only for returned strings and not for the main plug-in interface.
Header comments in translated plug-ins begin with a dollar "$" character rather than the usual semicolon ";" character. The strings to be translated are then wrapped in a function that has a one character name "_" (underscore).
Example: In the Adjustable Fade effect, the Name header is changed from:
;name "Adjustable Fade"
to:
$name (_ "Adjustable Fade")
;control lines become $control. As with other translated headers, the $ symbol replaces the normal semicolon. The line is ignored by Nyquist as a comment, but is visible to Audacity for translation and for creating a widget.
The options in Multiple-choice widgets may be translated. For example:
;control var (_ "Translated left text") choice ((_ "Yes") (_ "No")) 0
The above example is not safe to use. See the "Limitations" section below.
Macros and portability: To allow portability of settings and macros, choices may include a non-translated form of each choice. The non-translated form is used by Macros but is not normally visible to users.
;control var (_ "Translated left text") choice (("Label1" (_ "Translated Label 1")) ("Label2" (_ "Translated Label 2"))) 0
Other user visible strings: Other strings that are visible to users are marked for translation using the "underscore" function. An example from the Adjustable Fade plug-in:
(format nil (_ "~aPercentage values cannot be negative.") err)
Control characters like (new line), (tab) are not supported. The workaround is to use Lisp format directives instead:
Bad (does not work correctly):
(print (_ "Line one.\nLine two."))
Good:
(print (format nil (_ "Line one.~%Line two.")))
Note that translations may contain Unicode characters that are not supported by Nyquist. It is therefore important that any translated strings that need to be machine readable (such as Multiple-Choice widget options) should also have a non-translated form.
;control var (_ "Translated left text") choice (("Label1" (_ "Translated Label 1")) ("Label2" (_ "Translated Label 2"))) 0
It is not currently possible to provide translations for a third party plug-in's main interface, unless the name is the same as a translated Nyquist plug-in that is already shipped with Audacity. It is highly recommended to NOT reuse the same name as a shipped plug-in for a third party plug-in.
Translations may be provided for return value messages and debug messages. To do this, the string must be marked for translation by wrapping it in the "underscore" function. The translation must also be provided in a specially formatted list variable *locale*.
The format for the *locale* list is: (LIST (language-list) [(language-list) ...])
where "language-list" is a list in the form: (LIST country-code (translations))
and the "translations" are list in the form: (LIST (List "string" "translation") [(List "string" "translation")...])
The *locale* list may contain any number of "language-list" elements, where each language-list is a list of two strings.
The first element of each "language-list" is the country code (for example "en" or "fr"),
The second item of each "language-list" is a list of translation pairs.
A "translation pair" is a list containing the default string (usually in English) and the translated string (in the language specified by the country code).
A working example may be found in the RMS effect.
Nyquist in the Audacity manual
This tutorial provides a brief introduction to using stereo tracks in Nyquist programming.
If a sound from an Audacity stereo track was given to Nyquist, the *TRACK* variable contains an array of sounds. Because all Nyquist "snd-..." low-level functions only can process mono signals, to use such a function, the *TRACK* array first must be split into single mono signals and afterwards be re-combined into an array before it is given back to Audacity.
In Sal, one could write:
Or in LISP, one could write:
(arrayp *track*) - tests if '*track*' is an array
(vector ... ) - re-combines the two mono signals into a stereo signal. A "vector" is an one-dimensional array
(aref *track* 0) - the left stereo channel [the 0-th slot of the array]
(aref *track* 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 sequentially, 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.
In the "nyquist.lsp" file in the Audacity "nyquist" sub-directory, there is a function "multichan-expand" defined, which 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:
This may look a bit more cryptic at first, but it can help to avoid long-winded audio processing functions.
This page provides a brief introduction to using the *SCRATCH* symbol in Nyquist programming.
*SCRATCH* is a global symbol, specific to Nyquist in Audacity, which is not deleted in-between plug-in runs. It provides a way for information to survive from one invocation of a plug-in to the next. However, you should not rely on the "value" of *SCRATCH* beyond a single invocation of a plug-in as it could be overwritten by another plug-in. It is better to use property lists of *SCRATCH*. That way, you get a whole name space rather than a single variable name, and with careful naming of the property keys, name collisions can be avoided.
To pass data from plug-in "effectX-partA" to "effectX-partB":
1. Assign a property name based on the effect name, e.g.: 'EFFECTX [or in SAL, which does not support the single-quote notation of LISP, write QUOTE(EFFECTX). ]
2. "effectX-partA" should delete any old property value:
3. "effectX-partA" should compute a new property value v and save it:
4. "effectX-partB" should access the property using:
5. When "effectX-partB" finishes, it should remove the property:
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 plug-ins operating on different inputs to collect data to feed into a plug-in 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.
In cases where *SCRATCH* data is not deleted immediately after use, and where there is the potential to leave large amounts of memory there, there should be another effect, e.g. "effectX-partCleanup", that simply calls:
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.
;control | var-name | text-left | widget-type | text-right | initial-value | minimum | maximum |
---|---|---|---|---|---|---|---|
;control
symbol
string
int
string
integer
integer
integer
;control
symbol
string
float (real)
string
float
float
float
;control
symbol
string
int-text
string
integer
integer / NIL
integer / NIL
;control
symbol
string
float-text
string
float
float / NIL
float / NIL
;control
symbol
string
string
string
string
-
-
;control
symbol
string
choice
string
integer
-
-
;control
symbol
string
time
string
float
float / NIL
float / NIL
;control
symbol
string
file
string
string
string
string
;control
-
-
text
string
-
-
-