[CM] memory fault within run macro

Bill Schottstaedt bil at ccrma.Stanford.EDU
Fri, 23 Nov 2007 05:02:10 -0800

In the CL version of CLM, each variable used in the run loop has
to have one type, and arrays are considered to be made up of
all elements of one type; each generator is considered a different
type, so run can't handle an array with a symbol, an oscil, and
a rand-interp -- run should have generated some sort of warning.
This limitation can be got around in Scheme by using def-clm-struct,
but not in CL (it's a very long story).  So, you can do this in CL
in the following, somewhat ugly way:

(defun make-nseband (&key (frequency 440.0) (bw .1))
  (values (make-oscil frequency)
	  (make-rand-interp frequency bw)))

(defmacro nseband (osc rnd &optional (fm 0))
  `(* (oscil ,osc ,fm)
      (rand-interp ,rnd)))

(definstrument test (&key (dur 1) (frq 440) (bw .10) (amp 1))
  (let* ((s1 (seconds->samples dur)))
     (osc rnd) 
     (make-nseband :frequency frq :bw bw)
      (loop for i from 0 to s1 do
	(outa i (* amp (nseband osc rnd))))))))

In Scheme (and ideally in CL), you could use def-clm-struct:

(def-clm-struct (nseband 
		 (lambda (g)
		   (set! (nseband-osc g) (make-oscil (nseband-frequency g)))
		   (set! (nseband-rnd g) (make-rand-interp (nseband-frequency g) (nseband-bw g)))
  (frequency 440.0) (bw 0.0)
  (osc #f :type clm) (rnd #f :type clm))

(define (nseband gen fm)
  (* (rand-interp (nseband-rnd gen))
     (oscil (nseband-osc gen) fm)))

(definstrument (test :key (dur 1) (frq 440) (bw .10) (amp 1))
  (let* ((s1 (seconds->samples dur))
	 (obj (make-nseband :frequency frq :bw bw)))
     (lambda ()
       (do ((i 0 (1+ i)))
	   ((= i s1))
	 (outa i (* amp (nseband obj 0.0)) *output*))))))

By the way, I think you're using "bw" as the rand-interp amplitude, but then
using the output of rand-inerp as ampitude modulation, so your
output will be between -bw and bw -- if you use 10, turn down
your amplifier!