d@88
|
1 (cl:in-package #:amuse-geerdes)
|
d@88
|
2
|
d@88
|
3 ;;; Compositions
|
d@88
|
4
|
d@88
|
5 ;; identifiers
|
d@88
|
6 (defun g-id (cat-id)
|
d@100
|
7 "Make a geerdes-identifier based on a catalogue id"
|
d@88
|
8 (make-instance 'geerdes-identifier-cat-id :cat-id cat-id))
|
d@88
|
9 (defun g-id-file-id (file-id)
|
d@100
|
10 "Make a geerdes-identifier based on a catalogue id"
|
d@88
|
11 (make-instance 'geerdes-identifier-file-id :file-id file-id))
|
d@88
|
12
|
d@100
|
13 (defgeneric cat-id (object)
|
d@134
|
14 (:documentation "Return a database catalogue id for object (for
|
d@134
|
15 Geerdes data, this is the company's own ID"))
|
d@100
|
16 (defgeneric file-id (object)
|
d@134
|
17 (:documentation "Return a database file id for object (for
|
d@134
|
18 Geerdes data, this is a unique integer identifier)"))
|
d@88
|
19 (defgeneric (setf cat-id) (value object))
|
d@88
|
20 (defgeneric (setf file-id) (value object))
|
d@88
|
21
|
d@88
|
22 (defmethod cat-id ((object geerdes-composition))
|
d@88
|
23 (%db-cat-id object))
|
d@88
|
24 (defmethod cat-id ((object geerdes-identifier-cat-id))
|
d@88
|
25 (slot-value object 'cat-id))
|
d@88
|
26 (defmethod file-id ((object geerdes-composition))
|
d@88
|
27 (%db-file-id object))
|
d@88
|
28 (defmethod file-id ((object geerdes-identifier-file-id))
|
d@88
|
29 (slot-value object 'file-id))
|
d@88
|
30 (defmethod (setf cat-id) (value (object geerdes-composition))
|
d@88
|
31 (setf (%db-cat-id object) value))
|
d@88
|
32 (defmethod (setf cat-id) (value (object geerdes-identifier-cat-id))
|
d@88
|
33 (setf (slot-value object 'cat-id) value))
|
d@88
|
34 (defmethod (setf file-id) (value (object geerdes-composition))
|
d@88
|
35 (setf (%db-file-id object) value))
|
d@88
|
36 (defmethod (setf file-id) (value (object geerdes-identifier-file-id))
|
d@88
|
37 (setf (slot-value object 'file-id) value))
|
d@88
|
38
|
d@88
|
39 ;; Composition
|
d@88
|
40
|
d@88
|
41 (defmethod get-composition ((identifier geerdes-identifier))
|
d@88
|
42 (let* ((composition (get-geerdes-composition identifier)))
|
d@88
|
43 (%initialise-notes composition)
|
d@88
|
44 (%initialise-constituents composition)))
|
d@88
|
45
|
d@88
|
46 (defgeneric get-geerdes-composition (identifier))
|
d@88
|
47 (defmethod get-geerdes-composition ((identifier geerdes-identifier-cat-id))
|
d@88
|
48 #.(clsql:locally-enable-sql-reader-syntax)
|
d@88
|
49 (let* ((cat-id (cat-id identifier))
|
d@88
|
50 (file-info (car (clsql:select [id] [timebase]
|
d@88
|
51 :from [midi_file]
|
d@88
|
52 :where [= [cat_id] cat-id]
|
d@88
|
53 :flatp t
|
d@88
|
54 :result-types :auto)))
|
d@88
|
55 (timebase (second file-info))
|
d@88
|
56 (file-id (first file-info))
|
d@88
|
57 (composition (make-instance 'geerdes-composition
|
d@88
|
58 :id identifier
|
d@88
|
59 :file-id file-id
|
d@88
|
60 :cat-id cat-id
|
d@88
|
61 :midi-timebase timebase)))
|
d@88
|
62 (setf (%midi-events composition) (get-db-events file-id)
|
d@88
|
63 (%midi-constituents composition) (get-db-constituents file-id))
|
d@88
|
64 #.(clsql:restore-sql-reader-syntax-state)
|
d@88
|
65 composition))
|
d@88
|
66 (defmethod get-geerdes-composition ((identifier geerdes-identifier-file-id))
|
d@88
|
67 #.(clsql:locally-enable-sql-reader-syntax)
|
d@88
|
68 (let* ((file-id (file-id identifier))
|
d@88
|
69 (file-info (car (clsql:select [cat_id] [timebase]
|
d@88
|
70 :from [midi_file]
|
d@88
|
71 :where [= [id] file-id]
|
d@88
|
72 :flatp t
|
d@88
|
73 :result-types :auto)))
|
d@88
|
74 (timebase (second file-info))
|
d@88
|
75 (cat-id (first file-info))
|
d@88
|
76 (composition (make-instance 'geerdes-composition
|
d@88
|
77 :id identifier
|
d@88
|
78 :cat-id cat-id
|
d@88
|
79 :file-id file-id
|
d@88
|
80 :midi-timebase timebase)))
|
d@88
|
81 (setf (%midi-events composition) (get-db-events file-id)
|
d@88
|
82 (%midi-constituents composition) (get-db-constituents file-id))
|
d@88
|
83 #.(clsql:restore-sql-reader-syntax-state)
|
d@88
|
84 composition))
|
d@88
|
85
|
d@88
|
86 (defun get-db-events (file-id)
|
d@88
|
87 (clsql:query
|
d@88
|
88 (concatenate 'string "
|
d@133
|
89 SELECT track, channel, start, duration, patch, pitch, velocity, id, event_id, mel_duration
|
d@88
|
90 FROM midi_event LEFT JOIN derived_midi_monody ON (id=event_id)
|
d@88
|
91 WHERE file_id=" (princ-to-string file-id)
|
d@88
|
92 " ORDER BY start")))
|
d@88
|
93 (defun get-db-constituents (file-id)
|
d@88
|
94 (clsql:query (concatenate 'string "
|
d@88
|
95 SELECT track, channel, start, duration,
|
d@88
|
96 param.num, param.value, pb.value, tp.value, ts.num, ts.denom
|
d@88
|
97 FROM midi_constituent c
|
d@88
|
98 LEFT JOIN midi_pb pb ON (id=pb.constituent_id)
|
d@88
|
99 LEFT JOIN midi_tempo tp ON (id=tp.constituent_id)
|
d@88
|
100 LEFT JOIN midi_timesig ts ON (id=ts.constituent_id)
|
d@88
|
101 LEFT JOIN midi_param param ON (id=param.constituent_id)
|
d@88
|
102 WHERE c.file_id=" (princ-to-string file-id)
|
d@101
|
103 " ORDER BY start")))
|
d@101
|
104
|
d@101
|
105 (defmethod monody ((composition geerdes-composition))
|
d@101
|
106 (unless (amuse-geerdes::%monody composition)
|
d@101
|
107 (setf (amuse-geerdes::%monody composition)
|
d@101
|
108 (get-monody composition)))
|
d@101
|
109 (amuse-geerdes::%monody composition))
|
d@101
|
110
|
d@101
|
111 (defgeneric get-monody (composition))
|
d@101
|
112 (defmethod get-monody ((composition geerdes-composition))
|
d@101
|
113 ;;; FIXME: FIXED-[THIS IS DANGEROUS - IT EDITS NOTE LENGTH]
|
d@101
|
114 ;; FIXME: As a result of this fix, notes no longer eq their monody
|
d@101
|
115 ;; versions
|
d@101
|
116 ;;; FIXME: This is a serious issue. Needs to be addressed by
|
d@101
|
117 ;; a proper implementation of constituent with annotations
|
d@101
|
118 ;;; From DTM: - Select notes
|
d@101
|
119 ;; on channel 4
|
d@101
|
120 (let ((vocal-line (loop for event being the elements of (lead-vocal-part composition)
|
d@101
|
121 collect (copy-event event))))
|
d@101
|
122 (when vocal-line
|
d@101
|
123 (let* ((comp (make-instance 'geerdes-composition
|
d@101
|
124 :file-id (file-id composition)
|
d@101
|
125 :time (timepoint composition)
|
d@101
|
126 :tempi (tempi composition)
|
d@101
|
127 :time-signatures (time-signatures composition)
|
d@101
|
128 :interval (duration composition)))
|
d@101
|
129 (vocal-composition (sequence:adjust-sequence comp
|
d@101
|
130 (length vocal-line)
|
d@101
|
131 :initial-contents vocal-line))
|
d@101
|
132 (monody (make-instance 'geerdes-monody
|
d@101
|
133 :time (timepoint composition)
|
d@101
|
134 :file-id (file-id composition)
|
d@101
|
135 :tempi (tempi composition)
|
d@101
|
136 :time-signatures (time-signatures composition)
|
d@101
|
137 :interval (duration composition))) ;; Overly inclusive?
|
d@101
|
138 (monody-events (monodificate vocal-composition)))
|
d@101
|
139 (sequence:adjust-sequence monody (length monody-events)
|
d@101
|
140 :initial-contents monody-events)))))
|
d@101
|
141
|
d@101
|
142 (defgeneric lead-vocal-part (time-ordered-constituent)
|
d@101
|
143 (:method (toc) (remove-if-not #'lead-vocalp toc)))
|
d@101
|
144
|
d@101
|
145 (defgeneric lead-vocalp (event)
|
d@101
|
146 (:method (e) (declare (ignore e)) nil))
|
m@103
|
147 (defmethod lead-vocalp ((event geerdes-pitched-event))
|
d@101
|
148 (= (midi-channel event) 4))
|
d@114
|
149
|
d@130
|
150 (defmethod crotchet ((object geerdes-object))
|
d@139
|
151 (make-standard-period 1))
|
d@115
|
152
|