annotate implementations/geerdes/methods.lisp @ 127:dc862a0c7b9c

implementations/mtp/: add mtp-object darcs-hash:20070730142106-c0ce4-1db39f1d64c3b0f779dacf3474d1385e12b2d1cc.gz
author Marcus Pearce <m.pearce@gold.ac.uk>
date Mon, 30 Jul 2007 15:21:06 +0100
parents cf198383852d
children b849c4fc4c26
rev   line source
d@88 1 (cl:in-package #:amuse-geerdes)
d@88 2
d@88 3 ;;; Compositions
d@88 4
d@88 5 ;; identifiers
d@88 6 (defun g-id (cat-id)
d@100 7 "Make a geerdes-identifier based on a catalogue id"
d@88 8 (make-instance 'geerdes-identifier-cat-id :cat-id cat-id))
d@88 9 (defun g-id-file-id (file-id)
d@100 10 "Make a geerdes-identifier based on a catalogue id"
d@88 11 (make-instance 'geerdes-identifier-file-id :file-id file-id))
d@88 12
d@100 13 (defgeneric cat-id (object)
d@100 14 (:documentation "Return a catalogue id for object"))
d@100 15 (defgeneric file-id (object)
d@100 16 (:documentation "Return a file id (unique db id) for object"))
d@88 17 (defgeneric (setf cat-id) (value object))
d@88 18 (defgeneric (setf file-id) (value object))
d@88 19
d@88 20 (defmethod cat-id ((object geerdes-composition))
d@88 21 (%db-cat-id object))
d@88 22 (defmethod cat-id ((object geerdes-identifier-cat-id))
d@88 23 (slot-value object 'cat-id))
d@88 24 (defmethod file-id ((object geerdes-composition))
d@88 25 (%db-file-id object))
d@88 26 (defmethod file-id ((object geerdes-identifier-file-id))
d@88 27 (slot-value object 'file-id))
d@88 28 (defmethod (setf cat-id) (value (object geerdes-composition))
d@88 29 (setf (%db-cat-id object) value))
d@88 30 (defmethod (setf cat-id) (value (object geerdes-identifier-cat-id))
d@88 31 (setf (slot-value object 'cat-id) value))
d@88 32 (defmethod (setf file-id) (value (object geerdes-composition))
d@88 33 (setf (%db-file-id object) value))
d@88 34 (defmethod (setf file-id) (value (object geerdes-identifier-file-id))
d@88 35 (setf (slot-value object 'file-id) value))
d@88 36
d@88 37 ;; Composition
d@88 38
d@88 39 (defmethod get-composition ((identifier geerdes-identifier))
d@88 40 (let* ((composition (get-geerdes-composition identifier)))
d@88 41 (%initialise-notes composition)
d@88 42 (%initialise-constituents composition)))
d@88 43
d@88 44 (defgeneric get-geerdes-composition (identifier))
d@88 45 (defmethod get-geerdes-composition ((identifier geerdes-identifier-cat-id))
d@88 46 #.(clsql:locally-enable-sql-reader-syntax)
d@88 47 (let* ((cat-id (cat-id identifier))
d@88 48 (file-info (car (clsql:select [id] [timebase]
d@88 49 :from [midi_file]
d@88 50 :where [= [cat_id] cat-id]
d@88 51 :flatp t
d@88 52 :result-types :auto)))
d@88 53 (timebase (second file-info))
d@88 54 (file-id (first file-info))
d@88 55 (composition (make-instance 'geerdes-composition
d@88 56 :id identifier
d@88 57 :file-id file-id
d@88 58 :cat-id cat-id
d@88 59 :midi-timebase timebase)))
d@88 60 (setf (%midi-events composition) (get-db-events file-id)
d@88 61 (%midi-constituents composition) (get-db-constituents file-id))
d@88 62 #.(clsql:restore-sql-reader-syntax-state)
d@88 63 composition))
d@88 64 (defmethod get-geerdes-composition ((identifier geerdes-identifier-file-id))
d@88 65 #.(clsql:locally-enable-sql-reader-syntax)
d@88 66 (let* ((file-id (file-id identifier))
d@88 67 (file-info (car (clsql:select [cat_id] [timebase]
d@88 68 :from [midi_file]
d@88 69 :where [= [id] file-id]
d@88 70 :flatp t
d@88 71 :result-types :auto)))
d@88 72 (timebase (second file-info))
d@88 73 (cat-id (first file-info))
d@88 74 (composition (make-instance 'geerdes-composition
d@88 75 :id identifier
d@88 76 :cat-id cat-id
d@88 77 :file-id file-id
d@88 78 :midi-timebase timebase)))
d@88 79 (setf (%midi-events composition) (get-db-events file-id)
d@88 80 (%midi-constituents composition) (get-db-constituents file-id))
d@88 81 #.(clsql:restore-sql-reader-syntax-state)
d@88 82 composition))
d@88 83
d@88 84 (defun get-db-events (file-id)
d@88 85 (clsql:query
d@88 86 (concatenate 'string "
d@88 87 SELECT track, channel, start, duration, patch, pitch, velocity, id, event_id
d@88 88 FROM midi_event LEFT JOIN derived_midi_monody ON (id=event_id)
d@88 89 WHERE file_id=" (princ-to-string file-id)
d@88 90 " ORDER BY start")))
d@88 91 (defun get-db-constituents (file-id)
d@88 92 (clsql:query (concatenate 'string "
d@88 93 SELECT track, channel, start, duration,
d@88 94 param.num, param.value, pb.value, tp.value, ts.num, ts.denom
d@88 95 FROM midi_constituent c
d@88 96 LEFT JOIN midi_pb pb ON (id=pb.constituent_id)
d@88 97 LEFT JOIN midi_tempo tp ON (id=tp.constituent_id)
d@88 98 LEFT JOIN midi_timesig ts ON (id=ts.constituent_id)
d@88 99 LEFT JOIN midi_param param ON (id=param.constituent_id)
d@88 100 WHERE c.file_id=" (princ-to-string file-id)
d@101 101 " ORDER BY start")))
d@101 102
d@101 103 (defmethod monody ((composition geerdes-composition))
d@101 104 (unless (amuse-geerdes::%monody composition)
d@101 105 (setf (amuse-geerdes::%monody composition)
d@101 106 (get-monody composition)))
d@101 107 (amuse-geerdes::%monody composition))
d@101 108
d@101 109 (defgeneric get-monody (composition))
d@101 110 (defmethod get-monody ((composition geerdes-composition))
d@101 111 ;;; FIXME: FIXED-[THIS IS DANGEROUS - IT EDITS NOTE LENGTH]
d@101 112 ;; FIXME: As a result of this fix, notes no longer eq their monody
d@101 113 ;; versions
d@101 114 ;;; FIXME: This is a serious issue. Needs to be addressed by
d@101 115 ;; a proper implementation of constituent with annotations
d@101 116 ;;; From DTM: - Select notes
d@101 117 ;; on channel 4
d@101 118 (let ((vocal-line (loop for event being the elements of (lead-vocal-part composition)
d@101 119 collect (copy-event event))))
d@101 120 (when vocal-line
d@101 121 (let* ((comp (make-instance 'geerdes-composition
d@101 122 :file-id (file-id composition)
d@101 123 :time (timepoint composition)
d@101 124 :tempi (tempi composition)
d@101 125 :time-signatures (time-signatures composition)
d@101 126 :interval (duration composition)))
d@101 127 (vocal-composition (sequence:adjust-sequence comp
d@101 128 (length vocal-line)
d@101 129 :initial-contents vocal-line))
d@101 130 (monody (make-instance 'geerdes-monody
d@101 131 :time (timepoint composition)
d@101 132 :file-id (file-id composition)
d@101 133 :tempi (tempi composition)
d@101 134 :time-signatures (time-signatures composition)
d@101 135 :interval (duration composition))) ;; Overly inclusive?
d@101 136 (monody-events (monodificate vocal-composition)))
d@101 137 (sequence:adjust-sequence monody (length monody-events)
d@101 138 :initial-contents monody-events)))))
d@101 139
d@101 140 (defgeneric lead-vocal-part (time-ordered-constituent)
d@101 141 (:method (toc) (remove-if-not #'lead-vocalp toc)))
d@101 142
d@101 143 (defgeneric lead-vocalp (event)
d@101 144 (:method (e) (declare (ignore e)) nil))
m@103 145 (defmethod lead-vocalp ((event geerdes-pitched-event))
d@101 146 (= (midi-channel event) 4))
d@114 147
d@114 148 (defmethod crotchet ((identifier geerdes-identifier))
d@115 149 (make-instance 'floating-period :interval 1))
d@115 150
d@115 151 (defmethod get-applicable-time-signatures ((anchored-period anchored-period) (composition midi-composition))
d@115 152 (%find-overlapping anchored-period (time-signatures composition)))
d@115 153 (defmethod get-applicable-tempi ((anchored-period anchored-period) (composition midi-composition))
d@115 154 (%find-overlapping anchored-period (tempi composition)))
d@115 155 (defmethod get-applicable-key-signatures ((anchored-period anchored-period) (composition midi-composition))
d@115 156 (%find-overlapping anchored-period (key-signatures composition)))
d@115 157
d@115 158 (defun %find-overlapping (period1 period-list)
d@115 159 (let ((result-list))
d@115 160 (dolist (period2 period-list result-list)
d@115 161 (cond
d@115 162 ((before period1 period2)
d@115 163 (return-from %find-overlapping (reverse result-list)))
d@115 164 ((not (before period2 period1))
d@115 165 (push period2 result-list))))))