Difference between revisions of "Introduction to Nyquist and Lisp Programming"

From Audacity Wiki
Jump to: navigation, search
(I can't see the point linking to audacityteam.org copy of the pages, so changed to internal links)
(This page has been transferred to the [https://manual.audacityteam.org/man/introduction_to_nyquist_and_lisp_programming.htmlAudacity Manual]. - P1 removed)
 
(14 intermediate revisions by 2 users not shown)
Line 1: Line 1:
== Nyquist ==
+
This page has been transferred to the [https://manual.audacityteam.org/man/introduction_to_nyquist_and_lisp_programming.htmlAudacity Manual].
# '''Introduction to Nyquist and Lisp Programming'''
 
# [[Programming in Nyquist]]
 
# [[Creating Nyquist Plug-ins]]
 
 
 
Beginning with version 1.1.1, Audacity allows you to use the Nyquist programming language to write your own plug-in effects for Audacity. Unlike VST and LADSPA plug-ins, Nyquist plug-ins can be written using an ordinary text editor and don’t need to be compiled.
 
 
 
Nyquist was written by [http://www-2.cs.cmu.edu/%7Erbd/ 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 only a subset of Nyquist’s functionality, allowing you to take simple Nyquist functions and use them to process audio data. Audacity doesn’t include any support for debugging Nyquist code, so if you are trying to write a complicated plug-in, you may find it easier to get the full version of Nyquist and develop there, then turn it into an Audacity plug-in. Nyquist is available from the Carnegie Mellon University Computer Music Project:
 
 
 
* [http://www-2.cs.cmu.edu/%7Emusic/music.software.html CMU Computer Music Project Software] – download the full Nyquist here.
 
 
 
Nyquist supports both a Lisp syntax and a more conventional 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 plug-ins for use with Audacity, choose the appropriate Nyquist Manual for your version of Audacity and preferred syntax:
 
 
 
* [http://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/manual/home.html Nyquist version 2.37 Manual] – entirely using Lisp syntax
 
* [http://www.cs.cmu.edu/%7Erbd/doc/nyquist/ Nyquist 3.1x Reference Manual] – the latest Nyquist Manual (mostly using SAL syntax).
 
 
 
Note that you don’t need to download Nyquist in order to write simple plug-ins to use with Audacity. All the basic instructions you need to work with Lisp and the 2.37 Manual are below. If you want to explore SAL as well, and for the latest Nyquist features in Audacity, see [http://wiki.audacityteam.org/wiki/Nyquist_Documentation Nyquist Documentation] on the [http://wiki.audacityteam.org/ Wiki].
 
 
 
=== Lisp ===
 
Nyquist is based on Lisp. If you have programmed in Lisp before, you can skim this section or go directly to the [http://www.audacityteam.org/help/nyquist2 next page]. 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, <tt>setf</tt>, is the name of the function (it stands for set-field). <tt>setf</tt> is used to assign a value to a variable. (There are other similar functions, like <tt>set</tt> and <tt>setq</tt>, but <tt>setf</tt> is the most powerful, so it’s the one we’ll use in our examples.) After <tt>setf</tt> comes <tt>area</tt>, 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 <tt>expt</tt> (exponent) function raises its first argument to the power of the second argument. Therefore <tt>(* 3.14159 (expt radius 2))</tt> means 3.14159 times the square of <tt>radius</tt>, 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 <tt>defun</tt> function is used to define a new function. The first argument is the name of the function, in this case <tt>circlearea</tt>. 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 <tt>r</tt>, 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 <tt>(2 3 4 5)</tt>, 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 <tt>list</tt> 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 <tt>first</tt> and <tt>rest</tt> functions. (Traditionally, these were called <tt>car</tt> and <tt>cdr</tt>, respectively, but<tt>first</tt> and <tt>rest</tt> are much easier to remember. Both sets of names are supported in Nyquist.) The output of <tt>(first mylist)</tt> is 1, and the output of <tt>(rest mylist)</tt> is the list <tt>(2 3 4 5)</tt>. So the second element of the list is <tt>(first (rest mylist))</tt>.
 
 
 
=== Lisp function reference ===
 
Here’s a list of some of the basic lisp functions you might need. For a complete list of Lisp / Nyquist functions, see the [http://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/manual/home.html Nyquist version 2.37 Reference Manual].
 
 
 
'''Note: Symbols in Nyquist (like variable names and function names) are not case-sensitive. They are converted to uppercase internally.'''
 
 
 
==== Math functions ====
 
 
 
{| style="border-spacing:0; width: 50em;"
 
| style="background-color:transparent;border-top:0.05pt solid #000000;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(+ a b)'''</tt>
 
| style="background-color:transparent;border-top:0.05pt solid #000000;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| addition
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(- a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| subtraction
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(* a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| multiplication
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(/ a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| division
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(truncate a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| round down to integer (floor)
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(float a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| integer to floating-point
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(rem a b c ...)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| remainder
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(min a b c ...)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| minimum
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(max a b c ...)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| maximum
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(abs a)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| absolute value
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(random n)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| random integer between 1 and n-1
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(sin a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| sine
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(cos a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| cosine
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(tan a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| tangent
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(expt a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| exponent (a to the power of b)
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(sqrt a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| square root
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(< a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| test for a less than b
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(<= a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| test for a less than or equal to b
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(> a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| test for a greater than b
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(>= a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| test for a greater than or equal to b
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(= a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| test for equality
 
 
 
|-
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(/= a b)'''</tt>
 
| style="background-color:transparent;border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| test for inequality
 
 
 
|}
 
==== List functions ====
 
 
 
{| style="border-spacing:0; width: 50em;"
 
| style="border-top:0.05pt solid #000000;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(first l)'''</tt>
 
| style="border-top:0.05pt solid #000000;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| first element of a list (car)
 
 
 
|-
 
| style="border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(rest l)'''</tt>
 
| style="border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| rest of the list (cdr)
 
 
 
|-
 
| style="border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(reverse l)'''</tt>
 
| style="border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| reverse a list
 
 
 
|-
 
| style="border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(list a b ...)'''</tt>
 
| style="border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| construct a list
 
 
 
|-
 
| style="border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(append l1 l2)'''</tt>
 
| style="border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| append two lists
 
 
 
|-
 
| style="border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(length l)'''</tt>
 
| style="border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| length of a list
 
 
 
|-
 
| style="border-top:none;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(maplist function l)'''</tt>
 
| style="border-top:none;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| apply a function to every element in a list
 
 
 
|}
 
==== Control ====
 
 
 
{| style="border-spacing:0; width: 50em;"
 
| style="border-top:0.05pt solid #000000;border-bottom:0.05pt solid #000000;border-left:0.05pt solid #000000;border-right:none;padding:0.049cm;"| <tt>'''(if expr expr1 expr2)'''</tt>
 
| style="border-top:0.05pt solid #000000;border-bottom:0.05pt solid #000000;border-left:none;border-right:0.05pt solid #000000;padding:0.049cm;"| if expr is true, evaluates expr1, otherwise evaluates expr2
 
 
 
|}
 
=== [[Programming in Nyquist]] ===
 
 
 
[[Category:Nyquist]]
 

Latest revision as of 12:45, 1 October 2018

This page has been transferred to the Manual.