Nyquist Programming Question

Hello good people.

I’ve been pulling my hair out for a day or two with a Nyquist problem, so I thought I would appeal to all of you to see if you could help.

I’m developing a simple plug-in – it introduces a delay on one channel of the stereo input – and the strange thing is that it works fine from the Nyquist interpreter, but does nothing as an Audacity plug in. In other words, I have a function defined (phase-sound) and when I perform the following in Nyquist:

(play (phase-sound s delay))

it works fine, but when I do

(phase-sound s delay)

in Audacity the sound is unchanged.

i can’t help but think that the problem stems from a misunderstanding between behaviors and sounds, but for the life of my I can’t figure it out.

The above function, phase-sound, is defined as:

(defun phase-sound (s d-time)
    (setf s-rate 44100.0)
    (setf dtime (/ d-time s-rate))
    (if (< d-time 0) (
        vector
            (cue (aref s 0))
            (at dtime (cue (aref s 1)))
        )
        (vector
            (at (- 0.0 dtime) (cue (aref s 0)))
            (cue (aref s 1))
        )
    )
)

(what the above does is create a stereo vector, with one channel delayed for negative inputs, the other delayed for positive inputs).

As I said, this works fine in the Nyquist interpreter, but returns unaltered audio when in Audacity.

Any insight or guidance would be appreciated!

Thanks.

With Nyquist in Audacity try the following:

(sum (s-rest (get-duration 1))
     (phase-sound s d-time))

It’s not enough to delay the s variable (shifting the sound to the right), because Nyquist recognises an “empty hole” of silence a the beginning of the sound and then automatically shifts the start-time t0 to the beginning of the delayed sound with the result that the sound is inserted at the original place.

If you want to produce a delay with Nyquist in Audacity, you must tell Nyquist that the silence at the beginning of the sound is intentional by producing a piece of silence with the length of the Audacity selection and the “sum” (add) the delayed sound to the silence.

For example this doesn’t produce a delay of 100ms with Nyquist in Audacity:

(at 0.1 (cue s))

because the start-time is also shifted by 0.1 seconds and the sound then is inserted at the original place, so the effect is “no delay”. Only if you “sum” it to a piece of “silence” it works:

(sum (s-rest (get-duration 1))
     (at 0.1 (cue s)))

This produces a delay of 100ms.

Also a couple of other issues:

You cannot create a sound with a negative start time as Nyquist is unaware of anything prior to time = 0 (the beginning of the selection).

The amount of time shift will be relative to the length of the selection, so for example in Edgar’s example:

(sum (s-rest (get-duration 1))
     (at 0.1 (cue s)))

This will create a delay of 0.1 relative to the length of the selection. So for a selection length of 1 second, the delay will be 0.1 seconds, but for a selection length of 5 seconds the delay will be 0.5 seconds. To create a delay of “absolute” length 0.1 seconds you can wrap the function in (abs-env).
Example:

(abs-env
   (sim (s-rest 1)
      (at 0.1 (cue s))))

Hint:
You don’t need to specify (setf s-rate 44100.0) as the sample rate of the selection can be accessed from the global variable sound-srate

Thank you. This makes sense and I’ll try it.

One question: The code snippet:

(sum (s-rest (get-duration 1))
     (phase-sound s d-time))

Appends the rest to sound s (which is an array). I assume that because I at working to delay only one channel that I would apply it to only one channel (say, via (aref s 0)) and then reconstruct the sound with one channel delayed, one non-delayed (with (vector), for example).

Thanks. I thought that could be the case (and it’s why I put the logic in the code to delay on channel for positive values of delay, and the other channel positively for negative values).

Hint:
You don’t need to specify (setf s-rate 44100.0) as the sample rate of the selection can be accessed from the global variable sound-srate

:slight_smile:

The code as posted is pretty rough. I just wanted to get something working before I cleaned it up.

Thanks for your help.

Or I should say I tried. Looking at the code I may have done the opposite!

Yes. For example:

(setq dtime 0.1)

(abs-env
  (vector
    (aref s 0)
      (sim (at 0 (cue (s-rest (get-duration 1))))
             (at dtime (cue (aref s 1))))))

Cool. It works. Thanks for your help.

Final code is this:

(defun phase-sound (s d-time)
    (setf dtime (/ d-time *sound-srate*))
    (if (> d-time 0) (
        vector
            (sum (s-rest (get-duration dtime))(at dtime (cue (aref s 0))))
            (cue (aref s 1))
        )
        (vector
            (cue (aref s 0))
            (sum (s-rest (get-duration (- 0 dtime)))(at (- 0 dtime)(cue (aref s 1))))
        )
    )
)

(I’m not sure what the abs-env in your code snippet does, but the plug-in seems to work without it.)

Thanks for all of your help!

As in my previous post:

It may be worth noting that (sim) and (sum) are the same, but they do not put one sound after the other.
(sim sound1 sound2) will mix sound1 and sound2 so they play the same time.

(sim (at t1 (cue sound1))(at t2 (cue sound2))) will mix sound1 and sound2 but with sound1 starting at t1 and sound2 starting at t2.
The slightly tricky bit with this is that the mix will be shifted so that the earliest sound will actually be at time=0
but this means that the length of (s-rest) in your code is unimportant as long as it is no more than the total length of the sound.
The length of the selection in seconds can be found using (get-duration 1)

Tip: If ever you need the length of the selection in samples, you can get that from the global variable LEN

OK, thanks. I think I understand now.

I’ve only been playing with Nyquist for a few days. The relationship between the sounds and their environment seems pretty complicated, and the interaction of that with the Audacity environment (and way that it does things) makes it even more complicated.

Thanks again.