Introduction to Nyquist and Lisp Programming - Audacity Manual

# Introduction to Nyquist and Lisp Programming

From Audacity Development Manual
Nyquist was written by Roger B. Dannenberg and was intended to be used as a complete programming language for audio synthesis and analysis, with support for MIDI, audio recording and playback, file I/O, object-oriented programming, profiling, debugging and more. Audacity uses a subset of Nyquist's functionality, allowing you to use Nyquist functions in Audacity. Audacity also provides additional features and commands for Nyquist, including the ability to create plugins.
There is also a standalone version of Nyquist available from the Carnegie Mellon University Computer Music Project.

## Nyquist

Nyquist allows you to use the Nyquist programming language to write your own plugin effects for Audacity. Unlike VST and LADSPA plugins, Nyquist plugins are written in plain text and don't need to be compiled.

Nyquist supports both a Lisp syntax and a more C-like syntax called SAL. Audacity versions prior to 1.3.8 only support Lisp, but the current Audacity 2.0 series supports both Lisp and SAL. To write plugins for use with Audacity, choose the appropriate Nyquist Manual for your version of Audacity and preferred syntax:

- Nyquist version 2.37 Manual \xe2\x80\x93 entirely using Lisp syntax
- Nyquist 3.1x Reference Manual \xe2\x80\x93 the latest Nyquist Manual (mostly using SAL syntax).

Note that you don't need to download Nyquist in order to write simple plugins to use with Audacity. All the basic instructions you need to work with Lisp and the 2.37 Manual are below. For the latest Nyquist features in Audacity.

### Lisp

Nyquist is based on Lisp. If you have programmed in Lisp before, you can skim this section or go directly to the next page: Programming in Nyquist . Otherwise, here's an extremely brief introduction to Lisp:

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 \xe2\x80\x93 they're all functions like everything else, using prefix notation, where the name of the function (or operator) comes 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 \xe2\x80\x93 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 \xe2\x80\x93 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, butfirst 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)).

### Some common Lisp functions

For a more comprehensive list of functions, refer to the language reference in the Nyquist manual.

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

#### Math functions

Lisp | SAL | Description
(+ a b) | a + b | addition
(- a b) | a - b | subtraction
(* a b) | a * b | multiplication
(/ a b) | a / b | division
(truncate expr) | truncate (expr) | round down expr to integer (floor)
(float expr) | float (expr) | integer expr to floating-point
(rem a b ...) | rem (a b...) | remainder of a list of numbers
(min a b ...) | min (a b ...) | minimum
(max a b ...) | max (a b ...) | maximum
(abs expr) | abs (expr) | absolute value of a number
(random n) | random (n) | random integer between 1 and n-1
(rrandom) | rrandom () | Floating-point random between 0 and 1
(sin expr) | sin (expr) | sine
(cos expr) | cos (expr) | cosine
(tan expr) | tan (expr) | tangent
(expt expr) | expt (expr) | exponent (a to the power of b)
(sqrt expr) | sqrt (expr) | square root
(< a b) | a < b | test for a less than b
(<= a b) | a <= b | test for a less than or equal to b
(> a b) | a > b | test for a greater than b
(>= a b) | a >= b | test for a greater than or equal to b
(= a b) | a = b | test for equality
(/= a b) | a /= b | test for inequality

#### Math Examples

n-th power of x:

     power(x, n) ;; in SAL
     (power x n) ;; in LISP

n-th root of a number:

     power(x, 1.0 / n) ;; in SAL
     (power x (/ 1.0 n)) ;; in LISP

n-th root of a sound s:

     return s-exp(s-log(s) * (1.0 / n)) ;; in SAL
     (s-exp (mult (s-log s) (/ 1.0 n))) ;; in LISP

n-th root with two sounds x and n:

     return s-exp(s-log(x) * s-recip(n))  ;; in SAL
     (s-exp (mult (s-log x) (s-recip n))) ;; in LISP

#### List functions

Lisp | SAL | Description
--- | --- | ---
(first expr) | first (expr) | first element of a list (car)
(rest expr) | rest (expr) | rest of the list (cdr)
(reverse expr) | reverse (expr) | reverse a list
(list expr ...) | list (expr...) | construct a list of expressions
(append expr ...) | append (expr...) | append two or more lists
(length expr) | length (expr) | length of a list
(maplist fcn list1 list...) | maplist (fcn list1 list...) | apply a function to every element in a list

#### Conditional Expressions

Lisp | SAL | Description
--- | --- | ---
(if test-expr true-stmt [false-stmt]) | if test-expr then true-stmt [else false-stmt] | If test-expr is true, evaluates true-stmt, otherwise evaluates false-stmt
(when test-expr statement) | when test-expr statement | When test-expr is true, evaluate statement
(unless test-expr statement) | unless test-expr statement | When test-expr is false, evaluate statement
(cond [(pred1 expr1) [(pred2 expr2) ... ]]) |  | When pred1is true, evaluate expr1, else if pred2 is true...
(case test-expr [(value statement) ... ]) |  | Evaluate statement for the first value that matches test-expr

## Links

> Programming in Nyquist

|< Nyquist