dUSt: Dynamic Universal Sweeper Toolkit

PLATFORM: Windows (Vista) only.
DEVELOPED: March 2012
CHANNELS: Mono or Stereo
LENGTH SUPPORT: 299 seconds
STATUS: Tested approx. 1 day

Allirhight, i’m back with a new plug-in as i take my nyquist plug-ins into the
unknown territories of multi-channels (in this case stereo) especially made
for you two dudes who still use Audi126.

I’ve been listening to a bunch of disco house music lately and wanted to
do something like Stardust’s awesome tune “Music Sounds Better With You”
where the music sounds all muddy but gradually goes back to “normal”

Now, I’m smart enough to know that’s some type of sweep effect, but not
enough to know what type (or even what a sweep is). Fortunately, I found
a site on the iNET that explained that most sweeps are nothing more than
bass cut filters that change frequency cutoff as time progresses. I imagine
most musicians accomplish this with a fancy knob or something, but that
out of my price range.

Well, I needed one of those, so, being somewhat handy at the language of
Nyquist and XLISP, I managed to get this one done.

Basically, it’s a ratio (aka linear) filter sweep with set time points you can
enter frequency cutoff values in. It’s got 4 sweep filters:

  1. Bass Cut (aka Hi-Pass)
  2. Treb Cut (aka Lo-Pass)
  3. Band Cut
  4. HiLo Cut (aka Band Pass)

I probably should include instructions, but oh well.
Here’s some hints:
01: filT: 1=Bass Cut, 2=Treb Cut, 3=Band Cut, 4=HiLo Cut
02: -1 means off
03: The “times” are all based on percentage of audio selected.
04. You HAVE to use 000% and 100%, all others are optional.
05. bw = bandwidth (only used with the Band Cut and HiLo Cut sweep filters)
06. chZ = channels you are inputing, if you mess this up, the plugin won’t work.
07. The frequencies are all in hectohertz, that’s hz * 100, so 200 hHz = 20,000 hz

Well, that’s about it. Hopefully someone can get some use out of it and you can
make some groovy tunes with it.
dUSt-v01.0.NY (34.6 KB)
Here’s the screenshot:
Oh yeah, things learned this plugin:

  1. MAKE-ARRAY for stereo does NOT work with SETQ (I spent half a day figuring that out).
  2. PRINC is good for debug code as it doesn’t print quotes (although it doesn’t line return either).
  3. Error manuals are the future…
  4. SND-PWL stinks.


Oh yeah, you might want to test this plug-in out on some generated white noise
in Audacity if you get a chance. It’s pretty interesting, especially if you view
the audio in “Spectrum” (available in the drop down menu of each track).

Here’s some neat graphs:
Band Cut Filter x3.jpg
HILO Cut.jpg
Oh yeah, here’s an audio example of a bass cut sweep done in dUSt that
ends in a HiLo Swept vocal (effect):::

As multi-channel sounds are arrays, a very easy way to test for an array is with “arrayp”

(arrayp expr) - is this an array?
;    expr - the expression to check
;    returns - t if the value is an array, nil otherwise

For example:

(setq CH (if (arrayp s) 2 1))

“SETQ” means “set the quoted value of a symbol” http://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/xlisp/xlisp-ref/xlisp-ref-239.htm
“SETF” means “set the value of a field” http://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/xlisp/xlisp-ref/xlisp-ref-238.htm

SETQ can be used with MAKE-ARRAY, but to set the values of elements in the array (array “fields”) you need to use SETF

(setq my-array (make-array 16))     ; make the array

(dotimes (i 16)                     ; set each element to its index
  (setf (aref my-array i) i))       ;   by the setf function

(format nil “string”) is better. http://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/xlisp/xlisp-ref/xlisp-ref-121.htm

(setq my-array (make-array 16))     ; make the array

(dotimes (i 16)                     ; set each element to its index
  (setf (aref my-array i) i))       ;   by the setf function

(format T "My Array: ~% ~a" my-array)
(format nil "Done.~%~% Array output to Debug window.")

SND-PWL stinks.

As I think I wrote previously, Mr. Dannenberg (creator of the Nyquist programming language) wrote in the Nyquist manual:
“Do not call this function. Use pwl instead (see Section “Piece-wise Approximations”).”

Audacity 1.2.6 is not recommended for Vista.

There are several bugs in Audacity 1.2.6 that are known to occur for many users of Windows Vista or Windows 7.
The recommended version of Audacity for these operating systems is currently Audacity 1.3.14 (soon to be replaced with Audacity 2.0)

Couple of Steve answers:

  1. This plug-in was made and tested on Vista. Always have used 126 on Vista.
    It should be noted that you can move the program’s folder to another folder
    and then uninstall it, and it will work (although it will use the registry). I’ve
    had no problems except for occasional crashes when recording, a necessary
    “evil” I put up with since I love the program.

  2. I used SETQ and VECTOR to make stereo tracks with this plugin. I tried
    using make-array with SETQ but it didn’t work. The MOST annoying thing
    was that, even though it wasn’t working, Nyquist would still return a stereo
    track of just a double copy of the left channel. Fortunately, I made a left
    channel white noise, right channel sine/curve wave and noticed it in time
    to fix the problem.

  3. I dunno why I put in that “name your input” ChZ switch. I guess it’s just part
    of the “personality” of the program.

  4. R.D. was right about that SND-PWL function, anything that uses sample units
    as time is lame (IMO). I used SND-PWL once in a plug-in because I was so happy
    that I finally figured out the “breakpoints” code, and I hardly think it was worth
    the extra code. Too bad, as I love many of the SND utilities available through
    Nyquist via XLISP. I just wish RD would axe all the other stuff and stick to making
    those SND modules, that would be so dope…

Oh yeah, here’s a longer version of the sample tune that I made using the plugin
and some loops from Equinox Sounds, “Darkside Drum N Bass” (a pack most worth
getting). I think it represents my “trip” through Nyquist pretty well (sorry the
bitrate is so low, but I had to compress it to 80 to upload it here):::

Like I said, uses dUSt and also the bouncing ball effect via David Sky (RIP).
His plugins are a real inspiration to me…

Well that’s about it for me, just got a job at a Marina here. Learning the maritime
“arts”, who knows where I’ll take my 126 plugins after this one…

My comment regarding Audacity 1.2.6 was really for the benefit of other readers.
Some users are able to use Audacity 1.2.6 on Vista with relatively few problems, but this combination is certainly not reliable enough to be recommended. One of the more common problems is Audacity 1.2.x crashing when a recording is stopped, which can be disastrous if someone was making an important, never to be repeated live recording. Possibly one of the most important benefits of current versions of Audacity for most users is that it is far more stable on modern computer systems.

You may have been running into a bug related to bug 425. It’s useful to know about these things so that you can work around them until the bug gets fixed. Here’s another example of it that can run in the Nyquist Prompt:

The following code is correct, but it does not produce the expected result in any version of Audacity:

(setq myarray (make-array 2))
(setf (aref myarray 0)(scale 0.5 (noise 1)))
(setf (aref myarray 1)(scale 0.5 (hzosc 2)))

What this should do is to create an array called “mayarray” and put white noise (amplitude 0.5) into the left track and a 2 Hz sine wave into the right track.
Because of the bug, it doesn’t do that - it creates a 2 Hz sine wave in both left and right channels.

A simple workaround for this problem is to apply a dummy function to the array, for example scaling by a factor of 1.0 (which should have no effect):

(setq myarray (make-array 2))
(setf (aref myarray 0)(scale 0.5 (noise 1)))
(setf (aref myarray 1)(scale 0.5 (hzosc 2)))
(scale 1  myarray)

Now the array contains the correct data.

I’d probably not use the word “lame” but I know what you mean :wink: and that’s why the functions pwl, pwl-list and the rest are there. All of these functions are derived from snd-pwl but have been transposed into more useful forms. If you look in the file nyquist.lsp you will find each of the piece-wise approximation functions defined.
For example, the function pwl-list that you used in dUSt is defined by:

(defun pwl-list (breakpoints)
  (let ((t0 (local-to-global 0)))
    (snd-pwl t0 *control-srate* (breakpoints-convert breakpoints t0))))

where the function breakponts-convert is defined by:

(defun breakpoints-convert (list t0)
  (prog (sample-count result sust (last-count 0))
    (setf sust (get-sustain))
    (setf sample-count 
      (truncate (+ 0.5 (* (- (local-to-global (* (car list) sust)) t0)
    ; now we have a new sample count to put into result list
    ; make sure result is non-decreasing
    (cond ((< sample-count last-count)
       (setf sample-count last-count)))
    (setf last-count sample-count)
    (push sample-count result)
    (cond ((cdr list)
       (setf list (cdr list))
       (push (float (car list)) result)))
    (setf list (cdr list))
    (cond (list
       (go loop)))
    (return (reverse result))))

This function is a bit tricky to read, but what it’s doing is taking 2 parameters - 1) a list of alternating times and values and 2) a start time.
So you may have something like:
(0.1 1 0.2 1) 0
where the times in the list are 0.1 and 0.2
the values in the list are 1 and 1
the start time is 0

The times in the list are then converted to numbers of samples at the current control rate and real (global) time according to the current environment.
This means that the number of samples will be calculated correctly, even with code like this:

(sustain 2.0 (mult (osc 60)(pwl 0.05 1 0.2 0.2 1 0)))

Sorry for the lateness in reply, my boat marina job didn’t work out and I’ve been
focusing on training to be a warehouse worker (just got my forklift certification
from Goodwill where I got to drive a forklift for 5 minutes…tons of fun!).

In regards to SND-PWL, yeah, that’s the code it took me (forever) to figure out.
It’s a lot easier once you do some experiments, but just looking at it made me
dizzy for some reason.

Also, in this plug-in I’ve been working on I’m using PWL-LIST to create a
“modulator-line” to use with “Mult” (SND-PROD) to do a fade-out or fade-in.

The trouble I was having is that using the “usual” 1.0 for the end time wasn’t
producing a line that equaled the length of the selected audio, it was much

What I found out was if I use 20 (instead of 1.0), then a line is produced that
equals the length of audio. So, in this case, 20 = 100%, which takes some math
to get the other numbers correct.

But, then again, in other application, I’ve found that 1.0 does do the intended

Pretty neat though. I’m currently studying some Reggae loop kits “Big Fish
Audio–Dread the Reggae Collection” in effort to become a Ragga dynamo.
I’m hopin de sounds will give sum inspiration to de new plugin mon…

Most probably you were doing something at the “control rate” rather than at the “sound rate”.
“Control” signals are generally produced at a much lower sample rate than sounds as it is a lot more efficient in terms of CPU, RAM and processing time.
The default control rate in Audacity is 2205 Hz (1/20th of 44.1 kHz which you probably have as the sound rate).

Is there anyway to change that control rate in Nyquist?
Not sure if it really matters, except maybe in waveform to be oscillated
creation (might sound better?).

(control-srate-abs srate beh) [LISP]
Evaluate beh with control-srate set to sample rate srate.

If you need to create a “control” signal (for example for modulating a wave) that is at a high (audio band) frequency then it would usually be better to create the signal at the sound rate rather than the control rate. The control rate is intended for relatively slowly changing control signals such as ASDR envelopes.

The general pattern for changing global XLISP variables temporally is using PROGV, for example:

(progv '(*control-srate*) '(*sound-srate*)
   ; the code inside PROGV uses *control-srate* = *sound-srate*
)  ; end of PROGV automatically restores the original *control-srate*

Using PROGV means that all control sounds inside the PROGV are computed with the value of sound-srate, while using FORCE-SRATE only the argument is computed at a different sample-rate:

(force-srate *sound-srate* <sound>)

Instead of sound-srate in both cases any positive number can be used to specify a sample-rate.

Known Bugs: Using a sample-rate of zero will delete the selected sound from the Audacity audio track, using a negative sample-rate will lead to an endless loop, that fortunately can be stopped via the “Abort” button in the Audacity “Applying Effect” window.

  • edgar

That’s not really a “bug” is it? If there are 0 samples per second, then there will be no sound.

The bug is that FORCE-SRATE does’nt check for zero or negative numbers. With Audacity_2.0.1 alpha on 64-bit Debian the following code in the Nyquist prompt deletes all selected samples from the Audacity audio track:

(force-srate 0 s)

Or maybe this is another 64-bit bug and the code wors on 32-bit systems? I still haven’t checked this.

No, the sample-rate is a frequency and with a frequency of zero one sample has 1/f = infinite period time, so the “correct” behaviour would be either to display a “division by zero” error or if not, then the first sample must produce a memory overflow crashing Nyquist as well as Audacity. There is no zero frequency without infinite time, and no negative frequency without negative time.

It would be of course make more sense to check for invalid values like zero and negative numbers.

  • edgar

We could argue all day about this :wink:
If we have 0 arguments per hour, how many arguments do we have in a day? How long will it be, from now, until we have an argument?
In real number mathematics division by zero is undefined.

I agree that, unless Roger has a Tardis hidden away, negative frequencies should be error trapped, and if we do that it would make sense to throw a “division by zero” error for zero frequency. :slight_smile:

An infinite amount of time, as I already said above. With 1Hz 1/f=1s, with 0.1Hz, 1/f=10s, with 0.01Hz 1/f=100s. The smaller the Hz number, the longer the time. This will go on like that until the reciprocal of zero frequency meets positive infinity.

I know, but audio processing is physics, not real number math.

and ultimately physics is a philosophical construct that aims to make sense of physical phenomena, in which infinity is a useful concept but without foundation in empirical fact. “At 5 O’clock” is a concept that we happily use everyday, but really an instantaneous moment in time is just as nonsensical as a division by zero.

That doesn’t quite work because sound-srate is not evaluated, thus it is likely to give an error: “bad argument type - SOUND-SRATE
Two alternative ways to make it work:

(progv '(*control-srate*) `(,*sound-srate*)   ; backquote bracket comma *sound-srate* close-bracket
  ; inner code


(progv '(*control-srate*) (list *sound-srate*)  ; *sound-srate* is evaluated
  ; inner code