Combining and sub-scripts in .NY files

I have been posting and replying to title “Noise gate vs insert room sound” in the “Audiobook Production” forum with mixed results. Although the purpose for my posts involves audiobooks my questions may be more about programming. Please allow me to quote some of my posts from that forum to supply a history of my idea keeping in mind that the audio signal is a single mono voice recording with areas of speech punctuated by “near” silent sections. Very near an on/off type of signal.

"I recently watched a YouTube video describing how to copy a segment of quiet room sound and use the Punch Copy/Paste plugins to replace segments of not-so-quiet room sound or other extraneous noise. This process was touted as sounding more natural than a noise gate that can easily replace such segments with silence. It occurred to me that a sort of combination of the two would be ideal. I can imagine a plugin that would replace the low decibel segments (mouth noise, chair squeaks, page turns) between sentences or words with a pre-selected segment of quiet room sound, possibly with the looping function of Punch Copy/Paste. Does anyone know of any work done in this area? "

“However, I am suggesting, as mentioned in my first post, a way to find and replace anomalous noises such a page turns, chair squeaks, etc. with a clean piece of room sound. To that end I am thinking of some adaptation of the Silence Finder or Sound Finder plugins combined with the Punch Copy/Paste plugin to find and replace sections between phrases with a pre-selected segment of audio, probably clean room sound.”

Currently I am looking into the “Silence Finder” plugin written by Jeremy R. Brown to be the “search” part of the function I envision. The issue here is that the “Silence Finder” plugin only labels (finds) the end of a silence, whereas the “Sound Finder” plugin labels the beginning AND end of a found sound. This might be the first part of this project; to modify “Silence Finder”, possibly using ideas from “Sound Finder”, to calculate the beginning and end of a found silence.

Next, I could envision using that found silence information within the plugin to “select” that range of samples and issue a call (sub-script?) to the “Punch Paste” part of the “Punch Copy/Paste” system to replace it with a previously copied section of clean room sound.

Crazy, right? Does anybody have any ideas on how this might be accomplished? Thanks

As I wrote in the other forum thread, I don’t think that will work. I’ll explain why:

Silence / Sound finder plug-ins work by detecting where the audio level is above a specified threshold. If the audio is above the threshold, then it is considered to be “sound”. If the audio is below the threshold then it is considered to be “silence”.

The threshold level needs to be set low enough so that it does not label the ends of words, or quiet parts of words (such as “f” sounds) as silence.
If a page turn or chair squeak or any other “noise” is above the threshold, then Sound Finder / Silence Finder considers it to be “sound”. The threshold must be set higher than the noises that you want marked as “silence”.

Punch Copy/Paste is a useful tool for covering up “noises”, such as chair squeaks and page turns. The problem is, that if the noises are loud enough to be disturbing to listen to, then they are probably going to be too loud for Sound / Silence Finder to mark as “silence” - they will be marked as “sounds”, so your proposed effect will skip over those noises when what you actually want is to cover up those noises.

I’ve posted a plug-in that can mark silences with region labels: Noise gate vs insert room sound - #14 by steve
Feel free to use and/or modify it as you wish.

Regarding the “Subject” of this forum thread, it is not currently possible to launch a Nyquist plug-in from another Nyquist plug-in.

You can call a sequence of Nyquist plug-ins from a Macro (https://manual.audacityteam.org/man/macros.html)

You can also combine Nyquist effects by writing them into one plug-in. For example, if you have one very simple plug-in that amplifies the selected audio by 6dB:

(scale (db-to-linear 6.0) *track*)

and another simple plug-in that applies a 1000 Hz high pass filter:

(highpass2 *track* 1000)

then you could create a new plug-in that combines the code from the first two:

(setf temp (scale (db-to-linear 6.0) *track*))
(highpass2 temp 1000)

Thanks again Steve, for this reply and the plugin from the other folder. So calls to external plugins are out. That’s clear enough. This is going to be a process so I will post a few more questions today.

  1. I have downloaded and installed “setupnyqiderun315.exe” that has a “manual” built-in but it does not define language such as “defun” or “setf” that I see as part of some plugins I have examined. How does one begin programming such as this, or at least find a current list of functions/actions?

  2. Putting aside the idea of WHAT is being found and/or marked/labeled, how would you suppose a plugin could be written that would act upon a found/marked/labeled segment? Would it act upon it immediately as part of a looping process and move on to the next, or might it act upon a group of previously defined labels, perhaps as a separate plugin?

The Nyquist manual is here: http://www.cs.cmu.edu/~rbd/doc/nyquist/indx.html
Note that this is the manual for the stand alone version of Nyquist. There’s a few differences between that and Audacity’s version, but it is mostly the same.

Nyquist is based on the LISP programming language. Specifically the variety called XLisp. The XLisp manual is very useful for everything except audio functions that are specific to Nyquist. https://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/xlisp/xlisp-index.htm

Information about writing Nyquist plug-ins: https://wiki.audacityteam.org/wiki/Nyquist_Plug-ins_Reference

and also: https://manual.audacityteam.org/man/nyquist.html

It would be quite tricky if you are wanting to work on long tracks, because Nyquist runs entirely in RAM.

One approach could be to first create a track that is the same length as the track that you want to process, that is entirely “room tone”.
Then create 3 Nyquist plug-ins.

  1. The first plug-in detects the places that the room tone will be used. It writes a list of times to scratch (Missing features - Audacity Support)
  2. The second plug-in reads the list from scratch, and creates a rectangle wave with zero amplitude at the times that need to be overwritten, and an amplitude of 1 (0 dB) at all other times. This rectangle wave would then be multiplied by the first track (the original audio track) so as to mute the parts that are to be overwritten.
  3. The third plug-in does a similar thing to the second, except that it will be used to mute parts of the “room tone” track.

I would then create a Macro that:

  1. Applies the first plug-in to the first track
  2. Applies the second plug-in to the first track
  3. Applies the third plug-in to the second track
  4. Mixes the the two tracks.

You can actually use code from other plug-ins through the load command.
You have to declare variables manually that are normally assigned through the “;control” statements or duplicate all/some of them in your code.
Example:

(load "H:\\audacity\\win\\Release\\Plug-ins\\highpass.ny" :verbose t)

In the debug window it should display something like this (if you have the right path):

; loading "H:\audacity\win\Release\Plug-ins\highpass.ny"

However, you want probably use it with shipped plug-ins but unfortunately, the introduction of translated plug-ins breaks the load command:

error: unbound variable - $NYQUIST
if continued: try evaluating symbol again
Function: #<Subr-LOAD: #15020908>

Perhaps we should modify some of the shipped plug-ins: “effect.ny” being the GUI and “effect.lsp” being the effect’s processing functions, thus making the processing functions available to users.