m@24
|
1 (cl:in-package #:amuse)
|
m@24
|
2
|
m@24
|
3 ;;; Pulling compositions from the database
|
m@24
|
4
|
m@24
|
5 (defgeneric get-composition (identifier))
|
m@24
|
6
|
d@33
|
7 ;;; Getting constituents from compositions
|
d@33
|
8 ;; IS this the mechanism we want to use
|
d@72
|
9 (defgeneric time-signatures (composition)
|
d@72
|
10 (:documentation "Returns all time-signatures in a composition
|
d@72
|
11 Probably shouldn't be exported - can be replaced
|
d@72
|
12 by (get-applicable-time-signature commposition composition)"))
|
d@72
|
13 (defgeneric (setf time-signatures) (sequence composition)
|
d@72
|
14 (:documentation "Sets all time-signatures in a composition.
|
d@72
|
15 Is this wanted here?"))
|
d@72
|
16 (defgeneric tempi (composition)
|
d@72
|
17 (:documentation "Returns all tempi in a composition Probably
|
d@72
|
18 shouldn't be exported - can be replaced
|
d@72
|
19 by (get-applicable-tempi commposition composition)"))
|
d@72
|
20 (defgeneric (setf tempi) (sequence composition)
|
d@72
|
21 (:documentation "Sets all tempi in a composition.
|
d@72
|
22 Is this wanted here?"))
|
d@72
|
23 (defgeneric key-signatures (composition)
|
d@72
|
24 (:documentation "Returns all key-signatures in a composition
|
d@72
|
25 Probably shouldn't be exported - can be replaced
|
d@72
|
26 by (get-applicable-key-signature commposition composition)"))
|
d@72
|
27 (defgeneric (setf key-signatures) (sequence composition)
|
d@72
|
28 (:documentation "Sets all key sigs in a composition.
|
d@72
|
29 Is this wanted here?"))
|
d@33
|
30
|
m@24
|
31 ;;; Simple Accessors
|
m@24
|
32
|
m@24
|
33 ;; pitch-based
|
m@24
|
34
|
m@24
|
35 (defgeneric pitch (object &key kind)) ; ? Maybe this returns the pitch
|
m@24
|
36 ; in its ur form?
|
m@24
|
37 (defgeneric chromatic-pitch (pitch-designator)) ; How simple are these
|
m@24
|
38 (defgeneric diatonic-pitch (pitch-designator)) ; if has to be computed?
|
m@81
|
39 (defgeneric mips-pitch (pitch-designator))
|
m@24
|
40 (defgeneric frequency (object)) ;?
|
m@81
|
41
|
m@86
|
42 (defgeneric octave (pitch-designator)
|
m@86
|
43 (:documentation "Return an integer representing the octave of
|
m@86
|
44 pitch-designator where middle c is defined to be the lowest pitch in
|
m@86
|
45 octave 4."))
|
m@86
|
46
|
m@86
|
47 (defgeneric diatonic-pitch-accidental (pitch-designator)
|
m@86
|
48 (:documentation "Return an integer representing the inflection of a
|
m@86
|
49 diatonic pitch where where negative values indicate numbers of flats,
|
m@86
|
50 0 indicates natural and positive values indicate numbers of sharps."))
|
m@86
|
51
|
m@81
|
52 (defgeneric middle-c (pitch-designator)
|
m@81
|
53 (:documentation "Returns the value of middle C in the particular
|
m@81
|
54 representation of pitch used by PITCH-DESIGNATOR."))
|
d@72
|
55 (defgeneric midi-pitch-number (pitch-designator)
|
d@72
|
56 (:documentation "Takes a pitch-designator (usually a pitched
|
d@72
|
57 event) and returns an integer between 0 and 127 representing
|
d@72
|
58 the chromatic pitch designated (60=middle C, 48 the C below
|
d@72
|
59 that, etc.)"))
|
m@24
|
60 (defgeneric meredith-chromatic-pitch-number (pitch-designator)
|
d@72
|
61 (:documentation "Takes a pitch-designator (usually a pitched
|
d@72
|
62 event) and returns an integer representing the chromatic pitch
|
d@72
|
63 designated (39=middle C, 27 the C below that, etc.)")
|
d@72
|
64 ;; David Meredith's PhD and ps13 code. FIXME: What is the legal
|
d@72
|
65 ;; range of this?
|
m@24
|
66 (:method (p) (- (midi-pitch-number p) 21)))
|
m@81
|
67 (defgeneric meredith-morphetic-pitch-number (pitch-designator)
|
m@81
|
68 (:documentation "Returns an integer representing the morphetic pitch
|
m@81
|
69 (7 per octave, An0 = 0, An1 = 7, middle c = 23) designated."))
|
m@81
|
70 (defgeneric asa-pitch-string (pitch-designator)
|
m@81
|
71 (:documentation "Returns a string representing the designated ASA
|
m@81
|
72 pitch name which has three parts: a letter name in the set
|
m@81
|
73 {A,B,C,D,E,F,G}, an inflection in the set {n,f,s,ff,ss,fff,sss,...}
|
m@81
|
74 and an octave number. E.g., Cn4 = Middle C."))
|
m@81
|
75 (defgeneric diatonic-pitch-name (pitch-designator)
|
m@81
|
76 (:documentation "Returns a char in the set
|
m@81
|
77 {#\A,#\B,#\C,#\D,#\E,#\F,#\G}, representing the pitch name of
|
m@81
|
78 PITCH-DESIGNATOR."))
|
m@24
|
79 (defgeneric pitch-class (pitch-designator)
|
d@72
|
80 (:documentation "Takes a pitch-designator (usually a pitched
|
d@72
|
81 event) and returns an integer between 0 and 12 representing
|
d@72
|
82 the octave-independant pitch, with c=0, c#=1, etc.")
|
m@24
|
83 (:method (p) (mod (midi-pitch-number p) 12)))
|
m@24
|
84 (defgeneric span (pitch-interval-designator))
|
m@24
|
85
|
m@24
|
86 ;; time
|
m@24
|
87
|
m@24
|
88 (defgeneric duration (period-designator))
|
m@24
|
89 (defgeneric (setf duration) (value period-designator))
|
m@24
|
90 (defgeneric timepoint (moment-designator))
|
m@24
|
91 (defgeneric (setf timepoint) (value moment-designator))
|
m@24
|
92 (defgeneric cut-off (anchored-period-designator) ; name?
|
d@72
|
93 (:documentation "Returns a <moment> representing the point at
|
d@72
|
94 which the anchored period has ended.")
|
m@24
|
95 (:method (apd) (time+ (moment apd) (floating-period apd))))
|
m@24
|
96
|
m@24
|
97 ;; others
|
m@24
|
98
|
m@24
|
99 ;; I've given the time-sig accessors general names because it allows
|
m@24
|
100 ;; for symbols in time-signatures as well as numbers - numerator is an
|
m@24
|
101 ;; odd accessor if the time sig is C (even in common practice) but
|
m@24
|
102 ;; it's meaning is clear. beat-units-per-bar is clearer, though, I
|
m@24
|
103 ;; think.
|
m@24
|
104
|
m@24
|
105 (defgeneric beat-units-per-bar (time-signature))
|
m@24
|
106 (defgeneric time-signature-numerator (time-signature)
|
m@24
|
107 (:method (ts) (beat-units-per-bar ts)))
|
m@24
|
108 (defgeneric beat-units (time-signature))
|
m@24
|
109 (defgeneric time-signature-denominator (time-signature)
|
m@24
|
110 (:method (ts) (beat-units ts)))
|
d@33
|
111 (defgeneric tactus-duration (time-signature)
|
d@33
|
112 ;; basic, but should do?
|
d@33
|
113 (:method (ts)
|
d@33
|
114 (cond
|
d@33
|
115 ((and (not (= (beat-units-per-bar ts) 3))
|
d@33
|
116 (= (rem (beat-units-per-bar ts) 3) 0))
|
d@33
|
117 ;; compound time
|
d@33
|
118 (* (/ 4 (beat-units ts))
|
d@33
|
119 3))
|
d@33
|
120 (t (/ 4 (beat-units ts))))))
|
m@24
|
121
|
m@24
|
122 (defgeneric key-signature-sharps (key-signature))
|
m@45
|
123 (defgeneric key-signature-mode (ks))
|
m@24
|
124
|
m@24
|
125 (defgeneric bpm (tempo)) ;; in bpm
|
m@24
|
126 (defgeneric microseconds-per-crotchet (tempo)
|
m@24
|
127 ;; As used (when rounded) in MIDI
|
m@24
|
128 (:method (tp) (/ 60000000 (bpm tp))))
|
m@24
|
129
|
m@24
|
130 ;;; Coerce-type accessors
|
m@24
|
131
|
m@24
|
132 ;; Should I be including these default methods? Should the accessors
|
m@24
|
133 ;; be direct slot accessors or the generics I'm using? Should we
|
m@24
|
134 ;; return the object itself if it already is in the target class?
|
m@24
|
135
|
m@24
|
136 (defgeneric anchored-period (anchored-period-designator)
|
m@24
|
137 (:method (apd) (make-anchored-period (onset apd) (duration apd))))
|
m@24
|
138
|
m@24
|
139 (defgeneric floating-period (period-designator)
|
m@24
|
140 (:method (pd) (make-floating-period (duration pd))))
|
m@24
|
141
|
m@24
|
142 (defgeneric moment (moment-designator)
|
m@24
|
143 (:method (md) (make-moment (timepoint md))))
|
m@24
|
144
|
m@24
|
145 (defgeneric onset (anchored-period-designator)
|
m@24
|
146 (:method (apd) (moment apd)))
|
m@24
|
147 (defgeneric (setf onset) (value anchored-period-designator))
|
m@24
|
148
|
m@24
|
149 ;;; Time Protocol (or moments?)
|
m@24
|
150
|
m@24
|
151 ;; negative times/durations -> ERROR?
|
m@24
|
152
|
m@24
|
153 ;; time+: <time> <duration> -> <time>
|
m@24
|
154 ;; <duration> <time> -> <time> (same as previous?)
|
m@24
|
155 ;; <duration> <duration> -> <duration> (or a distinct duration+?)
|
m@24
|
156 ;; <time> <time> -> ERROR?
|
m@24
|
157 ;;
|
m@24
|
158 ;; time-: <time> <time> -> <duration>
|
m@24
|
159 ;; <time> <duration> -> <time>
|
m@24
|
160 ;; <duration> <duration> -> <duration> (or a distinct duration-?)
|
m@24
|
161 ;; <duration> <time> -> ERROR?
|
m@24
|
162 ;; <anchored> <anchored> -> (time- (moment o1) (moment o2)) ? or error?
|
m@24
|
163
|
m@24
|
164 (defgeneric time+ (object1 object2))
|
m@24
|
165 (defgeneric time- (object1 object2))
|
m@24
|
166
|
m@24
|
167 (defgeneric time> (object1 object2))
|
m@24
|
168 (defgeneric time< (object1 object2)
|
m@24
|
169 (:method (o1 o2) (time> o2 o1)))
|
m@24
|
170 (defgeneric time= (object1 object2))
|
m@24
|
171 (defgeneric time>= (object1 object2)
|
m@24
|
172 (:method (o1 o2) (or (time> o1 o2) (time= o1 o2))))
|
m@24
|
173 (defgeneric time<= (object1 object2)
|
m@24
|
174 (:method (o1 o2) (or (time< o1 o2) (time= o1 o2))))
|
m@24
|
175 (defgeneric time/= (object1 object2)
|
m@24
|
176 (:method (o1 o2) (not (time= o1 o2))))
|
m@24
|
177
|
m@24
|
178 ;;; Duration protocol
|
m@24
|
179
|
m@24
|
180 (defgeneric duration> (object1 object2))
|
m@24
|
181 (defgeneric duration< (object1 object2)
|
m@24
|
182 (:method (o1 o2) (duration> o2 o1)))
|
m@24
|
183 (defgeneric duration= (object1 object2))
|
m@24
|
184 (defgeneric duration>= (object1 object2)
|
m@24
|
185 (:method (o1 o2) (or (duration> o1 o2) (duration= o1 o2))))
|
m@24
|
186 (defgeneric duration<= (object1 object2)
|
m@24
|
187 (:method (o1 o2) (or (duration< o1 o2) (duration= o1 o2))))
|
m@24
|
188 (defgeneric duration/= (object1 object2)
|
m@24
|
189 (:method (o1 o2) (not (duration= o1 o2))))
|
m@24
|
190
|
m@24
|
191 ;; for linear scaling:
|
m@24
|
192 (defgeneric duration* (object1 object2))
|
m@24
|
193 (defgeneric duration/ (object1 number))
|
m@24
|
194
|
m@24
|
195 ;;; Pitch protocol
|
m@24
|
196
|
m@24
|
197 ;; pitch+: <pitch> <pitch> -> ERROR
|
m@24
|
198 ;; <pitch> <interval> -> <pitch>
|
m@24
|
199 ;; <interval> <pitch> -> <pitch> (same as previous?)
|
m@24
|
200 ;; <interval> <interval> -> <interval> (or a distinct interval+?)
|
m@24
|
201 ;;
|
m@24
|
202 ;; pitch-: <pitch> <pitch> -> <interval>
|
m@24
|
203 ;; <pitch> <interval> -> <pitch>
|
m@24
|
204 ;; <interval> <interval> -> <interval>
|
m@24
|
205 ;; <interval> <pitch> -> ERROR
|
m@24
|
206
|
m@24
|
207 (defgeneric pitch+ (object1 object2))
|
m@24
|
208 (defgeneric pitch- (object1 object2))
|
m@24
|
209
|
m@24
|
210 (defgeneric pitch> (object1 object2))
|
m@24
|
211 (defgeneric pitch< (object1 object2)
|
m@24
|
212 (:method (o1 o2) (pitch> o2 o1)))
|
m@24
|
213 (defgeneric pitch= (object1 object2))
|
m@24
|
214 (defgeneric pitch>= (object1 object2)
|
m@24
|
215 (:method (o1 o2) (or (pitch> o1 o2) (pitch= o1 o2))))
|
m@24
|
216 (defgeneric pitch<= (object1 object2)
|
m@24
|
217 (:method (o1 o2) (or (pitch< o1 o2) (pitch= o1 o2))))
|
m@24
|
218 (defgeneric pitch/= (object1 object2)
|
m@24
|
219 (:method (o1 o2) (not (pitch= o1 o2))))
|
m@24
|
220
|
m@24
|
221 ;;; Interval protocol (emphasise _pitch_ not _time_ interval?)
|
m@24
|
222
|
m@24
|
223 (defgeneric interval> (object1 object2))
|
m@24
|
224 (defgeneric interval< (object1 object2)
|
m@24
|
225 (:method (o1 o2) (interval> o2 o1)))
|
m@24
|
226 (defgeneric interval= (object1 object2))
|
m@24
|
227 (defgeneric interval>= (object1 object2)
|
m@24
|
228 (:method (o1 o2) (or (interval> o1 o2) (interval= o1 o2))))
|
m@24
|
229 (defgeneric interval<= (object1 object2)
|
m@24
|
230 (:method (o1 o2) (or (interval< o1 o2) (interval= o1 o2))))
|
m@24
|
231 (defgeneric interval/= (object1 object2)
|
m@24
|
232 (:method (o1 o2) (not (interval= o1 o2))))
|
m@24
|
233
|
m@24
|
234 ;;; Allen's (1984) interval relations
|
m@24
|
235 ;;; . equals already defined as INTERVAL= above
|
m@24
|
236 ;;; . inverses ommitted for now (just use CL:NOT)
|
m@24
|
237 ;;; . can all be defined in terms of MEETS (apparently)
|
m@24
|
238
|
m@24
|
239 (defgeneric meets (object1 object2))
|
m@24
|
240 (defgeneric before (object1 object2))
|
m@24
|
241 (defgeneric overlaps (object1 object2))
|
m@24
|
242 (defgeneric during (object1 object2))
|
m@24
|
243 (defgeneric starts (object1 object2))
|
m@24
|
244 (defgeneric ends (object1 object2))
|
m@24
|
245
|
m@24
|
246 ;;; and extensions thereof ...
|
m@24
|
247
|
m@24
|
248 (defgeneric subinterval (object1 object2)
|
m@24
|
249 (:method (o1 o2) (or (starts o1 o2) (during o1 o2) (ends o1 o2))))
|
m@24
|
250
|
m@24
|
251 (defgeneric disjoint (object1 object2)
|
m@24
|
252 (:method (o1 o2)
|
m@24
|
253 (or (before o1 o2) (meets o1 o2) (meets o2 o1) (before o2 o1))))
|
m@24
|
254
|
m@24
|
255 ;;; More time-based functions
|
d@33
|
256
|
d@33
|
257 (defgeneric period= (object1 object2)
|
d@33
|
258 (:method (x y) nil))
|
d@33
|
259
|
d@33
|
260 (defgeneric find-overlapping (anchored-period sequence)
|
d@33
|
261 ;; Returns all members of a sequence of period signifiers that overlap
|
d@33
|
262 ;; with the supplied period
|
d@33
|
263 (:method (ap s) (remove-if #'(lambda (x) (amuse:disjoint ap x)) s)))
|
d@33
|
264
|
m@24
|
265 ;; Return the anchored-period representing the intersection of two
|
m@24
|
266 ;; anchored-period-specifiers.
|
m@24
|
267 (defgeneric period-intersection (anchored-period-specifier1
|
m@24
|
268 anchored-period-specifier2))
|
m@24
|
269
|
m@24
|
270 (defgeneric inter-onset-interval (moment-designator1 moment-designator2)
|
m@24
|
271 (:method (md1 md2) (time- (moment md2) (moment md1))))
|
m@24
|
272
|
m@24
|
273
|
m@24
|
274 ;;; Time Signature
|
m@24
|
275
|
d@33
|
276 (defgeneric get-applicable-time-signatures (anchored-period composition)
|
d@33
|
277 (:method (ap c) (find-overlapping ap (time-signatures c))))
|
m@24
|
278
|
m@67
|
279 (defgeneric time-signature-equal (ts1 ts2))
|
m@67
|
280
|
m@24
|
281 ;;; Tempo
|
m@24
|
282
|
d@33
|
283 (defgeneric get-applicable-tempi (anchored-period composition)
|
d@33
|
284 (:method (ap c) (find-overlapping ap (tempi c))))
|
m@24
|
285
|
m@67
|
286 (defgeneric tempo-equal (t1 t2))
|
m@67
|
287
|
m@24
|
288 ;;; Tonality (Key Signature / Mode)
|
m@24
|
289
|
m@24
|
290 (defgeneric get-applicable-key-signatures (object1 object2))
|
m@24
|
291
|
m@67
|
292 (defgeneric key-signature-equal (ks1 ks2))
|
m@67
|
293
|
m@24
|
294 ;;; Dynamics
|
m@24
|
295 ;;; Voice
|
m@81
|
296 ;;; Boundary Strength (phrasing)
|