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)))))) |