Mercurial > hg > amuse
changeset 88:8ea75cc8bc2c
Basic geerdes functionality moved to implementations/geerdes from separate package
darcs-hash:20070720161242-f76cc-fd256cbbb81d8c418a6c7c45844264184c5ed932.gz
author | David Lewis <d.lewis@gold.ac.uk> |
---|---|
date | Fri, 20 Jul 2007 17:12:42 +0100 |
parents | 19a263fb92d1 |
children | 0b4c624910f1 |
files | amuse-geerdes.asd base/classes.lisp implementations/geerdes/classes.lisp implementations/geerdes/connect.lisp implementations/geerdes/constructors.lisp implementations/geerdes/methods.lisp implementations/geerdes/package.lisp tools/segmentation/simple-example.lisp utils/package.lisp utils/utils.lisp |
diffstat | 10 files changed, 372 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/amuse-geerdes.asd Fri Jul 20 17:12:42 2007 +0100 @@ -0,0 +1,13 @@ +(asdf:defsystem amuse-geerdes + :name "amuse-geerdes" + :depends-on ("amuse" "clsql") + :components + ((:module implementations + :components + ((:module geerdes + :components + ((:file "package") + (:file "connect" :depends-on ("package")) + (:file "classes" :depends-on ("package")) + (:file "constructors" :depends-on ("package" "classes")) + (:file "methods" :depends-on ("package" "classes" "constructors")))))))) \ No newline at end of file
--- a/base/classes.lisp Wed Jul 18 16:12:58 2007 +0100 +++ b/base/classes.lisp Fri Jul 20 17:12:42 2007 +0100 @@ -37,7 +37,7 @@ (defclass pitch (pitch-designator) ()) (defclass chromatic-pitch (pitch) ((number :accessor %chromatic-pitch-number :initarg :number))) -(defclass diatonic-pitch (pitch) +(defclass diatonic-pitch (pitch) ((name :accessor %diatonic-pitch-name :initarg :name) (accidental :accessor %diatonic-pitch-accidental :initarg :accidental) (octave :accessor %diatonic-pitch-octave :initarg :octave))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/implementations/geerdes/classes.lisp Fri Jul 20 17:12:42 2007 +0100 @@ -0,0 +1,52 @@ +(cl:in-package #:amuse-geerdes) + +(defclass property-list-mixin () + ((properties :initarg :properties :accessor properties :initform nil))) + +(defclass geerdes-identifier (identifier) ()) +(defclass geerdes-identifier-cat-id (geerdes-identifier) + ((cat-id :initarg :cat-id + :initform 'nil))) +(defclass geerdes-identifier-file-id (geerdes-identifier) + ((file-id :initarg :file-id + :initform 'nil))) + +(defclass geerdes-composition (midi-composition property-list-mixin) + ((db-entry :initarg :db-entry + :initform nil + :accessor %db-entry) + (bar-numbers :initform nil + :accessor %bar-numbers) + (monody :initform nil + :accessor %monody) + (caches :initform nil + :accessor %caches) + (midi-constituents :initarg :constituents + :accessor %midi-constituents) + (midi-events :initarg :midi-events + :accessor %midi-events) + (midi-timebase :initarg :midi-timebase + :accessor %midi-timebase) + (identifier :initarg :id + :accessor %fast-identifier) + (db-cat-id :initarg :cat-id + :accessor %db-cat-id) + (db-file-id :initarg :file-id + :accessor %db-file-id))) + +(defclass geerdes-monody (monody geerdes-composition) + ;; FIXME: necessary slots? Do we even use them? + ((inter-onset-intervals :initarg :i-o-i + :initform nil + :accessor %i-o-i) + (inter-onset-interval-mode :initarg :ioi-mode + :initform 0 + :accessor %ioi-mode))) + +(defclass geerdes-pitched-event (midi-pitched-event property-list-mixin) + ((id :initarg :id + :accessor %geerdes-pitched-event-id))) + +(defclass geerdes-percussive-event (midi-percussive-event property-list-mixin) + ((id :initarg :id + :accessor %geerdes-percussive-event-id)))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/implementations/geerdes/connect.lisp Fri Jul 20 17:12:42 2007 +0100 @@ -0,0 +1,11 @@ +(in-package #:amuse-geerdes) + +;; N.B. This file contains an access password for the database in +;; plain text... + +(defun get-amuse-connection () + (clsql:connect '("vaughan-williams.doc.gold.ac.uk" "amuse" "LispMidi" "clsql") + :if-exists :old :database-type :mysql)) + +;; might as well connect while I'm at it +(get-amuse-connection)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/implementations/geerdes/constructors.lisp Fri Jul 20 17:12:42 2007 +0100 @@ -0,0 +1,178 @@ +(cl:in-package #:amuse-geerdes) + +(defgeneric %initialise-notes (composition)) +(defmethod %initialise-notes ((composition geerdes-composition)) + (let ((notes) (l 0) (last-time 0) (monody-notes) + (monody (make-instance 'geerdes-monody :file-id (file-id composition))) + (timebase (%midi-timebase composition))) + (dolist (row (%midi-events composition)) + (let* ((note (if (pitched-row-p row) + (make-geerdes-pitched-event (%fast-pitch row) + (%fast-velocity row) + (%fast-patch row) + (%fast-channel row) + (%fast-track row) + (%fast-onset row timebase) + (%fast-duration row timebase) + (%fast-id row)) + (make-geerdes-percussive-event (%fast-pitch row) + (%fast-velocity row) + (%fast-patch row) + (%fast-channel row) + (%fast-track row) + (%fast-onset row timebase) + (%fast-duration row timebase) + (%fast-id row))))) + (when (%fast-monodyp row) + (push note monody-notes)) + (when (> (timepoint (cut-off note)) last-time) + (setf last-time (timepoint (cut-off note)))) + (push note notes) + (incf l))) + (sequence:adjust-sequence composition l :initial-contents (reverse notes)) + (setf (duration composition) last-time + (timepoint composition) 0) + (when monody-notes + (setf (%monody composition) (sequence:adjust-sequence monody (length monody-notes) + :initial-contents (reverse monody-notes)) + (timepoint (%monody composition)) (timepoint (elt monody 0)) + (duration (%monody composition)) (- (timepoint (cut-off (car monody-notes))) + (timepoint (elt monody 0))))) + composition)) + +(defgeneric %initialise-constituents (composition)) +(defmethod %initialise-constituents ((composition geerdes-composition)) + ;; FIXME: Should the duration of composition be affected by this? On + ;; the one hand, it makes no difference to the musical content, but + ;; on the other, it seems illogical to reach outside the period. + (let ((timebase (%midi-timebase composition)) + (time-sigs) + (tempi) + (mystery 0)) + (dolist (row (%midi-constituents composition)) + (cond + ((%fast-tempo row) + (push (make-tempo + (microsecond-per-crotchet-to-bpm + (%fast-tempo row)) + (%fast-onset row timebase) + (%fast-duration row timebase)) + tempi)) + ((%fast-numerator row) + (push (make-basic-time-signature + (%fast-numerator row) + (%fast-denominator row) + (%fast-onset row timebase) + (%fast-duration row timebase)) + time-sigs)) + (t (incf mystery)))) + (setf (time-signatures composition) (reverse time-sigs) + (tempi composition) (reverse tempi)) + (when (%monody composition) + (setf (time-signatures (%monody composition)) (time-signatures composition) + (tempi (%monody composition)) (tempi composition))) + (format t "There are ~D constituents not processed~%" mystery) + composition)) + +(defun %fast-track (row) + (first row)) +(defun %fast-channel (row) + (second row)) +(defun %fast-onset (row timebase) + (/ (third row) timebase)) +(defun %fast-duration (row timebase) + (/ (fourth row) timebase)) +(defun %fast-patch (event-row) + (fifth event-row)) +(defun %fast-pitch (event-row) + (sixth event-row)) +(defun %fast-velocity (event-row) + (seventh event-row)) +(defun %fast-id (event-row) + (eighth event-row)) +(defun %fast-monodyp (event-row) + (ninth event-row)) + +(defun %fast-tempo (tp-row) + (eighth tp-row)) +(defun %fast-numerator (ts-row) + (ninth ts-row)) +(defun %fast-denominator (ts-row) + (tenth ts-row)) + +(defun pitched-row-p (event-row) + (and (not (= (%fast-channel event-row) 10)) + (< (%fast-patch event-row) 112))) + +(defun make-geerdes-pitched-event (pitch-number velocity patch + channel track onset duration id) + (make-instance 'geerdes-pitched-event + :number pitch-number + :velocity velocity + :patch patch + :channel channel + :track track + :time onset + :interval duration + :id id)) + +(defun make-geerdes-percussive-event (pitch-number velocity patch + channel track onset duration id) + (make-instance 'geerdes-percussive-event + :sound pitch-number + :velocity velocity + :patch patch + :channel channel + :track track + :time onset + :interval duration + :id id)) + +(defgeneric copy-event (event)) +(defmethod copy-event ((event geerdes-pitched-event)) + (with-slots ((channel amuse-midi::channel) + (track amuse-midi::track) + (number amuse::number) + (time amuse::time) + (interval amuse::interval) + (velocity amuse-midi::velocity) + (patch amuse-midi::patch) id) + event + (make-instance 'geerdes-pitched-event + :channel channel + :track track + :number number + :time time + :interval interval + :velocity velocity + :patch patch + :id id))) +(defmethod copy-event ((event geerdes-percussive-event)) + (with-slots ((channel amuse-midi::channel) + (track amuse-midi::track) + (time amuse::time) + (interval amuse::interval) + (velocity amuse-midi::velocity) + (patch amuse-midi::patch) + (sound amuse-midi::sound) id) + event + (make-instance 'geerdes-percussive-event + :channel channel + :track track + :time time + :interval interval + :velocity velocity + :patch patch + :sound sound + :id id))) + +;; We want any function that generates a sequence from a geerdes +;; composition to preserve all slot values: +(defmethod sequence:make-sequence-like :around ((o geerdes-composition) + length + &key (initial-element nil iep) + (initial-contents nil icp)) + (declare (ignore iep icp length initial-element initial-contents)) + (let ((result (call-next-method))) + (setf (%db-entry result) (%db-entry o)) + result))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/implementations/geerdes/methods.lisp Fri Jul 20 17:12:42 2007 +0100 @@ -0,0 +1,97 @@ +(cl:in-package #:amuse-geerdes) + +;;; Compositions + +;; identifiers +(defun g-id (cat-id) + (make-instance 'geerdes-identifier-cat-id :cat-id cat-id)) +(defun g-id-file-id (file-id) + (make-instance 'geerdes-identifier-file-id :file-id file-id)) + +(defgeneric cat-id (object)) +(defgeneric file-id (object)) +(defgeneric (setf cat-id) (value object)) +(defgeneric (setf file-id) (value object)) + +(defmethod cat-id ((object geerdes-composition)) + (%db-cat-id object)) +(defmethod cat-id ((object geerdes-identifier-cat-id)) + (slot-value object 'cat-id)) +(defmethod file-id ((object geerdes-composition)) + (%db-file-id object)) +(defmethod file-id ((object geerdes-identifier-file-id)) + (slot-value object 'file-id)) +(defmethod (setf cat-id) (value (object geerdes-composition)) + (setf (%db-cat-id object) value)) +(defmethod (setf cat-id) (value (object geerdes-identifier-cat-id)) + (setf (slot-value object 'cat-id) value)) +(defmethod (setf file-id) (value (object geerdes-composition)) + (setf (%db-file-id object) value)) +(defmethod (setf file-id) (value (object geerdes-identifier-file-id)) + (setf (slot-value object 'file-id) value)) + +;; Composition + +(defmethod get-composition ((identifier geerdes-identifier)) + (let* ((composition (get-geerdes-composition identifier))) + (%initialise-notes composition) + (%initialise-constituents composition))) + +(defgeneric get-geerdes-composition (identifier)) +(defmethod get-geerdes-composition ((identifier geerdes-identifier-cat-id)) + #.(clsql:locally-enable-sql-reader-syntax) + (let* ((cat-id (cat-id identifier)) + (file-info (car (clsql:select [id] [timebase] + :from [midi_file] + :where [= [cat_id] cat-id] + :flatp t + :result-types :auto))) + (timebase (second file-info)) + (file-id (first file-info)) + (composition (make-instance 'geerdes-composition + :id identifier + :file-id file-id + :cat-id cat-id + :midi-timebase timebase))) + (setf (%midi-events composition) (get-db-events file-id) + (%midi-constituents composition) (get-db-constituents file-id)) + #.(clsql:restore-sql-reader-syntax-state) + composition)) +(defmethod get-geerdes-composition ((identifier geerdes-identifier-file-id)) + #.(clsql:locally-enable-sql-reader-syntax) + (let* ((file-id (file-id identifier)) + (file-info (car (clsql:select [cat_id] [timebase] + :from [midi_file] + :where [= [id] file-id] + :flatp t + :result-types :auto))) + (timebase (second file-info)) + (cat-id (first file-info)) + (composition (make-instance 'geerdes-composition + :id identifier + :cat-id cat-id + :file-id file-id + :midi-timebase timebase))) + (setf (%midi-events composition) (get-db-events file-id) + (%midi-constituents composition) (get-db-constituents file-id)) + #.(clsql:restore-sql-reader-syntax-state) + composition)) + +(defun get-db-events (file-id) + (clsql:query + (concatenate 'string " + SELECT track, channel, start, duration, patch, pitch, velocity, id, event_id + FROM midi_event LEFT JOIN derived_midi_monody ON (id=event_id) + WHERE file_id=" (princ-to-string file-id) + " ORDER BY start"))) +(defun get-db-constituents (file-id) + (clsql:query (concatenate 'string " + SELECT track, channel, start, duration, + param.num, param.value, pb.value, tp.value, ts.num, ts.denom + FROM midi_constituent c + LEFT JOIN midi_pb pb ON (id=pb.constituent_id) + LEFT JOIN midi_tempo tp ON (id=tp.constituent_id) + LEFT JOIN midi_timesig ts ON (id=ts.constituent_id) + LEFT JOIN midi_param param ON (id=param.constituent_id) + WHERE c.file_id=" (princ-to-string file-id) + " ORDER BY start"))) \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/implementations/geerdes/package.lisp Fri Jul 20 17:12:42 2007 +0100 @@ -0,0 +1,16 @@ +(cl:defpackage #:amuse-geerdes + (:use #:common-lisp #:amuse #:amuse-utils #:amuse-midi #:amuse-segmentation) + (:export + ;; classes + #:geerdes-composition + #:geerdes-monody + ;; identifier constructors + #:g-id + #:g-id-file-id + ;; database identification + #:cat-id + #:file-id + ;; other (caching) + #:properties) + (:documentation "Package for MIDI pop-song database, originating + from Geerdes, a commercial supplier.")) \ No newline at end of file
--- a/tools/segmentation/simple-example.lisp Wed Jul 18 16:12:58 2007 +0100 +++ b/tools/segmentation/simple-example.lisp Fri Jul 20 17:12:42 2007 +0100 @@ -71,4 +71,3 @@ modal-count value))) hits) (values i-o-i-list (* modal-value rounding-divisor) (and real-time i-o-i-secs-list)))) -
--- a/utils/package.lisp Wed Jul 18 16:12:58 2007 +0100 +++ b/utils/package.lisp Fri Jul 20 17:12:42 2007 +0100 @@ -14,4 +14,6 @@ #:get-n-gram #:n-gram-stats #:monodificate + #:significantly-louderp + #:substantially-louderp ))
--- a/utils/utils.lisp Wed Jul 18 16:12:58 2007 +0100 +++ b/utils/utils.lisp Fri Jul 20 17:12:42 2007 +0100 @@ -30,8 +30,8 @@ (amuse:microseconds-per-crotchet tempo)))))) (defmethod beats-to-seconds ((object1 moment) (object2 constituent)) - (beats-to-seconds (make-anchored-period 0 - (timepoint object1)) + (beats-to-seconds (time- (timepoint object1) + (make-moment 0)) object2)) ;; Not as simple as it seems - have to take into account numbering