Binson Echorec 2019

A combination of a Binson Echorec magnetic drum echo, a nice reverb (Steve’s) and Steve’s Desk-EQ. The Idea is that you want to apply a combination of effects to a guitar track, instead of first adjusting tone, then adding reverb… (you get the idea). Together with the passthru option I think this is a usable plugin.
Modifying parameters and using preview until it sounds good is the simple process. A compressor included after the tone control should have been nice, but it must wait. Some parameters are not adjustable, in order to have as few controls as possible.
binson2019.ny (7.38 KB)

I’ve only had a quick look so far. It looks good.

A little “trick” that you may find interesting / useful:

When you have “optional” controls that are commented out by default (such as “head-times”), rather than simply hard coding the default values as:

(setq head-times 0)

you can test to see if the variable is bound to a value, and set the default value if it is not bound.

(unless (boundp 'head-times)
  (setq head-times 0))

The benefit of this is that if you want to make the control active, all you have to do is to uncomment the control (rather than uncomment the control and comment or delete the hard coded value).

Also, for future reference, although I like the reverb that Rodger wrote, there are also some reverb functions built into Nyquist (much simpler to use, so good for prototyping effects):

Thanks for the tip, really good.
Would you say that the built in reverbs are better, I mean apart from that they consist of only one line of code?

Reverb is one of those effects where tiny subtle differences make a huge difference, and a good reverb in one context can sound terrible when used with different material (and vice versa). If you’re interested in reverb effects, you should really try them out for yourself. Personally, I quite like John Chowning’s version (jcrev), but when I wrote my Stereo Reverb effect, I must have thought that Roger’s version sounded best for that application.

Of course the built-in Nyquist reverbs aren’t really just one line of code - It’s just that the code for the other reverbs is somewhere else, so we only need to see the function call. It would be perfectly possible to put Roger’s reverb code, or my Stereo Reverb code, in a separate file, and call it with just a couple of lines of code (one line to load the file, then one line to call the function).

Thank you Steve,
I will add the reverbs to the drop down list and try them out. Yes, of course the code is there, but I don’t need to bother, and that is good. I guess that they are as good as Roger’s.
Some questions:
Is there any possibility to listen to all tracks in the preview. The echo can sound good by itself but when you listen with bass and it is not good. And another hard one: Can you trick the plugin to work with live data?
And another: Can you change the preview dialog to not modal? It would be good to be able to change the settings while you listen.

Interesting question.
I’ve not tried this in a plug-in, but it works in the Nyquist Prompt:

;version 4
;control gain "Gain" float "" 1 0 10
;control track "Process track" int "" 1 1 10

(setf id (get '*track* 'index) )
;(print id)

(if (= track id)
 (mult *track* gain)
  "")  ;An empty string is a "no-op"

That’s an easy question - No :wink:

Again, No.

See this topic: *Selection* Variable Not Updating While Nyquist Plugin Is Running

It “may” be possible in the future to have “real-time preview” (like Audacity’s “Bass and Treble” and “Distortion” effects) in Nyquist effects, but that’s not yet possible.

Thanks again Steve for all the time you spend on answering my questions!
About listening to all tracks -

(setf id (get '*track* 'index) )
;(print id)

(if (= track id)
 (mult *track* gain)
  "")  ;An empty string is a "no-op"

I can see that it is possible to select a specific track, but can you retreive several tracks in the plugin, perhaps to an array and then use (sum track[1] track[2] … track ) to play all tracks together with the currently selected track (or part of the track)

I’m not sure what you mean.

The idea of that code is that you can select all tracks in the project (or all the ones that you want to hear in the preview), and select one track to apply the effect to - in the case of that code, the “effect” is just simple amplification. During preview, Audacity plays back a mix of all selected tracks. By default, the Nyquist effect is applied to each of the tracks individually, but for all tracks where “id” is not equal to “track” (set by the control), the effect does nothing, so you hear unprocessed tracks for all selected tracks, except for the track that matches “id”. The track that matches “id” is amplified by “gain”.

Yes, that is exactly the function I was looking for. My problem is that the extent of my Lisp knowledge is what you have seen in my code. I must look up “setf” so that I can understand the first (and second) line in the example. And I don’t see how I can get the id of e.g. the lead guitar track?

My first dozen or so plug-ins, I had to look up everything. It’s like travelling to another country where no-one speaks English, armed with nothing more than a phrase book. Gradually, things begin to stick, but even now I keep the Xlisp and Nyquist manual bookmarked so I can look things up when needed.

Assigning values to variables is done with the SET command, but this does not work:

(set val 10)

That’s an error because Nyquist looks at “val” and says “Error, I don’t know what VAL is”.
The error is because when Nyquist sees VAL, it tries to evaluate it, but it’s not yet been set, so it is “unknown”.

How LISP gets round this is to “quote” the variable (with a single quote before the variable).
This works:

(set 'val 10)

and so does the keyword equivalent:

(set (quote val) 10)

For early Lispers, quoting variables before setting them was so tedious, that a shorthand version of “set quoted” was created. The command was SETQ.

(setq val 10)

Nobody would ever write (set (quote val) 10) these days.

SETF is similar to SETQ, but it’s a more powerful command. It means “set field”. A “field” may be a simple variable (which works in exactly the same way as SETQ, or may be an element in an array, or an item in a list, and possibly other things that don’t immediately come to my mind.

Because SETF can do everything that SETQ can do (and more), many Lispers don’t use SETQ at all, but use SETF instead.

I think that’s enough for this post - I’ll send another post shortly with a quick description of that code.

A description of this code:

;version 4
;control gain "Gain" float "" 1 0 10
;control track "Process track" int "" 1 1 10

(setf id (get '*track* 'index))
;(print id)

(if (= track id)
 (mult *track* gain)

;version 4

This is a “header” that tells Audacity to treat the code as version 4 syntax.

;control gain "Gain" float "" 1 0 10
;control track "Process track" int "" 1 1 10

A pair of slider widgets.The first returns a floating point (decimal) number. The second returns an integer.

(setf id (get '*track* 'index))

Sets the variable “id” to the value of the expression that follows it.
(get 'track 'index) Gets the INDEX property from TRACK.

;(print id)

A comment. If the semicolon is removed, the value of “id” is printed and can be seen in the debug output.

(if (= track id)
 (mult *track* gain)

This is an “IF… THEN… ELSE…” construct.

IF the value of “track” (which is set by the integer slider widget) is equal to the value of “id”

THEN multiply TRACK by “gain”. TRACK is a special variable in version 4 syntax that passes the audio selection from Audacity to Nyquist.
Nyquist processes each selected track in turn, so TRACK has the audio from the track that Nyquist is currently processing.
GAIN was set by the floating point slider widget.
Multiplying a sound by a number, is identical to “amplifying” the sound. Each sample in the sound is multiplied by the value.

ELSE return an empty string. Audacity treats an empty string from Nyquist as an instruction to do nothing (a “no-op”)

Nyquist should always return something to Audacity, even if it’s only an empty string. If Nyquist returns nothing or NIL, Audacity thinks its an error. If Nyquist returns an empty string, it thinks “ok, do nothing - leave this track unchanged”.

So if all tracks are selected, then the plugin loops over all tracks, and the code compares the track index to the value of the slider? I did not see thru the built in loop although you said so… Thanks a lot Steve, now I understand so much more. I will surely use this, but tomorrow I will have a session with the other band members and show them the plugin and hopefully make the lead guitarist happy. Gnight from Sweden

The band is really happy with the plugin, and now I have added the code to enable preview with all tracks. Magic! A few lines of code and the plugin is so much more usable. The only thing that does not work is the print command (but I do not see where the output should have come anyway).
Is there a way to retreive the index of one single selected track? If you have 30 tracks it would be nice to not have to scroll and count. For now I move the track to the top - index=1.
If I only select one track - is there a way to use (get track index) to set the index value to a slide bar control?

For the PRINT command to work, you have to un-comment it (remove the semicolon at the start of the line). If you run the effect using the Debug button instead of the OK button, a “Debug” window will open after the effect has completed. The Debug button will show any errors, debug messages, and the output from PRINT commands.

If you run a Nyquist effect with the OK button rather than the Debug button, any debug output (including PRINT commands) will be output to Audacity’s “log”: Help Menu: Diagnostics - Audacity Manual

Excellent :slight_smile:

You could easily create a separate plug-in to do that. You could even assign a keyboard shortcut to the plug-in (Shortcuts Preferences - Audacity Manual)

The code is just one line:

(format nil "~a" (get '*selection* 'tracks))

If there’s only one track, you could override the track id check. Example from the previous “amplify track” code:

(if (or (= track id)
        (= (length (get '*selection* 'tracks)) 1))
 (mult *track* gain)

Yes, that is good. If only one track is selected we must assume that this is the track to be processed regardless of any track index setting by the slide bar