Reversing sounds with Nyquist

The Nyquist function S-REVERSE is not defined in Audacity’s version of Nyquist, so if it is necessary to reverse a sound in a Nyquist plug-in, then a suitable function must be written.

For short sounds, this can be done quite simply, by reading the the sound into an array, reversing the array, and then converting the array to a list.
Here’s a fairly efficient way to do this:

(setf ln (truncate len))
(setf half (1- (truncate (/ ln 2.0))))
(setf ar (snd-fetch-array *track* ln ln))
(setf ln (1- ln))

(dotimes (i half (snd-from-array 0 *sound-srate* ar))
  (setf temp (aref ar i))
  (setf alt (- ln i))
  (setf (aref ar i)(aref ar alt))
  (setf (aref ar alt) temp))

The main limitation of the above code is that it will fail if the sound is too long. The maximum length is about a million samples.
An interesting point to note is that although SND-FETCH-ARRAY modifies sound, it is not necessary to use SND-COPY because the original sound is not required once we have the sample values.

For handling longer sounds, we can use SND-FETCH-ARRAY to iterate over the track, grabbing less than a million samples at a time, reverse them, and temporarily push them onto a list. SEQREP may then be used to grab the sounds from the list and combine them into a single sound:

(defun reverse-buf (buf ln)
  (let ((output (make-array ln)))
    (do* ((i 0 (1+ i))
          (j (- ln i 1) (1- j)))
         ((< j 0) (snd-from-array 0 *sound-srate* output))
      (setf (aref output i)(aref buf j)))))

(defun snd-reverse (sig ln lnfinal bufcount &aux (rslt ()))
  (dotimes (i bufcount)
    (setf buffer (snd-fetch-array sig ln ln))
    (push (reverse-buf buffer ln) rslt))
  (when (> lnfinal 0)
    (setf buffer (snd-fetch-array sig lnfinal lnfinal))
    (push (reverse-buf buffer lnfinal) rslt))
  (seqrep (i (length rslt))(cue (nth i rslt))))

(setf lnmax 100000) ;Experimental value for best processing time.
(setf ln (truncate (min lnmax len)))
(setf lnfinal (rem (truncate len) ln))
(setf bufcount (/ (truncate len) ln))

(multichan-expand #'snd-reverse *track* ln lnfinal bufcount)

The above code is unsurprisingly a lot slower that Audacity’s built-in Reverse effect, but is not horribly slow. On my budget i7 laptop, a 1 hour stereo track takes a little under 3 minutes to process (considerably quicker than Sliding Stretch.)

One small peculiarity when processing stereo tracks is the the progress bar appears to freeze half way through processing. This is harmless, though a little annoying. This problem also occurs with other effects that do not return the processed sound immediately.

I’ve not tested on Windows or Mac, but there may be a limit to the length of audio that can be processed, as this script requires a lot RAM to hold the reversed sound while the list is being built. Audacity on Windows and Mac is currently a 32-bit application (2GB maximum RAM available for Nyquist).