changeset 175:7e8d95d00267

Bars independant of time sigs darcs-hash:20080313112352-40ec0-0805528027499f30d3812fa6c4e65596d1ff40fe.gz
author d.lewis <d.lewis@gold.ac.uk>
date Thu, 13 Mar 2008 11:23:52 +0000
parents 9b152d515275
children cddf83554c08
files base/generics.lisp base/methods.lisp
diffstat 2 files changed, 99 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/base/generics.lisp	Thu Mar 13 11:22:29 2008 +0000
+++ b/base/generics.lisp	Thu Mar 13 11:23:52 2008 +0000
@@ -409,3 +409,49 @@
 ;;; Dynamics 
 ;;; Voice 
 ;;; Boundary Strength (phrasing) 
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Experimental:
+;;
+
+;;; Proposed new metre functions
+;; These should provide sufficient functionality that the users need
+;; not refer to get-applicable-time-signatures unless they really mean
+;; it. In turn, this means that barline based representations have a
+;; better chance at guessing.
+
+;; Notes:
+;; * iteration is possible with
+;;     (do ((beat (current-beat (make-moment 0) composition))
+;;                (current-beat (cut-off beat) composition))) ...
+;;   [That's probably not very efficient. there must be better ways]
+;; * gsharp and tabcode can answer bar questions, but not beat
+;; questions. Appropriate conditions and restarts will be needed.
+;; * a good test of this functionality will prob be amuse-harmony.
+
+(defgeneric bar-period (time-signature implementation-object)
+  (:documentation "Returns a <period> with a duration equal to the
+  duration of a bar in the given time signature for the given
+  implementation. FIXME: this isn't guaranteed to be
+  meaningful (double time signatures break this"))
+(defgeneric current-bar (moment composition)
+  (:documentation "Returns an <anchored-period> representing the
+  bar which contains moment"))
+
+(defgeneric beat-period (moment time-signature implementation-object)
+  (:documentation "Takes a moment, time signature object and crotchet and returns
+  an <anchored-period> for the containing beat containing moment. This
+  is more useful when there's a complex time signature (not currently
+  possible) in which tactus is different in different parts of the
+  bar (e.g. 3+3+2/8)"))
+(defgeneric current-beat (moment composition)
+  (:documentation "Returns an <anchored-period> representing the
+  tactus unit which contains moment"))
+
+
+;;;;;;;;;;;;;;
+;;
+;;
+
+(defgeneric get-applicable-clefs (anchored-period constituent))
--- a/base/methods.lisp	Thu Mar 13 11:22:29 2008 +0000
+++ b/base/methods.lisp	Thu Mar 13 11:23:52 2008 +0000
@@ -508,4 +508,56 @@
                                              &key initial-element
                                              (initial-contents nil icp))
   (declare (ignore length o initial-element initial-contents icp))
-  (%recompute-standard-composition-period (call-next-method)))
\ No newline at end of file
+  (%recompute-standard-composition-period (call-next-method)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Experimental:
+;;
+
+;; Some not obviously correct implementations of the new metre
+;; functions. These are no worse than we're already using (they should
+;; be more or less equivalent)
+
+(defmethod bar-period ((time-signature standard-time-signature)
+                       object)
+  (make-standard-period (* (duration (crotchet object))
+                           (time-signature-numerator time-signature)
+                           (/ 4 (time-signature-denominator time-signature)))))
+        
+(defmethod current-bar ((moment standard-moment) (composition composition))
+  (let* ((time-sig (car (get-applicable-time-signatures
+                         (make-standard-anchored-period (timepoint moment)
+                                                        (duration (crotchet composition)))
+                         composition)))
+         (bar-duration (bar-period time-sig composition)))
+    (do* ((start (onset time-sig) next-start)
+          (next-start (time+ start bar-duration) (time+ start bar-duration)))
+         ((time> next-start moment)
+          (make-standard-anchored-period (timepoint start)
+                                         (duration bar-duration))))))
+
+(defmethod beat-period ((moment standard-moment)
+                        (time-signature standard-time-signature)
+                        (composition composition))
+  ;; Simple example - standard-time-signature has constant tactus
+  (let* ((containing-bar (current-bar moment composition))
+         (beat-duration (* (duration (crotchet composition))
+                           (tactus-duration time-signature)))
+         (beat-period (make-standard-anchored-period (timepoint containing-bar)
+                                                     beat-duration)))
+    (do ()
+        ((time> (cut-off beat-period) moment) beat-period)
+      (setf (timepoint beat-period) (timepoint (cut-off beat-period))))))
+
+(defmethod current-beat ((moment standard-moment) (composition composition))
+  ;; Assume at most one time signature per bar (otherwise, this is hell)
+  (let* ((time-sig (car (get-applicable-time-signatures (current-bar moment composition) composition))))
+    (if time-sig
+        (beat-period moment time-sig composition)
+        ;; If no time-sig, there's no way of answering this
+        ;; directly. There may be sensible defaults, but it's the job
+        ;; of an implementation's author to solve that.
+        (error 'insufficient-information :operation 'beat-period :datatype (class-of composition)))))
+