;nyquist plug-in
;version 4
;type generate
;name "Arbitrary Waveform Generator..."
;action "Generating waveform..."
;author "Steve Daulton"
;copyright "Released under terms of the GNU General Public License version 2"
;; INSTRUCTIONS:
;;
;; Define the shape of one cycle of the waveform as a list of
;; numbers in the range +/- 1, separated by spaces.
;;
;; These numbers represent the sample value at evenly spaced
;; intervals between the start and end of the waveform.
;; Any number of numbers may be used.
;; The plug-in will interpolate (linear) from one defined point to
;; the next.
;;
;; Example - to create a triangle waveform, the list could be:
;; 0 1 0 -1 0
;;
;; Set "MIDI note number" to the desired pitch
;; Set the required duration in seconds
;;
;; TIP: The defined waveform should normally start an end at zero.
;control bpstring "List of waveform points" string "" "0 1 0 -1 0"
;control pitch "MIDI note number" float "" 60 0 127
;control duration "Duration (seconds)" float-text "" 30 0 3600
(defun list-from-string(string)
(let ((string (format nil "'(~a)" string)))
(eval (read (make-string-input-stream string)))))
(defun make-cycle (bplist)
(let ((interval (/ 1.0 (length bplist)))
(breakpoints ()))
(do ((i (- (length bplist) 1) (- i 1)))
((= i 0))
(if (not (numberp (nth i bplist)))
(throw 'err
(format nil "Error.\nList must be numbers separated by spaces.~%~
Decimal numbers must use a dot as the decimal separator.")))
(push (nth i bplist) breakpoints)
(push interval breakpoints))
(push (first bplist) breakpoints)
(pwlvr-list breakpoints)))
(defun generate(bplist)
(let* ((lookuptable (maketable (make-cycle bplist))))
(osc pitch duration lookuptable)))
(setf bplist (list-from-string bpstring))
(cond
((< (length bplist) 2)
"Error.\nAt least two points must be defined.")
((< duration (/ 1 *sound-srate*))
"Error.\nDuration is less than one sample.")
(t
(catch 'err (generate bplist))))