(definstrument pqw (start dur spacing-freq carrier-freq amplitude ampfun indexfun partials &key (degree 0.0) (distance 1.0) (reverb-amount 0.005)) ;; phase-quadrature waveshaping used to create asymmetric (i.e. single side-band) spectra. ;; The basic idea here is a variant of sin x sin y - cos x cos y = cos (x + y) (let* ((normalized-partials (normalize-partials partials)) (spacing-cos (make-oscil spacing-freq (/ pi 2.0))) (spacing-sin (make-oscil spacing-freq)) (carrier-cos (make-oscil carrier-freq (/ pi 2.0))) (carrier-sin (make-oscil carrier-freq)) (sin-coeffs (partials->polynomial normalized-partials mus-chebyshev-second-kind)) (cos-coeffs (partials->polynomial normalized-partials mus-chebyshev-first-kind)) (amp-env (make-env ampfun :scaler amplitude :duration dur)) (ind-env (make-env indexfun :duration dur)) (loc (make-locsig :degree degree :distance distance :reverb reverb-amount)) (vib 0.0) (ax 0.0) (fax 0.0) (yfax 0.0) (r (/ carrier-freq spacing-freq)) (tr (make-triangle-wave :frequency 5 :amplitude (hz->radians (* .005 spacing-freq)))) (rn (make-rand-interp :frequency 12 :amplitude (hz->radians (* .005 spacing-freq)))) (beg (floor (* start *srate*))) (end (+ beg (floor (* dur *srate*))))) (run (loop for i from beg to end do (setf vib (+ (triangle-wave tr) (rand-interp rn))) (setf ax (* (min 1.0 (env ind-env)) (oscil spacing-cos vib))) (setf fax (polynomial cos-coeffs ax)) (setf yfax (* (oscil spacing-sin vib) (polynomial sin-coeffs ax))) (locsig loc i (* (env amp-env) (- (* (oscil carrier-sin (* vib r)) yfax) (* (oscil carrier-cos (* vib r)) fax)))))))) ; (pqw 0 .5 200 1000 .2 '(0 0 25 1 100 0) '(0 1 100 0) '(2 .1 3 .3 6 .5)) ; to see the asymmetric spectrum most clearly, set the index function above to '(0 1 100 1)