changeset 183:5b2d0e5a99f1

More tabcode, plus fixes for gsharp key-sigs and some new restart symbols in amuse darcs-hash:20080721130227-40ec0-858017ddbc42513731d0119e704926768906dbc6.gz
author d.lewis <d.lewis@gold.ac.uk>
date Mon, 21 Jul 2008 14:02:27 +0100
parents 470e83242576
children 94803c723ccd
files base/package.lisp implementations/tabcode/amuse-tabcode.asd implementations/tabcode/classes.lisp implementations/tabcode/ecolm.lisp implementations/tabcode/methods.lisp implementations/tabcode/package.lisp tools/gsharp-output.lisp tools/midi-output.lisp tools/package.lisp
diffstat 9 files changed, 219 insertions(+), 108 deletions(-) [+]
line wrap: on
line diff
--- a/base/package.lisp	Thu Jul 10 12:48:05 2008 +0100
+++ b/base/package.lisp	Mon Jul 21 14:02:27 2008 +0100
@@ -150,4 +150,8 @@
            #:diatonic-pitch-mp
 	   #:current-beat
 	   #:current-bar
+	   ;; condition restart options
+	   #:use-whole-bar
+	   #:use-crotchet-beat
+	   #:guess
 	   ))
--- a/implementations/tabcode/amuse-tabcode.asd	Thu Jul 10 12:48:05 2008 +0100
+++ b/implementations/tabcode/amuse-tabcode.asd	Mon Jul 21 14:02:27 2008 +0100
@@ -1,8 +1,7 @@
 (asdf:defsystem amuse-tabcode
-  :depends-on (amuse tabcode)
+  :depends-on (amuse tabcode amuse-harmony)
   :components
   ((:file "package")
    (:file "classes" :depends-on ("package"))
    (:file "methods" :depends-on ("package" "classes"))
-   (:file "tabcode-import" :depends-on ("package" "classes"))
-   (:file "ecolm" :depends-on ("tabcode-import" "methods" "classes" "package"))))
\ No newline at end of file
+   (:file "tabcode-import" :depends-on ("package" "classes"))))
\ No newline at end of file
--- a/implementations/tabcode/classes.lisp	Thu Jul 10 12:48:05 2008 +0100
+++ b/implementations/tabcode/classes.lisp	Mon Jul 21 14:02:27 2008 +0100
@@ -16,6 +16,10 @@
 (defclass tabcode-time-signature (standard-anchored-period tabcode-object)
   ((word :initarg :word :reader word)
    (ul)(ll)(ur)(lr)))
+(defgeneric ul (timesig))
+(defgeneric ll (timesig))
+(defgeneric ur (timesig))
+(defgeneric lr (timesig))
 (defmethod ul ((timesig tabcode-time-signature))
   (unless (slot-boundp timesig 'ul)
     (let ((ul (tabcode::ul (word timesig))))
--- a/implementations/tabcode/ecolm.lisp	Thu Jul 10 12:48:05 2008 +0100
+++ b/implementations/tabcode/ecolm.lisp	Mon Jul 21 14:02:27 2008 +0100
@@ -1,4 +1,4 @@
-(in-package #:amuse-tabcode)
+(in-package #:amuse-ecolm)
 
 (defun get-ecolm-connection ()
   (clsql:connect (list "127.0.0.1" "ecolm" "basicuser" "basicuser" "29183")
@@ -11,8 +11,9 @@
    (tabcode :initarg :code :accessor %tabcode)))
 
 (defclass ecolm-search ()
-  ((piece-title :initarg :p-title :reader piece-title)
-   (source-title :initarg :s-title :reader source-title)))
+  ((piece-title :initarg :piece :reader piece-title)
+   (source-title :initarg :source :reader source-title)
+   (cluster-name :initarg :cluster :reader cluster-name)))
 
 (defun edition-text-id (ecolm-id)
   (unless (or (slot-boundp ecolm-id 'edition-text-id)
@@ -51,5 +52,64 @@
 	(%tabcode identifier))))
 
 (defmethod get-composition ((identifier ecolm-identifier))
-  (get-composition-from-tabwords
-   (tabcode::parse-tabcode-string (tabcode identifier))))
\ No newline at end of file
+  (amuse-tabcode::get-composition-from-tabwords
+   (tabcode::parse-tabcode-string (tabcode identifier))))
+
+(defun make-ecolm-search (&key (piece-title nil) (source-title nil) (cluster-name nil))
+  (make-instance 'ecolm-search
+		 :piece piece-title
+		 :source source-title
+		 :cluster cluster-name))
+
+(defun ecolm-search (&key (piece-title nil) (source-title nil) (cluster-name nil))
+  (get-ecolm-search-results (make-ecolm-search :piece-title piece-title
+					       :source-title source-title
+					       :cluster-name cluster-name)))
+
+(defun get-ecolm-search-results (ecolm-search)
+  (let ((prefixes '("SELECT DISTINCT p.`Piece ID` FROM Pieces p"))
+	(where-clauses '("WHERE 1"))
+	(results)
+	(query-string "") (sourcep))
+    (when (and (slot-boundp ecolm-search 'piece-title)
+	       (piece-title ecolm-search))
+      (push " LEFT JOIN Piece_Names pn USING (`Piece ID`) "
+	    prefixes)
+      (push (format nil " AND (`Piece Title` LIKE '~D' OR `PieceName Alias` LIKE '~D') "
+		    (piece-title ecolm-search) (piece-title ecolm-search))
+	    where-clauses))
+    (when (and (slot-boundp ecolm-search 'source-title)
+	       (source-title ecolm-search))
+      (setf sourcep t)
+      (push " LEFT JOIN Sources s ON p.`Source ID`=s.`Source ID`
+              LEFT JOIN Source_Names sn ON s.`Source ID`=sn.`Source ID` "
+	    prefixes)
+      (push (format nil " AND (`Source Title` LIKE '~D' OR `SourceName Alias` LIKE '~D') "
+		    (source-title ecolm-search) (source-title ecolm-search))
+	    where-clauses))
+    (when (and (slot-boundp ecolm-search 'cluster-name)
+	       (cluster-name ecolm-search))
+      (push (if sourcep
+		" LEFT JOIN Cluster_Pieces cp ON p.`Piece ID`=cp.`Piece ID`
+                  LEFT JOIN Clusters c1 ON cp.`Cluster ID`=c1.`Cluster ID`
+                  LEFT JOIN Cluster_Sources cs on s.`Source ID`=cs.`Source ID`
+                  LEFT JOIN Clusters c2 ON cs.`Cluster ID`=c2.`Cluster ID` "
+		" LEFT JOIN Cluster_Pieces cp ON p.`Piece ID`=cp.`Piece ID`
+                  LEFT JOIN Clusters c1 ON cp.`Cluster ID`=c1.`Cluster ID` ")
+	    prefixes)
+      (push (format nil " AND (c1.`Cluster Name` LIKE '~D'~D)"
+		    (cluster-name ecolm-search)
+		    (if sourcep
+			(format nil "OR c2.`Cluster Name` LIKE '~D'"
+				(cluster-name ecolm-search))
+			""))
+		    
+	    where-clauses))
+    (setf query-string (concatenate 'string
+				    (apply #'concatenate
+					   'string (reverse prefixes))
+				    (apply #'concatenate
+					   'string (reverse where-clauses)))
+	  results (clsql:query query-string))
+    (remove-if-not #'edition-text-id (mapcar #'(lambda (x) (make-instance 'ecolm-identifier :p-id x)) results))))
+
--- a/implementations/tabcode/methods.lisp	Thu Jul 10 12:48:05 2008 +0100
+++ b/implementations/tabcode/methods.lisp	Mon Jul 21 14:02:27 2008 +0100
@@ -4,9 +4,21 @@
   ())
 (defmethod time-signatures ((composition tabcode-composition))
   (metrical-signs composition))
-
+(defmethod amuse-tools:get-patch-for-midi ((event tabcode-object))
+  24)
+(defmethod amuse-tools:get-velocity-for-midi ((event tabcode-object))
+  70)
+(defmethod amuse-tools:default-tempo-for-midi ((tab-comp tabcode-composition))
+  (make-standard-tempo-period 60 (timepoint tab-comp) (duration tab-comp)))
 (defmethod get-applicable-key-signatures (object (composition tabcode-composition))
- ())
+  (restart-case 
+      (error 'insufficient-information
+	     :operation 'beat-period
+	     :datatype (class-of composition))
+    (amuse:guess () (multiple-value-bind (x key)
+			(amuse-harmony:krumhansl-key-finder composition composition)
+		      (declare (ignore x))
+		      (list key)))))
 
 (defmethod crotchet ((object tabcode-object))
   (make-standard-period 1))
@@ -18,68 +30,82 @@
 
 (defmethod current-beat ((moment standard-moment) (composition tabcode-composition))
   ;; clearly broken, but can unbreak unusual cases as they arise (?!)
-  (let ((bar (current-bar moment composition))
-	(metre (find-if #'(lambda (x) (and (time< moment (cut-off x))
-					   (time>= moment (onset x))))
-			(metrical-signs composition))))
-    (unless (and bar metre)
-      (error 'insufficient-information
-	     :operation 'beat-period
-	     :datatype (class-of composition)))
-    (let ((beats-in-bar) (beat-duration))
-      (cond
-	((ur metre)
-	 ;; we have a weird compound signature, goodness knows what to
-	 ;; do. This probably means that one of them is a proportion
-	 ;; sign.
-	 (error 'insufficient-information
-		:operation 'beat-period
-		:datatype (class-of composition)))
-	((and (ll metre)
-	      (numberp (ll metre)) ;; we have a `standard
-	      (numberp (ul metre)));; time sig'
-	 (setf beats-in-bar (ul metre)
-	       beat-duration (/ 4 (ll metre)))
-	 (when (and (> beats-in-bar 3)
-		    (= (rem beats-in-bar 3) 0))
-	   (setf beats-in-bar (/ beats-in-bar 3)
-		 beat-duration (* beat-duration 3))))
-	((and (null (ll metre))
-	      (numberp (ul metre)))
-	 (setf beats-in-bar (ul metre))
-	 (do ((proportion 4 (/ proportion 2)))
-	     ((= (rem (/ (duration bar) proportion)
-		      beats-in-bar) 0)
-	      (setf beat-duration proportion))
-	   (unless (>= proportion 1/4)
-	     (setf beat-duration (round (/ (duration bar)
-					   beats-in-bar)))
-	     (return))))
-	((null (ll metre))
-	 (cond
-	   ((string= (ul metre) "C")
-	    (setf beats-in-bar 4)
-	    (setf beat-duration 1))
-	   ((string= (ul metre) "C/")
-	    (setf beats-in-bar 2)
-	    (setf beat-duration 2)))
-	 ;; clearly wrong, but for the time being try this (better is
-	 ;; work out for the whole piece
-	 (do ((proportion 4 (/ proportion 2)))
-	     ((= (rem (/ (duration bar) proportion)
-		      beats-in-bar) 0)
-	      (setf beat-duration proportion))
-	   (unless (>= proportion 2)
-	     (setf beat-duration 2)
-	     (return)))))
-      (unless (= (rem (duration bar)
-		      (* beat-duration beats-in-bar))
-		 0)
-	(print "Bar length doesn't match metrical symbol, I think"))
-      (let ((beat-period (make-standard-anchored-period
-			  (timepoint bar) beat-duration)))
-	(do ()
-	    ((time> (cut-off beat-period) moment) beat-period)
-	  (setf (timepoint beat-period)
-		(timepoint (cut-off beat-period))))))))
-	
\ No newline at end of file
+  (let ((bar (current-bar moment composition)))
+    (restart-case
+	(let ((metre (find-if #'(lambda (x) (and (time< moment (cut-off x))
+						 (time>= moment (onset x))))
+			      (metrical-signs composition))))
+	  (unless (and bar metre)
+	    (error 'insufficient-information
+		   :operation 'beat-period
+		   :datatype (class-of composition)))
+	  (let ((beats-in-bar) (beat-duration))
+	    (cond
+	      ((ur metre)
+	       ;; we have a weird compound signature, goodness knows what to
+	       ;; do. This probably means that one of them is a proportion
+	       ;; sign. Better errors would be a gould start.
+	       (error 'insufficient-information
+		      :operation 'beat-period
+		      :datatype (class-of composition)))
+	      ((and (ll metre)
+		    (numberp (ll metre)) ;; we have a `standard
+		    (numberp (ul metre)));; time sig'
+	       (setf beats-in-bar (ul metre)
+		     beat-duration (/ 4 (ll metre)))
+	       (when (and (> beats-in-bar 3)
+			  (= (rem beats-in-bar 3) 0))
+		 (setf beats-in-bar (/ beats-in-bar 3)
+		       beat-duration (* beat-duration 3))))
+	      ((and (null (ll metre))
+		    (numberp (ul metre)))
+	       (setf beats-in-bar (ul metre))
+	       (do ((proportion 4 (/ proportion 2)))
+		   ((= (rem (/ (duration bar) proportion)
+			    beats-in-bar) 0)
+		    (setf beat-duration proportion))
+		 (unless (>= proportion 1/4)
+		   (setf beat-duration (round (/ (duration bar)
+						 beats-in-bar)))
+		   (return))))
+	      ((null (ll metre))
+	       (cond
+		 ((string= (ul metre) "C")
+		  (setf beats-in-bar 4)
+		  (setf beat-duration 1))
+		 ((string= (ul metre) "C/")
+		  (setf beats-in-bar 2)
+		  (setf beat-duration 2)))
+	       ;; clearly wrong, but for the time being try this (better is
+	       ;; work out for the whole piece
+	       (do ((proportion 4 (/ proportion 2)))
+		   ((= (rem (/ (duration bar) proportion)
+			    beats-in-bar) 0)
+		    (setf beat-duration proportion))
+		 (unless (>= proportion 2)
+		   (setf beat-duration 2)
+		   (return)))))
+	    (unless (= (rem (duration bar)
+			    (* beat-duration beats-in-bar))
+		       0)
+	      (print "Bar length doesn't match metrical symbol, I think"))
+	    (find-current-beat-with-bar-start-and-constant-beat
+	     moment bar beat-duration)))
+      (amuse:use-whole-bar () :report "Use whole bar" bar)
+      (amuse:use-crotchet-beat () :report "Use crotchet as beat"
+			 (find-current-beat-with-bar-start-and-constant-beat
+			  moment bar 1))
+      (use-value-for-beat (new-beat) :report "Supply beat"
+			  :interactive (lambda ()
+					 (format t "Beat value:")
+					 (list (eval (read))))
+			  (find-current-beat-with-bar-start-and-constant-beat
+			   moment bar new-beat)))))
+    
+(defun find-current-beat-with-bar-start-and-constant-beat (current-moment bar-period beat-duration)
+  (let ((beat-period (make-standard-anchored-period
+		      (timepoint bar-period) beat-duration)))
+    (do ()
+	((time> (cut-off beat-period) current-moment) beat-period)
+      (setf (timepoint beat-period)
+	    (timepoint (cut-off beat-period))))))
\ No newline at end of file
--- a/implementations/tabcode/package.lisp	Thu Jul 10 12:48:05 2008 +0100
+++ b/implementations/tabcode/package.lisp	Mon Jul 21 14:02:27 2008 +0100
@@ -1,5 +1,5 @@
 (cl:defpackage "AMUSE-TABCODE"
   (:use "CL" "AMUSE" "AMUSE-UTILS" "TABCODE")
-  (:export "COURSE" "WORD" "TABCODE-PITCHED-EVENT" "TABCODE-COMPOSITION"
-           "TABCODE-TIME-SIGNATURE" "TABCODE-FILE-IDENTIFIER"
-           "ECOLM-IDENTIFIER" "GET-ECOLM-CONNECTION"))
+  (:export "TABCODE-OBJECT" "COURSE" "WORD" "TABCODE-PITCHED-EVENT"
+	   "TABCODE-COMPOSITION"
+           "TABCODE-TIME-SIGNATURE" "TABCODE-FILE-IDENTIFIER"))
--- a/tools/gsharp-output.lisp	Thu Jul 10 12:48:05 2008 +0100
+++ b/tools/gsharp-output.lisp	Mon Jul 21 14:02:27 2008 +0100
@@ -98,7 +98,11 @@
   ;; FIXME: Throughout this, I assume that
   ;; get-applicable-time-signatures isn't '()
   (let ((time-signatures (get-applicable-time-signatures composition composition))
-        (key-signatures (get-applicable-key-signatures composition composition))
+        (key-signatures (handler-bind ((insufficient-information
+				       #'(lambda (c)
+					   (declare (ignore c))
+					   (invoke-restart 'guess))))
+			  (get-applicable-key-signatures composition composition)))
         (layers))
     (multiple-value-bind (layer-events layer-scores)
         ;; Get hash-tables of events by layer and counts of events
@@ -166,33 +170,39 @@
 ;;                                   :crotchet crotchet-beats))
 ;;         (bar-starts (mapcar #'car beat-starts))
          (bar-starts (let ((starts))
-                       (do ((bar-period (amuse::current-bar (make-standard-moment 0) composition)
-                                        (amuse::current-bar (cut-off bar-period) composition)))
+                       (do ((bar-period (current-bar (make-standard-moment 0) composition)
+                                        (current-bar (cut-off bar-period) composition)))
                            ((time>= (cut-off bar-period) (cut-off composition))
                             (reverse (cons (timepoint bar-period) starts)))
                          (push (timepoint bar-period) starts))))
          (beat-starts (if time-signatures
-                          (let ((starts) (current))
-                            (do* ((bars bar-starts)
-                                  (beat-period (amuse::current-beat (make-standard-moment 0) composition)
-                                               (amuse::current-beat (cut-off beat-period) composition))
-                                  (beat-time (timepoint beat-period) (timepoint beat-period)))
-                                 ((time>= (cut-off beat-period) (cut-off composition))
-				  (progn
-				    (when (and (cdr bars)
-                                         (>= beat-time (second bars)))
-				      (push (reverse current) starts)
-				      (setf current nil
-					    bars (cdr bars)))
-				    (push beat-time current)
-				    (reverse (cons (reverse current) starts))))
-                              (when (and (cdr bars)
-                                         (>= beat-time (second bars)))
-                                (push (reverse current) starts)
-                                (setf current nil
-                                      bars (cdr bars)))
-                              (push beat-time current)))
-                          (mapcar #'list bar-starts)))
+                          (handler-bind
+			      ((insufficient-information
+				#'(lambda (c)
+				    (declare (ignore c))
+				    (invoke-restart 'use-whole-bar))))
+			    (let ((starts) (current))
+			      (do* ((bars bar-starts)
+				    (beat-period (current-beat (make-standard-moment 0) composition)
+						 (current-beat (cut-off beat-period) composition))
+				    (beat-time (timepoint beat-period) (timepoint beat-period)))
+				   ((time>= (cut-off beat-period) (cut-off composition))
+				    (progn
+				      (when (and (cdr bars)
+						 (>= beat-time (second bars)))
+					  (push (reverse current) starts)
+					  (setf current nil
+						bars (cdr bars)))
+				      (push beat-time current)
+				      (reverse (cons (reverse current) starts))))
+				(when (and (cdr bars)
+					   (>= beat-time (second bars)))
+				  (push (reverse current) starts)
+				  (setf current nil
+					bars (cdr bars)))
+				(push beat-time current))))
+			  
+			  (mapcar #'list bar-starts)))
          (ons) (position)
          (clusters) (bar) (bar-no 0)
          (body (gsharp::body layer)))
@@ -232,7 +242,7 @@
         (gsharp::add-bar bar body bar-no)
         (incf bar-no)
         (setf position 0))
-      (when (and key-signatures
+#+nil      (when (and key-signatures
                  (<= (timepoint (car key-signatures))
                      (caar ons)))
         (gsharp::add-element (make-gsharp-key-signature (car key-signatures) layer)
@@ -334,7 +344,7 @@
 
 (defgeneric make-gsharp-key-signature (key-signature layer))
 (defmethod make-gsharp-key-signature ((key-signature standard-key-signature) layer)
-  (let ((alterations (make-array 7))
+  (let ((alterations (make-array 7 :initial-element :natural))
         (order-of-sharps #(3 0 4 1 5 2 6))
         (order-of-flats #(6 2 5 1 4 0 3)))
     (if (< (key-signature-sharps key-signature) 0)
--- a/tools/midi-output.lisp	Thu Jul 10 12:48:05 2008 +0100
+++ b/tools/midi-output.lisp	Mon Jul 21 14:02:27 2008 +0100
@@ -96,6 +96,10 @@
 	      patch-list)
 	(setf (aref patches channel) patch)))))
 		
+(defgeneric default-tempo-for-midi (anchored-period)
+  (:method ((o standard-anchored-period))
+    (make-standard-tempo-period *default-tempo* (timepoint o) (duration o))))
+(defparameter *default-tempo* 80)
 
 (defgeneric global-messages (sequence)
   (:method (s) (declare (ignore s)) nil))
@@ -106,10 +110,13 @@
 	(temp)
 	(time-sigs (time-signatures sequence))
 	(events))
-    (dolist (tempo tempi)
-      (setf temp (tempo-message tempo))
-      (when temp
-	(push temp events)))
+    (if tempi
+	(dolist (tempo tempi)
+	  (setf temp (tempo-message tempo))
+	  (when temp
+	    (push temp events)))
+	(push (tempo-message (default-tempo-for-midi sequence))
+	      events))
     (dolist (time-sig time-sigs events)
       (setf temp (time-sig-message time-sig))
       (when temp
--- a/tools/package.lisp	Thu Jul 10 12:48:05 2008 +0100
+++ b/tools/package.lisp	Mon Jul 21 14:02:27 2008 +0100
@@ -10,4 +10,5 @@
 	   #:get-channel-for-midi
 	   #:get-pitch-for-midi
 	   #:get-velocity-for-midi
+	   #:default-tempo-for-midi
 	   ))