Customizable/Combined Delay + Volume + Panning Effect

Please move this to “Feature Requests” if appropriate.

Basically, I’m looking for some way to automate/customize multiple parameters all at the same time: volume, panning, delay/time. I see that the “Bouncing Ball Delay with Panning” and “Delay with Stereo Flip” plugins address some of these things, but they’re not customizable in the way that I want. I also really like the delay function in Audacity (in addition to traditional delay effects, it’s actually GREAT for making drum beats), but what these things can’t do that I would LOVE to see:

  1. change the delay duration with each successive iteration. I would like to be able to have the first delay occur after 250 ms, second one after 225 ms, then 200 etc.
  2. modulate the volume change with each successive iteration. I would like to be able to have first delay be +1 dB, second be +3 dB, third be -2 dB etc
  3. modulate the panning anywhere from -1.000 (all the way left) to 1.000 (all the way right) on any given delay.
  4. modulate the pitch up/down (although I realize this could be challenging/problematic, because it requires changing the timing by lengthening/shrinking the sample – so personally I would be completely happy to NOT have this functionality integrated)

Ideally (for me, anyway) this would function based off of imported text. That way you could set all the parameters in a spreadsheet, convert it to zero-markup text and throw that into a Nyquist prompt window. Does this sound like something that would be possible with Nyquist? It would also not have limitations on duration (currently can’t go over a 5 second delay), or number of repeats. With not having duration limitations, this could be used as a really sophisticated beat/rhythm builder as well as an actual delay function. Seriously, REALLY sophisticated – I don’t know of any existing rhythm/drums program that allows you to easily control all these parameters in one fell swoop like this, and I’ve been looking!

Or, alternatively, does anyone know how to achieve this same thing with existing plugins? Compatible with Audacity or not. It sounds like Logic Pro has a feature called Delay Designer that allows you to customize most of these things (, but it’s a no-go for me because I’m on Windows, and also don’t think it allows for the level of customizability that I’m seeking. I want to control ALL of the parameters down to the millisecond / fraction of a dB / fraction of a percent panning for ALL iterations of the delay. Am I dreaming?

What do you mean they’re not customisable? They are Nyquist plugins, of course you can customise them - you just need to learn a bit about how to do it :smiley:

You keep asking about all sorts of specialist effects that you want to use - there’s no getting away from it - you need to learn a bit about writing and modifying Nyquist plugins. Nyquist plugins may not be as pretty as many of the modern VST plugins, but they are totally customisable.

If you’re game to give it a go, grab yourself a copy of NotePad++ from here: and find out how to:

  1. Enable parentheses matching. Nyquist uses lots of parentheses, and it is a big help to be able to match the “)” with the “(”.
  2. Enable “Lisp” syntax highlighting. Nyquist is based on a version of Lisp, and standard Lisp syntax highlighting will colour code many of the keywords, which makes the code easier to read.
  3. Set the default indentation when using “Tab” to two spaces.

When you’ve got that set up, give me a shout and I’ll help you to make some custom delay effects. How about that for an offer?

I get that Nyquist is customizable. I just meant that those particular plugins aren’t set up to control the parameters in the way that I want to control them.

A man can dream, can’t he? :wink: I’m trying to take a long game approach. I know these things won’t happen tomorrow. I just want to get them out there, see if anyone else is excited by the possibilities. I always have ten different music-related things I want to try/practice/learn. Some things I can do on my own, other things I have to reach out to people with different skill sets. Have you read about Paul Lanksy’s concept of the “instrument-builder” and how they interact with composers, listeners and performers? I have the utmost respect for people that develop musical instruments, and people that develop software applications for musical use. And I think for them to really do their jobs well, it’s important for them to hear from composers and musicians about what tools they wish they had. That’s all I’m doing. I wish I had the ability to do this thing, and I throw it out there to someone that might have the technical knowhow to make it all happen, because I certainly don’t!

And this might seem like a specialist effect based on how I’m describing it, but it would be very adaptable to all kinds of uses. It’s basically just the automation and customization of repetitions (which encompasses reverb, delay, echo, recurring loops, beats, repeating melodic fragments etc.) while being able to control the variables of duration/timing, volume and stereo placement. Anyone that does any kind of looping or beat creation would immediately see how many creative possibilities this would open up.

I’m game. I really don’t know jack about programming, but I can give it a go.

The big thing for me is this: I want to be able to set all three parameters (duration, pan, volume) independently for each and every delay. If you think this is possible, I can definitely try to muddle through it. If you have doubts, I should probably try something else first. If I can get it working, I would be happy to share my spreadsheet that makes it all work. I have it pretty much figured out already - I’d just have to figure out a way to integrate the Nyquist code.

I can get Notepad set up as you say. So should we maybe try to start with an existing code/plugin and see if I can make any sense of it? Is there one that you think has the “guts” that I can start with and try to tweak into what I want? Or start something from scratch?

It’s a very good offer indeed. Thanks.

Start from scratch I think - then we can take baby steps first while you get the hang of it.

I’ve moved this to the Nyquist board - hopefully you will find it :wink:
Give a shout when you have Notepad++ set up and we’ll get started.

I think this is done. I just clicked the button by “( )” under the Auto-Completion tab.

I can’t find this. Off to a rough start already!

Look for “Language” settings (and remember, Google is your friend :wink:)

Ahh! Got it. I assumed it was under settings like everything else.

Okay, I think I’m set up. What next?

OK, let’s make a plugin :smiley:

There are two parts to a plugin: a “header” and the “Nyquist code”. The header tells Audacity what the file is and what to do with it, and the Nyquist code is the actual commands for Nyquist (“Nyquist” being the audio programming language).

Full information about headers here:

We will write this as a “version 3” plugin (version 4 is more recent, but version 3 is probably a bit easier for our first plugin).
It will be a “process” type plugin, because it is processing the selected audio.
We will call it “A delay…” (starting with “A” will put it near the top of the effects list so that it is easier to find. The “…” is a convention for names of effects that pop up an interface before they do anything (Notice that in the Effect menu, the “Fade In” and “Fade Out” effects do not have “…”, but “Amplify…” does).

We don’t need all the optional headers, so let’s start with this:

;nyquist plugin
;version 3
;type process
;name "A Delay..."

We will make this first shot a very simple delay effect with just one slider control:

;control delay "Delay by" real "seconds" 1 0 10

The “slider widget” is described here:
Can you work out what the above code does?

Let’s try it.
All together you should have:

;nyquist plugin
;version 3
;type process
;name "A Delay..."

;control delay "Delay by" real "seconds" 1 0 10

Save that to your Audacity plugins folder as “a-delay.ny” (see:

Quick note about naming:
Audacity works on all sorts of computers, so it is best to name files using characters that are universally “safe”. The safest way to name files is to only use letters, numbers, hyphen “-”, underscore “_” only. Start the name with a letter, no spaces and keep to lower case.

Start, or restart Audacity so that Audacity finds the plugin. It should be listed near the top of the “below the dividing line” part of the Effect menu.
It does not do anything yet, but if you “apply” it, it should pop up an interface.
See that when you “apply” it, it returns a number. That is called the “return value”. Do you see where that number is coming from?

Although we needed to restart Audacity so that it could find the plugin, fortunately we don’t need to restart Audacity each time we update the file. Once Audacity knows that the plugin exists we can just update the plugin “.NY” file and re-save the file to update it (overwrite the older version).

Time for a cup of tea. Back soon.

Part 2 - “sounds”.

The way that Nyquist gets sound from Audacity, is that Audacity passes the selected audio to Nyquist as the value of a symbol “S”.

A “symbol” can be thought of as the name of a “thing”. It does not really matter what that “thing” is, and that “thing” may change. The key concept is that we have a “thing” and it has a “value” and a “name”. It sounds really unprofessional to keep writing “thing”, so let’s use the proper term: a “variable”. As the name implies, the value of a “variable” may change.

The name of a variable is a single string of letters. Nyquist is not “case sensitive”, that is, it ignores upper/lower case distinctions in variable names (and commands).
Names should be one word (no spaces) starting with a letter, and made of only letters and numbers. Normally we would choose names that are reasonably short but meaningful.

Unlike some other computer languages, Nyquist does not care what “type” of thing the variable is. Whether it is a numeric value, a string of letters (called a “string”), or even a “sound”, it is just a “variable” to Nyquist.

To set the value of a variable, we use the command (the “function”) SETQ or the function SETF.
SETF is the more powerful of the two, so we shall use that for now.

As Nyquist is based on the LISP programming language, it follows the same rules of always placing functions in parentheses (“brackets”). Thus to create a variable called “my-number” and give it the value “6”, we can write:

(setf my-number 6)

Because Nyquist is case insensitive, this is identical to writing:

(SETF My-NuMbER 6)

but generally we would want to be consistent with our use of upper and lower case characters.

The number “6” is a type of variable called an “integer” (a whole number). Fractional numbers are referred to as “floats” (short for “floating point number”).
Thus you can also have

(setf my-number 6.2)

which sets the variable called “my-number” to the fractional (“float”) value “6.2”.

Another type of “thing” is a “character”. A “character” is a single text element, like the letter “A” or “a” or “3” or “@”. Note that the “character” 3 is not the same as the integer number 3 - one is a text element and the other is a number.
We could set a variable called “my-character” to have the value of #C. The “#” indicates that “C” means “character C”.

(setf my-character #C)

Another type of “thing” is a “string” (a “string of characters”). Normally we would put a string in double quotes to indicate that it is a string. For example:

(setf my-string "this is a string")

Yes I know, I said we would be dealing with “sounds” - let’s do that now:

The reason that I’ve been going on about different “data types”, is that Nyquist treats “sounds” as just another “type” of data. Just as we can have a variable called “my-variable” and it can have a value that is an integer, or a float, or a character, or a string, it could have a value that is a “sound”.

In version 3 effect plugins, there is one pre-defined variable that has the name “S” (or “s”, upper or lower case does not matter) that has the value which is the “sound” that is passed from the selected track in Audacity to Nyquist.
Stereo sounds are a bit different and we will come to that later - for now we will deal just with single track mono sounds.

In the Nyquist Prompt effect, if you select some audio and then run the code:

(print s)

You will probably notice that Nyquist is doing something (if enough audio is selected then you will see a progress bar), and then it finishes. Nothing appears to have happened.
Now try doing the same, but use the Debug button. The Debug button can be very useful for showing what is going on, especially if there are errors.
After running with Debug, you will see in the debug window, something like:

#<Sound: #b1b732d0>

That is a printed representation of the “sound” object that was the value of “S”.

Let’s do something with a sound. What happens if we multiply a sound by a numerical value?
Try this in the Nyquist Prompt:

(mult s 0.3)

Try that with different values. Can you see what is happening?

What happens if we add a numerical value to a sound?
Try this in the Nyquist Prompt:

(sum s 0.3)

Try that with different values. Can you see what is happening?

“SUM” is a function that can add sounds, or numbers, or both.
There is also a function called “SIM” (from the word “simultaneous”), which is identical to the function “SUM”.

(sim s -0.2)

(sum 3 4 5)

(sim 1 2 20)

To complete this section, let’s go back to our delay effect and see if we can create a simple delay.

  (mult 0.8 s)
  (at-abs 0.5 (cue (mult 0.5 s))))

Can you see what is happening?

Each of the functions used in this code is defined in the Nyquist manual - do look them up:
CUE (don’t worry about this one just yet)

Try that code in the Nyquist prompt with different numeric values. Can you see what it is doing?

Finally (for this section), lets put that code into out plugin.
If you recall, we created a control:

;control delay "Delay by" real "seconds" 1 0 10

That creates a variable called “delay” and gives it a value between 0 and 10 (default value “1”). We can use that value in our code by replacing the “absolute time value” (which was originally 0.5) with our “variable”:

;nyquist plugin
;version 3
;type process
;name "A Delay..."

;control delay "Delay by" real "seconds" 1 0 10

  (mult 0.8 s)
  (at-abs delay (cue (mult 0.5 s))))

Thus ends part 2. How’s it going? Any questions? Can you add controls to set the levels for the original sound and the delayed sound?

Sweet. I will have to wait until later to start on this, hopefully tonight (UTC−05:00). I’ll attempt to muddle my way through this and hopefully try to mess with the variables to see if I can get it to do what I would predict it should do. I’ll let you know how it goes.

Okay, so Nyquist differentiates between the two. But how do I? I only have one way to input a 3, AFAIK.

Just curious – is it possible to set both the onset of the delay AND the duration?

So let’s say the source sound is 500 ms long. Is it possible to have the first delay start at 750 ms, but then “cut it” at 1 sec? And if we were to “cut it” before it runs its full 500 ms, I’m assuming it could potentially end at a non-zero crossing, thus causing that “crackle.” Or will the full 500 ms of sound play out with each delay no matter what?

If you use a slider widget in the form:

;control variable ""text-left" int "text-right" <default> <min> <max>

Note the “int”. That means that the variable value will be an integer (whole number).

If you use a slider widget in the form:

;control variable ""text-left" float "text-right" <default> <min> <max>

Note the “float”. That means that the variable value will be floating point number (fractional number).

If you use a text input widget in the form:

 ;control variable-name "text-left" string "text-right" "default-string"

Note the “string”. That means that the variable value will be a string (“text”).

Fortunately we are able to convert between a text “3” and an integer “3” and a fractional “3.0” (in any direction). We’ll come to that later :wink:

Baby steps. Let’s not run before walking :smiley:
If necessary we can apply fade in / fade out to avoid crackles (much faster processing than looking for zero crossing points).

I know. I just want to know if it’s possible, in theory. Because that would be awesome, and it would help keep me motivated.

I did not have time to do any of this stuff last night. Hopefully this weekend.

Probably :smiley:
Let’s see how far we get.

No worries, I’m not in a rush.