So far we’ve got how to generate tones and how to amplify them.
What would be useful would be if we could “shape” them so that they are not just a constant volume.
To do this we need to “multiply” them by something that varies - a number does not vary, it is a “constant”.
Nyquist provides a feature called “control signals”.
A Control signal is much like a sound (a waveform) but to improve efficiency they use a low sample rate, typically 1/20th of the track sample rate.
When a control signal is multiplied by a sound, the higher sample rate of the two is used for the output.
To create control signals we can use “piece-wise approximations” Nyquist Functions
The version that we will use is pwlv Nyquist Functions
Let’s say that we want to create an envelope that rises from 0.2 up to 0.8 at half way and back down to 0 again at the end.
Much like the Audacity Envelope tool we create a number of “control points” which are pairs of “time and level” values.
The correct order of values for pwlv is:
time1, level1, time2, level2, time3, level3…
The first time value is assumed to be zero so that value is not entered.
So our function for the “envelope” is:
(pwlv 0.2 0.5 0.8 1 0)
If you run that command on its own it will produce a very short waveform because of the low sample rate being “squashed” when it gets back to the Audacity track, so let’s try multiplying it by a sound:
(mult (osc 72)
(pwlv 0.2 0.5 0.8 1 0))
Or if we want an exact time duration we can use something like:
;; note that we use absolute time values for both the
;; sound and the control signal
(abs-env
(mult (pwlv 0.2 1.5 0.8 3 0)
(osc (hz-to-step 440) 3)))
So finally we get round to something useful - a little “beep” for our plug-in.
(setq dur 0.1)
(setq hz 1000)
(abs-env
(mult (pwlv 0 (* dur 0.1) 0.8 (* dur 0.9) 0.8 dur 0)
(osc (hz-to-step hz) dur)))
I have used a “variable” called “dur” to hold the required duration - in this case 0.1 seconds,
and the variable “hz” to hold the frequency - in this case 1000 Hz.
To make the code easier to use in our bigger plug-in, I’ll wrap the whole thing in a “function”. XLISP function
We will create our own custom function called “beep” and it will take 2 “arguments” (parameter values) which will be the frequency and the duration.
;;; make a beep
(defun beep (hz dur)
(abs-env
(mult (pwlv 0 (* dur 0.1) 0.8 (* dur 0.9) 0.8 dur 0)
(osc (hz-to-step hz) dur))))
On its own this function does nothing. To make it do something we have to call the function (use it):
;;; make a beep
(defun beep (hz dur)
(abs-env
(mult (pwlv 0 (* dur 0.1) 0.8 (* dur 0.9) 0.8 dur 0)
(osc (hz-to-step hz) dur))))
; use the function 'beep' with a frequency of 440 Hz and a duration of 0.5 seconds
(beep 440 0.5)
to be continued…