If you get to a sufficient understanding where you can explain it clearly enough for anyone to understand, please explain it to me and I’ll put it in the Nyquist documentation.
I spent about a week staring at this type of thing to get an understanding of it, but I still can’t explain it clearly and I still sometimes get caught out - I think it’s a bit magic
There’s only really one “warp” occurring, but there are two different “contexts” (my word). There is “real” time (24 hours in a day) and there is “Audacity” time (selection = 1 second). “Audacity” time is the “logical” or “local” time. “Real” time is “global” time.
Here’s some text to read through a hundred times: http://www.cs.cmu.edu/~rbd/doc/nyquist/part4.html#index125
“pre-un-stretched” time has both “logical” and “real” values.
The “logical” time for the selected audio starts at t=0 and ends at t=1
The “real” time for the selected audio starts at the start of the selection and ends at the end of the selection BUT…
Nyquist does not know the “track” time. Audacity passes the audio data in the variable “S” but it does not pass start and end times, so Nyquist only gets the actual audio data. As far as Nyquist is concerned the “real” time at the start of the selection is t=0 and the end time is equal to the duration.
The length of the final sound is changed by moving the Y value.
“Creates a piece-wise linear envelope with breakpoints at (0, l1), (t2, l2), etc., ending with (tn, ln).”
This envelope is created at the “control rate” (2205 Hz by default in Audacity).
We can change (force) the sample rate of a PWL envelope like this:
(force-srate 44100 (pwlv 0.3 0.7 0.9 1 0))
or to force it to the sample rate of the audio track (the default Sound sample rate)
(force-srate *sound-srate* (pwlv 0.3 0.7 0.9 1 0))
Note that for PWLV the initial start time of 0.0 is implied, so the first number (0.3) is the value at time=0
Back to the Time Warp:
(pwlv 0 oldseconds warpednewseconds)
This creates a “Sound” (at the Control Rate) that rises from 0,0 to oldseconds,warpednewseconds
The final X = oldseconds
The final Y = warpednewseconds
The PWL envelope creates a mapping
The “X” values represent the “Real” time of our original signal
The “Y” values represent the times that we are mapping them to.
(warp fn beh) http://www.cs.cmu.edu/~rbd/doc/nyquist/part8.html#index570
“Evaluates beh with warp modified by fn. The idea is that beh and fn are written in the same time system, and fn warps that time system to local time.”
Strictly speaking we should not be applying “warp” to “S” because “S” is a “Sound” and not a “behaviour”, but in this case it does what we want because we want to work with the “real” start and stop time of both “S” and “fn”.
(get-duration 1) tells us the “real” time for the duration of the sound “S”.
(/ len sound-srate) is the number of samples divided by the sound sample rate, so that is also the “real” time for the duration of out input sound “S”.
(pwlv y0 (get-duration 1) y1) creates a control signal that has a duration equal to the duration of out input sound “S”. The initial level is y0 and the final level is y1
If we want to do something fancier and apply a variable stretch to the sound, then we need to do it properly and apply warp to a behaviour.
We can do that by using the function “SOUND” to apply warp to the sound “S”.
;; X values are the logical times of the input sound
;; Y values are the logical times of the stretched sound
(setq X0 0) ;start of input sound
(setq Y0 0) ;start of stretched sound
(setq X1 0.5) ;half way through input sound
(setq Y1 0.1)
(setq X2 1) ;end of input sound
(setq Y2 1)
;; convert logical times to real times
(setq X0 (get-duration X0))
(setq Y0 (get-duration Y0))
(setq X1 (get-duration X1))
(setq Y1 (get-duration Y1))
(setq X2 (get-duration X2))
(setq Y2 (get-duration Y2))
;; apply *warp* to sound
(setq beh (sound s))
(sound-warp (pwlv y0 x1 y1 x2 y2) beh)
Try applying this to a faded out tone or a click track so that you can see what happens.