problem with a plug-in (generate)

Hello. I try to write a plug - in from a script of P. Morales. It does not work. Do you understand the problem?
Beforehand thank you for your help.

This is malformed:

(defun sound
 (scale 0.1 (tibetan (freq offset dur rise dec)))

A function definition must have its arguments listed in parentheses after the name of the function:

(defun finction-name (arg1 arg2 ...)
  function body)

If there are no arguments, then it still needs the parentheses:

(defun finction-name ()
  function body)

Your function definition “sound” is missing a “)” at the end.

(freq offset dur rise dec)

This is incorrect because:
a) “freq” is not a function
b) If “freq” is supposed to be a variable (rather than a function), it needs to have a value, either scoped globally or passed to your “sound” function as an argument.

Also, best not to use “sound” as a function name as it is already a defined function in Nyquist.

Perhaps you meant:

(defun mysound ()
 (scale 0.1 (tibetan pitch offset dur rise dec)))

 (stretch 1 (mysound))

Thank you.
I try to use the following code:

(defun mytone ()
 (sine pitch dur))

I added the code following in the plug-in “generate”

;control pitch "pitch" real "MIDI pitch" 55 36 84

The problem is in this code.

(setf pitch (step–to–hz))

The nyquist console indicates the following error;

error: illegal character - -30
Function: #<Subr-(null): #407d328>

Do you understand my error?

“step-to-hz” converts a MIDI note number (“step”) into Hz.
For example, A4 is MIDI note number 69 and the frequency of a sine wave at A4 is 440 Hz (standard tuning).

(print (step-to-hz 69)) ; prints 440

(print (hz-to-step 440)) ; prints 69

(step-to-hz) is no good because you have not told the “step-to-hz” function what number to convert. “step-to-hz” takes one “argument” (the “step” number).

Thank you.
I would want to evoke the code of Pedro Jose Morales “b5.lsp”.

(defun lfo-pitch-control ()
 (pwlv 0.25  0.6 0.25  1.4 0.5  2.0 0.95  2.2 0.25  3.4 0.5  3.8 0.78   dur -0.2))
(defun starship (frq scl)
 (apply #' sim
  (mapcar #' (lambda (offset)
   (fmosc (hz-to-step (+ frq offset)) (scale scl (lfo-pitch-control))))
     '(0.0 4.3 9.5 23.0 39.0 84.0))))

I would want to evoke the following part of the code:

(lambda (offset)
   (fmosc (hz-to-step (+ frq offset)) (scale scl (lfo-pitch-control))))

In the user manual of R. B Dannenberg, the author indicates: (lambda args expr…) - make a function closure
args - formal argument list (lambda list) (quoted)
My question is thus the following one: apparently, the “lambda” function is followed by arguments.


Is it the first argument?

(fmosc (hz-to-step (+ frq offset))

Is it the second argument?

(scale scl (lfo-pitch-control)

Is it the third argument of the “lambda” function?
Beforehand, thank you for your answer.

The XLISP manual provides more information about lambda:

(lambda (offset)
  (fmosc (hz-to-step (+ frq offset)) (scale scl (lfo-pitch-control))))

The name of the function is: lambda
The argument list is enclosed in parentheses. There is just one argument: offset
The last part is the body: (fmosc (hz-to-step (+ frq offset)) (scale scl (lfo-pitch-control)))

The body contains one function: fmosc

(fmosc (hz-to-step (+ frq offset))
       (scale scl(lfo-pitch-control)))

fmosc requires at least two arguments. In this case it has exactly two arguments.

The first argument of fmosc defines the pitch:

(hz-to-step (+ frq offset))

The second argument of fmosc defines the modulation:

(scale scl(lfo-pitch-control))

Thank you.
The user manual of the XLISP function (mapcar indicate:
(mapcar function list1 [list2 … ])
If the function (lambda with its list which has that an argument is the "list1 “, I presume that the " list 2” is:

'(0.0 4.5 9.4 23.0 39.0 84.0)

It is right?
This is an unevaluated list.
My question is the following one. I tried to understand how the values of the “list 2” act on the generated sound wave. I did not understand the logic.
How do we choose these values?
Beforehand thank you for your answer.

I presume that you are referring to this code:

(mapcar #'(lambda (off)
                  (osc (hz-to-step (+ frq (* off offset))) dur *tibetan-table*))
               '(0 1 2 3 4 -1 -2 -3 -4))

This is quite tricky to read, but we can break it down into sections by looking where the “(” match with “)”.

Note that the function CAR returns the first element of a list, so when the XLISP manual says “successive CARs”, it means the first term, then the next term, then the next. It is simply taking each element of the list in turn.

From the outer brackets we see:

(mapcar #'(lambda .....)
         '(0 1 2 3 4 -1 -2 -3 -4))

so '(0 1 2 3 4 -1 -2 -3 -4) is the list that the lambda expression is applied to.

Then moving into the lambda expression:

(lambda (off) (osc ....))

we have an unnamed function with a local variable “off” and the body of the lambda expression consists of the function OSC.
This function is applied to successive terms from the list.

Moving in further to the OSC function we see that OSC has three arguments:
(osc step duration table)

(osc (hz-to-step (+ frq (* off offset)))

The “step” argument is (hz-to-step (+ frq (* off offset)))
The “duration” argument is the variable “dur”
The “table” argument is the symbol “tibetan-table

The interesting thing here is that the “step” argument is a function that includes the variable “off” [which was defined as a local variable of the lambda expression]

So, moving back out again, the lambda expression has an argument “off” that is used within the function “hz-to-step”.
MAPCAR applies the lambda expression to each term in the list. In other words, each of the numbers in the list becomes the “off” variable.

To see how this works, lets take a simple example that can be run in the Nyquist Prompt. Use the Debug button to see the output:

(mapcar #'(lambda (x) (print x)) '(1 2 3 2 1))

Here, the symbol “x” is a local variable of the unnamed function (the lambda expression) and '(1 2 3 2 1) is the list that the lambda expression is applied to.
Within the body of the lambda expression is the function (print x).
So what happens with MAPCAR is that the first element of the list [the number 1] is passed to the lambda expression and printed. Then the next element of the list [the number 2] and so on. The result is:


In our more complex example, the numbers 0, 1, 2, 3, 4, -1, -2, -3, and -4 are passed to the lambda expression and are evaluated within the HZ-TO-STEP function, so that a series of “step” values is created which can be used by the OSC function. Thus the code creates a list of sounds.