Main Page       Index


defphrase.lsp


 defphrase
 1.00
 (c) Steven Jones

 Contact jones57@swbell.net include the word "nyquist" in subject line  31 October 2004

 The contents of this file are released under the terms of the GNU General
 Public License. See the file LICENSE.txt

 Macros for defining musical phrases.


macro

defphrase

 (defphrase name bars count unit [cuelist...])
 Define a new "phrase" where a "phrase" is a sound generating function of 
 the form

      (name (&optional (reps 1)) ...)

 The optional reps argument (default 1) controls the number of repetitions
 of the phrase.

 name     - symbol. The name of the new function.
 
 bars     - integer. Number of "bars" in the phrase.

 count    - integer. Number of basic units per bar.

 unit     - flonum or symbol. Duration value of basic time unit in seconds.
            Unit time may be specified either as a real number or 
            symbolically. See get-time-symbol-value in tempo.lsp

 cuelist - forms. An arbitrary number of LISP statements which form a cue 
           list for name. Typically a cue list has the form:

           (at (* start (* uu xx))(cue (somefn ...)))
         
           The start variable is defined internally to the new function and 
           contains the absolute starting time for the current phrase 
           repetition. The uu and xx values are offsets from the start of 
           the phrase for this specific event and somefn is a sound 
           generating function. See also att macro below.

 NOTE 1    Within name four local variables are defined:
           phrase-len, bar-len, rep and start.
            
           phrase-len contains the absolute time in seconds of a single 
           pass of the phrase.

           bar-len contains the duration of a single bar in seconds

           rep is the looping index  0, 1, 2, ... reps-1

           start is set to the absolute start time of the current repetition.
           start = 0*phrase-len, 1*phrase-len, 2*phrase-len..(n-1)*phrase-len

 NOTE 2   It is often necessary to "ground" a phrase at time zero. This is 
          particularly true if the first event of a phrase does not occur
          at local time 0.  The simplest way to do this is to include a 
          "null sound" generating function in the cue list. Something like:

          (at 0 (cue (s-rest)))

          Occasionally this is not enough. There is a weird phenomenon on 
          some 2 channel behaviors which causes the sound to pan to alternate 
          channels on alternates calls. This is probably a bug in Nyquist but 
          is elusive enough that it is hard to reproduce. An apparent hack is 
          to ground the specific behavior at time zero as above. For example 
          if a call to (snare) is exhibiting this problem, include 

          (at 0 (cue (scale 0 (snare)))) 


macro

att

 (att bar count fn)
 Used only in conjunction with defphrase to cue function fn at specific
 count and bar.
 
 bar   - integer. Bar number
 count - integer. Count of basic unit within bar
 fn    - form. Sound generating statement
 
 (att bar count fn) expands to

      (at (+ start (* bar-length bar)(* unit-time count))(cue fn))

 See examples.


example

defphrase

;; @doc example defphrase
;; Define a 1 bar 4/4 phrase to play c major arpeggio on quarters notes
;;
;; (defphrase foo 1 4 q
;;    (at (+ start (* q 0))(cue (piano c3 q)))
;;    (at (+ start (* q 1))(cue (piano e4 q)))
;;    (at (+ start (* q 2))(cue (piano g4 q)))
;;    (at (+ start (* q 3))(cue (piano c4 q))))
;;
;; Use (foo n) to render the phrase n times
;;
;;
;; Define a 2 bar phrase as above but utilizing the att macro
;; 
;; (defphrase baz 2 4 q
;;    (att 0 0 (piano c3 q))
;;    (att 0 1 (piano e4 q))
;;    (att 0 2 (piano g4 q))
;;    (att 0 3 (piano c4 q))
;;    (att 1 0 (piano g4 q))
;;    (att 1 1 (piano e4 q))
;;    (att 1 2 (piano c4 h)))
;;


View the Sourcecode :



;; defphrase
;; 1.00
;; (c) Steven Jones
;;
;; Contact jones57@swbell.net include the word "nyquist" in subject line  31 October 2004
;;
;; The contents of this file are released under the terms of the GNU General
;; Public License. See the file LICENSE.txt
;;
;; Macros for defining musical phrases.
;;

(require 'tempo)
(provide 'defphrase)
(current-file "defphrase")


;; @doc macro defphrase
;; (defphrase name bars count unit [cuelist...])
;; Define a new "phrase" where a "phrase" is a sound generating function of 
;; the form
;;
;;      (name (&optional (reps 1)) ...)
;;
;; The optional reps argument (default 1) controls the number of repetitions
;; of the phrase.
;;
;; name     - symbol. The name of the new function.
;; 
;; bars     - integer. Number of "bars" in the phrase.
;;
;; count    - integer. Number of basic units per bar.
;;
;; unit     - flonum or symbol. Duration value of basic time unit in seconds.
;;            Unit time may be specified either as a real number or 
;;            symbolically. See get-time-symbol-value in tempo.lsp
;;
;; cuelist - forms. An arbitrary number of LISP statements which form a cue 
;;           list for name. Typically a cue list has the form:
;;
;;           (at (* start (* uu xx))(cue (somefn ...)))
;;         
;;           The start variable is defined internally to the new function and 
;;           contains the absolute starting time for the current phrase 
;;           repetition. The uu and xx values are offsets from the start of 
;;           the phrase for this specific event and somefn is a sound 
;;           generating function. See also att macro below.
;;
;; NOTE 1    Within name four local variables are defined:
;;           phrase-len, bar-len, rep and start.
;;            
;;           phrase-len contains the absolute time in seconds of a single 
;;           pass of the phrase.
;;
;;           bar-len contains the duration of a single bar in seconds
;;
;;           rep is the looping index  0, 1, 2, ... reps-1
;;
;;           start is set to the absolute start time of the current repetition.
;;           start = 0*phrase-len, 1*phrase-len, 2*phrase-len..(n-1)*phrase-len
;;
;; NOTE 2   It is often necessary to "ground" a phrase at time zero. This is 
;;          particularly true if the first event of a phrase does not occur
;;          at local time 0.  The simplest way to do this is to include a 
;;          "null sound" generating function in the cue list. Something like:
;;
;;          (at 0 (cue (s-rest)))
;;
;;          Occasionally this is not enough. There is a weird phenomenon on 
;;          some 2 channel behaviors which causes the sound to pan to alternate 
;;          channels on alternates calls. This is probably a bug in Nyquist but 
;;          is elusive enough that it is hard to reproduce. An apparent hack is 
;;          to ground the specific behavior at time zero as above. For example 
;;          if a call to (snare) is exhibiting this problem, include 
;;
;;          (at 0 (cue (scale 0 (snare)))) 
;;

;; NOTE 3   The property list for the symbol name contains the following 
;;          properties:
;;          'BARS  - Value of the bars argument
;;          'COUNT - Value of the count argument
;;          'UNIT  - Value of the unit argument
;;
;; See also examples below
;;

(defmacro defphrase (name bars count unit &rest cuelist)
  `(progn 
     (defun ,name (&optional (reps 1))
       (let (phrase-len bar-len start)
	 (setq unit-time (get-time-symbol-value ,unit))
	 (setq bar-len (* ,count unit-time))
	 (setq phrase-len (* ,bars bar-len))
	 (simrep (rep reps)
		 (progn
		   (setq start (* rep phrase-len))
		   (sim ,@cuelist)))))
     (putprop ',name ,bars 'bars)
     (putprop ',name ,count 'count)
     (putprop ',name ,unit 'unit)
     ))


;; @doc macro att
;; (att bar count fn)
;; Used only in conjunction with defphrase to cue function fn at specific
;; count and bar.
;; 
;; bar   - integer. Bar number
;; count - integer. Count of basic unit within bar
;; fn    - form. Sound generating statement
;; 
;; (att bar count fn) expands to
;;
;;      (at (+ start (* bar-length bar)(* unit-time count))(cue fn))
;;
;; See examples.
;;

(defmacro att (bar count fn)
  `(at (+ start (* bar-len ,bar)(* unit-time ,count))(cue ,fn)))


;; @doc example defphrase
;; Define a 1 bar 4/4 phrase to play c major arpeggio on quarters notes
;;
;; (defphrase foo 1 4 q
;;    (at (+ start (* q 0))(cue (piano c3 q)))
;;    (at (+ start (* q 1))(cue (piano e4 q)))
;;    (at (+ start (* q 2))(cue (piano g4 q)))
;;    (at (+ start (* q 3))(cue (piano c4 q))))
;;
;; Use (foo n) to render the phrase n times
;;
;;
;; Define a 2 bar phrase as above but utilizing the att macro
;; 
;; (defphrase baz 2 4 q
;;    (att 0 0 (piano c3 q))
;;    (att 0 1 (piano e4 q))
;;    (att 0 2 (piano g4 q))
;;    (att 0 3 (piano c4 q))
;;    (att 1 0 (piano g4 q))
;;    (att 1 1 (piano e4 q))
;;    (att 1 2 (piano c4 h)))
;;


Main Page       Index