User:Stevethefiddle/Introduction to Nyquist

From Audacity Wiki
Jump to: navigation, search

Nyquist

A language for composition and sound synthesis.
Nyquist is a sound synthesis and composition language offering a Lisp syntax as well as an imperative language syntax and a powerful integrated development environment. Nyquist is an elegant and powerful system based on functional programming.
 
Related article(s):

Nyquist was developed by Roger B. Dannenberg, Professor of Computer Science, Art, and Music at Carnegie Mellon University. It 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, which provide capabilities to generate, analyze or process audio data with simple Nyquist functions, or develop plug-ins that extend Audacity's capabilities. Unlike VST and LADSPA plug-ins, Nyquist plug-ins can be written using an ordinary text editor and don't need to be compiled.

The full, standalone version of Nyquist is available from CMU Computer Music Project Software. Note that you do not need to download Nyquist in order to use with Audacity as the language is built into Audacity.

The Nyquist programming language is based on Lisp but now includes an alternative syntax called SAL. The most recent version of the Nyquist reference manual uses mostly SAL syntax. An older (2.37) version of the manual is also available that uses Lisp syntax throughout. Both manuals and additional documentation are available here.

Lisp

In Lisp (and therefore Nyquist), everything is an S-Expression. Put simply, commands begin with the name of the function, followed by any additional parameters ('arguments'), and the entire command is enclosed in parentheses.

Here is a very simple example:

  (setf answer (+ 5 3))

This simply sets the variable 'answer' to the sum of 5 and 3. Note that it is written (+ 5 3) and not (5 + 3). In Lisp syntax, the function (in this case '+') always comes first, and the arguments ('5' and '3') come after.

A slightly more complex example and more detailed description:

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

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).

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) 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, we could 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)))

SAL

Nyquist SAL is based on Rick Taube's SAL language, which is part of Common Music. SAL offers the power of Lisp but features a simple, Algol-like syntax. When using SAL syntax, Nyquist reads the commands, translates them into Lisp, and evaluates the commands. Users that have experience programming in other computer languages may find SAL syntax more familiar.

SAL syntax is inherently command oriented. A SAL plug-in should consist of a sequence of SAL commands including define commands to define variables and functions. There must be a function definition for main. After performing the commands in sequence, Audacity calls main (with no parameters). The value returned from main is the result of the plug-in (normally this should be a sound).

One exception to this is the Nyquist Prompt... effect. Since defining main just to evaluate and return a simple expression is so awkward, you can simply type

  return expression


Normally, that would not be a legal statement as a top-level command in SAL, but in Nyquist Prompt..., special processing embeds the return statement into a declaration of function main, which is then called. This trick also works for regular plug-ins, but defining main is the preferred style.

In SAL, most operators must be separated from identifiers by white space. For example, play-file is one identifier, but play - file is an expression for "play minus file," where play and file are two separate identifiers. Spaces are not needed around commas and parentheses.


Whereas in Lisp syntax we had:

  (setf answer (+ 5 3)

in SAL syntax we might have:

  define variable answer = 5
  set answer += 3
  return answer

Because 'variable' is a keyword, it is not actually necessary to precede it with 'define', so the above could be written more concisely as:

  variable answer = 3 + 5
  return answer

Further information about SAL syntax can be found in the Nyquist 3.x manual.