m@24
|
1 (cl:in-package #:amuse)
|
m@24
|
2
|
m@24
|
3 ;;; Pulling compositions from the database
|
m@24
|
4
|
d@123
|
5 (defgeneric get-composition (identifier)
|
d@123
|
6 (:documentation "Returns a composition of type dependant on
|
d@123
|
7 identifier"))
|
m@24
|
8
|
m@89
|
9 (defgeneric monody (object)
|
m@89
|
10 (:documentation "Returns a monody."))
|
m@89
|
11 (defgeneric ensure-monody (object)
|
m@89
|
12 (:documentation "Returns a generalised boolean."))
|
m@89
|
13
|
d@33
|
14 ;;; Getting constituents from compositions
|
d@33
|
15 ;; IS this the mechanism we want to use
|
d@72
|
16 (defgeneric time-signatures (composition)
|
d@72
|
17 (:documentation "Returns all time-signatures in a composition
|
d@72
|
18 Probably shouldn't be exported - can be replaced
|
d@72
|
19 by (get-applicable-time-signature commposition composition)"))
|
d@72
|
20 (defgeneric (setf time-signatures) (sequence composition)
|
d@72
|
21 (:documentation "Sets all time-signatures in a composition.
|
d@72
|
22 Is this wanted here?"))
|
d@72
|
23 (defgeneric tempi (composition)
|
d@72
|
24 (:documentation "Returns all tempi in a composition Probably
|
d@72
|
25 shouldn't be exported - can be replaced
|
d@72
|
26 by (get-applicable-tempi commposition composition)"))
|
d@72
|
27 (defgeneric (setf tempi) (sequence composition)
|
d@72
|
28 (:documentation "Sets all tempi in a composition.
|
d@72
|
29 Is this wanted here?"))
|
d@72
|
30 (defgeneric key-signatures (composition)
|
d@72
|
31 (:documentation "Returns all key-signatures in a composition
|
d@72
|
32 Probably shouldn't be exported - can be replaced
|
d@72
|
33 by (get-applicable-key-signature commposition composition)"))
|
d@72
|
34 (defgeneric (setf key-signatures) (sequence composition)
|
d@72
|
35 (:documentation "Sets all key sigs in a composition.
|
d@72
|
36 Is this wanted here?"))
|
d@33
|
37
|
m@24
|
38 ;;; Simple Accessors
|
m@24
|
39
|
m@24
|
40 ;; pitch-based
|
m@24
|
41
|
m@24
|
42 (defgeneric pitch (object &key kind)) ; ? Maybe this returns the pitch
|
m@24
|
43 ; in its ur form?
|
c@106
|
44 (defgeneric chromatic-pitch (pitch-designator))
|
c@106
|
45 (defgeneric diatonic-pitch (pitch-designator))
|
m@24
|
46 (defgeneric frequency (object)) ;?
|
m@81
|
47
|
m@86
|
48 (defgeneric octave (pitch-designator)
|
m@86
|
49 (:documentation "Return an integer representing the octave of
|
m@86
|
50 pitch-designator where middle c is defined to be the lowest pitch in
|
m@86
|
51 octave 4."))
|
m@86
|
52
|
c@106
|
53 (defgeneric diatonic-pitch-octave (pitch-designator)
|
c@106
|
54 (:documentation "Return an integer representing the diatonic octave
|
c@106
|
55 of PITCH-DESIGNATOR."))
|
c@106
|
56
|
m@86
|
57 (defgeneric diatonic-pitch-accidental (pitch-designator)
|
m@86
|
58 (:documentation "Return an integer representing the inflection of a
|
m@86
|
59 diatonic pitch where where negative values indicate numbers of flats,
|
m@86
|
60 0 indicates natural and positive values indicate numbers of sharps."))
|
m@86
|
61
|
c@108
|
62 (defgeneric diatonic-pitch-mp (pitch-designator)
|
c@108
|
63 (:documentation "Return an integer representing the morphetic pitch
|
c@108
|
64 \(in MIPS terms) of a diatonic pitch."))
|
c@108
|
65 (defgeneric diatonic-pitch-cp (pitch-designator)
|
c@108
|
66 (:documentation "Return an integer representing the chromatic pitch
|
c@108
|
67 \(in MIPS terms) of a diatonic pitch."))
|
c@108
|
68
|
m@81
|
69 (defgeneric middle-c (pitch-designator)
|
m@81
|
70 (:documentation "Returns the value of middle C in the particular
|
m@81
|
71 representation of pitch used by PITCH-DESIGNATOR."))
|
d@72
|
72 (defgeneric midi-pitch-number (pitch-designator)
|
d@72
|
73 (:documentation "Takes a pitch-designator (usually a pitched
|
d@72
|
74 event) and returns an integer between 0 and 127 representing
|
d@72
|
75 the chromatic pitch designated (60=middle C, 48 the C below
|
d@72
|
76 that, etc.)"))
|
m@81
|
77 (defgeneric asa-pitch-string (pitch-designator)
|
m@81
|
78 (:documentation "Returns a string representing the designated ASA
|
m@81
|
79 pitch name which has three parts: a letter name in the set
|
m@81
|
80 {A,B,C,D,E,F,G}, an inflection in the set {n,f,s,ff,ss,fff,sss,...}
|
m@81
|
81 and an octave number. E.g., Cn4 = Middle C."))
|
c@112
|
82 (defgeneric asa-interval-string (pitch-designator)
|
c@112
|
83 (:documentation "Returns a string representing the designated ASA
|
c@112
|
84 interval name which has two or three parts: a direction in the set
|
c@112
|
85 {r,f} (absent for unisons/primes), a type in the set
|
c@112
|
86 {p,ma,mi,a,d,aa,dd,aaa,ddd,...}, and a size number. E.g. rma2 =
|
c@112
|
87 rising major second."))
|
m@81
|
88 (defgeneric diatonic-pitch-name (pitch-designator)
|
m@81
|
89 (:documentation "Returns a char in the set
|
m@81
|
90 {#\A,#\B,#\C,#\D,#\E,#\F,#\G}, representing the pitch name of
|
m@81
|
91 PITCH-DESIGNATOR."))
|
m@24
|
92 (defgeneric pitch-class (pitch-designator)
|
d@72
|
93 (:documentation "Takes a pitch-designator (usually a pitched
|
d@72
|
94 event) and returns an integer between 0 and 12 representing
|
d@72
|
95 the octave-independant pitch, with c=0, c#=1, etc.")
|
m@24
|
96 (:method (p) (mod (midi-pitch-number p) 12)))
|
m@24
|
97 (defgeneric span (pitch-interval-designator))
|
m@24
|
98
|
m@24
|
99 ;; time
|
m@24
|
100
|
d@123
|
101 (defgeneric duration (period-designator)
|
d@123
|
102 (:documentation "Returns a value. Probably should only apply do
|
d@123
|
103 periods (rather than designators?)"))
|
d@123
|
104 (defgeneric (setf duration) (value period-designator)
|
d@123
|
105 (:documentation "As with duration, should probably work only
|
d@123
|
106 with periods"))
|
d@123
|
107 (defgeneric timepoint (moment-designator)
|
d@123
|
108 (:documentation "Returns a value for a moment. Does this make
|
d@123
|
109 any sense on a designator?"))
|
d@123
|
110 (defgeneric (setf timepoint) (value moment-designator)
|
d@123
|
111 (:documentation "Sets timepoint. What does this mean for a
|
d@123
|
112 designator?"))
|
m@24
|
113 (defgeneric cut-off (anchored-period-designator) ; name?
|
d@72
|
114 (:documentation "Returns a <moment> representing the point at
|
d@121
|
115 which the anchored period has ended. By default, is calculated
|
d@121
|
116 as the result of running time+ on the onset and period of the
|
d@121
|
117 object.")
|
m@24
|
118 (:method (apd) (time+ (moment apd) (floating-period apd))))
|
m@95
|
119 (defgeneric crotchet (object)
|
m@95
|
120 (:documentation "Returns a period, the duration of which represents
|
m@95
|
121 a crotchet in the time representation used by object."))
|
m@24
|
122
|
m@24
|
123 ;; others
|
m@24
|
124
|
m@24
|
125 ;; I've given the time-sig accessors general names because it allows
|
m@24
|
126 ;; for symbols in time-signatures as well as numbers - numerator is an
|
m@24
|
127 ;; odd accessor if the time sig is C (even in common practice) but
|
d@100
|
128 ;; its meaning is clear. beat-units-per-bar is clearer, though, I
|
m@24
|
129 ;; think.
|
m@24
|
130
|
d@123
|
131 (defgeneric beat-units-per-bar (time-signature)
|
d@123
|
132 (:documentation "In a standard, fraction-like time-signature or
|
d@123
|
133 a symbolic equivalent, this is the numerator."))
|
m@24
|
134 (defgeneric time-signature-numerator (time-signature)
|
d@123
|
135 (:method (ts) (beat-units-per-bar ts))
|
d@123
|
136 (:documentation "Not obviously meaningful for non fraction-like
|
d@123
|
137 time signatures"))
|
d@123
|
138 (defgeneric beat-units (time-signature)
|
d@123
|
139 (:documentation "In a standard, fraction-like time-signature or
|
d@123
|
140 a symbolic equivalent, this is the numerator (n.b.,
|
d@123
|
141 tactus-duration is the method of choice for compound time
|
d@123
|
142 sensitive queries."))
|
m@24
|
143 (defgeneric time-signature-denominator (time-signature)
|
d@123
|
144 (:method (ts) (beat-units ts))
|
d@123
|
145 (:documentation "Not obviously meaningful for non fraction-like
|
d@123
|
146 time signatures"))
|
d@33
|
147 (defgeneric tactus-duration (time-signature)
|
d@33
|
148 ;; basic, but should do?
|
d@33
|
149 (:method (ts)
|
d@33
|
150 (cond
|
d@33
|
151 ((and (not (= (beat-units-per-bar ts) 3))
|
d@33
|
152 (= (rem (beat-units-per-bar ts) 3) 0))
|
d@33
|
153 ;; compound time
|
d@33
|
154 (* (/ 4 (beat-units ts))
|
d@33
|
155 3))
|
d@123
|
156 (t (/ 4 (beat-units ts)))))
|
d@123
|
157 (:documentation "Returns a number of crotchets to represent the
|
d@123
|
158 tactus, based on some idea of time signature patterns. Should,
|
d@123
|
159 in future, return a duration rather than a number."))
|
m@24
|
160
|
d@123
|
161 (defgeneric key-signature-sharps (key-signature)
|
d@123
|
162 (:documentation "Simple query for normal key-signatures."))
|
d@123
|
163 (defgeneric key-signature-mode (ks)
|
d@123
|
164 (:documentation "Query that only makes sense for midi-like key
|
d@123
|
165 signatures"))
|
m@24
|
166
|
d@123
|
167 (defgeneric bpm (tempo)
|
d@123
|
168 (:documentation "Basic tempo query")) ;; in bpm
|
m@24
|
169 (defgeneric microseconds-per-crotchet (tempo)
|
m@24
|
170 ;; As used (when rounded) in MIDI
|
d@123
|
171 (:method (tp) (/ 60000000 (bpm tp)))
|
d@123
|
172 (:documentation "Basic tempo query for MIDI. N.B. This will be
|
d@123
|
173 a fraction and must be rounded before being used for output."))
|
m@24
|
174
|
m@24
|
175 ;;; Coerce-type accessors
|
m@24
|
176
|
m@24
|
177 ;; Should I be including these default methods? Should the accessors
|
m@24
|
178 ;; be direct slot accessors or the generics I'm using? Should we
|
m@24
|
179 ;; return the object itself if it already is in the target class?
|
m@24
|
180
|
m@24
|
181 (defgeneric anchored-period (anchored-period-designator)
|
d@123
|
182 (:method (apd) (make-anchored-period (onset apd) (duration apd)))
|
d@123
|
183 (:documentation "Coerce any anchored period to a plain anchored
|
d@123
|
184 period"))
|
m@24
|
185
|
m@24
|
186 (defgeneric floating-period (period-designator)
|
d@123
|
187 (:method (pd) (make-floating-period (duration pd)))
|
d@123
|
188 (:documentation "Coerce any period to a floating period"))
|
m@24
|
189
|
m@24
|
190 (defgeneric moment (moment-designator)
|
d@123
|
191 (:method (md) (make-moment (timepoint md)))
|
d@123
|
192 (:documentation "Coerce any moment(-designator?), including an
|
d@123
|
193 anchored-period to a moment"))
|
m@24
|
194
|
m@24
|
195 (defgeneric onset (anchored-period-designator)
|
d@123
|
196 (:method (apd) (moment apd))
|
d@123
|
197 (:documentation "Return a moment for the start of an anchored period"))
|
m@24
|
198 (defgeneric (setf onset) (value anchored-period-designator))
|
m@24
|
199
|
m@24
|
200 ;;; Time Protocol (or moments?)
|
m@24
|
201
|
m@24
|
202 ;; negative times/durations -> ERROR?
|
m@24
|
203
|
m@24
|
204 ;; time+: <time> <duration> -> <time>
|
m@24
|
205 ;; <duration> <time> -> <time> (same as previous?)
|
m@24
|
206 ;; <duration> <duration> -> <duration> (or a distinct duration+?)
|
m@24
|
207 ;; <time> <time> -> ERROR?
|
m@24
|
208 ;;
|
m@24
|
209 ;; time-: <time> <time> -> <duration>
|
m@24
|
210 ;; <time> <duration> -> <time>
|
m@24
|
211 ;; <duration> <duration> -> <duration> (or a distinct duration-?)
|
m@24
|
212 ;; <duration> <time> -> ERROR?
|
m@24
|
213 ;; <anchored> <anchored> -> (time- (moment o1) (moment o2)) ? or error?
|
m@24
|
214
|
d@102
|
215 (defgeneric time+ (object1 object2)
|
d@102
|
216 (:documentation "Addition for time designators"))
|
d@102
|
217 (defgeneric time- (object1 object2)
|
d@102
|
218 (:documentation "Subtraction for time designators"))
|
m@24
|
219
|
d@102
|
220 (defgeneric time> (object1 object2)
|
d@118
|
221 (:documentation "> operator for moment designators"))
|
m@24
|
222 (defgeneric time< (object1 object2)
|
d@118
|
223 (:documentation "< operator for moment designators")
|
m@24
|
224 (:method (o1 o2) (time> o2 o1)))
|
d@102
|
225 (defgeneric time= (object1 object2)
|
d@118
|
226 (:documentation "= operator for moment designators"))
|
m@24
|
227 (defgeneric time>= (object1 object2)
|
d@118
|
228 (:documentation ">= operator for moment designators")
|
m@24
|
229 (:method (o1 o2) (or (time> o1 o2) (time= o1 o2))))
|
m@24
|
230 (defgeneric time<= (object1 object2)
|
d@118
|
231 (:documentation "<= operator for moment designators")
|
m@24
|
232 (:method (o1 o2) (or (time< o1 o2) (time= o1 o2))))
|
m@24
|
233 (defgeneric time/= (object1 object2)
|
d@118
|
234 (:documentation "not = operator for moment designators")
|
m@24
|
235 (:method (o1 o2) (not (time= o1 o2))))
|
m@24
|
236
|
m@24
|
237 ;;; Duration protocol
|
m@24
|
238
|
d@118
|
239 (defgeneric duration> (object1 object2)
|
d@118
|
240 (:documentation "> operator for period designators"))
|
m@24
|
241 (defgeneric duration< (object1 object2)
|
d@118
|
242 (:documentation "< operator for period designators")
|
m@24
|
243 (:method (o1 o2) (duration> o2 o1)))
|
d@118
|
244 (defgeneric duration= (object1 object2)
|
d@118
|
245 (:documentation "= operator for period designators"))
|
m@24
|
246 (defgeneric duration>= (object1 object2)
|
d@118
|
247 (:documentation ">= operator for period designators")
|
m@24
|
248 (:method (o1 o2) (or (duration> o1 o2) (duration= o1 o2))))
|
m@24
|
249 (defgeneric duration<= (object1 object2)
|
d@118
|
250 (:documentation "<= operator for period designators")
|
m@24
|
251 (:method (o1 o2) (or (duration< o1 o2) (duration= o1 o2))))
|
m@24
|
252 (defgeneric duration/= (object1 object2)
|
d@118
|
253 (:documentation "not = operator for period designators")
|
m@24
|
254 (:method (o1 o2) (not (duration= o1 o2))))
|
m@24
|
255
|
m@24
|
256 ;; for linear scaling:
|
d@118
|
257 (defgeneric duration* (object1 object2)
|
d@118
|
258 (:documentation "Multiplication operator for period
|
d@118
|
259 designators. Intuitively, this makes sense, but it may cause us
|
d@118
|
260 trouble with some implementations in the future."))
|
d@118
|
261 (defgeneric duration/ (object1 number)
|
d@118
|
262 (:documentation "Division operator for period designators. This
|
d@118
|
263 may turn out not to mean much. Division is probably useful, but
|
d@118
|
264 we may need to define what we mean with care."))
|
m@24
|
265
|
m@24
|
266 ;;; Pitch protocol
|
m@24
|
267
|
m@24
|
268 ;; pitch+: <pitch> <pitch> -> ERROR
|
m@24
|
269 ;; <pitch> <interval> -> <pitch>
|
m@24
|
270 ;; <interval> <pitch> -> <pitch> (same as previous?)
|
m@24
|
271 ;; <interval> <interval> -> <interval> (or a distinct interval+?)
|
m@24
|
272 ;;
|
m@24
|
273 ;; pitch-: <pitch> <pitch> -> <interval>
|
m@24
|
274 ;; <pitch> <interval> -> <pitch>
|
m@24
|
275 ;; <interval> <interval> -> <interval>
|
m@24
|
276 ;; <interval> <pitch> -> ERROR
|
m@24
|
277
|
m@24
|
278 (defgeneric pitch+ (object1 object2))
|
m@24
|
279 (defgeneric pitch- (object1 object2))
|
m@24
|
280
|
m@24
|
281 (defgeneric pitch> (object1 object2))
|
m@24
|
282 (defgeneric pitch< (object1 object2)
|
m@24
|
283 (:method (o1 o2) (pitch> o2 o1)))
|
m@24
|
284 (defgeneric pitch= (object1 object2))
|
m@24
|
285 (defgeneric pitch>= (object1 object2)
|
m@24
|
286 (:method (o1 o2) (or (pitch> o1 o2) (pitch= o1 o2))))
|
m@24
|
287 (defgeneric pitch<= (object1 object2)
|
m@24
|
288 (:method (o1 o2) (or (pitch< o1 o2) (pitch= o1 o2))))
|
m@24
|
289 (defgeneric pitch/= (object1 object2)
|
m@24
|
290 (:method (o1 o2) (not (pitch= o1 o2))))
|
m@24
|
291
|
m@24
|
292 ;;; Interval protocol (emphasise _pitch_ not _time_ interval?)
|
m@24
|
293
|
m@24
|
294 (defgeneric interval> (object1 object2))
|
m@24
|
295 (defgeneric interval< (object1 object2)
|
m@24
|
296 (:method (o1 o2) (interval> o2 o1)))
|
m@24
|
297 (defgeneric interval= (object1 object2))
|
m@24
|
298 (defgeneric interval>= (object1 object2)
|
m@24
|
299 (:method (o1 o2) (or (interval> o1 o2) (interval= o1 o2))))
|
m@24
|
300 (defgeneric interval<= (object1 object2)
|
m@24
|
301 (:method (o1 o2) (or (interval< o1 o2) (interval= o1 o2))))
|
m@24
|
302 (defgeneric interval/= (object1 object2)
|
m@24
|
303 (:method (o1 o2) (not (interval= o1 o2))))
|
m@24
|
304
|
m@24
|
305 ;;; Allen's (1984) interval relations
|
m@24
|
306 ;;; . equals already defined as INTERVAL= above
|
m@24
|
307 ;;; . inverses ommitted for now (just use CL:NOT)
|
m@24
|
308 ;;; . can all be defined in terms of MEETS (apparently)
|
m@24
|
309
|
m@24
|
310 (defgeneric meets (object1 object2))
|
m@24
|
311 (defgeneric before (object1 object2))
|
m@24
|
312 (defgeneric overlaps (object1 object2))
|
m@24
|
313 (defgeneric during (object1 object2))
|
m@24
|
314 (defgeneric starts (object1 object2))
|
m@24
|
315 (defgeneric ends (object1 object2))
|
m@24
|
316
|
m@24
|
317 ;;; and extensions thereof ...
|
m@24
|
318
|
m@24
|
319 (defgeneric subinterval (object1 object2)
|
m@24
|
320 (:method (o1 o2) (or (starts o1 o2) (during o1 o2) (ends o1 o2))))
|
m@24
|
321
|
m@24
|
322 (defgeneric disjoint (object1 object2)
|
m@24
|
323 (:method (o1 o2)
|
m@24
|
324 (or (before o1 o2) (meets o1 o2) (meets o2 o1) (before o2 o1))))
|
m@24
|
325
|
m@24
|
326 ;;; More time-based functions
|
d@33
|
327
|
d@33
|
328 (defgeneric period= (object1 object2)
|
d@33
|
329 (:method (x y) nil))
|
d@33
|
330
|
d@33
|
331 (defgeneric find-overlapping (anchored-period sequence)
|
d@33
|
332 ;; Returns all members of a sequence of period signifiers that overlap
|
d@33
|
333 ;; with the supplied period
|
d@33
|
334 (:method (ap s) (remove-if #'(lambda (x) (amuse:disjoint ap x)) s)))
|
d@33
|
335
|
m@24
|
336 ;; Return the anchored-period representing the intersection of two
|
m@24
|
337 ;; anchored-period-specifiers.
|
m@24
|
338 (defgeneric period-intersection (anchored-period-specifier1
|
m@24
|
339 anchored-period-specifier2))
|
m@24
|
340
|
m@24
|
341 (defgeneric inter-onset-interval (moment-designator1 moment-designator2)
|
m@24
|
342 (:method (md1 md2) (time- (moment md2) (moment md1))))
|
m@24
|
343
|
m@24
|
344
|
m@24
|
345 ;;; Time Signature
|
m@24
|
346
|
d@33
|
347 (defgeneric get-applicable-time-signatures (anchored-period composition)
|
d@123
|
348 (:method (ap c) (find-overlapping ap (time-signatures c)))
|
d@123
|
349 (:documentation "Return a list of time-signatures that are
|
d@123
|
350 relevant to <anchored-period>. The period may contain
|
d@123
|
351 information such as staff position and voicing, and the method
|
d@123
|
352 may use this to filter its response"))
|
m@24
|
353
|
d@123
|
354 (defgeneric time-signature-equal (ts1 ts2)
|
d@123
|
355 (:documentation "Comparison operator. The definition of
|
d@123
|
356 equality is left open for implementers"))
|
m@67
|
357
|
m@24
|
358 ;;; Tempo
|
m@24
|
359
|
d@33
|
360 (defgeneric get-applicable-tempi (anchored-period composition)
|
d@123
|
361 (:method (ap c) (find-overlapping ap (tempi c)))
|
d@123
|
362 (:documentation "Return a list of tempi that are relevant to
|
d@123
|
363 <anchored-period>. The period may contain information such as
|
d@123
|
364 staff position and voicing, and the method may use this to
|
d@123
|
365 filter its response"))
|
m@24
|
366
|
d@123
|
367 (defgeneric tempo-equal (t1 t2)
|
d@123
|
368 (:documentation "Comparison operator. The definition of
|
d@123
|
369 equality is left open for implementers"))
|
m@67
|
370
|
m@24
|
371 ;;; Tonality (Key Signature / Mode)
|
m@24
|
372
|
d@123
|
373 (defgeneric get-applicable-key-signatures (object1 object2)
|
d@123
|
374 (:documentation "Return a list of key-signatures that are
|
d@123
|
375 relevant to <anchored-period>. The period may contain
|
d@123
|
376 information such as staff position and voicing, and the method
|
d@123
|
377 may use this to filter its response"))
|
m@24
|
378
|
d@123
|
379 (defgeneric key-signature-equal (ks1 ks2)
|
d@123
|
380 (:documentation "Comparison operator. The definition of
|
d@123
|
381 equality is left open to implementers"))
|
m@67
|
382
|
m@24
|
383 ;;; Dynamics
|
m@24
|
384 ;;; Voice
|
m@81
|
385 ;;; Boundary Strength (phrasing)
|