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