m@24: (cl:in-package #:amuse) m@24: j@287: ;;; Identifiers j@287: j@287: (defgeneric identifier (object)) j@287: j@287: (defgeneric event-id (object)) j@287: j@287: (defgeneric composition-id (object)) j@287: m@24: ;;; Pulling compositions from the database m@24: d@123: (defgeneric get-composition (identifier) d@123: (:documentation "Returns a composition of type dependant on d@123: identifier")) m@24: d@169: (defgeneric get-constituents (constituent-identifier) d@169: (:documentation "Returns a list of constituents matching the d@169: criteria in identifier")) d@169: m@89: (defgeneric monody (object) m@89: (:documentation "Returns a monody.")) m@89: (defgeneric ensure-monody (object) m@89: (:documentation "Returns a generalised boolean.")) m@89: d@33: ;;; Getting constituents from compositions d@33: ;; IS this the mechanism we want to use d@72: (defgeneric time-signatures (composition) d@72: (:documentation "Returns all time-signatures in a composition d@72: Probably shouldn't be exported - can be replaced d@72: by (get-applicable-time-signature commposition composition)")) d@72: (defgeneric (setf time-signatures) (sequence composition) d@72: (:documentation "Sets all time-signatures in a composition. d@72: Is this wanted here?")) d@72: (defgeneric tempi (composition) d@72: (:documentation "Returns all tempi in a composition Probably d@72: shouldn't be exported - can be replaced d@72: by (get-applicable-tempi commposition composition)")) d@72: (defgeneric (setf tempi) (sequence composition) d@72: (:documentation "Sets all tempi in a composition. d@72: Is this wanted here?")) d@72: (defgeneric key-signatures (composition) d@72: (:documentation "Returns all key-signatures in a composition d@72: Probably shouldn't be exported - can be replaced d@72: by (get-applicable-key-signature commposition composition)")) d@72: (defgeneric (setf key-signatures) (sequence composition) d@72: (:documentation "Sets all key sigs in a composition. d@72: Is this wanted here?")) d@33: m@24: ;;; Simple Accessors m@24: m@24: ;; pitch-based m@24: m@24: (defgeneric pitch (object &key kind)) ; ? Maybe this returns the pitch m@24: ; in its ur form? d@136: (defgeneric chromatic-pitch (pitch)) d@136: (defgeneric diatonic-pitch (pitch)) m@24: (defgeneric frequency (object)) ;? m@81: d@136: (defgeneric octave (pitch) m@86: (:documentation "Return an integer representing the octave of d@136: pitch where middle c is defined to be the lowest pitch in m@86: octave 4.")) m@86: d@136: (defgeneric diatonic-pitch-octave (pitch) c@106: (:documentation "Return an integer representing the diatonic octave d@136: of pitch.")) c@106: d@136: (defgeneric diatonic-pitch-accidental (pitch) m@86: (:documentation "Return an integer representing the inflection of a m@86: diatonic pitch where where negative values indicate numbers of flats, m@86: 0 indicates natural and positive values indicate numbers of sharps.")) m@86: d@136: (defgeneric diatonic-pitch-mp (pitch) c@108: (:documentation "Return an integer representing the morphetic pitch c@108: \(in MIPS terms) of a diatonic pitch.")) d@136: (defgeneric diatonic-pitch-cp (pitch) c@108: (:documentation "Return an integer representing the chromatic pitch c@108: \(in MIPS terms) of a diatonic pitch.")) c@108: d@136: (defgeneric middle-c (pitch) m@81: (:documentation "Returns the value of middle C in the particular d@136: representation of pitch used by PITCH.")) d@136: (defgeneric midi-pitch-number (pitch) d@136: (:documentation "Takes a pitch (usually a pitched event) and d@136: returns an integer between 0 and 127 representing the chromatic d@136: pitch represented (60=middle C, 48 the C below that, etc.)")) d@136: (defgeneric asa-pitch-string (pitch) m@81: (:documentation "Returns a string representing the designated ASA m@81: pitch name which has three parts: a letter name in the set m@81: {A,B,C,D,E,F,G}, an inflection in the set {n,f,s,ff,ss,fff,sss,...} m@81: and an octave number. E.g., Cn4 = Middle C.")) d@136: (defgeneric asa-interval-string (pitch) c@112: (:documentation "Returns a string representing the designated ASA c@112: interval name which has two or three parts: a direction in the set c@112: {r,f} (absent for unisons/primes), a type in the set c@112: {p,ma,mi,a,d,aa,dd,aaa,ddd,...}, and a size number. E.g. rma2 = c@112: rising major second.")) d@136: (defgeneric diatonic-pitch-name (pitch) m@81: (:documentation "Returns a char in the set m@81: {#\A,#\B,#\C,#\D,#\E,#\F,#\G}, representing the pitch name of d@136: PITCH.")) d@136: (defgeneric pitch-class (pitch) d@136: (:documentation "Takes a pitch (usually a pitched event) and d@136: returns an integer between 0 and 12 representing the d@136: octave-independant pitch, with c=0, c#=1, etc.") m@24: (:method (p) (mod (midi-pitch-number p) 12))) d@136: (defgeneric span (pitch-interval)) m@24: m@24: ;; time m@24: d@136: (defgeneric duration (period) d@136: (:documentation "Returns a real. Probably should only apply do d@136: standard-periods (rather than periods? or should it return d@136: something other than a value in other cases)")) d@136: (defgeneric (setf duration) (value period) d@136: (:documentation "As with duration, perhaps this should work only d@136: with standard-periods")) d@136: (defgeneric timepoint (moment) d@136: (:documentation "Returns a number for a moment. Does this make d@136: any sense on an abstrace class? Should it just apply to d@136: standard-moment?")) d@136: (defgeneric (setf timepoint) (value moment) d@136: (:documentation "Sets timepoint. What does this mean for an d@136: abstract class? Should it just apply to standard-moment")) d@136: (defgeneric cut-off (anchored-period) ; name? d@72: (:documentation "Returns a representing the point at d@121: which the anchored period has ended. By default, is calculated d@121: as the result of running time+ on the onset and period of the d@121: object.") d@136: (:method (apd) (time+ (moment apd) (period apd)))) d@136: (defgeneric crotchet (object) m@95: (:documentation "Returns a period, the duration of which represents m@95: a crotchet in the time representation used by object.")) m@24: m@24: ;; others m@24: m@24: ;; I've given the time-sig accessors general names because it allows m@24: ;; for symbols in time-signatures as well as numbers - numerator is an m@24: ;; odd accessor if the time sig is C (even in common practice) but d@100: ;; its meaning is clear. beat-units-per-bar is clearer, though, I m@24: ;; think. m@24: d@123: (defgeneric beat-units-per-bar (time-signature) d@123: (:documentation "In a standard, fraction-like time-signature or d@123: a symbolic equivalent, this is the numerator.")) m@24: (defgeneric time-signature-numerator (time-signature) d@123: (:method (ts) (beat-units-per-bar ts)) d@123: (:documentation "Not obviously meaningful for non fraction-like d@123: time signatures")) d@123: (defgeneric beat-units (time-signature) d@123: (:documentation "In a standard, fraction-like time-signature or d@134: a symbolic equivalent, this is the denominator (n.b. the d@134: difference between this and @code{tactus-duration} is only d@134: visible for compound time, where this returns the lower portion d@134: of the time signature, but @code{tactus-duration} returns the d@134: higher-level unit).")) m@24: (defgeneric time-signature-denominator (time-signature) d@123: (:method (ts) (beat-units ts)) d@123: (:documentation "Not obviously meaningful for non fraction-like d@123: time signatures")) d@33: (defgeneric tactus-duration (time-signature) j@305: ;; basic, but should do? NO! This defines 6/4 as compound. We need j@305: ;; proper simplep and compoundp predicates. d@33: (:method (ts) j@305: (warn "FIXME: tactus-duration is broken") d@33: (cond j@305: ;; ((and (not (= (beat-units-per-bar ts) 3)) j@305: ;; (= (rem (beat-units-per-bar ts) 3) 0)) j@305: ((and (= (beat-units ts) 8) d@33: (= (rem (beat-units-per-bar ts) 3) 0)) d@33: ;; compound time d@33: (* (/ 4 (beat-units ts)) d@33: 3)) d@123: (t (/ 4 (beat-units ts))))) d@123: (:documentation "Returns a number of crotchets to represent the d@123: tactus, based on some idea of time signature patterns. Should, d@123: in future, return a duration rather than a number.")) m@24: d@123: (defgeneric key-signature-sharps (key-signature) d@123: (:documentation "Simple query for normal key-signatures.")) d@123: (defgeneric key-signature-mode (ks) d@123: (:documentation "Query that only makes sense for midi-like key d@123: signatures")) m@24: d@123: (defgeneric bpm (tempo) d@123: (:documentation "Basic tempo query")) ;; in bpm m@24: (defgeneric microseconds-per-crotchet (tempo) m@24: ;; As used (when rounded) in MIDI d@123: (:method (tp) (/ 60000000 (bpm tp))) d@123: (:documentation "Basic tempo query for MIDI. N.B. This will be d@123: a fraction and must be rounded before being used for output.")) m@24: m@24: ;;; Coerce-type accessors m@24: m@24: ;; Should I be including these default methods? Should the accessors m@24: ;; be direct slot accessors or the generics I'm using? Should we m@24: ;; return the object itself if it already is in the target class? m@24: d@136: (defgeneric anchored-period (anchored-period) d@123: (:method (apd) (make-anchored-period (onset apd) (duration apd))) d@123: (:documentation "Coerce any anchored period to a plain anchored d@123: period")) m@24: d@136: (defgeneric period (period) d@136: (:method (pd) (make-period (duration pd))) d@123: (:documentation "Coerce any period to a floating period")) m@24: d@136: (defgeneric moment (moment) d@123: (:method (md) (make-moment (timepoint md))) d@136: (:documentation "Coerce any moment, including an d@123: anchored-period to a moment")) m@24: d@136: (defgeneric onset (anchored-period) d@139: (:method (ap) (moment ap)) d@123: (:documentation "Return a moment for the start of an anchored period")) d@136: (defgeneric (setf onset) (value anchored-period)) m@24: m@24: ;;; Time Protocol (or moments?) m@24: m@24: ;; negative times/durations -> ERROR? m@24: m@24: ;; time+: