annotate base/methods.lisp @ 121:4198b52e612b

More docstrings darcs-hash:20070727142154-f76cc-f59d4ad1216346f392d5b9f9e5b153a6f07a9bd9.gz
author David Lewis <d.lewis@gold.ac.uk>
date Fri, 27 Jul 2007 15:21:54 +0100
parents d574d015f5af
children efaa02d21690
rev   line source
m@24 1 (cl:in-package #:amuse)
m@24 2
m@89 3 ;;; monody
m@89 4
m@89 5 (defmethod ensure-monody ((m monody))
m@89 6 (let ((result t))
m@89 7 (dotimes (i (1- (length m)) result)
m@89 8 ;; assumes the events are time ordered which (since monody is a
m@89 9 ;; subclass of time-ordered-constituent) they ought to be.
m@89 10 (let ((e1 (elt m i))
m@89 11 (e2 (elt m (1+ i))))
m@89 12 (unless (or (before e1 e2) (meets e1 e2))
m@89 13 (setf result nil))))))
m@89 14
c@109 15 ;;; diatonic pitch (represented using MIPS)
m@81 16
c@109 17 (defmethod asa-pitch-string ((mp diatonic-pitch))
c@106 18 (mips:p-pn (list (%p-pc mp) (%p-pm mp))))
c@106 19
c@109 20 (defmethod diatonic-pitch-octave ((mp diatonic-pitch))
c@106 21 (let* ((asa-string (asa-pitch-string mp))
c@106 22 (start (position-if #'digit-char-p asa-string)))
c@106 23 (values (parse-integer asa-string :start start))))
m@86 24
c@109 25 (defmethod diatonic-pitch-accidental ((mp diatonic-pitch))
c@106 26 (let* ((asa-string (asa-pitch-string mp))
c@106 27 (start 1)
c@106 28 (end (position-if #'digit-char-p asa-string))
c@106 29 (malist '((#\n . 0) (#\s . +1) (#\f . -1)))
c@106 30 (multiplier (cdr (assoc (char asa-string 1) malist))))
c@106 31 (* multiplier (- end start))))
c@106 32
c@109 33 (defmethod diatonic-pitch-name ((mp diatonic-pitch))
c@106 34 (elt (asa-pitch-string mp) 0))
m@86 35
c@109 36 (defmethod middle-c ((mp diatonic-pitch))
c@109 37 (make-diatonic-pitch 39 23))
m@81 38
c@109 39 (defmethod midi-pitch-number ((mp diatonic-pitch))
c@106 40 (+ (%p-pc mp) 21))
c@106 41
c@109 42 (defmethod octave ((mp diatonic-pitch))
c@106 43 (1- (floor (midi-pitch-number mp) 12)))
c@106 44
c@109 45 (defmethod diatonic-pitch ((mp diatonic-pitch))
m@81 46 mp)
m@81 47
c@109 48 (defmethod print-object ((o diatonic-pitch) stream)
c@106 49 (print-unreadable-object (o stream :type t)
c@106 50 (let ((asa-string (asa-pitch-string o)))
c@106 51 (write asa-string :stream stream))))
m@81 52
c@111 53 (defmethod asa-interval-string ((mpi diatonic-pitch-interval))
c@111 54 (mips:pi-pin (%diatonic-pitch-interval-span mpi)))
c@111 55
c@111 56 (defmethod print-object ((o diatonic-pitch-interval) stream)
c@111 57 (print-unreadable-object (o stream :type t)
c@111 58 (let ((asa-string (asa-interval-string o)))
c@111 59 (write asa-string :stream stream))))
c@111 60
m@81 61 ;;; Chromatic pitch
m@81 62
m@86 63 (defmethod octave ((cp chromatic-pitch))
c@106 64 (1- (floor (%chromatic-pitch-number cp) 12)))
m@86 65
m@81 66 (defmethod middle-c ((cp chromatic-pitch))
m@81 67 (make-chromatic-pitch 60))
m@81 68
m@24 69 (defmethod chromatic-pitch ((pitch-designator chromatic-pitch))
m@24 70 pitch-designator)
m@24 71
m@24 72 (defmethod midi-pitch-number ((pitch-designator chromatic-pitch))
m@24 73 (%chromatic-pitch-number pitch-designator))
m@24 74
m@24 75 (defmethod midi-pitch-number ((pitch-designator pitch))
m@24 76 (%chromatic-pitch-number (chromatic-pitch pitch-designator)))
m@24 77
m@113 78 (defmethod print-object ((o chromatic-pitch) stream)
m@113 79 (print-unreadable-object (o stream :type t)
m@113 80 (write (midi-pitch-number o) :stream stream)))
m@113 81
m@113 82 (defmethod print-object ((o chromatic-pitch-interval) stream)
m@113 83 (print-unreadable-object (o stream :type t)
m@113 84 (write (span o) :stream stream)))
m@113 85
m@113 86
c@111 87 (defmethod span ((pitch-interval-designator chromatic-pitch-interval))
c@111 88 (%chromatic-pitch-interval-span pitch-interval-designator))
m@24 89
m@24 90 (defmethod duration ((period-designator period))
m@24 91 (%period-interval period-designator))
m@24 92
d@33 93 (defmethod (setf duration) ((value real) (period-designator period))
d@33 94 (setf (%period-interval period-designator) value))
d@33 95
m@24 96 (defmethod timepoint ((moment-designator moment))
m@24 97 (%moment-time moment-designator))
m@24 98
d@33 99 (defmethod (setf timepoint) ((value real) (moment-designator moment))
d@33 100 (setf (%moment-time moment-designator) value))
d@33 101
d@73 102 (defmethod cut-off ((anchored-period-designator anchored-period))
d@73 103 (make-instance 'moment
d@73 104 :time (+ (%moment-time anchored-period-designator)
d@73 105 (%period-interval anchored-period-designator))))
d@73 106
m@113 107 (defmethod print-object ((o moment) stream)
m@113 108 (print-unreadable-object (o stream :type t)
m@113 109 (write (timepoint o) :stream stream)))
m@113 110
m@113 111 (defmethod print-object ((o period ) stream)
m@113 112 (print-unreadable-object (o stream :type t)
m@113 113 (write (duration o) :stream stream)))
m@113 114
m@113 115
m@113 116
m@24 117 (defmethod beat-units-per-bar ((time-signature basic-time-signature))
m@24 118 (%basic-time-signature-numerator time-signature))
m@24 119
m@24 120 (defmethod beat-units ((time-signature basic-time-signature))
m@24 121 (%basic-time-signature-denominator time-signature))
m@24 122
m@67 123 (defmethod time-signature-equal ((ts1 basic-time-signature)
m@67 124 (ts2 basic-time-signature))
m@67 125 (let ((n1 (time-signature-numerator ts1))
m@67 126 (n2 (time-signature-numerator ts2))
m@67 127 (d1 (time-signature-denominator ts1))
m@67 128 (d2 (time-signature-denominator ts2)))
m@67 129 (and n1 n2 (= n1 n2)
m@67 130 d1 d2 (= d1 d2))))
m@67 131
m@113 132 (defmethod print-object ((bts basic-time-signature) stream)
m@113 133 (print-unreadable-object (bts stream :type t)
m@113 134 (format stream "~A/~A" (beat-units-per-bar bts) (beat-units bts))))
m@113 135
m@24 136 (defmethod key-signature-sharps ((key-signature basic-key-signature))
m@24 137 (%basic-key-signature-sharp-count key-signature))
m@24 138
m@45 139 (defmethod key-signature-mode ((ks midi-key-signature))
m@45 140 (%midi-key-signature-mode ks))
m@45 141
m@113 142 (defmethod print-object ((mks midi-key-signature) stream)
m@113 143 (print-unreadable-object (mks stream :type t)
m@113 144 (format stream "~A ~A"
m@113 145 (%basic-key-signature-sharp-count mks)
m@113 146 (%midi-key-signature-mode mks))))
m@113 147
m@67 148 (defmethod key-signature-equal ((ks1 basic-key-signature)
m@67 149 (ks2 basic-key-signature))
m@67 150 (let ((s1 (key-signature-sharps ks1))
m@67 151 (s2 (key-signature-sharps ks2)))
m@67 152 (and s1 s2 (= s1 s2))))
m@67 153
m@67 154 (defmethod key-signature-equal ((ks1 midi-key-signature)
m@67 155 (ks2 midi-key-signature))
m@67 156 (let ((s1 (key-signature-sharps ks1))
m@67 157 (s2 (key-signature-sharps ks2))
m@67 158 (m1 (key-signature-mode ks1))
m@67 159 (m2 (key-signature-mode ks2)))
m@67 160 (and s1 s2 (= s1 s2)
m@67 161 m1 m2 (= m1 m2))))
m@67 162
m@24 163 (defmethod bpm ((tempo tempo))
m@24 164 (%tempo-bpm tempo))
m@24 165
m@113 166 (defmethod print-object ((tempo tempo) stream)
m@113 167 (print-unreadable-object (tempo stream :type t)
m@113 168 (write (bpm tempo) :stream stream)))
m@113 169
m@67 170 (defmethod tempo-equal ((t1 tempo) (t2 tempo))
m@67 171 (and (bpm t1) (bpm t2) (= t1 t2)))
m@67 172
m@67 173
m@24 174 ;; Time protocol
m@24 175
m@24 176 (defmethod time+ ((object1 moment) (object2 period))
d@121 177 "Returns a <moment>. Implemented as a straightforward
d@121 178 summation."
m@24 179 (make-moment (+ (timepoint object1) (duration object2))))
m@24 180
m@24 181 (defmethod time+ ((object1 period) (object2 moment)) ;?
d@121 182 "Returns a <moment>. Implemented as a straightforward summation
d@121 183 and defined by default as (time+ <moment> <period>)."
m@24 184 (time+ object2 object1))
m@24 185
m@24 186 (defmethod time+ ((object1 period) (object2 period))
d@121 187 "Returns a <period>. Implemented as a straightforward
d@121 188 summation."
m@24 189 (make-floating-period (+ (duration object1)
m@24 190 (duration object2))))
m@24 191
m@24 192 (defmethod time+ ((object1 moment) (object2 moment))
d@121 193 "Returns <condition:undefined-action>. The question makes no
d@121 194 sense."
m@24 195 (error 'undefined-action :operation 'time+ :datatype (list (class-of object1) (class-of object2))))
m@24 196
m@24 197 (defmethod time- ((object1 moment) (object2 moment))
d@121 198 "Returns <anchored-period> with an onset at object2 and
d@121 199 extending to object1"
m@24 200 (make-anchored-period (timepoint object2)
m@24 201 (- (timepoint object1)
m@24 202 (timepoint object2))))
m@24 203
m@24 204 (defmethod time- ((object1 moment) (object2 period))
d@121 205 "Simple subtraction - Returns a <moment>"
m@24 206 (make-moment (- (timepoint object1) (duration object2))))
m@24 207
m@24 208 (defmethod time- ((object1 period) (object2 moment)) ;?
d@121 209 "Returns <condition:undefined-action>. The question makes no
d@121 210 sense"
m@24 211 (error 'undefined-action
m@24 212 :operation 'time-
m@24 213 :datatype (list (class-of object1) (class-of object2))))
m@24 214
m@24 215 (defmethod time- ((object1 period) (object2 period))
d@121 216 "Returns <floating-period> spanning the difference of the
d@121 217 periods"
m@24 218 (make-floating-period (- (duration object2)
m@24 219 (duration object1))))
m@24 220
m@24 221 ;; these ones are less certain. I've just put them in, but think I
m@24 222 ;; should remove them and force the user to specify what they mean
m@24 223 ;; when they give objects that are both moments *and* periods to these
m@24 224 ;; functions.
m@24 225
m@24 226 (defmethod time- ((object1 anchored-period) (object2 anchored-period)) ;?
m@24 227 (time- (moment object1) (moment object2)))
m@24 228
m@24 229 (defmethod time- (object1 (object2 anchored-period)) ;?
m@24 230 (time- object1 (moment object2)))
m@24 231
m@24 232 (defmethod time- ((object1 anchored-period) object2) ;?
m@24 233 (time- (moment object1) object2))
m@24 234
m@24 235 (defmethod time> ((object1 moment) (object2 moment))
m@24 236 (> (timepoint object1) (timepoint object2)))
m@24 237
d@73 238 (defmethod time< ((object1 moment) (object2 moment))
d@73 239 (< (timepoint object1) (timepoint object2)))
d@73 240
m@24 241 (defmethod time= ((object1 moment) (object2 moment))
m@24 242 (= (timepoint object1) (timepoint object2)))
m@24 243
m@24 244 (defmethod duration> ((object1 period) (object2 period))
m@24 245 (> (duration object1) (duration object2)))
m@24 246
m@24 247 (defmethod duration= ((object1 period) (object2 period))
m@24 248 (= (duration object1) (duration object2)))
m@24 249
m@24 250 (defmethod duration* ((object1 period) (object2 number))
m@24 251 (make-floating-period (* (duration object1) object2)))
m@24 252
m@24 253 (defmethod duration* ((object1 number) (object2 period))
m@24 254 (duration* object2 object1))
m@24 255
m@24 256 (defmethod duration/ ((object1 period) (object2 number))
m@24 257 (make-floating-period (/ (duration object1) object2)))
m@24 258
c@111 259 ;;;; Pitch protocol
m@24 260
c@111 261 ;;; Some catch-all methods for undefined operations and cases where we
c@111 262 ;;; don't have enough information:
c@111 263 (macrolet ((def (name class1 class2)
c@111 264 `(defmethod ,name ((object1 ,class1) (object2 ,class2))
c@111 265 (error 'undefined-action :operation ',name
c@111 266 :datatype (list (class-of object1) (class-of object2))))))
c@111 267 (def pitch+ pitch-designator pitch-designator)
c@111 268 (def pitch- pitch-interval-designator pitch-designator))
m@24 269
c@111 270 (macrolet ((def (name class1 class2)
c@111 271 `(defmethod ,name ((object1 ,class1) (object2 ,class2))
c@111 272 (error 'insufficient-information :operation ',name
c@111 273 :datatype (list (class-of object1) (class-of object2))))))
c@111 274 (def pitch+ pitch-designator pitch-interval-designator)
c@111 275 (def pitch+ pitch-interval-designator pitch-designator)
c@111 276 (def pitch+ pitch-interval-designator pitch-interval-designator)
c@111 277 (def pitch- pitch-designator pitch-designator)
c@111 278 (def pitch- pitch-designator pitch-interval-designator)
c@111 279 (def pitch- pitch-interval-designator pitch-interval-designator))
m@24 280
c@111 281 ;;; chromatic pitch intervals
m@24 282
c@111 283 (defmethod pitch+ ((object1 chromatic-pitch)
c@111 284 (object2 chromatic-pitch-interval))
c@111 285 (make-chromatic-pitch (+ (midi-pitch-number object1) (span object2))))
c@111 286
c@111 287 (defmethod pitch+ ((object1 chromatic-pitch-interval)
c@111 288 (object2 chromatic-pitch))
c@111 289 (make-chromatic-pitch (+ (span object1) (midi-pitch-number object2))))
c@111 290
c@111 291 (defmethod pitch+ ((object1 chromatic-pitch-interval)
c@111 292 (object2 chromatic-pitch-interval))
c@105 293 (make-chromatic-pitch-interval (+ (span object1) (span object2))))
m@24 294
c@111 295 (defmethod pitch- ((object1 chromatic-pitch)
c@111 296 (object2 chromatic-pitch))
c@111 297 (make-chromatic-pitch-interval
c@105 298 (- (midi-pitch-number object1) (midi-pitch-number object2))))
m@24 299
c@111 300 (defmethod pitch- ((object1 chromatic-pitch)
c@111 301 (object2 chromatic-pitch-interval))
c@105 302 (make-chromatic-pitch (- (midi-pitch-number object1) (span object2))))
m@24 303
c@111 304 (defmethod pitch- ((object1 chromatic-pitch-interval)
c@111 305 (object2 chromatic-pitch-interval))
c@105 306 (make-chromatic-pitch-interval (- (span object1) (span object2))))
m@24 307
c@111 308 (defmethod pitch> ((object1 chromatic-pitch)
c@111 309 (object2 chromatic-pitch))
c@111 310 (> (midi-pitch-number object1) (midi-pitch-number object2)))
m@24 311
c@111 312 (defmethod pitch= ((object1 chromatic-pitch)
c@111 313 (object2 chromatic-pitch))
c@111 314 (= (midi-pitch-number object1) (midi-pitch-number object2)))
m@24 315
c@111 316 (defmethod interval> ((object1 chromatic-pitch-interval)
c@111 317 (object2 chromatic-pitch-interval))
c@111 318 (> (span object1) (span object2)))
m@24 319
c@111 320 (defmethod interval= ((object1 chromatic-pitch-interval)
c@111 321 (object2 chromatic-pitch-interval))
c@111 322 (= (span object1) (span object2)))
m@24 323
c@111 324 ;;; diatonic pitch intervals
m@24 325
c@111 326 (defmethod pitch+ ((object1 diatonic-pitch) (object2 diatonic-pitch-interval))
c@111 327 (let* ((cp (%p-pc object1))
c@111 328 (mp (%p-pm object1))
c@111 329 (span (span object2))
c@111 330 (cps (first span))
c@111 331 (mps (second span)))
c@111 332 (make-mips-pitch (+ cp cps) (+ mp mps))))
c@111 333
c@111 334 (defmethod pitch+ ((object1 diatonic-pitch-interval) (object2 diatonic-pitch))
c@111 335 (let* ((cp (%p-pc object2))
c@111 336 (mp (%p-pm object2))
c@111 337 (span (span object1))
c@111 338 (cps (first span))
c@111 339 (mps (second span)))
c@111 340 (make-mips-pitch (+ cp cps) (+ mp mps))))
c@111 341
c@111 342 (defmethod pitch+ ((object1 diatonic-pitch-interval)
c@111 343 (object2 diatonic-pitch-interval))
c@111 344 (let* ((span1 (span object1))
c@111 345 (span2 (span object2)))
c@111 346 (make-mips-pitch-interval (+ (first span1) (first span2))
c@111 347 (+ (second span1) (second span2)))))
c@111 348
c@111 349 (defmethod pitch- ((object1 diatonic-pitch) (object2 diatonic-pitch))
c@111 350 (let ((cp1 (%p-pc object1))
c@111 351 (mp1 (%p-pm object1))
c@111 352 (cp2 (%p-pc object2))
c@111 353 (mp2 (%p-pm object2)))
c@111 354 (make-mips-pitch-interval (- cp1 cp2) (- mp1 mp2))))
c@111 355
c@111 356 (defmethod pitch- ((object1 diatonic-pitch) (object2 diatonic-pitch-interval))
c@111 357 (let* ((cp (%p-pc object1))
c@111 358 (mp (%p-pm object1))
c@111 359 (span (span object2))
c@111 360 (cps (first span))
c@111 361 (mps (second span)))
c@111 362 (make-mips-pitch (- cp cps) (- mp mps))))
c@111 363
c@111 364 (defmethod pitch- ((object1 diatonic-pitch-interval)
c@111 365 (object2 diatonic-pitch-interval))
c@111 366 (let ((span1 (span object1))
c@111 367 (span2 (span object2)))
c@111 368 (make-mips-pitch-interval (- (first span1) (first span2))
c@111 369 (- (second span1) (second span2)))))
c@111 370
c@111 371 (defmethod pitch> ((p1 diatonic-pitch) (p2 diatonic-pitch))
c@111 372 (error 'undefined-action :operation 'pitch>
c@111 373 :datatype (list (class-of p1) (class-of p2))))
c@111 374
c@111 375 (defmethod pitch= ((p1 diatonic-pitch) (p2 diatonic-pitch))
c@111 376 (let ((c1 (%p-pc p1)) (m1 (%p-pm p1))
c@111 377 (c2 (%p-pc p2)) (m2 (%p-pm p2)))
c@111 378 (and c1 c2 (= c1 c2)
c@111 379 m1 m2 (= m1 m2))))
m@24 380
m@24 381
m@24 382 ;; Allen
m@24 383
m@24 384 (defmethod meets ((object1 anchored-period)
m@24 385 (object2 anchored-period))
m@24 386 (or (time= (cut-off object1) object2)
m@24 387 (time= (cut-off object2) object1)))
m@24 388
m@24 389 (defmethod before ((object1 anchored-period)
m@24 390 (object2 anchored-period))
m@24 391 (time> object2 (cut-off object1)))
m@24 392
m@24 393 (defmethod overlaps ((object1 anchored-period)
m@24 394 (object2 anchored-period))
m@24 395 ;; FIXME: Is there a tidier method?
m@24 396 (or (and (time> object2 object1) ; object1 starts before object2
m@24 397 (time> (cut-off object1) object2) ; object1 ends after object2 starts
m@24 398 (time> (cut-off object2) (cut-off object1))) ; object1 ends before object2 does
m@24 399 (and (time> object1 object2) ; object1 starts after object2
m@24 400 (time> (cut-off object2) object1) ; object1 starts before object2 ends
m@24 401 (time> (cut-off object1) (cut-off object2))))) ; object1 ends after object2 does
m@24 402
m@24 403 (defmethod during ((object1 anchored-period)
m@24 404 (object2 anchored-period))
m@24 405 (and (time> object1 object2)
m@24 406 (time< (cut-off object2) (cut-off object2))))
m@24 407
m@24 408 (defmethod starts ((object1 anchored-period)
m@24 409 (object2 anchored-period))
m@24 410 (time= object1 object2))
m@24 411
m@24 412 (defmethod ends ((object1 anchored-period)
m@24 413 (object2 anchored-period))
m@24 414 (time= (cut-off object1) (cut-off object2)))
m@24 415
m@24 416 ;; ...and
m@24 417
d@33 418 (defmethod period= ((object1 anchored-period)
c@105 419 (object2 anchored-period))
d@33 420 (and (time= object1 object2)
d@33 421 (duration= object1 object2)))
d@33 422 (defmethod period= ((object1 floating-period)
d@33 423 (object2 floating-period))
d@33 424 (duration= object1 object2))
d@33 425
m@24 426 (defmethod period-intersection ((object1 anchored-period)
m@24 427 (object2 anchored-period))
m@24 428 (cond
m@24 429 ((disjoint object1 object2)
m@24 430 ;; if they don't overlap, return nil, not a negative-valued
m@24 431 ;; period
m@24 432 nil)
m@24 433 ((let* ((start (if (time> (onset object2) (onset object1))
m@24 434 (onset object2)
m@24 435 (onset object1)))
m@24 436 (duration (duration (time- (if (time> (cut-off object2) (cut-off object1))
m@24 437 (cut-off object1)
m@24 438 (cut-off object2))
m@24 439 start))))
m@24 440 (make-anchored-period (timepoint start) duration)))))
m@24 441
m@24 442