How to reverse and change speed in one effect

I’m trying to find a “Duplicate” effect in Nyquist, so I can use it to duplicate L and R and convert one of the duplicates to mono, but for another effect, duplicate the mono 2 times to make 3 channels. Also, if I try to use the stereo one with mono sound, how would I write a message pointing out that it is mono, use the other effect, without always saying the same message? Here is the code I’m trying to write, with the question-mark showing what command I need…
(if (stereo track)
(?DUPLICATE?)
(vector
(snd-function (aref track 0))
(snd-function (aref track 1)))
(snd-function track))

for the other, just duplicating twice to make 3 channels total.

Sorry I cut that off. I sent too early by accident…

Help?

Nyquist is included with Audacity, but it is separate from Audacity.

When a Nyquist plug-in runs, it returns some kind of data to Audacity, and Audacity then decides what to do with that data. For example if a Nyquist effect returns audio data, then Audacity replaces the selected audio with the audio returned by Nyquist. If the returned data is text, then Audacity displays the text in a message window. See here for more information about “return values”: Missing features - Audacity Support

Note that Nyquist has no direct way of creating or deleting tracks, no direct way to modify the sample rate or bit depth of an Audacity track, no direct way of editing tracks… All that Nyquist does directly is to operate on data that is passed to it, and return some kind of data.


Recent versions of Audacity provide Nyquist with one big new feature - the ability to send Macro Scripting commands (See: Macros - Audacity Manual)
By sending Macro Scripting commands to Audacity, Nyquist is able to tell Audacity to do things. Most (but not all) of Audacity’s features can be controlled by scripting commands. You will find the full list of standard commands here: Scripting Reference - Audacity Manual

IMPORTANT:

A Nyquist plug-in may modify the project by returning data to the project (where the “return value” is audio or labels),
OR
A Nyquist plug-in may tell Audacity to modify the project via Macro scripting commands.
YOU CANNOT DO BOTH IN THE SAME PLUG-IN.


There is a workaround if you need to modify the project with Nyquist AND modify the project via scripting commands:

  1. Create a Macro.
  2. Use Macro commands to tell Audacity to modify the project
  3. Launch Nyquist plug-ins from the Macro when you want Nyquist to modify the project.


    Back to your question about duplicating tracks:
    Use the “Duplicate:” Macro scripting command.

You can use the “Duplicate:” Macro scripting command from within a Nyquist plug-in like this:

(aud-do "Duplicate:")

But note that the plug-in must only modify the project from Nyquist, OR modify the project via scripting commands.

Note also that Audacity does not stop you trying to modify the project in both ways within the same plug-in, but the behaviour if you do is “undefined” - that means that the result is unpredictable and may cause unexpected results - Don’t do it.

This did nothing, was there something I’m missing or didn’t get?

;nyquist plug-in
;version 4
;name "Convert from Stereo to 3 Channels..."
;action "Making extra channel..."
;info "This effect makes a temporary third channel from stereo"

(if is-stereo
     (*track*
     (aud-do "Duplicate:")
     (vector
       (snd-function (aref *track* 0))
       (snd-function (aref *track* 1))
     (snd-function *track*))
       (throw 'err "Track error.\nStereo track required. If you are trying to convert a mono file, use Convert from mono to 3 channels.")))

I’m trying to have it check if it is stereo, and if it is, duplicate the stereo channel with one being mono, the other 2 remaining with no effect, but if it is mono, pop up a message saying that it has to be stereo, or use the other mono version.

Nothing happened.

Try running the plug-in with the Debug button.
The first line of the debug output indicates the error in the code.

Also note that to use THROW, there must also be a CATCH.
See: https://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/xlisp/xlisp-ref/xlisp-ref-281.htm

This came up, is the 1 on the bottom the first line, or second? Does the “Null” mean Zeroth? Some programs incorrectly read 0 = First, 1 = Second, 2 = Third, … instead of 0 = Null, 1 = First, 2 = Second, 3 = Third …

Here is what I got:

error: unexpected EOF
Function: #<Subr-(null): #486b7a0>
Arguments:
#<File-Stream: #4682ac0>
#(
1>

Also, there is a syntax error in the IF statement.
It should be (in pseudo code)

(if something
    (do-something)
    (do-something-else))

You have

(if is-stereo
     (*track*
     (aud-do "Duplicate:")
     ...

The implication of (track is that track is a function name, which it isn’t. track is a variable (a symbol representing the selected audio).

I assume what you mean is:

(if is-stereo
    *track*
    (aud-do "Duplicate"))

but that will also fail because IS-STEREO has not been defined.

You probably want to define IS-STEREO like this:

(setf is-stereo (arrayp *track*))

(see: https://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/xlisp/xlisp-ref/xlisp-ref-030.htm)

That means that your “(” and “)” don’t match. You are missing one or more “close parentheses”.
A common cause of this error is if you have a quoted string that isn’t closed.

Example:

(print "Hello World)

Note the missing quote at the end of “Hello World”.
Check to see the error message if you debug that in the Nyquist Prompt.

I got the stereo channel to duplicate, but doesn’t merge one of the stereo tracks from 2 to 1… now how to block if mono with a “Error” message, and if stereo, merge one of the stereo channels to one mono, making 3 channels?

Here is what I have… so far:

;nyquist plug-in
;version 4
;type generate
;name "Convert from Stereo to 3 Channels..."
;action "Making extra channel..."
;info "This effect makes a temporary third channel from stereo"

(setf is-stereo (array p *track*))
     (aud-do "Duplicate:")
     (vector
       (snd-function (aref *track* 0))
       (snd-function (aref *track* 1))
     (snd-function *track*))
       (catch 'mytag (+ 1 (throw 'err "Track error.\nStereo track required. If you are trying to convert a mono file, use Convert from mono to 3 channels." else)))

do the single-quotes matter?
(catch ‘mytag’ (+ 1 (throw 'err “Track error.\nStereo track required. If you are trying to convert a mono file, use Convert from mono to 3 channels.” else)))

Tried this…

;nyquist plug-in
;version 4
;type generate
;name "Convert from Stereo to 3 Channels..."
;action "Making extra channel..."
;info "This effect makes a temporary third channel from stereo"

(setf is-stereo (array p *track*))
     (aud-do "Duplicate:")
     (vector
       (snd-function (aref *track* 0))
       (snd-function (aref *track* 1))
     (snd-function *track*))
       (print "Track error.\nStereo track required. If you are trying to convert a mono file, use Convert from mono to 3 channels." else)))

…and “Print” didn’t work…

…which is better, “print” or “throw 'err”?

When you include code in your post, please use the “</>” button to create code tags. In the message editing widow they look like this:


You then insert your code between the and
like this:

Type or paste your code here
...

The code tags ensure that the code formatting is preserved.

It depends what you want to do.
I’ll write about PRINT here, then another post about THROW.

PRINT writes a string (text) to the default output stream - For Nyquist in Audacity the default output stream is the debug window. It also returns the string. Thus if a PRINT statement is the final line run, then the string will be returned to Audacity and Audacity will display it in a message window.
See: XLISP print

The PRINT statement can be useful when debugging code. For example this code fails:

(setf data (list "A" "B" "C" "D"))
(setf myarray (make-array 4))

(setf count 1)
(dolist (val data)
  (setf (aref myarray count) val)
  (setf count (+ count 1)))

(print myarray)

The debug output is not particularly easy to understand

error: index out of range - 4
Function: #<FSubr-SETF: #55555868d418>
Arguments:
  (AREF MYARRAY COUNT)
  VAL
Function: #<FSubr-DOLIST: #555558c6e088>
Arguments:
  (VAL DATA)
  (SETF (AREF MYARRAY COUNT) VAL)
  (SETF COUNT (+ COUNT 1))
... (more)...

To see what is happening within the DOLIST loop, we can add =https://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/xlisp/xlisp-ref/xlisp-ref-199.htmPRINC and PRINT statements like this:

(setf data (list "A" "B" "C" "D"))
(setf myarray (make-array 4))

(setf count 1)
(dolist (val data)
  ; print some stuff to help debug
  (princ "Count is: ")
  (princ count)
  (princ " and val is: ")
  (print val)
  ; end of print statements
  (setf (aref myarray count) val)
  (setf count (+ count 1)))

(print myarray)

The debug output is then:

Count is: 1 and val is: "A"
Count is: 2 and val is: "B"
Count is: 3 and val is: "C"
Count is: 4 and val is: "D"
error: index out of range - 4
Function: #<FSubr-SETF: #555558681858>
Arguments:
  (AREF MYARRAY COUNT)
  VAL
Function: #<FSubr-DOLIST: #555558687e78>

So we can see that the list is being stepped through correctly, but our “count” variable is wrong because =https://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/xlisp/xlisp-ref/xlisp-ref-029.htmthe index for elements of an array should start at zero.

We can then fix our code like this:

(setf data (list "A" "B" "C" "D"))
(setf myarray (make-array 4))

(setf count 0)
(dolist (val data)
  ; print some stuff to help debug
  (princ "Count is: ")
  (princ count)
  (princ " and val is: ")
  (print val)
  ; end of print statements
  (setf (aref myarray count) val)
  (setf count (+ count 1)))

(print myarray)

and see that it now works as expected.

After getting it working correctly, the diagnostic PRINT statements should be removed:

(setf data (list "A" "B" "C" "D"))
(setf myarray (make-array 4))

(setf count 0)
(dolist (val data)
  (setf (aref myarray count) val)
  (setf count (+ count 1)))

(print myarray)

Unlike PRINT, the THROW statement does not print anything. What it does is to stop the program immediately and send a message to it’s associated CATCH.

See: XLISP throw
and: XLISP catch

Those pages include examples, so probably not worthwhile for me to add more examples here.

I’m not sure what you are hoping to do here, but it won’t work.

     (vector
       (snd-function (aref *track* 0))
       (snd-function (aref *track* 1))
     (snd-function *track*))

Looking at the parentheses, the start of the function call is “(vector …” and the end of that function call is the final “)”

VECTOR creates an array, and each argument is an element of the array.
You code is creating an array where the first element is (snd-function (aref track 0)), the second element is (snd-function (aref track 1)) and the final element is (snd-function track).

I suspect that you have miscounted the opening “(” and closing “)”.

I would very highly recommend NOT relying on counting parentheses. Use a text editor that can highlight matching parentheses, such as NotePad++ (it’s free).

Steve, about this…

     (vector
       (snd-function (aref *track* 0))
       (snd-function (aref *track* 1))
     (snd-function *track*))

…I’m trying to merge the duplicated stereo track to mono, without merging the other. I’m trying to duplicate both left and right channels, and merge them to make 1 stereo and 1 mono. 3 channels. Not to be mean, but if you made the program, how is this hard to understand? Basically, I want to copy a stereo track/channel to itself, and mix the copied track/channel without affecting the original. This…

 ;nyquist plug-in
;version 4
;type generate
;name "Convert from Stereo to 3 Channels..."
;action "Making extra channel..."
;info "This effect makes a temporary third channel from stereo"

(setf data (list "A" "B" "C" "D"))
(setf myarray (make-array 4))

(setf count 1)
(dolist (val data)
  ; print some stuff to help debug
  (princ "Count is: ")
  (princ count)
  (princ " and val is: ")
  (print val)
  ; end of print statements
  (setf (aref myarray count) val)
  (setf count (+ count 1)))
(setf data (list "A" "B" "C" "D"))
(setf myarray (make-array 4))

(setf count 0)
(dolist (val data)
  ; print some stuff to help debug
  (princ "Count is: ")
  (princ count)
  (princ " and val is: ")
  (print val)
  ; end of print statements
  (setf (aref myarray count) val)
  (setf count (+ count 1)))
(setf data (list "A" "B" "C" "D"))
(setf myarray (make-array 4))

(setf count 0)
(dolist (val data)
  (setf (aref myarray count) val)
  (setf count (+ count 1)))

(print myarray)

…doesn’t work. It says that it “Nyquist returns value: 1”. When I tried to debug, the error message came up, I think the part relevant to the problem is “error: index out of range - 4”, because I believe it tried to duplicate 2 to 4, and remove 1 to 3, since it said “4” in part of the message, and “1” in the other, because 2+2=4-1=3. Options are to make one plugin that makes mono and stereo convert to 3 channels/tracks, or separate ones that only work for specified number of channels/tracks, which a message will come up if it isn’t right.
lrc.png

I didn’t write the Nyquist programming language. Nyquist was developed at CMU.

Nyquist cannot add or remove Audacity tracks, or change a mono track to stereo, or change a stereo track to mono.

Nyquist can convert stereo audio to mono, but it can’t change the Audacity tracks.

You can use Macro commands from Nyquist to add or remove tracks.

You cannot use Macro commands to change the Audacity tracks and Nyquist commands to change the audio in the same plug-in.

There are a few exceptions, but the basic rule is that you need to decide whether to use Macro commands or normal Nyquist commands in the plug-in, and don’t attempt to mix the two.

If you change the code to this:

;nyquist plug-in
;version 4
;type generate
;name "Convert from Stereo to 3 Channels..."
;action "Making extra channel..."
;info "This effect makes a temporary third channel from stereo"

(setf data (list "A" "B" "C" "D"))
(setf myarray (make-array 4))

(setf count 1)
(dolist (val data)
  ; print some stuff to help debug
  (princ "Loop 1 -Count is: ")
  (princ count)
  (princ " and val is: ")
  (print val)
  ; end of print statements
  (setf (aref myarray count) val)
  (setf count (+ count 1)))
(setf data (list "A" "B" "C" "D"))
(setf myarray (make-array 4))

(setf count 0)
(dolist (val data)
  ; print some stuff to help debug
  (princ "Loop 2 - Count is: ")
  (princ count)
  (princ " and val is: ")
  (print val)
  ; end of print statements
  (setf (aref myarray count) val)
  (setf count (+ count 1)))
(setf data (list "A" "B" "C" "D"))
(setf myarray (make-array 4))

(setf count 0)
(dolist (val data)
  (setf (aref myarray count) val)
  (setf count (+ count 1)))

(print myarray)

Then you will see which DOLIST loop the error is occurring in.

If you enable Advanced Mixing Options in Preferences, then this


will export as a three channel track.

(Multi-channel export is not available in Macros)

Accessed by: Edit > Preferences > Import Export (on a Mac Audacity > Preferences > Import Export )

The link you sent me is for “Mac”, not “Win”. I have Windows 10, So I’m assuming “Use custom mix” does the same as “Use Advanced Mixing Options”? Do I need a Macintosh emulator for Windows?