mirror of
				https://github.com/cookiengineer/audacity
				synced 2025-11-04 16:14:00 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			197 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Common Lisp
		
	
	
	
	
	
			
		
		
	
	
			197 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Common Lisp
		
	
	
	
	
	
;; sliders.lsp -- communicate with NyquistIDE to implement control panels
 | 
						|
;; Roger B. Dannenberg
 | 
						|
;; April 2015
 | 
						|
 | 
						|
;;    (stop-on-zero s) -- a sound that returns 1 until s goes to zero, then
 | 
						|
;;            the sound terminates. If s comes from a slider and you multiply
 | 
						|
;;            a sound by (stop-on-zero s), you can interactively stop it
 | 
						|
;;    (make-slider-panel "name" color) -- sets panel name for the following
 | 
						|
;;            sliders
 | 
						|
;;    (make-slider "param" [initial [low high]]) -- create slider named 
 | 
						|
;;            "param" with optional range and initial value. Also returns
 | 
						|
;;            a sound.
 | 
						|
;;    (make-button "param" normal) -- create a button named "param" with
 | 
						|
;;            a starting value of normal (either 0 or 1). While the button
 | 
						|
;;            in the panel is pressed, the value changes to 1 or 0.
 | 
						|
;;    (get-slider-value "param") -- when called with a string, this looks up
 | 
						|
;;            the slider value by name
 | 
						|
;;    (slider-panel-close "name") -- close the panel window. Values of any 
 | 
						|
;;            existing sliders become undefined.
 | 
						|
;;    (slider "panel" "name" [dur]) -- make a signal from slider value
 | 
						|
;;    (slider "name" [dur]) -- make a signal from slider in current panel
 | 
						|
;;    (get-slider-value "panel" "name") -- get a float value
 | 
						|
;;    (get-slider-value "name") -- get a float in current panel
 | 
						|
 | 
						|
;; *active-slider-panel* is the current panel to which sliders are added
 | 
						|
;;
 | 
						|
(if (not (boundp '*active-slider-panel*))
 | 
						|
    (setf *active-slider-panel* nil))
 | 
						|
 | 
						|
;; *panels-in-use* is an assoc list of panels, where each panel
 | 
						|
;;   is a list of allocated sliders stored as (name number)
 | 
						|
;;
 | 
						|
(if (not (boundp '*panels-in-use*))
 | 
						|
    (setf *panels-in-use* nil))
 | 
						|
 | 
						|
;; allocate-slider-num -- find an unused slider number
 | 
						|
;;   linear search is used to avoid maintaining a parallel structure
 | 
						|
;;   for faster searching. We search starting at slider #10, leaving
 | 
						|
;;   sliders 0-9 unused; for example, you might want to control them
 | 
						|
;;   via open sound control, so this gives you 10 sliders that are
 | 
						|
;;   off limits to allocation by the SLIDER function.
 | 
						|
;;   
 | 
						|
;;   This code takes advantage of the fact that dotimes and dolist
 | 
						|
;;   return nil when they end normally, so we signal that we found
 | 
						|
;;   or did not find i by explictly returning. Note that RETURN
 | 
						|
;;   returns from the innermost dotimes or dolist -- they do not
 | 
						|
;;   return from allocate-slider-num.
 | 
						|
;;
 | 
						|
(defun allocate-slider-num ()
 | 
						|
  (dotimes (n 990)
 | 
						|
    (let ((i (+ n 10)))
 | 
						|
      (cond ((not (dolist (panel *panels-in-use*)
 | 
						|
                    (cond ((dolist (pair (cdr panel))
 | 
						|
                             (cond ((eql (second pair) i) (return t))))
 | 
						|
                           (return t)))))
 | 
						|
              (return i))))))
 | 
						|
 | 
						|
;; remove panel from list of panels
 | 
						|
(defun slider-panel-free (panel)
 | 
						|
  (setf *panels-in-use* (remove panel *panels-in-use* :test #'equal)))
 | 
						|
 | 
						|
(setfn stop-on-zero snd-stoponzero)
 | 
						|
 | 
						|
(defun make-slider-panel (name &optional (color 0))
 | 
						|
  (let ((panel (assoc name *panels-in-use* :test #'equal)))
 | 
						|
    ;; first find if panel already exists. If so, free the resources
 | 
						|
    (cond (panel
 | 
						|
           (slider-panel-free panel)))
 | 
						|
    (setf *active-slider-panel* (list name))
 | 
						|
    (setf *panels-in-use* (cons *active-slider-panel* *panels-in-use*))
 | 
						|
    (format t "slider-panel-create: \"~A\" ~A~%" name color)))
 | 
						|
 | 
						|
(defun make-slider (name &optional (init 0) (low 0) (high 1))
 | 
						|
  (let ((num (allocate-slider-num)))
 | 
						|
    (cond ((null num)
 | 
						|
           (format t "WARNING: MAKE-SLIDER is out of slider numbers. ~A~%"
 | 
						|
                     "No slider created."))
 | 
						|
          ((not (and (stringp name) (numberp init) 
 | 
						|
                     (numberp low) (numberp high)))
 | 
						|
           (display 
 | 
						|
            "WARNING: MAKE-SLIDER called with bad arguments. No slider created"
 | 
						|
            name init low high)))
 | 
						|
    ;; make sure we have an active panel
 | 
						|
    (cond ((null *active-slider-panel*)
 | 
						|
           (make-slider-panel "Controls")))
 | 
						|
    ;; insert new slider into list of sliders in active panel. This
 | 
						|
    ;; is aliased with an element in the assoc list *panels-in-use*.
 | 
						|
    (rplacd *active-slider-panel* (cons (list name num) 
 | 
						|
                                        (cdr *active-slider-panel*)))
 | 
						|
    (format t "slider-create: \"~A\" ~A ~A ~A ~A~%" name num init low high)
 | 
						|
    num))
 | 
						|
 | 
						|
(defun make-button (name &optional (normal 0))
 | 
						|
  (let ((num (allocate-slider-num)))
 | 
						|
    (cond ((null num)
 | 
						|
           (format t "WARNING: MAKE-BUTTON is out of slider numbers. ~A~%"
 | 
						|
                     "No button created."))
 | 
						|
          ((not (and (stringp name) (numberp normal)))
 | 
						|
           (display 
 | 
						|
            "WARNING: MAKE-BUTTON called with bad arguments. No button created"
 | 
						|
            name normal)))
 | 
						|
    ;; make sure we have an active panel
 | 
						|
    (cond ((null *active-slider-panel*)
 | 
						|
           (slider-panel "Controls")))
 | 
						|
    ;; insert new button into list of controls in active panel. This
 | 
						|
    ;; is aliased with an element in the assoc list *panels-in-use*.
 | 
						|
    (rplacd *active-slider-panel* (cons (list name num) 
 | 
						|
                                        (cdr *active-slider-panel*)))
 | 
						|
    (format t "button-create: \"~A\" ~A ~A~%" name num normal)
 | 
						|
    num))
 | 
						|
 | 
						|
(defun close-slider-panel (name)
 | 
						|
  (let ((panel (assoc name *panels-in-use* :test #'equal)))
 | 
						|
    (cond ((not (stringp name))
 | 
						|
           (display "WARNING: SLIDER-PANEL-CLOSED called with bad argument."
 | 
						|
                    name)))
 | 
						|
    (cond (panel
 | 
						|
           (slider-panel-free panel)
 | 
						|
           (format t "slider-panel-close: \"~A\"~%" name))
 | 
						|
          (t
 | 
						|
           (format t "WARNING: slider panel ~A not found.~%" name)))))
 | 
						|
 | 
						|
;; SLIDER-LOOKUP - find the slider by name
 | 
						|
;;
 | 
						|
(defun slider-lookup (name slider)
 | 
						|
  (let ((panel (assoc name *panels-in-use* :test #'equal)) s)
 | 
						|
    (cond ((null panel)
 | 
						|
           (error "Could not find slider panel named" name)))
 | 
						|
    (setf s (assoc slider (cdr panel) :test #'equal))
 | 
						|
    (cond ((null s)
 | 
						|
           (error "Could not find slider named" s)))
 | 
						|
    (second s)))
 | 
						|
 | 
						|
 | 
						|
;; SLIDER - creates a signal from real-time slider input
 | 
						|
;; 
 | 
						|
;; options are:
 | 
						|
;;   (SLIDER number [dur])
 | 
						|
;;   (SLIDER "name" [dur]) -- look up slider in current slider panel
 | 
						|
;;   (SLIDER "panel" "name" [dur]) -- look up panel, then look up slider
 | 
						|
;;
 | 
						|
(defun slider (id &optional slider-name dur)
 | 
						|
    (cond ((and (numberp id) (null slider-name))
 | 
						|
           (setf dur 1.0))
 | 
						|
          ((and (numberp id) (numberp slider-name) (null dur))
 | 
						|
           (setf dur slider-name))
 | 
						|
          ((and (stringp id) (null slider-name))
 | 
						|
           (setf dur 1.0)
 | 
						|
           (setf id (slider-lookup (car *active-slider-panel*) id)))
 | 
						|
          ((and (stringp id) (numberp slider-name) (null dur))
 | 
						|
           (setf dur slider-name)
 | 
						|
           (setf id (slider-lookup (car *active-slider-panel*) id)))
 | 
						|
          ((and (stringp id) (stringp slider-name) (null dur))
 | 
						|
           (setf dur 1.0)
 | 
						|
           (setf id (slider-lookup id slider-name)))
 | 
						|
          ((and (stringp id) (stringp slider-name) (numberp dur))
 | 
						|
           (setf id (slider-lookup id slider-name)))
 | 
						|
          (t
 | 
						|
           (error "SLIDER called with invalid arguments")))
 | 
						|
    (setf dur (get-duration dur))
 | 
						|
    (setf id (round id)) ;; just to make sure it's an integer
 | 
						|
    (cond ((or (< id 0) (>= id 1000))
 | 
						|
           (error "SLIDER index out of bounds" id)))
 | 
						|
    (display "slider" id slider-name dur)
 | 
						|
    (snd-slider id *rslt* *sound-srate* dur))
 | 
						|
 | 
						|
 | 
						|
(if (not (boundp '*lpslider-cutoff*))
 | 
						|
    (setf *lpslider-cutoff* 20.0))
 | 
						|
 | 
						|
(defun lpslider (id &optional slider-name dur)
 | 
						|
  (lp (slider id slider-name dur) 20.0))
 | 
						|
 | 
						|
;; save built-in get-slider-value so we can redefine it
 | 
						|
(if (not (fboundp 'prim-get-slider-value))
 | 
						|
    (setfn prim-get-slider-value get-slider-value))
 | 
						|
 | 
						|
(defun get-slider-value (id &optional slider-name)
 | 
						|
  (cond ((and (numberp id) (null slider-name)) nil)
 | 
						|
        ((and (stringp id) (null slider-name))
 | 
						|
         (setf id (slider-lookup (car *active-slider-pael*) id)))
 | 
						|
        ((and (stringp id) (stringp slider-name))
 | 
						|
         (setf id (slider-lookup id slider-name)))
 | 
						|
        (t
 | 
						|
         (error "GET-SLIDER-VALUE called with invalid arguments")))
 | 
						|
  ;; further parameter checking is done in get-slider-value:
 | 
						|
  (prim-get-slider-value id))
 | 
						|
 | 
						|
(autonorm-off)
 | 
						|
(snd-set-latency 0.02)
 | 
						|
(print "**********sliders.lsp************************")
 | 
						|
(print "WARNING: AUTONORM IS NOW TURNED OFF")
 | 
						|
(print "WARNING: AUDIO LATENCY SET TO 20MS")
 | 
						|
(print "To restore settings, execute (autonorm-on) and")
 | 
						|
(print "  (set-audio-latency 0.3)")
 | 
						|
(print "*********************************************")
 |