This is a mini-tutorial about how Nyquist adds sounds, numbers and vectors.

The examples may be run in the Nyquist Prompt effect, and use "version 4" LISP syntax (in Audacity 2.1.2/2.1.3 ensure that "Use legacy (version 3) syntax" is NOT enabled). Note that in the code examples, text that occurs after a semicolon is treated by Nyquist as a "comment" and is ignored. Comments are provided to help people reading the code to understand what the code means.

There are three similar functions in Nyquist for adding things: "+", "SUM", "SIM"

The first is a straightforward arithmetic "add" function that adds a list of numbers. It can operate on integers (whole numbers) or "floats" ("floating point" numbers)

The function "SIM" is identical to the function "SUM". For clarity, "SIM" is more often used when referring to sounds, and "SUM" used when referring to numbers, but as they are functionally identical they are interchangeable. In the following examples I shall use "SUM", but "SIM" could be used and there would be no difference.

"SUM" (and "SIM") may be used to add numbers, returning the same result as "+", but is slightly slower because the underlying code is more complex.

The "SUM" function can also work with "sounds". Nyquist treats mono sounds as a distinct data type. With "SUM" we can add a numeric value to a sound, which adds the numeric value to the value (amplitude) of each individual audio sample. To demonstrate this, we can use the special word *TRACK*.

The word *TRACK* is itself a special kind of symbol called a "variable" that represents data. Nyquist treats the word *TRACK* to represent the audio that is selected in the Audacity track (note that the asterisks are part of this special name). The audio may be mono or stereo. If it is a mono track (one audio channel), then *TRACK* will be a "sound". If the track is stereo, then *TRACK* will be an array containing two "sounds".

In this example we will add the numeric value "0.3" to a mono sound from a selection in a mono audio track:

As we can see, the selected waveform has been offset by +0.3. In other words, +0.3 has been added to each sample in the selection.

Adding Sounds:

The "SUM" function is also able to add sounds together. Adding sounds is also known as "mixing". In the simple case of adding sounds that have the same sample rate, addition is performed by adding the value (amplitude) of each individual audio sample from one sound, with the corresponding sample of the other sound.

In this example, we will introduce another function, "MULT", which as the name suggests provides a multiplication function that works with sounds. "Multiplying" a sound by a numeric amount is commonly known as "amplifying". If we multiply a sound by 2, then each sample value is doubled (samples with negative values become twice as negative). Doubling the amplitude of each sample value doubles the overall level of the audio - in other words, the audio is amplified by a factor of 2, which is roughly equivalent to +6 dB.

This first code snippet will generate a sine tone with a frequency of 440 Hz. By default the function HZOSC generates a sine tone with an amplitude of +/- 1.0 (0 dB), but we have multiplied it by 0.5, so it is "amplified" (attenuated) to a lower level of +/- 0.5. The returned audio replaces whatever was previously selected in the track

Now we can see (and hear) that the sine tone has been mixed with (added to) the track audio.

Working with Stereo Sounds

Nyquist handles stereo as an array ("vector") containing two "sounds". The first element of the array is the left channel and the second element is the right channel. Audacity tracks are either mono or stereo, so returning audio from Nyquist must either be a mono sound, or an array containing two sounds. Unfortunately there is currently no way for Nyquist to tell Audacity to create a stereo track, so to generate stereo audio with Nyquist it is necessary to make a selection in a stereo audio track.

If Nyquist returns an array of 2 sounds into a selected stereo track, the first sound element is the left channel and the second sound element is the right channel.

If Nyquist returns a mono sound into a selected stereo track, the sound is written into both channels (the sound is duplicated)

If Nyquist returns an array of 2 sounds into a selected mono track, an error is shown

If Nyquist returns an array of one sound, or more than 2 sounds, and error is shown

To create an array of sounds, we can either declare the array first, and then add the sounds,Example:

Explanation:In the first of these two examples, the MAKE-ARRAY function creates an array with 2 elements, and is assigned to the variable "stereo". We then use the AREF command to access the first element (index 0) and set it to the sound generated by (hzosc 220), which is a 220 Hz sine tone.The second element (index 1) is set to a 440 Hz sine tone.Note: If we run this example as is, Nyquist returns the result of the final line, which is the 440 Hz "sound" and NOT the (stereo) array of sounds. If we wish to return the stereo array, we can do so by adding a final line with the variable "stereo"

In the second example, we create an initialized vector containing two sounds in one step. Nyquist returns the evaluation of this command, which is the stereo audio.

Adding Stereo Sounds

The command SIM (same as "SUM") is described in the Nyquist manual as (abridged):

Returns a sound which is the sum of the given behaviors evaluated with the current value of *warp*. If behaviors return multiple channel sounds, the corresponding channels are added. If the number of channels does not match, the result has as many channels as the argument with the most channels. For example, if a two-channel sound [L, R] is added to a four-channel sound [C1, C2, C3, C4], the result is [L + C1, R + C2, C3, C4]. Arguments to sim may also be numbers. If all arguments are numbers, sim is equivalent (although slower than) the LISP + function. If a number is added to a sound, snd-offset is used to add the number to each sample of the sound....

Unfortunately the manual does not explicitly state what happens when adding a number to a stereo sound, though we can deduce the behaviour by considering the multi-channel example (also worth noting that Audacity tracks currently support a maximum of 2 channels).

In the example of adding [L, R] to [C1, C2, C3, C4], the first element of the first array ("L") is added to the first element of the second array ("C1"), the second element of the first array ("R") is added to the second element of the second array ("C2"), and nothing is added to C3 or C4.Schematically:[L, R] + [C1, C2, C3, C4] = [L+C1, R+C2, C3, C4]

You are using *track*, which is a stereo sound, so you are still adding those mono A1, A2,... terms to the left channel only. The same goes for the right channel of "stereo".

There are a couple of ways round this problem:

One is to replace each occurrence of *track* with (aref *track* 0) when calculating the left channel of "stereo", and (aref *track* 1) when calculating the right channel.

The other, and in my opinion better way, is to move the DSP code into a function. This cuts down on a lot of duplicate code. You're wanting to apply exactly the same process to both left and right channels, so we can write the code once and use it twice.

This is the code that you are wanting to apply to each channel - I've replace the variable *TRACK* with a new name "SIG" (abbreviation of "signal") because we want to processes the signal (mono sound) from the left channel, and then the signal from the right channel