(defun harmonic-series (frequency n &key (ratio 1)(sel nil)(start 1)(notes nil) &aux (output-list nil)) "returns a list of the harmonic-series with fundamental < frequency > and < n > harmonics. Key arguments: < ratio > < sel > (must be 'odd or 'even), < start >, < notes >" (if sel ;;; 1 (if (equal sel 'even) ;;; 2 (loop for j from 1 to n and for r from (+ start 1) by (* 2 ratio) do ;;; 3 (push (* frequency r) output-list)) (if (equal sel 'odd) ;;; 4 (loop for j from 1 to n and for r from start by (* 2 ratio) do ;;; 5 (push (* frequency r) output-list)) (error "sel must be 'odd or 'even"))) ;;; 6 (loop for j from 1 to n and for r from start by ratio do ;;; 7 (setf output-list (push (* frequency r) output-list)))) (if notes ;;; 8 (nreverse (mapcar #'(lambda (x) ;;; 9 (note (float x))) output-list)) (nreverse output-list))) ;;; 10
(if < condition-form > < then-form > < else-form >) (defun simple (a b) (if ( > a b) a b)) (simple 1 2) (simple 2 2) (simple 3 2)so the very first if is testing the variable sel, if this variable is NIL, the first form (list) after the test will NOT be evaluated, and the interpreter will jump to the next form (starting at line 7) inside the if and evaluate it. In the case that sel is NOT NIL, this means that it is true for the test the first of the two forms inside the if gets evaluated (the form starting at line 2). In this case that form has another if statement, this time we test if the variable sel is equal to 'even (line 2), if this is true we execute the loop in line 3. Otherwise we jump to line 4 where the form that we have to evaluate is another if, we test now if the value of set is equal to 'odd, if this is true we execute the loop starting in line 5, otherwise we print an error message.
(cond (< condition-form-1 > < then-form-1-1 >...< then-form-1-m >) (< condition-form-1 > < then-form-2-1 >...< then-form-2-m >) ... (< condition-form-n > < then-form-n-1 >...< then-form-n-m >)) (defun simple (a b) (cond (( > a b) a) ((< a b) b) ( T 'a=b)))the new code using cond looks like this:
(defun harmonic-series (frequency n &key (ratio 1)(sel nil)(start 1)(notes nil) &aux (output-list nil)) "returns a list of the harmonic-series with fundamental < frequency > and < n > harmonics. Key arguments: < ratio > < sel > (must be 'odd or 'even), < start >, < notes >" (if sel (cond ((equal sel 'even) (loop for j from 1 to n and for r from (+ start 1) by (* 2 ratio) do (push (* frequency r) output-list))) ((equal sel 'odd) (loop for j from 1 to n and for r from start by (* 2 ratio) do (push (* frequency r) output-list))) (T (error "sel must be 'odd or 'even"))) (loop for j from 1 to n and for r from start by ratio do (setf output-list (push (* frequency r) output-list)))) (if notes (nreverse (mapcar #'(lambda (x) (note (float x))) output-list)) (nreverse output-list)))
(when < condition-form > < then-form-1 > < then-form-2 > ... < then-form-n) (defun harmonic-series (frequency n &key (ratio 1)(sel nil)(start 1)(notes nil) &aux (output-list nil)) "returns a list of the harmonic-series with fundamental < frequency > and < n > harmonics. Key arguments: < ratio > < sel > (must be 'odd or 'even), < start >, < notes >" (if sel (cond ((equal sel 'even) (loop for j from 1 to n and for r from (+ start 1) by (* 2 ratio) do (push (* frequency r) output-list))) ((equal sel 'odd) (loop for j from 1 to n and for r from start by (* 2 ratio) do (push (* frequency r) output-list))) (T (error "sel must be 'odd or 'even"))) (loop for j from 1 to n and for r from start by ratio do (setf output-list (push (* frequency r) output-list)))) (when notes (setf output-list (mapcar #'(lambda (x) (note (float x))) output-list))) (nreverse output-list))
(unless (not < condition-form >) < then-form-1 > < then-form-2 > ... < then-form-n >)
(rest '(a b)) - > (b) (rest '(a . b)) - > b
(a b c) <=> (a . (b c)) (rest '(a b c)) - > (b c) (rest '(a . (b c))) - > (b c)
((key-1 . item-1)(key-2 . item-1) ... (key-n . item-n))
(defvar phones '((john . "(415)-477-2233")(mary . "(408)-489-3458")(peter . "(415)-325-2154")))
(assoc 'peter phones) - > (PETER . "(415)-325-2154")
(rest (assoc 'peter phones)) - > "(415)-325-2154"
(rassoc "(408)-489-3458" phones) - > NIL
(rassoc "(408)-489-3458" phones :test #'equal) - > (MARY . "(408)-489-3458") and to retrieve the actual key name: (first (rassoc "(408)-489-3458" phones :test #'equal)) - > MARY
(defvar *pitch-frq-list* NIL) - > *PITCH-FRQ-LIST*
(defun my-pitch (note) " returns the frequency of note " (if (assoc note *pitch-frq-list* :test 'equal) ;;; 1 (rest (assoc note *pitch-frq-list* :test 'equal)) ;;; 2 (let* ((deg (position (first note) '(c cs d ds e f fs g gs a as b))) ;;; 3 (oct (rest note)) ;;; 4 (r (expt 2 (/ 1 12))) ;;; 5 (new (* (* 16.351596 (expt r deg)) (expt 2 oct)))) ;;; 6 (push (cons note new) *pitch-frq-list*) ;;; 7 new))) ;;; 8
(my-pitch '(c . 4)) - > 261.62 now if we see the state of our data base: *pitch-frq-list* - > (((C . 4) . 261.62)) it contains the only note the function learnt. (my-pitch '(a . 1)) - > 54.99 *pitch-frq-list* - > (((A . 1) . 54.99) ((C . 4) . 261.62))
(time (dotimes (i 10) (my-pitch '(C . 4)))) - > real time : 0.017 secs run time : 0.000 secs (time (dotimes (i 10) (my-pitch (cons 'a i)))) - > real time : 0.050 secs run time : 0.000 secs
*pitch-frq-list* - > (((A . 9) . 14079.998423118826) ((A . 8) . 7039.9992115594132) ((A . 7) . 3519.9996057797066) ((A . 6) . 1759.9998028898533) ((A . 5) . 879.99990144492665) ((A . 4) . 439.99995072246332) ((A . 3) . 219.99997536123166) ((A . 2) . 109.99998768061583) ((A . 0) . 27.499996920153958) ((A . 1) . 54.999993840307916) ((C . 4) . 261.62553600000001))
(defvar *note-names* '((c . 0) (cs . 1)(df . 1) (d . 2) (ds . 3)(ef . 3) (e . 4) (f . 5) (fs . 6)(gf . 6) (g . 7) (gs . 8)(af . 8) (a . 9) (as . 10)(bf . 10) (b . 11)))
(assoc 'as *note-names*) - > (AS . 10)
(defun my-pitch (note) " returns the frequency of note " (if (assoc note *pitch-frq-list* :test 'equal) (rest (assoc note *pitch-frq-list* :test 'equal)) (let* ((deg (rest (assoc (first note) *note-names*))) ;;; this line was changed (oct (rest note)) (r (expt 2 (/ 1 12))) (new (* (* 16.351596 (expt r deg)) (expt 2 oct)))) (push (cons note new) *pitch-frq-list*) new)))
(loop for i from 0 to 10 do (dolist (j *note-names*) (print (my-pitch (cons (car j) i)))))
(setf *note-names* '((c . 0) (c+ . .5) (cs . 1)(df . 1) (cs+ . 1.5)(df- . 1.5) (d . 2) (d+ . 2.5) (ds . 3)(ef . 3) (ds+ . 3.5)(ef- . 3.5) (e . 4) (e+ . 4.5) (f . 5) (f+ . 5.5) (fs . 6)(gf . 6) (fs+ . 6.5)(gf- . 6.5) (g . 7) (g+ . 7.5) (gs . 8)(af . 8) (gs+ . 8.5)(af- . 8.5) (a . 9) (a+ . 9.5) (as . 10)(bf . 10) (as+ . 10.5)(bf- . 10.5) (b . 11) (b+ . 11.5)))
(my-pitch '(a+ . 4)) or incorporate the new notes to our learned list using this function: (loop for i from 0 to 10 do (dolist (j *note-names*) (print (my-pitch (cons (car j) i)))))
(defun roundp (n1 n2) " predicate to test rounded numbers " (equal (round n1) (round n2))) here is the function: (defun my-note (frq) " returns the note corresponding to frq " (car (rassoc (round frq) *pitch-frq-list* :test 'roundp))) (my-note 440.2) - > (A . 4) (my-note 453) - > (A+ . 4) (my-note 452.2) - > NIL
©1996-98 by Juan Pampin, juan@ccrma.stanford.edu