annotate base/methods.lisp @ 109:a9a1c7aa86a9

rename mips-pitch -> diatonic-pitch darcs-hash:20070726131834-dc3a5-86b4b1aa5dc46bef8f25fa9111e2e08e51046c9b.gz
author c.rhodes <c.rhodes@gold.ac.uk>
date Thu, 26 Jul 2007 14:18:34 +0100
parents 8528c316fbcc
children f49aa290b5c3
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 pitch= ((p1 diatonic-pitch) (p2 diatonic-pitch))
c@106 37 (let ((c1 (%p-pc p1)) (m1 (%p-pm p1))
c@106 38 (c2 (%p-pc p2)) (m2 (%p-pm p2)))
m@83 39 (and c1 c2 (= c1 c2)
m@83 40 m1 m2 (= m1 m2))))
m@83 41
c@109 42 (defmethod middle-c ((mp diatonic-pitch))
c@109 43 (make-diatonic-pitch 39 23))
m@81 44
c@109 45 (defmethod midi-pitch-number ((mp diatonic-pitch))
c@106 46 (+ (%p-pc mp) 21))
c@106 47
c@109 48 (defmethod octave ((mp diatonic-pitch))
c@106 49 (1- (floor (midi-pitch-number mp) 12)))
c@106 50
c@109 51 (defmethod diatonic-pitch ((mp diatonic-pitch))
m@81 52 mp)
m@81 53
c@109 54 (defmethod print-object ((o diatonic-pitch) stream)
c@106 55 (print-unreadable-object (o stream :type t)
c@106 56 (let ((asa-string (asa-pitch-string o)))
c@106 57 (write asa-string :stream stream))))
m@81 58
m@81 59 ;;; Chromatic pitch
m@81 60
m@86 61 (defmethod octave ((cp chromatic-pitch))
c@106 62 (1- (floor (%chromatic-pitch-number cp) 12)))
m@86 63
m@81 64 (defmethod middle-c ((cp chromatic-pitch))
m@81 65 (make-chromatic-pitch 60))
m@81 66
m@24 67 (defmethod chromatic-pitch ((pitch-designator chromatic-pitch))
m@24 68 pitch-designator)
m@24 69
m@24 70 (defmethod midi-pitch-number ((pitch-designator chromatic-pitch))
m@24 71 (%chromatic-pitch-number pitch-designator))
m@24 72
m@24 73 (defmethod midi-pitch-number ((pitch-designator pitch))
m@24 74 (%chromatic-pitch-number (chromatic-pitch pitch-designator)))
m@24 75
m@24 76 (defmethod span ((pitch-interval-designator pitch-interval))
m@24 77 (%pitch-interval-span pitch-interval-designator))
m@24 78
m@24 79 (defmethod duration ((period-designator period))
m@24 80 (%period-interval period-designator))
m@24 81
d@33 82 (defmethod (setf duration) ((value real) (period-designator period))
d@33 83 (setf (%period-interval period-designator) value))
d@33 84
m@24 85 (defmethod timepoint ((moment-designator moment))
m@24 86 (%moment-time moment-designator))
m@24 87
d@33 88 (defmethod (setf timepoint) ((value real) (moment-designator moment))
d@33 89 (setf (%moment-time moment-designator) value))
d@33 90
d@73 91 (defmethod cut-off ((anchored-period-designator anchored-period))
d@73 92 (make-instance 'moment
d@73 93 :time (+ (%moment-time anchored-period-designator)
d@73 94 (%period-interval anchored-period-designator))))
d@73 95
m@24 96 (defmethod beat-units-per-bar ((time-signature basic-time-signature))
m@24 97 (%basic-time-signature-numerator time-signature))
m@24 98
m@24 99 (defmethod beat-units ((time-signature basic-time-signature))
m@24 100 (%basic-time-signature-denominator time-signature))
m@24 101
m@67 102 (defmethod time-signature-equal ((ts1 basic-time-signature)
m@67 103 (ts2 basic-time-signature))
m@67 104 (let ((n1 (time-signature-numerator ts1))
m@67 105 (n2 (time-signature-numerator ts2))
m@67 106 (d1 (time-signature-denominator ts1))
m@67 107 (d2 (time-signature-denominator ts2)))
m@67 108 (and n1 n2 (= n1 n2)
m@67 109 d1 d2 (= d1 d2))))
m@67 110
m@24 111 (defmethod key-signature-sharps ((key-signature basic-key-signature))
m@24 112 (%basic-key-signature-sharp-count key-signature))
m@24 113
m@45 114 (defmethod key-signature-mode ((ks midi-key-signature))
m@45 115 (%midi-key-signature-mode ks))
m@45 116
m@67 117 (defmethod key-signature-equal ((ks1 basic-key-signature)
m@67 118 (ks2 basic-key-signature))
m@67 119 (let ((s1 (key-signature-sharps ks1))
m@67 120 (s2 (key-signature-sharps ks2)))
m@67 121 (and s1 s2 (= s1 s2))))
m@67 122
m@67 123 (defmethod key-signature-equal ((ks1 midi-key-signature)
m@67 124 (ks2 midi-key-signature))
m@67 125 (let ((s1 (key-signature-sharps ks1))
m@67 126 (s2 (key-signature-sharps ks2))
m@67 127 (m1 (key-signature-mode ks1))
m@67 128 (m2 (key-signature-mode ks2)))
m@67 129 (and s1 s2 (= s1 s2)
m@67 130 m1 m2 (= m1 m2))))
m@67 131
m@24 132 (defmethod bpm ((tempo tempo))
m@24 133 (%tempo-bpm tempo))
m@24 134
m@67 135 (defmethod tempo-equal ((t1 tempo) (t2 tempo))
m@67 136 (and (bpm t1) (bpm t2) (= t1 t2)))
m@67 137
m@67 138
m@24 139 ;; Time protocol
m@24 140
m@24 141 (defmethod time+ ((object1 moment) (object2 period))
d@100 142 "(time+ <moment> <period>) -> <moment> Implemented as a
d@100 143 straightforward summation."
m@24 144 (make-moment (+ (timepoint object1) (duration object2))))
m@24 145
m@24 146 (defmethod time+ ((object1 period) (object2 moment)) ;?
d@100 147 "(time+ <period> <moment>) -> <moment> Implemented as a
d@100 148 straightforward summation."
m@24 149 (time+ object2 object1))
m@24 150
m@24 151 (defmethod time+ ((object1 period) (object2 period))
d@100 152 "(time+ <period> <period>) -> <period> Implemented as a
d@100 153 straightforward summation."
m@24 154 (make-floating-period (+ (duration object1)
m@24 155 (duration object2))))
m@24 156
m@24 157 (defmethod time+ ((object1 moment) (object2 moment))
d@100 158 "(time+ <moment> <moment>) -> <condition:undefined-action> The
d@100 159 question makes no sense."
m@24 160 (error 'undefined-action :operation 'time+ :datatype (list (class-of object1) (class-of object2))))
m@24 161
m@24 162 (defmethod time- ((object1 moment) (object2 moment))
m@24 163 (make-anchored-period (timepoint object2)
m@24 164 (- (timepoint object1)
m@24 165 (timepoint object2))))
m@24 166
m@24 167 (defmethod time- ((object1 moment) (object2 period))
m@24 168 (make-moment (- (timepoint object1) (duration object2))))
m@24 169
m@24 170 (defmethod time- ((object1 period) (object2 moment)) ;?
m@24 171 (error 'undefined-action
m@24 172 :operation 'time-
m@24 173 :datatype (list (class-of object1) (class-of object2))))
m@24 174
m@24 175 (defmethod time- ((object1 period) (object2 period))
m@24 176 (make-floating-period (- (duration object2)
m@24 177 (duration object1))))
m@24 178
m@24 179 ;; these ones are less certain. I've just put them in, but think I
m@24 180 ;; should remove them and force the user to specify what they mean
m@24 181 ;; when they give objects that are both moments *and* periods to these
m@24 182 ;; functions.
m@24 183
m@24 184 (defmethod time- ((object1 anchored-period) (object2 anchored-period)) ;?
m@24 185 (time- (moment object1) (moment object2)))
m@24 186
m@24 187 (defmethod time- (object1 (object2 anchored-period)) ;?
m@24 188 (time- object1 (moment object2)))
m@24 189
m@24 190 (defmethod time- ((object1 anchored-period) object2) ;?
m@24 191 (time- (moment object1) object2))
m@24 192
m@24 193 (defmethod time> ((object1 moment) (object2 moment))
m@24 194 (> (timepoint object1) (timepoint object2)))
m@24 195
d@73 196 (defmethod time< ((object1 moment) (object2 moment))
d@73 197 (< (timepoint object1) (timepoint object2)))
d@73 198
m@24 199 (defmethod time= ((object1 moment) (object2 moment))
m@24 200 (= (timepoint object1) (timepoint object2)))
m@24 201
m@24 202 (defmethod duration> ((object1 period) (object2 period))
m@24 203 (> (duration object1) (duration object2)))
m@24 204
m@24 205 (defmethod duration= ((object1 period) (object2 period))
m@24 206 (= (duration object1) (duration object2)))
m@24 207
m@24 208 (defmethod duration* ((object1 period) (object2 number))
m@24 209 (make-floating-period (* (duration object1) object2)))
m@24 210
m@24 211 (defmethod duration* ((object1 number) (object2 period))
m@24 212 (duration* object2 object1))
m@24 213
m@24 214 (defmethod duration/ ((object1 period) (object2 number))
m@24 215 (make-floating-period (/ (duration object1) object2)))
m@24 216
m@24 217 ;; Pitch protocol
m@24 218
m@24 219 (defmethod pitch+ ((object1 pitch-designator)
m@24 220 (object2 pitch-designator))
m@24 221 (error 'undefined-action :operation 'pitch+
m@24 222 :datatype (list (class-of object1) (class-of object2))))
m@24 223
m@24 224 (defmethod pitch+ ((object1 pitch-designator)
m@24 225 (object2 pitch-interval)) ; or should I check the
m@24 226 ; pitch/interval types?
d@34 227 (make-chromatic-pitch (+ (midi-pitch-number object1)
m@24 228 (span object2))))
m@24 229
m@24 230 (defmethod pitch+ ((object1 pitch-interval)
m@24 231 (object2 pitch-designator)) ;?
m@24 232 (pitch+ object2 object1))
m@24 233
m@24 234 (defmethod pitch+ ((object1 pitch-interval)
m@24 235 (object2 pitch-interval))
c@105 236 (make-chromatic-pitch-interval (+ (span object1) (span object2))))
m@24 237
m@24 238 (defmethod pitch- ((object1 pitch-designator)
m@24 239 (object2 pitch-designator))
c@105 240 (make-chromatic-pitch-interval
c@105 241 (- (midi-pitch-number object1) (midi-pitch-number object2))))
m@24 242
m@24 243 (defmethod pitch- ((object1 pitch-designator)
m@24 244 (object2 pitch-interval))
c@105 245 (make-chromatic-pitch (- (midi-pitch-number object1) (span object2))))
m@24 246
m@24 247 (defmethod pitch- ((object1 pitch-interval)
m@24 248 (object2 pitch-interval))
c@105 249 (make-chromatic-pitch-interval (- (span object1) (span object2))))
m@24 250
m@24 251 (defmethod pitch- ((object1 pitch-interval)
m@24 252 (object2 pitch-designator))
m@24 253 (error 'undefined-action :operation 'pitch-
m@24 254 :datatype (list (class-of object1) (class-of object2))))
m@24 255
m@24 256 (defmethod pitch> ((object1 pitch-designator)
m@24 257 (object2 pitch-designator))
d@34 258 (> (midi-pitch-number object1)
d@34 259 (midi-pitch-number object2)))
m@24 260
m@24 261 (defmethod pitch= ((object1 pitch-designator)
m@24 262 (object2 pitch-designator))
d@34 263 (= (midi-pitch-number object1)
d@34 264 (midi-pitch-number object2)))
m@24 265
m@24 266 (defmethod interval> ((object1 pitch-interval)
c@104 267 (object2 pitch-interval))
m@24 268 (> (span object1)
m@24 269 (span object2)))
m@24 270
m@24 271 (defmethod interval= ((object1 pitch-interval)
m@24 272 (object2 pitch-interval))
m@24 273 (= (span object1)
m@24 274 (span object2)))
m@24 275
m@24 276
m@24 277
m@24 278 ;; Allen
m@24 279
m@24 280 (defmethod meets ((object1 anchored-period)
m@24 281 (object2 anchored-period))
m@24 282 (or (time= (cut-off object1) object2)
m@24 283 (time= (cut-off object2) object1)))
m@24 284
m@24 285 (defmethod before ((object1 anchored-period)
m@24 286 (object2 anchored-period))
m@24 287 (time> object2 (cut-off object1)))
m@24 288
m@24 289 (defmethod overlaps ((object1 anchored-period)
m@24 290 (object2 anchored-period))
m@24 291 ;; FIXME: Is there a tidier method?
m@24 292 (or (and (time> object2 object1) ; object1 starts before object2
m@24 293 (time> (cut-off object1) object2) ; object1 ends after object2 starts
m@24 294 (time> (cut-off object2) (cut-off object1))) ; object1 ends before object2 does
m@24 295 (and (time> object1 object2) ; object1 starts after object2
m@24 296 (time> (cut-off object2) object1) ; object1 starts before object2 ends
m@24 297 (time> (cut-off object1) (cut-off object2))))) ; object1 ends after object2 does
m@24 298
m@24 299 (defmethod during ((object1 anchored-period)
m@24 300 (object2 anchored-period))
m@24 301 (and (time> object1 object2)
m@24 302 (time< (cut-off object2) (cut-off object2))))
m@24 303
m@24 304 (defmethod starts ((object1 anchored-period)
m@24 305 (object2 anchored-period))
m@24 306 (time= object1 object2))
m@24 307
m@24 308 (defmethod ends ((object1 anchored-period)
m@24 309 (object2 anchored-period))
m@24 310 (time= (cut-off object1) (cut-off object2)))
m@24 311
m@24 312 ;; ...and
m@24 313
d@33 314 (defmethod period= ((object1 anchored-period)
c@105 315 (object2 anchored-period))
d@33 316 (and (time= object1 object2)
d@33 317 (duration= object1 object2)))
d@33 318 (defmethod period= ((object1 floating-period)
d@33 319 (object2 floating-period))
d@33 320 (duration= object1 object2))
d@33 321
m@24 322 (defmethod period-intersection ((object1 anchored-period)
m@24 323 (object2 anchored-period))
m@24 324 (cond
m@24 325 ((disjoint object1 object2)
m@24 326 ;; if they don't overlap, return nil, not a negative-valued
m@24 327 ;; period
m@24 328 nil)
m@24 329 ((let* ((start (if (time> (onset object2) (onset object1))
m@24 330 (onset object2)
m@24 331 (onset object1)))
m@24 332 (duration (duration (time- (if (time> (cut-off object2) (cut-off object1))
m@24 333 (cut-off object1)
m@24 334 (cut-off object2))
m@24 335 start))))
m@24 336 (make-anchored-period (timepoint start) duration)))))
m@24 337
m@24 338