d@88
|
1 (cl:in-package #:amuse-geerdes)
|
d@88
|
2
|
j@288
|
3 ;; Identifiers
|
j@288
|
4 ;; FIXME: use standard constructor names?
|
j@288
|
5 ;; FIXME: use standard composition-identifier?
|
j@288
|
6 (defun g-id (cat-id)
|
j@288
|
7 "Make a geerdes-identifier based on a catalogue id"
|
j@288
|
8 (make-instance 'geerdes-identifier-cat-id
|
j@288
|
9 :cat-id cat-id))
|
j@288
|
10
|
j@288
|
11 (defun g-id-file-id (file-id)
|
j@288
|
12 "Make a geerdes-identifier based on the file id. This is used as
|
j@288
|
13 the standard composition-id."
|
j@288
|
14 (make-instance 'geerdes-identifier-file-id
|
j@288
|
15 :file-id file-id))
|
j@288
|
16
|
j@288
|
17 (defun make-geerdes-event-identifier (event-id)
|
j@288
|
18 (make-instance 'geerdes-event-identifier
|
j@288
|
19 :event-id event-id))
|
j@288
|
20
|
j@288
|
21 ;; Events
|
j@288
|
22
|
d@88
|
23 (defgeneric %initialise-notes (composition))
|
d@88
|
24 (defmethod %initialise-notes ((composition geerdes-composition))
|
d@88
|
25 (let ((notes) (l 0) (last-time 0) (monody-notes)
|
d@88
|
26 (monody (make-instance 'geerdes-monody :file-id (file-id composition)))
|
j@281
|
27 (timebase (midi-timebase composition)))
|
d@88
|
28 (dolist (row (%midi-events composition))
|
d@88
|
29 (let* ((note (if (pitched-row-p row)
|
d@136
|
30 (make-geerdes-pitched-event (%fast-pitch row)
|
d@136
|
31 (%fast-velocity row)
|
d@136
|
32 (%fast-patch row)
|
d@136
|
33 (%fast-channel row)
|
d@136
|
34 (%fast-track row)
|
d@136
|
35 (%fast-onset row timebase)
|
d@136
|
36 (%fast-duration row timebase)
|
j@298
|
37 (%fast-id row)
|
j@298
|
38 composition)
|
d@136
|
39 (make-geerdes-percussive-event (%fast-pitch row)
|
d@136
|
40 (%fast-velocity row)
|
d@136
|
41 (%fast-patch row)
|
d@136
|
42 (%fast-channel row)
|
d@136
|
43 (%fast-track row)
|
d@136
|
44 (%fast-onset row timebase)
|
d@136
|
45 (%fast-duration row timebase)
|
j@298
|
46 (%fast-id row)
|
j@298
|
47 composition))))
|
d@88
|
48 (when (%fast-monodyp row)
|
d@133
|
49 (let ((monody-note (copy-event note)))
|
d@133
|
50 (setf (duration monody-note) (%fast-monody-duration row timebase))
|
d@133
|
51 (push monody-note monody-notes)))
|
d@88
|
52 (when (> (timepoint (cut-off note)) last-time)
|
d@88
|
53 (setf last-time (timepoint (cut-off note))))
|
d@88
|
54 (push note notes)
|
d@88
|
55 (incf l)))
|
d@88
|
56 (sequence:adjust-sequence composition l :initial-contents (reverse notes))
|
d@88
|
57 (setf (duration composition) last-time
|
d@88
|
58 (timepoint composition) 0)
|
d@88
|
59 (when monody-notes
|
d@88
|
60 (setf (%monody composition) (sequence:adjust-sequence monody (length monody-notes)
|
d@88
|
61 :initial-contents (reverse monody-notes))
|
d@88
|
62 (timepoint (%monody composition)) (timepoint (elt monody 0))
|
d@88
|
63 (duration (%monody composition)) (- (timepoint (cut-off (car monody-notes)))
|
d@88
|
64 (timepoint (elt monody 0)))))
|
d@88
|
65 composition))
|
d@88
|
66
|
d@88
|
67 (defgeneric %initialise-constituents (composition))
|
d@88
|
68 (defmethod %initialise-constituents ((composition geerdes-composition))
|
d@88
|
69 ;; FIXME: Should the duration of composition be affected by this? On
|
d@88
|
70 ;; the one hand, it makes no difference to the musical content, but
|
d@88
|
71 ;; on the other, it seems illogical to reach outside the period.
|
j@281
|
72 (let ((timebase (midi-timebase composition))
|
d@88
|
73 (time-sigs)
|
d@88
|
74 (tempi)
|
d@88
|
75 (mystery 0))
|
d@88
|
76 (dolist (row (%midi-constituents composition))
|
d@88
|
77 (cond
|
d@88
|
78 ((%fast-tempo row)
|
d@136
|
79 (push (make-standard-tempo-period
|
d@88
|
80 (microsecond-per-crotchet-to-bpm
|
d@88
|
81 (%fast-tempo row))
|
d@88
|
82 (%fast-onset row timebase)
|
d@88
|
83 (%fast-duration row timebase))
|
d@88
|
84 tempi))
|
d@88
|
85 ((%fast-numerator row)
|
d@136
|
86 (push (make-standard-time-signature-period
|
d@88
|
87 (%fast-numerator row)
|
d@88
|
88 (%fast-denominator row)
|
d@88
|
89 (%fast-onset row timebase)
|
d@88
|
90 (%fast-duration row timebase))
|
d@88
|
91 time-sigs))
|
d@88
|
92 (t (incf mystery))))
|
d@88
|
93 (setf (time-signatures composition) (reverse time-sigs)
|
d@88
|
94 (tempi composition) (reverse tempi))
|
d@88
|
95 (when (%monody composition)
|
d@88
|
96 (setf (time-signatures (%monody composition)) (time-signatures composition)
|
d@88
|
97 (tempi (%monody composition)) (tempi composition)))
|
d@88
|
98 (format t "There are ~D constituents not processed~%" mystery)
|
d@88
|
99 composition))
|
d@88
|
100
|
d@88
|
101 (defun %fast-track (row)
|
d@88
|
102 (first row))
|
d@88
|
103 (defun %fast-channel (row)
|
d@88
|
104 (second row))
|
d@88
|
105 (defun %fast-onset (row timebase)
|
d@88
|
106 (/ (third row) timebase))
|
d@88
|
107 (defun %fast-duration (row timebase)
|
d@88
|
108 (/ (fourth row) timebase))
|
d@88
|
109 (defun %fast-patch (event-row)
|
d@88
|
110 (fifth event-row))
|
d@88
|
111 (defun %fast-pitch (event-row)
|
d@88
|
112 (sixth event-row))
|
d@88
|
113 (defun %fast-velocity (event-row)
|
d@88
|
114 (seventh event-row))
|
d@88
|
115 (defun %fast-id (event-row)
|
d@88
|
116 (eighth event-row))
|
d@88
|
117 (defun %fast-monodyp (event-row)
|
d@88
|
118 (ninth event-row))
|
d@133
|
119 (defun %fast-monody-duration (event-row timebase)
|
d@133
|
120 (/ (tenth event-row) timebase))
|
d@88
|
121
|
d@88
|
122 (defun %fast-tempo (tp-row)
|
d@88
|
123 (eighth tp-row))
|
d@88
|
124 (defun %fast-numerator (ts-row)
|
d@88
|
125 (ninth ts-row))
|
d@88
|
126 (defun %fast-denominator (ts-row)
|
d@88
|
127 (tenth ts-row))
|
d@88
|
128
|
d@88
|
129 (defun pitched-row-p (event-row)
|
d@88
|
130 (and (not (= (%fast-channel event-row) 10))
|
d@88
|
131 (< (%fast-patch event-row) 112)))
|
d@88
|
132
|
j@288
|
133 (defun make-geerdes-pitched-event (pitch-number velocity patch channel
|
j@298
|
134 track onset duration event-id
|
j@298
|
135 composition)
|
d@88
|
136 (make-instance 'geerdes-pitched-event
|
d@88
|
137 :number pitch-number
|
d@88
|
138 :velocity velocity
|
d@88
|
139 :patch patch
|
d@88
|
140 :channel channel
|
d@88
|
141 :track track
|
d@88
|
142 :time onset
|
d@88
|
143 :interval duration
|
j@288
|
144 :identifier (make-geerdes-event-identifier
|
j@298
|
145 event-id)
|
j@298
|
146 :composition composition))
|
d@88
|
147
|
d@88
|
148 (defun make-geerdes-percussive-event (pitch-number velocity patch
|
j@288
|
149 channel track onset duration
|
j@298
|
150 event-id composition)
|
d@88
|
151 (make-instance 'geerdes-percussive-event
|
d@88
|
152 :sound pitch-number
|
d@88
|
153 :velocity velocity
|
d@88
|
154 :patch patch
|
d@88
|
155 :channel channel
|
d@88
|
156 :track track
|
d@88
|
157 :time onset
|
d@88
|
158 :interval duration
|
j@288
|
159 :identifier (make-geerdes-event-identifier
|
j@298
|
160 event-id)
|
j@298
|
161 :composition composition))
|
d@88
|
162
|
d@88
|
163 (defmethod copy-event ((event geerdes-pitched-event))
|
d@88
|
164 (with-slots ((channel amuse-midi::channel)
|
d@88
|
165 (track amuse-midi::track)
|
d@88
|
166 (number amuse::number)
|
d@88
|
167 (time amuse::time)
|
d@88
|
168 (interval amuse::interval)
|
d@88
|
169 (velocity amuse-midi::velocity)
|
j@288
|
170 (patch amuse-midi::patch)
|
j@298
|
171 identifier
|
j@298
|
172 composition)
|
d@88
|
173 event
|
d@88
|
174 (make-instance 'geerdes-pitched-event
|
d@88
|
175 :channel channel
|
d@88
|
176 :track track
|
d@88
|
177 :number number
|
d@88
|
178 :time time
|
d@88
|
179 :interval interval
|
d@88
|
180 :velocity velocity
|
d@88
|
181 :patch patch
|
j@298
|
182 :identifier identifier
|
j@298
|
183 :composition composition)))
|
j@288
|
184
|
d@133
|
185 (defmethod copy-event ((event geerdes-percussive-event))
|
d@88
|
186 (with-slots ((channel amuse-midi::channel)
|
d@88
|
187 (track amuse-midi::track)
|
d@88
|
188 (time amuse::time)
|
d@88
|
189 (interval amuse::interval)
|
d@88
|
190 (velocity amuse-midi::velocity)
|
d@88
|
191 (patch amuse-midi::patch)
|
j@288
|
192 (sound amuse-midi::sound)
|
j@298
|
193 identifier
|
j@298
|
194 composition)
|
d@88
|
195 event
|
d@88
|
196 (make-instance 'geerdes-percussive-event
|
d@133
|
197 :channel channel
|
d@88
|
198 :track track
|
d@88
|
199 :time time
|
d@88
|
200 :interval interval
|
d@88
|
201 :velocity velocity
|
d@88
|
202 :patch patch
|
d@88
|
203 :sound sound
|
j@298
|
204 :identifier identifier
|
j@298
|
205 :composition composition)))
|
d@88
|
206
|
d@88
|
207 ;; We want any function that generates a sequence from a geerdes
|
d@88
|
208 ;; composition to preserve all slot values:
|
d@154
|
209 #+nil
|
d@88
|
210 (defmethod sequence:make-sequence-like :around ((o geerdes-composition)
|
d@88
|
211 length
|
d@88
|
212 &key (initial-element nil iep)
|
d@88
|
213 (initial-contents nil icp))
|
d@88
|
214 (declare (ignore iep icp length initial-element initial-contents))
|
d@88
|
215 (let ((result (call-next-method)))
|
d@88
|
216 (setf (%db-entry result) (%db-entry o))
|
d@88
|
217 result))
|