m@46
|
1 (cl:in-package #:amuse-mtp)
|
m@46
|
2
|
m@46
|
3 ;;; Compositions
|
m@46
|
4
|
m@46
|
5 #.(clsql:locally-enable-sql-reader-syntax)
|
m@46
|
6
|
m@87
|
7 (defvar *event-attributes*
|
m@87
|
8 (list [dataset-id] [composition-id] [event-id]
|
m@87
|
9 [onset] [dur] [deltast] [cpitch] [mpitch] [accidental] [keysig] [mode]
|
m@87
|
10 [barlength] [pulses] [phrase] [tempo] [dyn] [voice]))
|
m@87
|
11
|
m@53
|
12 (defgeneric get-dataset (identifer))
|
m@53
|
13
|
m@53
|
14 (defmethod get-dataset ((identifier mtp-dataset-identifier))
|
m@53
|
15 (let* ((dataset-id (dataset-id identifier))
|
m@53
|
16 (where-clause [= [dataset-id] dataset-id])
|
m@87
|
17 (db-dataset (clsql:select [*] :from [mtp-dataset] :where where-clause))
|
m@87
|
18 (db-compositions (clsql:select [composition-id][description]
|
m@87
|
19 :from [mtp-composition]
|
m@87
|
20 :order-by '(([composition-id] :asc))
|
m@87
|
21 :where where-clause))
|
m@87
|
22 (db-events (apply #'clsql:select
|
m@87
|
23 (append *event-attributes*
|
m@87
|
24 (list :from [mtp-event]
|
m@87
|
25 :order-by '(([composition-id] :asc)
|
m@87
|
26 ([event-id] :asc))
|
m@87
|
27 :where where-clause))))
|
m@87
|
28 (dataset (make-mtp-dataset :dataset-id (first db-dataset)
|
m@87
|
29 :description (second db-dataset)
|
m@87
|
30 :timebase (third db-dataset)
|
m@87
|
31 :midc (fourth db-dataset)))
|
m@53
|
32 (compositions nil)
|
m@87
|
33 (events nil))
|
m@87
|
34 ;; for each db-composition
|
m@87
|
35 (dolist (dbc db-compositions)
|
m@87
|
36 (let ((composition-id (first dbc))
|
m@87
|
37 (description (second dbc)))
|
m@87
|
38 ;; for each db-event
|
m@87
|
39 (do* ((dbes db-events (cdr dbes))
|
m@87
|
40 (dbe (car dbes) (car dbes))
|
m@87
|
41 (cid (second dbe) (second dbe)))
|
m@87
|
42 ((or (null dbes) (not (= cid composition-id)))
|
m@87
|
43 (setf db-events dbes))
|
m@87
|
44 (when dbe
|
m@87
|
45 (push (db-event->mtp-event dbe) events)))
|
m@87
|
46 (let* ((interval (+ (timepoint (car events)) (duration (car events))))
|
m@87
|
47 (composition
|
m@87
|
48 (make-mtp-composition :dataset-id dataset-id
|
m@87
|
49 :composition-id composition-id
|
m@87
|
50 :description description
|
m@87
|
51 :time 0
|
m@87
|
52 :interval interval)))
|
m@87
|
53 (sequence:adjust-sequence composition (length events)
|
m@87
|
54 :initial-contents (nreverse events))
|
m@87
|
55 (setf events nil)
|
m@87
|
56 (push composition compositions))))
|
m@53
|
57 (sequence:adjust-sequence dataset (length compositions)
|
m@53
|
58 :initial-contents (nreverse compositions))
|
m@53
|
59 dataset))
|
m@53
|
60
|
m@46
|
61 (defmethod get-composition ((identifier mtp-composition-identifier))
|
m@46
|
62 (let* ((dataset-id (dataset-id identifier))
|
m@46
|
63 (composition-id (composition-id identifier))
|
m@46
|
64 (where-clause [and [= [dataset-id] dataset-id]
|
m@46
|
65 [= [composition-id] composition-id]])
|
m@46
|
66 (description
|
m@51
|
67 (car (clsql:select [description] :from [mtp-composition]
|
m@46
|
68 :where where-clause :flatp t :field-names nil)))
|
m@87
|
69 (db-events (apply #'clsql:select
|
m@87
|
70 (append *event-attributes*
|
m@87
|
71 (list :from [mtp-event]
|
m@87
|
72 :order-by '(([event-id] :asc))
|
m@87
|
73 :where where-clause))))
|
m@46
|
74 (events nil))
|
m@87
|
75 (dolist (e db-events)
|
m@87
|
76 (push (db-event->mtp-event e) events))
|
m@46
|
77 (let* ((interval (+ (timepoint (car events)) (duration (car events))))
|
m@46
|
78 (composition
|
m@46
|
79 (make-mtp-composition :dataset-id dataset-id
|
m@46
|
80 :composition-id composition-id
|
m@46
|
81 :description description
|
m@46
|
82 :time 0
|
m@46
|
83 :interval interval)))
|
m@46
|
84 (sequence:adjust-sequence composition (length events)
|
m@46
|
85 :initial-contents (nreverse events))
|
m@46
|
86 composition)))
|
m@46
|
87
|
m@90
|
88 #.(clsql:restore-sql-reader-syntax-state)
|
m@90
|
89
|
m@87
|
90 (defun db-event->mtp-event (db-event)
|
m@87
|
91 (let* ((slots ; the order must match *event-attributes*
|
m@87
|
92 '(amuse::time amuse::interval deltast cpitch mpitch accidental
|
m@87
|
93 keysig mode barlength pulses phrase tempo dyn voice))
|
m@46
|
94 (mtp-event
|
m@87
|
95 (make-mtp-event :dataset-id (first db-event)
|
m@87
|
96 :composition-id (second db-event)
|
m@87
|
97 :event-id (third db-event))))
|
m@87
|
98 (do* ((slts slots (cdr slts))
|
m@87
|
99 (db-atts (nthcdr 3 db-event) (cdr db-atts)))
|
m@87
|
100 ((null slts) mtp-event)
|
m@87
|
101 (setf (slot-value mtp-event (car slts)) (car db-atts)))))
|
m@90
|
102
|
m@90
|
103 ;;; Monodies
|
m@90
|
104
|
m@90
|
105 (defmethod monody ((identifier mtp-composition-identifier))
|
m@90
|
106 (monody (get-composition identifier)))
|
m@90
|
107
|
m@90
|
108 (defmethod monody ((c mtp-composition))
|
m@90
|
109 (let ((monody (make-instance 'mtp-monody
|
m@90
|
110 :dataset-id (dataset-id c)
|
m@90
|
111 :composition-id (composition-id c)
|
m@90
|
112 :description (description c)
|
m@90
|
113 :time 0
|
m@90
|
114 :interval (duration c)))
|
m@90
|
115 (events nil)
|
m@90
|
116 (monody-voice 1))
|
m@90
|
117 (sequence:dosequence (event c)
|
m@90
|
118 (when (= (%mtp-voice event) monody-voice)
|
m@90
|
119 (push event events)))
|
m@90
|
120 (sequence:adjust-sequence
|
m@90
|
121 monody (length events)
|
m@90
|
122 :initial-contents (sort events #'< :key #'amuse:timepoint))
|
m@90
|
123 monody))
|
m@46
|
124
|
m@46
|
125 ;;; Constituents from compositions: time-signatures
|
m@46
|
126
|
m@87
|
127 (defgeneric timebase (object))
|
m@87
|
128
|
m@87
|
129 (defmethod timebase ((dataset mtp-dataset))
|
m@87
|
130 (dataset-timebase dataset))
|
m@87
|
131
|
m@46
|
132 #.(clsql:locally-enable-sql-reader-syntax)
|
m@87
|
133 (defmethod timebase ((composition mtp-composition))
|
m@87
|
134 (car (clsql:select [timebase] :from [mtp-dataset]
|
m@87
|
135 :where [= [dataset-id]
|
m@87
|
136 (dataset-id composition)]
|
m@87
|
137 :flatp t
|
m@87
|
138 :field-names nil)))
|
m@87
|
139 (defmethod timebase ((event mtp-event))
|
m@51
|
140 (car (clsql:select [timebase] :from [mtp-dataset]
|
m@46
|
141 :where [= [dataset-id]
|
m@46
|
142 (dataset-id event)]
|
m@46
|
143 :flatp t
|
m@46
|
144 :field-names nil)))
|
m@46
|
145 #.(clsql:restore-sql-reader-syntax-state)
|
m@46
|
146
|
m@69
|
147 (defmethod get-applicable-time-signatures ((e mtp-event) c)
|
m@69
|
148 (declare (ignore c))
|
m@69
|
149 (let ((pulses (%mtp-pulses e))
|
m@69
|
150 (barlength (%mtp-barlength e))
|
m@87
|
151 (timebase (timebase e)))
|
m@69
|
152 (list
|
m@69
|
153 (amuse:make-basic-time-signature pulses
|
m@69
|
154 (/ timebase (/ barlength pulses))
|
m@69
|
155 (timepoint e)
|
m@69
|
156 (duration e)))))
|
m@69
|
157
|
m@46
|
158 (defmethod time-signatures ((c mtp-composition))
|
m@46
|
159 (let ((results nil)
|
m@46
|
160 (interval 0)
|
m@46
|
161 (current nil))
|
m@46
|
162 (sequence:dosequence (event c)
|
m@70
|
163 (let ((ts (car (get-applicable-time-signatures event c))))
|
m@46
|
164 (when (and (%mtp-barlength event)
|
m@46
|
165 (%mtp-pulses event)
|
m@46
|
166 (or (null current)
|
m@46
|
167 (not (time-signature-equal ts current))))
|
m@46
|
168 (unless (null current)
|
m@46
|
169 (setf (duration current) interval)
|
m@46
|
170 (push current results))
|
m@46
|
171 (setf interval 0
|
m@46
|
172 current ts)))
|
m@46
|
173 (incf interval (%mtp-deltast event))
|
m@46
|
174 (incf interval (duration event)))
|
m@46
|
175 (when current
|
m@46
|
176 (setf (duration current) interval)
|
m@46
|
177 (push current results))
|
m@46
|
178 (nreverse results)))
|
m@46
|
179
|
m@46
|
180 ;;; Constituents from compositions: key-signatures
|
m@46
|
181
|
m@69
|
182 (defmethod get-applicable-key-signatures ((e mtp-event) c)
|
m@69
|
183 (declare (ignore c))
|
m@69
|
184 (let* ((sharps (%mtp-keysig e))
|
m@68
|
185 (mode (%mtp-mode e))
|
m@69
|
186 (midi-mode (and mode (if (= mode 0) 0 1))))
|
m@69
|
187 (list (amuse:make-midi-key-signature sharps midi-mode
|
m@69
|
188 (timepoint e)
|
m@69
|
189 (duration e)))))
|
m@46
|
190
|
m@68
|
191 (defmethod key-signatures ((c mtp-composition))
|
m@46
|
192 (let ((results nil)
|
m@46
|
193 (interval 0)
|
m@46
|
194 (current nil))
|
m@46
|
195 (sequence:dosequence (event c)
|
m@69
|
196 (let ((ks (car (get-applicable-key-signatures event c))))
|
m@46
|
197 (when (and (%mtp-keysig event)
|
m@46
|
198 (%mtp-mode event)
|
m@46
|
199 (or (null current)
|
m@46
|
200 (not (key-signature-equal ks current))))
|
m@46
|
201 (unless (null current)
|
m@46
|
202 (setf (duration current) interval)
|
m@46
|
203 (push current results))
|
m@46
|
204 (setf interval 0
|
m@46
|
205 current ks)))
|
m@46
|
206 (incf interval (%mtp-deltast event))
|
m@46
|
207 (incf interval (duration event)))
|
m@46
|
208 (when current
|
m@46
|
209 (setf (duration current) interval)
|
m@46
|
210 (push current results))
|
m@46
|
211 (nreverse results)))
|
m@46
|
212
|
m@46
|
213 ;;; Constituents from compositions: tempi
|
m@46
|
214
|
m@69
|
215 (defmethod get-applicable-tempi ((e mtp-event) c)
|
m@69
|
216 (declare (ignore c))
|
m@71
|
217 (list (amuse:make-tempo (%mtp-tempo e)
|
m@71
|
218 (timepoint e)
|
m@71
|
219 (duration e))))
|
m@69
|
220
|
m@46
|
221 (defmethod tempi ((c mtp-composition))
|
m@46
|
222 (let ((results nil)
|
m@46
|
223 (interval 0)
|
m@46
|
224 (current nil))
|
m@46
|
225 (sequence:dosequence (event c)
|
m@46
|
226 (when (and (%mtp-tempo event)
|
m@46
|
227 (or (null current)
|
m@46
|
228 (not (= (bpm current) (%mtp-tempo event)))))
|
m@46
|
229 (unless (null current)
|
m@46
|
230 (setf (duration current) interval)
|
m@46
|
231 (push current results))
|
m@69
|
232 (let ((new (car (get-applicable-tempi event c))))
|
m@46
|
233 (setf interval 0
|
m@46
|
234 current new)))
|
m@46
|
235 (incf interval (%mtp-deltast event))
|
m@46
|
236 (incf interval (duration event)))
|
m@46
|
237 (when current
|
m@46
|
238 (setf (duration current) interval)
|
m@46
|
239 (push current results))
|
m@46
|
240 (nreverse results)))
|
m@46
|
241
|
m@46
|
242 ;;; Events: Pitch
|
m@46
|
243
|
m@46
|
244 (defmethod chromatic-pitch ((e mtp-event))
|
m@46
|
245 (make-chromatic-pitch (%mtp-cpitch e)))
|
m@46
|
246
|
m@46
|
247 (defmethod midi-pitch-number ((e mtp-event))
|
m@46
|
248 (%mtp-cpitch e))
|
m@46
|
249
|
m@82
|
250 (defmethod meredith-morphetic-pitch-number ((e mtp-event))
|
m@82
|
251 ;; MIPS morphetic pitch is relative to An0 while mpitch is relative to Cn2
|
m@82
|
252 (- (%mtp-mpitch e) 12))
|
m@82
|
253
|
m@82
|
254 (defmethod mips-pitch ((e mtp-event))
|
m@82
|
255 (make-mips-pitch (meredith-chromatic-pitch-number e)
|
m@82
|
256 (meredith-morphetic-pitch-number e)))
|
m@82
|
257
|
m@46
|
258 (defmethod diatonic-pitch ((e mtp-event))
|
m@82
|
259 (diatonic-pitch (mips-pitch e)))
|
m@82
|
260
|
m@84
|
261 (defmethod asa-pitch-string ((e mtp-event))
|
m@84
|
262 (asa-pitch-string (mips-pitch e)))
|
m@84
|
263
|
m@82
|
264 #.(clsql:locally-enable-sql-reader-syntax)
|
m@82
|
265 (defmethod middle-c ((e mtp-event))
|
m@82
|
266 (let ((cpitch (car (clsql:select [midc] :from [dataset]
|
m@82
|
267 :where [= [dataset-id] (dataset-id e)]
|
m@82
|
268 :flatp t :field-names nil))))
|
m@82
|
269 (make-mtp-event :cpitch cpitch :mpitch (* (/ cpitch 12) 7))))
|
m@82
|
270 #.(clsql:restore-sql-reader-syntax-state)
|
m@79
|
271
|
m@79
|
272 ;;; Phrase boundaries
|
m@79
|
273
|
m@79
|
274 (defmethod boundary-strength ((s mtp-before-segmenter) (e mtp-event) c)
|
m@79
|
275 (declare (ignore s c))
|
m@79
|
276 (let ((phrase (%mtp-phrase e)))
|
m@79
|
277 (case phrase
|
m@79
|
278 (-1 1)
|
m@79
|
279 (t 0))))
|
m@79
|
280
|
m@79
|
281 (defmethod boundary-strength ((s mtp-after-segmenter) (e mtp-event) c)
|
m@79
|
282 (declare (ignore s c))
|
m@79
|
283 (let ((phrase (%mtp-phrase e)))
|
m@79
|
284 (case phrase
|
m@79
|
285 (1 1)
|
m@79
|
286 (t 0))))
|