Rectivert - Rectification and Inversion

Rectivert by Adam-V
Full or half wave rectification and inversion of an audio track with independent control over the left and right channels where the track is stereo.

Controls
There are duplicate controls for the left and right channels. For mono tracks, only the settings for the left channel will be used.

Rectification Type:
Determines the type of rectification to be performed.

    • Half
      Half wave rectification will be performed with only the top half of the waveform being kept. The bottom half of the waveform is discarded.
    • Half
      Half wave rectification will be performed with only the bottom half of the waveform being kept. The top half of the waveform is discarded.
  • Full
    Full wave rectification will be performed. The bottom half of the waveform is reflected around 0 and will appear in the upper half along with the original top half of the waveform.
  • None
    No rectification will be performed.

Invert:
Determines whether the waveform will be inverted. The bottom half becomes the top half and vice-versa. This is applied after any rectification is performed.

Download
V1.1 No functional changes, just reformatting to common lisp standard
Rectivert.ny (1.5 KB)
V1.0
Rectivert.ny (1.42 KB)

A nice neat little tool :slight_smile:

Some feedback that I hope you will find useful:

The multiple choice widget was introduced in “version 3” plug-ins, so it should be ;version 3 rather than ;version 1.

The ;info line contains:

Performs seperate half/full wave rectification and/or phase inversion on each channel of the given signal. If the signal is mono, the left channel setting will be applied.

which makes the plug-in extremely wide, so it would be better to split that line with a few more “n”.

Regarding formatting the code:
It is generally preferred to use spaces rather than tabs at the beginning of lines. Indenting lines by 2 spaces works well and prevents the code from being too spread out if someone views the code in an editor with large tab settings. Also the usual LISP convention is to not put closing brackets on separate lines.
As an example, your function:

;; with tabs
(defun rectify (sig rt)
	(cond
		((= 1 rt) (s-max sig 0.0))	;; + Half
		((= 2 rt) (s-min sig 0.0))	;; - Half
		((= 3 rt) (s-abs sig))		;; Full
		(sig)						;; None
	)
)



;; with spaces
(defun rectify (sig rt)
  (cond
    ((= 1 rt) (s-max sig 0.0))  ; + Half
    ((= 2 rt) (s-min sig 0.0))  ; - Half
    ((= 3 rt) (s-abs sig))      ; Full
    (sig)))                     ; None

A somewhat trivial point in this case, but perhaps mentioning for future reference - If the user chose the default settings (do nothing) and applied to a long track, the processing time will still be quite long because you are returning “S” to the track, thus forcing the waveform to be redrawn. It would perhaps be better to simply return a “Nothing to do” message in this case. More generally it’s preferable to not call processes that do nothing.

Have you come across (case expr [(value action) … ]) ?
The “rectify” function would be an ideal place to use “case” rather than “cond”:

(defun rectify (sig rt)
  (case rt
    (1 (s-max sig 0.0))  ; + Half
    (2 (s-min sig 0.0))  ; - Half
    (3 (s-abs sig))      ; Full
    (T (sig))))          ; None

One last thought, it might be nice to include an option for “Inverting then Rectifying” (which is not the same as “Rectifying then Inverting”).


Here’s a couple of little code snippets that you may find interesting:

Diode clipping (hard clipping of positive peaks)

(s-min s 0.5)

Crossover distortion:

(sim
  (sum -0.05 (s-max s 0.05))
  (sum 0.05 (s-min s -0.05)))

Massively over simplified tube distortion:

(setq drive 0.2)
(hp 
  (sim 
    (mult (- 1 drive )(s-min s 0))
    (mult (+ 1 drive)(s-max s 0)))
  10)

Attached, just as an example, is an adaptation of your plug-in which includes the suggestions from my previous post. This is not necessarily “the best way” to code it, it’s just how I would code it :wink:
(For very good examples of Nyquist coding, look at some of the code from Edgar-rft and Roger Dannenberg)
Rectivert2.ny (1.64 KB)

Great feedback Steve, Thank you.

I’ll update all my plug-ins to reflect the correct formatting.

I do have to disagree with you about inverting prior to rectifying though. For Full wave rectification it doesn’t matter as both positive and negative halves of the waveform end up on the same side regardless. For half wave rectification, inverting then applying -ve half wave rectification is the same as +ve half wave rectification then inverting. The reverse is also true.

Cheers,
Adam-V

I’m so relieved.
I get excited when I find someone else that takes an interest in Nyquist programming and I know that I can go over the top with my responses, but it’s really just my enthusiasm :stuck_out_tongue:

There’s a really good article about LISP formatting that Edgar-rft posted a link to - I’ll see if I can find it.

Good stuff :slight_smile: Let’s see if we can get to the answer.

Suppose the waveform is a ramp from 0 to +1 :

  1. Full wave rectify it and it is still a ramp from 0 to +1
    Invert it and it is a ramp from 0 to -1.

  2. Invert a ramp from 0 to +1 and it is a ramp from 0 to -1
    Full wave rectify it and it is a ramp from 0 to +1.

Edgar’s link was [u]Indenting Common Lisp[/u], part of [u]Symbolic programming using Common Lisp[/u] by Robert Strandh

A pretty much complete list of all free online Lisp books can be found in the [u]CLiki[/u] (Common Lisp Wiki) under [u]Lisp books[/u]

I see what you are saying however I think this is merely a perception issue.

Ignoring the post rectification inversion function for the moment it is true to say the following:

Waveform A is a ramp from 0 to 1
Waveform B is an inversion of waveform A and is therefore 0 to -1

Full wave rectification of A yields a ramp from 0 to 1
Full wave rectification of B yields a ramp from 0 to 1.

Now, taking the post-inversion into consideration, when applied to both the results are still the same but are now 0 to -1.

In your example you are really only comparing the result of an inversion because the full wave rectifications effectively cancel each other out as they result in the same all positive waveform which is then only inverted in the first example.

Cheers,
Adam-V

Thank you for the links Edgar. Indentation of LISP may take a bit of getting used to given I’m a daily user of c#!

I’m currently reading “COMMON LISP: A Gentle Introduction to Symbolic Computation” by David S. Touretzky.

Cheers,
Adam-V

If you’re new to Lisp then write your code as you can read it best. The rest will come automatically.

I have learned XLISP programming from the book [u]Common Lisp: A Gentle Introduction to Symbolic Computation[/u] by David Touretzky (edit: just noticed you already read it…)

XLISP is only a subset of Common Lisp (because XLISP is older than Common Lisp), but there are no explicit XLISP books (and AFAIK there never were any), that’s why I started the [u]XLISP 2.0[/u] documents collection together with David Sky (R.I.P) and Steven Jones in 2005.

Beware: The Nyquist manual in the German Audacity Forum (linked from the XLISP docs) is out of date, use the CMU [u]Nyquist Manual[/u] instead.

Another note - if you Google the internet: [u]XLISP 3.0[/u] (the current XLISP version) is a completely different language than XLISP 2.0 (used by Nyquist), and also XLISP-STAT is a different language. The X in XLISP stands for eXperimental Lisp, and that’s what XLISP is most about. There are many experimental derivates, and even the original XLISP versions 1.x, 2.x, and 3.x by David Betz are incompatible to each other.

Added an updated version containing formatting changes only.

Cheers,
Adam-V

When attempting to use Rectivert in a batch-chained command (in Audacity 2.0.5 on Windows 7) I get a message “Your batch command of Adam-V was not recognized”. It looks as if it does not like the colon in the name as the Rectivert part of the name appears in the parameters field?

That’s correct.
When a Chain is created, the names and parameters of each command are stored in a text file. The colon character “:” is used as the delimiter between the command name and the parameter list. Thus, when the chain text is parsed, the first part of the name (before the colon) is read as the name, and everything after the colon is read as being the parameter list.

The easiest solution is to modify the effect name.
Open the Rectivert.ny file in a plain text editor (such as NotePad or NotePad++) and change line 4 so there is no “:” in the name:

;name "Adam-V:Rectivert..."

Thanks, I later saw that the Nyquist file was simple text and had made the change you suggested. It seems strange to use a name that conflicts with the chaining convention though.

I agree that it would be better for plug-in authors to avoid this conflict so I’ve added a note in the manual warning about the problem.

Note that plug-ins on this forum are “unofficial” contributions from Audacity users. If I recall correctly this was Adam’s first ever plug-in, and may have been written before Nyquist plug-ins were supported in Chains.