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

Audacity and Nyquist

See also:

Audacity und Nyquist 2007   -  [german]
Audacity and Nyquist 2009   -  [english]
Audacity Nyquist Audio Interface   -  [english]

Nyquist, a Superset of XLisp

In Lisp (and therefore Nyquist), everything is an S-Expression, which is just a list of tokens (words) separated by whitespace and enclosed in parentheses. The name of the function is always the first token in an S-Expression, and all of the other tokens are arguments to this function. Here's a simple example:

   (setf area (* 3.14159 (expt radius 2)))

Let's break down this example. The outermost S-expression has three members. The first one, setf, is the name of the function (it stands for set-field). setf is used to assign a value to a variable. (There are other similar functions, like set and setq, but setf is the most powerful, so it's the one we'll use in our examples.) After setf comes area, which is the name of the variable we're going to set. Next comes the value to assign to this variable, which in this case is another S-expression.

Lisp doesn't have any special operators for Math functions - they're all functions like everything else, using prefix notation, where the name of the function (or operator) come before its arguments. So instead of 3*7 for the product of 3 and 7, in Lisp you would write (* 3 7). In Nyquist, the expt (exponent) function raises its first argument to the power of the second argument. Therefore (* 3.14159 (expt radius 2)) means 3.14159 times the square of radius, or the formula for the area of a circle.

Rather than typing in this full expression every time, let's define a function for the area of the circle, that we can call every time we need it:

   (defun circlearea (radius) (* 3.14159 (expt radius 2)))

The defun function is used to define a new function. The first argument is the name of the function, in this case circlearea. The second argument is a list of arguments to the function to be defined - this is one of the few cases where you have an S-expression that is not interpreted as a function call. Finally the last expression is the value of the function. Now if we want to compute the area of a circle of radius r, we just need to compute:

   (setf area (circlearea r))

An S-expression is just a representation of a list. Lisp uses lists to represent just about everything (the name LISP comes from LISt Processing language), so it's helpful to know how to manipulate lists. Let's start by assigning a list of numbers to a variable. You can't quite do this:

   (setf mylist (1 2 3 4 5))  <--  error!

The reason this doesn't work is that whenever Nyquist sees an S-expression, it tries to evaluate it as a function unless you tell it otherwise. Since there's no function named "1" that takes arguments (2 3 4 5), this will generate an error. To tell lisp that you want to treat an S-expression literally, and not to evaluate it as a function, you quote it. In Nyquist, you can quote a list by putting a single quotation mark before it, like this:

   (setf mylist '(1 2 3 4 5))

Nyquist also provides a list function that you can use to construct lists - this is useful if some of the elements of the list are functions:

   (setf mylist (list 1 2 3 4 (sqrt 25)))

To get things off of a list, you can use the first and rest functions. (Traditionally, these were called car and cdr, respectively, but first and rest are much easier to remember. Both sets of names are supported in Nyquist.) The output of (first mylist) is 1, and the output of (rest mylist) is the list (2 3 4 5). So the second element of the list is (first (rest mylist)).

Lisp function reference

Here's a list of some of the basic lisp functions you might need.

Math functions
 (+ a b)addition
 (- a b)subtraction
 (* a b)multiplication
 (/ a b)division
 (truncate a b)round down to integer (floor)
 (float a b)integer to floating-point
 (rem a b c ...)remainder
 (min a b c ...)minimum
 (max a b c ...)maximum
 (abs a)absolute value
 (random n)random integer between 1 and n-1
 (sin a b)sine
 (cos a b)cosine
 (tan a b)tangent
 (expt a b)exponent (a to the power of b)
 (sqrt a b)square root
 (< a b)test for a less than b
 (<= a b)test for a less than or equal to b
 (> a b)test for a greater than b
 (>= a b)test for a greater than or equal to b
 (= a b)test for equality
 (/= a b)test for inequality
List functions
 (first l)first element of a list (car)
 (rest l)rest of the list (cdr)
 (reverse l)reverse a list
 (list a b ...)construct a list
 (append l1 l2)append two lists
 (length l)length of a list
 (maplist function l)apply a function to every element in a list
Control
 (if expr expr1 expr2)if expr is true, evaluates expr1, otherwise evaluates expr2

For a complete list of Lisp / Nyquist functions, see the Nyquist Reference Manual.

Note: Symbols in Nyquist (like variable names and function names) are not case sensitive. They are converted to uppercase internally.

Programming in Nyquist

What makes Nyquist distinct from Lisp is that it is designed to work with sound, and has lots of built-in primitives and functions that synthesize, analyze, and manipulate sounds. Within Audacity, this makes it relatively easy to build complicated effects out of Nyquist's palette of built-in functions.

In Nyquist, a variable can hold a sound just as easily as it can hold a number or a string. There are a lot of functions provided that allow you to stretch, distort, and combine sounds very efficiently. It is even possible to "rip apart" a sound and access its individual samples, but that's beyond the scope of this tutorial.

To try out a Nyquist expression in Audacity, you can use "Nyquist Prompt" in the Effect menu. Whatever audio you have selected will be in the variable s, and the selection will be replaced with the result of the Nyquist expression you enter. Further down on this page you will learn how to create a plug-in effect using Nyquist.

Synthesizing

The following functions all create new sounds. You can use them to create "generate" plug-in effects, or you can combine these synthesized sounds with selected audio to produce interesting effects.

(noise)Generates white noise
(const value [duration])Generates a constant (silent) signal
(sine pitch [duration])Generates a sine wave at an indicated pitch and duration. The pitch is a MIDI note number, with 60 for middle C.
(hzosc hz)Generates a sine wave at a particular frequency in Hz.
(osc-saw hz)Generates a sawtooth wave at a particular frequency in Hz.
(osc-tri hz)Generates a triangle wave at a particular frequency in Hz.
(osc-pulse hz bias)Generates a square pulse with variable width at the indicated frequency (in Hertz). The bias parameter controls the pulse width and should be between -1 and +1, giving a pulse width from 0% (always at -1) to 100% (always at +1). When bias is zero, a square wave is generated.
(pluck pitch)Generates a sound at the given pitch created using a modified Karplus-Strong plucked string algorithm.

Envelopes

Nyquist has support for envelopes. By applying an envelope to a sound, you can control the overall shape of its amplitude. One of the easiest ways to construct an envelope is with the env function, which takes 7 parameters that are commonly used for shaping synthesized musical notes: attack time, decay time, release time, attack level, decay level, sustain level, and overall duration. See the figure below:

To apply an envelope to a sound, just use the mult function. So if s is a sound, then this is the sound with a simple envelope applied to it:

   (mult s (env 0.1 0.1 0.2 1.0 0.5 0.3 1.0))

One of the most general type of envelope is a piece-wise linear function, which can be constructed with the pwl function. The pwl function takes a list of parameters which denote (time, value) pairs. There is an implicit initial (time, value) pair of (0, 0), and an implicit final value of 0. There should always be an odd number of parameters, since the final time is not implicit. For example:

   ; symmetric rise to 0.7 (at time 1) and fall back to 0 (at time 2):
   (pwl 1.0 0.7 2.0)

Combining sounds

Besides multiplying two sounds with the mult function, you can add two sounds (or envelopes) with the add function.

Filters

Nyquist comes with a number of common filters built-in. Here are some of the more common ones:

(lp sound cutoff)Low-pass filter (first-order Butterworth). Cutoff may be a float or a signal (for time-varying filtering) and expresses hertz.
(hp sound cutoff)High-pass filter (first-order Butterworth). Cutoff may be a float or a signal (for time-varying filtering) and expresses hertz.
(comb sound hz decay)Applies a comb filter to sound, which emphasizes (resonates at) frequencies that are multiples of a hz.
(alpass sound decay hz)All-pass filter, creating a delay effect without the resonances of a comb filter.
(notch2 sound hz)Second-order notch filter centered at a frequency of hz.

Transforming and combining sounds

It is beyond the scope of this introductory tutorial to explain all of the ways that a sound can be transformed in Nyquist. These functions do not modify sounds directly, but instead modify the Nyquist environment. In order for these changes to affect sounds, you must use the cue function.

(stretch factor (cue sound))Changes the length of the sound being cued by the given factor.
(scale factor (cue sound))Scales the amplitude of the sound being cued by the given factor.
(loud dB (cue sound))Increases or decreases the volume of the sound being cued by the given number of decibels.
(at t (cue sound))Starts the given sound at a particular time in seconds. This can't be used to add silence at the beginning or end, but it can be used when combining two or more sounds.
(seq (cue s1) (cue s2))Creates a sequence of sound s1 followed by sound s2.
(sim (cue s1) (cue s2))Combines two sounds so that they are played simultaneously.

For more information, please read the Nyquist Reference Manual.

Creating Nyquist plug-ins

Creating a plug-in for Audacity using Nyquist is as simple as creating a text file with the extension ".ny" with some Nyquist code, adding a few comments to indicate the type of plug-in, and placing the file in Audacity's plug-ins directory. Here's a very simple plug-in as an example:

   ;nyquist plug-in
   ;version 1
   ;type process
   ;name "Fade In"
   ;action "Fading In..."
   (mult (ramp) s)

The first two lines of a Nyquist plug-in must be exactly as in the example above, or Audacity will not load it. (The version number is to support future expansions of the plug-in format.) The next line is the type of plug-in, which is discussed below. Then comes the name of the plug-in, which is what is displayed in the menu bar, and then the "action", which is what Audacity displays while it is busy processing the plug-in. There are other optional lines that may follow. Any line that does not begin with a semicolon (;) is assumed to contain Nyquist code and will be executed.

Audacity has support for three types of plug-ins that can be written in Nyquist:

   ;type generate
   ;type process
   ;type analyze

These correspond to the three menus that can contain plug-ins: Generate, Effect, and Analyze. Generate plug-ins are expected to generate new audio from scratch, Effect plug-ins ("process") modify existing audio in-place, and Analyze plug-ins process audio but do not modify it (though they are allowed to add labels).

For Effect and Analyze plug-ins, Audacity sets up the Nyquist environment so that the audio the user has selected is in the variable s. All of the expressions in the plug-in file are executed in order, and the return value of the last expression is substituted for the selection in Audacity. If the last expression does not return audio, Audacity returns an error.

Parameter dialogs

Audacity has limited support for plug-ins showing a dialog to get parameters from the user. Here is an example of a plug-in that opens a dialog:

   ;nyquist plug-in
   ;version 1
   ;type process
   ;name "Delay..."
   ;action "Performing Delay Effect..."
   ;info "Demo effect for Nyquist by Roger Dannenberg.\nThis effect 
      creates a fixed number of echos."  ; (should be all on one line)
   ;control decay "Decay amount" int "dB" 6 0 24
   ;control delay "Delay time" real "seconds" 0.5 0.0 5.0
   ;control count "Number of echos" int "times" 5 1 30

   (defun delays (s decay delay count)
     (if (= count 0) (cue s)
 	   (sim (cue s)
         (loud decay (at delay (delays s decay delay (- count 1)))))))
   (stretch-abs 1 (delays s (- 0 decay) delay count))

If Audacity finds at least one "control" line, it will open a dialog to prompt the user for certain parameters to the plug-in. Each parameter consists of a text box and a slider, and after the user has entered each one, the final value will be stored in a Nyquist variable with a name that you specify on the "control" line. Here's what the dialog for the Delay effect shown above looks like in Audacity for Linux:



Note that the "info" line is displayed at the top of the dialog, and that the "\n" becomes a newline. The parameters to the "control" line affect the appearance and limitations of the parameter. Each "control" line must consist of exactly the following 8 elements, in order:

  1. The word "control"
  2. The name of the control - this is the name of the Nyquist variable that will get set when the user manipulates the dialog.
  3. The label to the left of the control
  4. The type of value: either int (integer) or real.
  5. The label to the right of the value (usually the units like "Hz" or "dB").
  6. The default/initial value of the parameter
  7. The minimum value of the parameter
  8. The maximum value of the parameter

Returning labels

Instead of returning audio, a Nyquist plug-in can instead return a list of labels. A list of labels is simply a list of time/label pairs, for example:

   ((0.0 "start") (30.0 "middle") (60.0 "end"))

When a plug-in returns a list of exactly this form, Audacity will create a new label track and add the labels at those positions. This style of plug-in is usually of type "analyze".

Processing stereo tracks

Nyquist represents stereo tracks as an array of sounds (not a list). Many Nyquist functions automatically work with these arrays, but not all, so sometimes you may find it necessary to split up a stereo array, or reassemble one. Here are some useful functions:

(arrayp s)returns true if s is an array
(aref s 0)the first element in array s - the left channel
(aref s 1)the second element in array s - the right channel
(setf s (make-array 2))makes s into a new array of length 2
(setf (aref s 0) left)makes left the first element of array s
(setf (aref s 1) right)makes right the second element of array s

As a convenience, if the input to your Nyquist plug-in is stereo, but you only output a single (mono) sound, Audacity will automatically copy it to both the left and right channels.

Where to go from here

Audacity comes with some sample plug-ins that you can examine or modify as a starting point. The best way to learn Nyquist is to try it. If you're having trouble debugging, consider downloading the standalone version of Nyquist from CMU Computer Music Project - Software .

If you're having trouble getting Nyquist to work at all, please send your email to audacity-help@lists.sourceforge.net

If you are working on Nyquist plug-in effects and would like to share them with others, or if you would like to discuss general details of how to achieve certain effects in Nyquist, please join the audacity-users list.

Meanwhile since October 2004 there also exists an Audacity Nyquist mailing list: audacity-nyquist@lists.sourceforge.net.

Don't forget to consult the full Nyquist Reference Manual and the Nyquist Examples and Tutorials for more details of how Nyquist works.


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