[CM] re: sndlib in guile error

Bill Schottstaedt bil@ccrma.Stanford.EDU
Mon, 30 Aug 2004 03:40:42 -0700

 > (dynamic-call "mus_xen_init" lib)
 > (define osc (make-oscil 440))
 > (oscil osc)
 > but I get no sound. Could anyone help me?

(oscil osc) just gets the next sample from the oscillator -- you need
to call it repeatedly, writing the output to the DAC.  The hard part
is opening the DAC.  I added a complete example to sndlib.html,
taken with some changes from Snd's play.scm:

(use-modules (ice-9 format) (ice-9 optargs))

(define lib (dynamic-link "/home/bil/test/sndlib/sndlib.so"))
(dynamic-call "mus_sndlib_xen_initialize" lib)
(dynamic-call "mus_xen_init" lib)

(define* (open-play-output #:optional out-chans out-srate out-format out-bufsize)
   ;; returns (list audio-fd chans frames)
   (let* ((outchans (or out-chans 1))
	 (cur-srate (or out-srate (and (not (null? (sounds))) (srate)) 22050))
	 (pframes (or out-bufsize 256))
	 (frm (or out-format mus-lshort))
	 (outbytes (* pframes 2))     ; 2 here since we'll first try to send short (16-bit) data to the DAC
	 (audio-fd ;; ALSA throws an error where the rest of the audio cases simply report failure
	           ;;   so we turn off the "error" printout, catch the error itself, and toss it
	  (let ((val (catch #t
			    (lambda ()
			      (mus-audio-open-output mus-audio-default cur-srate outchans frm outbytes))
			    (lambda args -1)))) ; -1 returned in case of error
     (if (= audio-fd -1)
	;; ask card what it wants -- ALSA with some cards, for example, insists on 10 (virtual) channels and mus-lintn data!
	(let ((vals (make-vector 32)))
	  (mus-audio-mixer-read mus-audio-default mus-audio-format 32 vals)
	  (let ((fmt (inexact->exact (vector-ref vals 1))))
	    (mus-audio-mixer-read mus-audio-default mus-audio-channel 32 vals)
	    (set! outchans (inexact->exact (vector-ref vals 0)))
	    (let ((err (mus-audio-mixer-read mus-audio-default mus-audio-samples-per-channel 2 vals)))
	      (if (not (= err -1))
		  (set! pframes (inexact->exact (vector-ref vals 0))))
	      (let* ((bps (mus-bytes-per-sample fmt)))
		(set! outbytes (* bps pframes outchans))
		(set! audio-fd (catch #t
				      (lambda ()
					(mus-audio-open-output mus-audio-default cur-srate outchans fmt outbytes))
				      (lambda args -1))))))))
     (list audio-fd outchans pframes)))

(define* (play-sine freq amp)
   "(play-sine freq amp) plays a 1 second sinewave at freq and amp"
   (let* ((audio-info (open-play-output 1 22050 #f 256))
	 (audio-fd (car audio-info))
	 (outchans (cadr audio-info))
	 (pframes (caddr audio-info)))
     (if (not (= audio-fd -1))
	(let ((len 22050)
	      (osc (make-oscil freq))
	      (data (make-sound-data outchans pframes)))
	  (do ((beg 0 (+ beg pframes)))
	      ((> beg len))
	    (do ((i 0 (1+ i)))
		((= i pframes))
	      (sound-data-set! data 0 i (* amp (oscil osc)))) ; here is our oscillator
	    (mus-audio-write audio-fd data pframes))
	  (mus-audio-close audio-fd))