m@46: (cl:in-package #:amuse-mtp) m@46: m@46: ;;; Compositions m@46: m@46: #.(clsql:locally-enable-sql-reader-syntax) m@46: m@87: (defvar *event-attributes* m@87: (list [dataset-id] [composition-id] [event-id] m@87: [onset] [dur] [deltast] [cpitch] [mpitch] [accidental] [keysig] [mode] m@87: [barlength] [pulses] [phrase] [tempo] [dyn] [voice])) m@87: m@53: (defgeneric get-dataset (identifer)) m@53: m@53: (defmethod get-dataset ((identifier mtp-dataset-identifier)) m@53: (let* ((dataset-id (dataset-id identifier)) m@53: (where-clause [= [dataset-id] dataset-id]) m@149: (db-dataset (car (clsql:select [*] :from [mtp-dataset] :where where-clause))) m@87: (db-compositions (clsql:select [composition-id][description] m@87: :from [mtp-composition] m@87: :order-by '(([composition-id] :asc)) m@87: :where where-clause)) m@87: (db-events (apply #'clsql:select m@87: (append *event-attributes* m@87: (list :from [mtp-event] m@87: :order-by '(([composition-id] :asc) m@87: ([event-id] :asc)) m@87: :where where-clause)))) m@87: (dataset (make-mtp-dataset :dataset-id (first db-dataset) m@87: :description (second db-dataset) m@87: :timebase (third db-dataset) m@87: :midc (fourth db-dataset))) m@53: (compositions nil) m@87: (events nil)) m@87: ;; for each db-composition m@87: (dolist (dbc db-compositions) m@149: (let ((composition-id (car dbc)) m@149: (description (car dbc))) m@87: ;; for each db-event m@87: (do* ((dbes db-events (cdr dbes)) m@87: (dbe (car dbes) (car dbes)) m@87: (cid (second dbe) (second dbe))) m@87: ((or (null dbes) (not (= cid composition-id))) m@87: (setf db-events dbes)) m@87: (when dbe m@87: (push (db-event->mtp-event dbe) events))) m@149: (when events m@149: (let* ((interval (+ (timepoint (car events)) (duration (car events)))) m@149: (composition m@149: (make-mtp-composition :dataset-id dataset-id m@149: :composition-id composition-id m@149: :description description m@149: :time 0 m@149: :interval interval))) m@149: (sequence:adjust-sequence composition (length events) m@149: :initial-contents (nreverse events)) m@149: (setf events nil) m@149: (push composition compositions))))) m@53: (sequence:adjust-sequence dataset (length compositions) m@53: :initial-contents (nreverse compositions)) m@53: dataset)) m@53: m@46: (defmethod get-composition ((identifier mtp-composition-identifier)) m@46: (let* ((dataset-id (dataset-id identifier)) m@46: (composition-id (composition-id identifier)) m@46: (where-clause [and [= [dataset-id] dataset-id] m@46: [= [composition-id] composition-id]]) m@46: (description m@51: (car (clsql:select [description] :from [mtp-composition] m@46: :where where-clause :flatp t :field-names nil))) m@87: (db-events (apply #'clsql:select m@87: (append *event-attributes* m@87: (list :from [mtp-event] m@87: :order-by '(([event-id] :asc)) m@87: :where where-clause)))) m@46: (events nil)) m@87: (dolist (e db-events) m@87: (push (db-event->mtp-event e) events)) m@46: (let* ((interval (+ (timepoint (car events)) (duration (car events)))) m@46: (composition m@46: (make-mtp-composition :dataset-id dataset-id m@46: :composition-id composition-id m@46: :description description m@46: :time 0 m@46: :interval interval))) m@46: (sequence:adjust-sequence composition (length events) m@46: :initial-contents (nreverse events)) m@46: composition))) m@46: m@90: #.(clsql:restore-sql-reader-syntax-state) m@90: m@87: (defun db-event->mtp-event (db-event) m@87: (let* ((slots ; the order must match *event-attributes* m@87: '(amuse::time amuse::interval deltast cpitch mpitch accidental m@186: keysig mode barlength pulses phrase tempo dyn voice bioi)) m@46: (mtp-event m@87: (make-mtp-event :dataset-id (first db-event) m@87: :composition-id (second db-event) m@87: :event-id (third db-event)))) m@87: (do* ((slts slots (cdr slts)) m@87: (db-atts (nthcdr 3 db-event) (cdr db-atts))) m@87: ((null slts) mtp-event) m@87: (setf (slot-value mtp-event (car slts)) (car db-atts))))) m@90: m@90: ;;; Monodies m@90: m@90: (defmethod monody ((identifier mtp-composition-identifier)) m@90: (monody (get-composition identifier))) m@90: m@90: (defmethod monody ((c mtp-composition)) m@90: (let ((monody (make-instance 'mtp-monody m@90: :dataset-id (dataset-id c) m@90: :composition-id (composition-id c) m@90: :description (description c) m@90: :time 0 m@90: :interval (duration c))) m@90: (events nil) m@90: (monody-voice 1)) m@90: (sequence:dosequence (event c) m@90: (when (= (%mtp-voice event) monody-voice) m@90: (push event events))) m@90: (sequence:adjust-sequence m@90: monody (length events) m@90: :initial-contents (sort events #'< :key #'amuse:timepoint)) m@90: monody)) m@46: m@46: ;;; Constituents from compositions: time-signatures m@46: m@96: (defmethod crotchet ((dataset mtp-dataset)) d@136: (amuse:make-standard-period m@96: (/ (dataset-timebase dataset) 4))) m@87: m@46: #.(clsql:locally-enable-sql-reader-syntax) m@96: (defmethod crotchet ((composition mtp-composition)) m@96: (let ((timebase m@96: (car (clsql:select [timebase] :from [mtp-dataset] m@96: :where [= [dataset-id] m@96: (dataset-id composition)] m@96: :flatp t m@96: :field-names nil)))) d@136: (amuse:make-standard-period (/ timebase 4)))) m@96: (defmethod crotchet ((event mtp-event)) m@96: (let ((timebase m@96: (car (clsql:select [timebase] :from [mtp-dataset] m@96: :where [= [dataset-id] m@96: (dataset-id event)] m@96: :flatp t m@96: :field-names nil)))) d@136: (amuse:make-standard-period (/ timebase 4)))) m@46: #.(clsql:restore-sql-reader-syntax-state) m@46: m@69: (defmethod get-applicable-time-signatures ((e mtp-event) c) m@69: (declare (ignore c)) m@291: ;(format t "~&GATS ~A ~A ~A: pulses = ~A; barlength = ~A.~%" (dataset-id e) (composition-id e) (event-id e) (%mtp-pulses e) (%mtp-barlength e)) m@291: (let* ((pulses (%mtp-pulses e)) m@291: (barlength (%mtp-barlength e)) m@291: (timebase (* 4 (duration (crotchet e)))) m@291: (numerator (if (null pulses) 0 pulses)) m@291: (denominator (if (null barlength) m@291: 1 m@291: (/ timebase (/ barlength pulses))))) m@291: (list m@291: (amuse:make-standard-time-signature-period numerator m@291: denominator d@136: (timepoint e) d@136: (duration e))))) m@69: m@46: (defmethod time-signatures ((c mtp-composition)) m@46: (let ((results nil) m@46: (interval 0) m@46: (current nil)) m@46: (sequence:dosequence (event c) m@70: (let ((ts (car (get-applicable-time-signatures event c)))) m@46: (when (and (%mtp-barlength event) m@46: (%mtp-pulses event) m@46: (or (null current) m@46: (not (time-signature-equal ts current)))) m@46: (unless (null current) m@46: (setf (duration current) interval) m@46: (push current results)) m@46: (setf interval 0 m@46: current ts))) m@46: (incf interval (%mtp-deltast event)) m@46: (incf interval (duration event))) m@46: (when current m@46: (setf (duration current) interval) m@46: (push current results)) m@46: (nreverse results))) m@46: m@46: ;;; Constituents from compositions: key-signatures m@46: m@69: (defmethod get-applicable-key-signatures ((e mtp-event) c) m@69: (declare (ignore c)) m@69: (let* ((sharps (%mtp-keysig e)) m@68: (mode (%mtp-mode e)) m@69: (midi-mode (and mode (if (= mode 0) 0 1)))) d@136: (list (amuse:make-midi-key-signature-period sharps midi-mode d@136: (timepoint e) d@136: (duration e))))) m@46: m@68: (defmethod key-signatures ((c mtp-composition)) m@46: (let ((results nil) m@46: (interval 0) m@46: (current nil)) m@46: (sequence:dosequence (event c) m@69: (let ((ks (car (get-applicable-key-signatures event c)))) m@46: (when (and (%mtp-keysig event) m@46: (%mtp-mode event) m@46: (or (null current) m@46: (not (key-signature-equal ks current)))) m@46: (unless (null current) m@46: (setf (duration current) interval) m@46: (push current results)) m@46: (setf interval 0 m@46: current ks))) m@46: (incf interval (%mtp-deltast event)) m@46: (incf interval (duration event))) m@46: (when current m@46: (setf (duration current) interval) m@46: (push current results)) m@46: (nreverse results))) m@46: m@46: ;;; Constituents from compositions: tempi m@46: m@69: (defmethod get-applicable-tempi ((e mtp-event) c) m@69: (declare (ignore c)) d@136: (list (amuse:make-standard-tempo-period (%mtp-tempo e) d@136: (timepoint e) d@136: (duration e)))) m@69: m@46: (defmethod tempi ((c mtp-composition)) m@46: (let ((results nil) m@46: (interval 0) m@46: (current nil)) m@46: (sequence:dosequence (event c) m@46: (when (and (%mtp-tempo event) m@46: (or (null current) m@46: (not (= (bpm current) (%mtp-tempo event))))) m@46: (unless (null current) m@46: (setf (duration current) interval) m@46: (push current results)) m@69: (let ((new (car (get-applicable-tempi event c)))) m@46: (setf interval 0 m@46: current new))) m@46: (incf interval (%mtp-deltast event)) m@46: (incf interval (duration event))) m@46: (when current m@46: (setf (duration current) interval) m@46: (push current results)) m@46: (nreverse results))) m@46: m@46: ;;; Events: Pitch m@46: m@46: (defmethod chromatic-pitch ((e mtp-event)) m@46: (make-chromatic-pitch (%mtp-cpitch e))) m@46: m@46: (defmethod midi-pitch-number ((e mtp-event)) m@46: (%mtp-cpitch e)) m@46: m@110: (defmethod diatonic-pitch-cp ((e mtp-event)) m@110: ;; MIPS morphetic pitch is relative to An0 while cpitch is relative to Cn2 m@110: (- (%mtp-cpitch e) 21)) m@110: m@110: (defmethod diatonic-pitch-mp ((e mtp-event)) m@82: ;; MIPS morphetic pitch is relative to An0 while mpitch is relative to Cn2 m@82: (- (%mtp-mpitch e) 12)) m@82: m@46: (defmethod diatonic-pitch ((e mtp-event)) m@110: (make-mips-pitch (diatonic-pitch-cp e) m@110: (diatonic-pitch-mp e))) m@82: m@84: (defmethod asa-pitch-string ((e mtp-event)) m@110: (asa-pitch-string (diatonic-pitch e))) m@84: m@82: #.(clsql:locally-enable-sql-reader-syntax) m@82: (defmethod middle-c ((e mtp-event)) m@82: (let ((cpitch (car (clsql:select [midc] :from [dataset] m@82: :where [= [dataset-id] (dataset-id e)] m@82: :flatp t :field-names nil)))) m@82: (make-mtp-event :cpitch cpitch :mpitch (* (/ cpitch 12) 7)))) m@82: #.(clsql:restore-sql-reader-syntax-state) m@79: m@79: ;;; Phrase boundaries m@79: m@98: (defmethod ground-truth-segmenter-before ((c mtp-composition)) m@98: (declare (ignore c)) m@98: (make-instance 'mtp-before-segmenter)) m@98: m@98: (defmethod ground-truth-segmenter-after ((c mtp-composition)) m@98: (declare (ignore c)) m@99: (make-instance 'mtp-after-segmenter)) m@98: m@98: (defmethod ground-truth-segmenter-before ((e mtp-event)) m@98: (declare (ignore e)) m@98: (make-instance 'mtp-before-segmenter)) m@98: m@98: (defmethod ground-truth-segmenter-after ((e mtp-event)) m@98: (declare (ignore e)) m@99: (make-instance 'mtp-after-segmenter)) m@98: m@79: (defmethod boundary-strength ((s mtp-before-segmenter) (e mtp-event) c) m@79: (declare (ignore s c)) m@79: (let ((phrase (%mtp-phrase e))) m@79: (case phrase m@79: (-1 1) m@79: (t 0)))) m@79: m@79: (defmethod boundary-strength ((s mtp-after-segmenter) (e mtp-event) c) m@79: (declare (ignore s c)) m@79: (let ((phrase (%mtp-phrase e))) m@79: (case phrase m@79: (1 1) m@79: (t 0))))