Mercurial > hg > amuse
comparison tools/gsharp-output.lisp @ 202:3e7b33ae3a0d
Gsharp preview 'fixes'
committer: David Lewis <d.lewis@gold.ac.uk>
author | David Lewis <david@localhost.localdomain> |
---|---|
date | Wed, 08 Sep 2010 13:06:57 +0100 |
parents | 1d3cdca12aeb |
children |
comparison
equal
deleted
inserted
replaced
201:4e0a5c7026ca | 202:3e7b33ae3a0d |
---|---|
63 notehead (beams 0) (dots 0) (tied-p nil)) | 63 notehead (beams 0) (dots 0) (tied-p nil)) |
64 | 64 |
65 ;;;;;;;;;;;;;;;;;;;;; | 65 ;;;;;;;;;;;;;;;;;;;;; |
66 ;; Top-level methods | 66 ;; Top-level methods |
67 | 67 |
68 (defparameter *foo* nil) | |
69 | |
70 (defun write-gsharp-eps (composition pathname) | 68 (defun write-gsharp-eps (composition pathname) |
71 ;; write a score eps from a composition. Most of this can be copied | 69 ;; write a score eps from a composition. Most of this can be copied |
72 ;; straight (this is copied already from CSR's code) | 70 ;; straight (this is copied already from CSR's code) |
73 ;; Boilerplate stuff: | 71 ;; Boilerplate stuff: |
74 (let* ((frame (clim:make-application-frame 'gsharp:gsharp)) | 72 (let* ((frame (clim:make-application-frame 'gsharp::gsharp)) |
75 (clim:*application-frame* frame) | 73 (clim:*application-frame* frame) |
76 (esa:*esa-instance* frame)) | 74 (esa:*esa-instance* frame)) |
77 (clim:adopt-frame (clim:find-frame-manager :server-path '(:null)) frame) | 75 (clim:adopt-frame (clim:find-frame-manager :server-path '(:null)) frame) |
78 (clim:execute-frame-command frame '(gsharp::com-new-buffer)) | 76 (clim:execute-frame-command frame '(gsharp::com-new-buffer)) |
79 ;; Now generate the buffer | 77 ;; Now generate the buffer |
80 (make-objects-for-gsharp-buffer composition (car (esa:buffers frame))) | 78 (make-objects-for-gsharp-buffer composition (car (esa:buffers frame))) |
81 ;; (fill-gsharp-buffer-with-constituent (car (esa:buffers frame)) composition) | 79 ;; (fill-gsharp-buffer-with-constituent (car (esa:buffers frame)) composition) |
82 ;; Refresh and process | 80 ;; Refresh and process |
83 (setf (gsharp::modified-p (car (esa:buffers frame))) t) | 81 (setf (gsharp::modified-p (car (esa:buffers frame))) t) |
84 (gsharp::recompute-measures (car (esa:buffers frame))) | 82 (gsharp::recompute-measures (car (esa:buffers frame))) |
85 (setf *foo* (car (esa:buffers frame))) | |
86 ;; Print | 83 ;; Print |
87 (clim:execute-frame-command | 84 (clim:execute-frame-command |
88 frame `(gsharp::com-print-buffer-to-file ,pathname)) | 85 frame `(gsharp::com-print-buffer-to-file ,pathname)) |
89 (car (esa:buffers frame)))) | 86 (car (esa:buffers frame)))) |
87 | |
88 (defun gsharp-change-size-but-keep-bounding-box (left-margin right-edge buffer) | |
89 (declare (ignorable buffer)) | |
90 (setf gsharp-buffer::*default-left-margin* left-margin | |
91 (gsharp-buffer::left-margin buffer) left-margin | |
92 gsharp-buffer::*default-right-edge* right-edge | |
93 (gsharp-buffer::right-edge buffer) right-edge | |
94 gsharp::*scale* (/ (+ left-margin right-edge) 900) | |
95 gsharp::*top-margin* (/ 80 gsharp::*scale*))) | |
96 | |
97 (defun prepare-gsharp-for-single-system-stuff (buffer) | |
98 (gsharp-change-size-but-keep-bounding-box 5 1100 buffer) | |
99 (setf gsharp-measure::*staves-per-page* (length (gsharp::staves buffer)))) | |
100 | |
101 (defun write-gsharp-ps-single-system (composition pathname) | |
102 ;; write a score eps from a composition. Most of this can be copied | |
103 ;; straight (this is copied already from CSR's code) | |
104 ;; Boilerplate stuff: | |
105 (let* ((frame (clim:make-application-frame 'gsharp::gsharp)) | |
106 (clim:*application-frame* frame) | |
107 (esa:*esa-instance* frame)) | |
108 (clim:adopt-frame (clim:find-frame-manager :server-path '(:null)) frame) | |
109 (clim:execute-frame-command frame '(gsharp::com-new-buffer)) | |
110 ;; Now generate the buffer | |
111 (make-objects-for-gsharp-buffer composition (car (esa:buffers frame))) | |
112 ;; (fill-gsharp-buffer-with-constituent (car (esa:buffers frame)) composition) | |
113 ;; Refresh and process | |
114 (setf (gsharp::modified-p (car (esa:buffers frame))) t) | |
115 (gsharp::recompute-measures (car (esa:buffers frame))) | |
116 (prepare-gsharp-for-single-system-stuff (car (esa:buffers frame))) | |
117 (gsharp::recompute-measures (car (esa:buffers frame))) | |
118 ;; Print | |
119 (clim:execute-frame-command | |
120 frame `(gsharp::com-print-buffer-to-file ,pathname)) | |
121 (car (esa:buffers frame)))) | |
122 | |
123 (defun gsharp-preview (composition) | |
124 ;; see above for origin of this code | |
125 (let* ((frame (clim:make-application-frame 'gsharp::gsharp-minimal)) | |
126 (clim:*application-frame* frame) | |
127 (esa:*esa-instance* frame)) | |
128 (clim:adopt-frame (clim:find-frame-manager :server-path '(:clx)) frame) | |
129 (clim:execute-frame-command frame '(gsharp::com-new-buffer)) | |
130 ;; Now generate the buffer | |
131 (make-objects-for-gsharp-buffer composition (car (esa:buffers frame))) | |
132 ;; (fill-gsharp-buffer-with-constituent (car (esa:buffers frame)) composition) | |
133 ;; make views, cursors, input states, etc. | |
134 (let ((view (make-instance 'gsharp::orchestra-view | |
135 :buffer (car (esa:buffers frame)) | |
136 :cursor (gsharp::make-initial-cursor | |
137 (car (esa:buffers frame)))))) | |
138 (push view (gsharp::views gsharp::*application-frame*)) | |
139 (setf (gsharp::view (car (gsharp::windows gsharp::*application-frame*))) view | |
140 (gsharp::input-state gsharp::*application-frame*) (gsharp::make-input-state))) | |
141 ;; Refresh and process | |
142 (setf (gsharp::modified-p (car (esa:buffers frame))) t) | |
143 (gsharp::recompute-measures (car (esa:buffers frame))) | |
144 (gsharp::update-page-numbers frame) | |
145 #+nil | |
146 (clim:redisplay-frame-panes frame) | |
147 (clim:run-frame-top-level frame))) | |
148 | |
149 (defparameter *composition-event-maps* (make-hash-table :test 'eq)) | |
90 | 150 |
91 ;;;;;;;;;;;;;;;;;;;;;;;; | 151 ;;;;;;;;;;;;;;;;;;;;;;;; |
92 ;; | 152 ;; |
93 ;; Big `walking through data structures' type functions | 153 ;; Big `walking through data structures' type functions |
94 | 154 |
100 gsharp-layer-string, and from this, the connections are | 160 gsharp-layer-string, and from this, the connections are |
101 made. gsharp-staff-string defaults to calling gsharp-layer-string, | 161 made. gsharp-staff-string defaults to calling gsharp-layer-string, |
102 so in most cases there will be a single staff for each layer. Events | 162 so in most cases there will be a single staff for each layer. Events |
103 are added, and then staves are sorted using staff<. A proper layout | 163 are added, and then staves are sorted using staff<. A proper layout |
104 object would be another way of doing this." | 164 object would be another way of doing this." |
105 (let ((layer-names (make-hash-table :test #'equal)) | 165 (multiple-value-bind (layer-events layer-staves) |
106 (layer-events (make-hash-table)) | 166 (%gather-objects-for-gsharp-output composition buffer) |
107 (layer-staves (make-hash-table)) | 167 ;; Add events/notes/clusters |
108 (staff-names (make-hash-table :test #'equal)) | |
109 (staff-name)(staff)(layer-name)(layer) | |
110 (segment)) | |
111 (sequence::dosequence (event composition) | |
112 ;; can't do percussion parts yet: | |
113 (when (pitchedp event) | |
114 (setf layer-name (gsharp-layer-string event) | |
115 layer (gethash layer-name layer-names) | |
116 staff-name (gsharp-staff-string event) | |
117 staff (gethash staff-name staff-names)) | |
118 (if staff | |
119 ;; this looks a little cryptic, but we're keeping note of | |
120 ;; whether the mean pitch is above C for clef guessing. | |
121 (setf (third staff) (+ (third staff) 1) | |
122 (second staff) (+ (second staff) (min (floor (midi-pitch-number event) 60) 1))) | |
123 (setf staff (list (gsharp::make-fiveline-staff :name staff-name) | |
124 (min (floor (midi-pitch-number event) 60) | |
125 1) | |
126 1) | |
127 (gsharp::buffer (car staff)) buffer | |
128 (gethash staff-name staff-names) staff)) | |
129 (if layer | |
130 (progn | |
131 (unless (find (first staff) (gethash layer layer-staves)) | |
132 (push (first staff) (gethash layer layer-staves))) | |
133 (push event (gethash layer layer-events))) | |
134 (if segment | |
135 (setf layer (gsharp::make-layer (list (first staff)) | |
136 :body (gsharp::make-slice :bars nil) | |
137 :name layer-name | |
138 :segment segment) | |
139 (gsharp::layers segment) (cons layer (gsharp::layers segment)) | |
140 (gethash layer-name layer-names) layer | |
141 (gethash layer layer-staves) (list staff) | |
142 (gethash layer layer-events) (list event)) | |
143 (setf layer (gsharp::make-layer (list (first staff)) | |
144 :body (gsharp::make-slice :bars nil) | |
145 :name layer-name) | |
146 segment (make-instance 'gsharp::segment | |
147 :buffer buffer | |
148 :layers (list layer)) | |
149 (gsharp-buffer:segment layer) segment | |
150 (gethash layer-name layer-names) layer | |
151 (gethash layer layer-staves) (list (first staff)) | |
152 (gethash layer layer-events) (list event)))))) | |
153 (maphash #'(lambda (key val) | |
154 (declare (ignore key)) | |
155 (unless (>= (second val) (/ (third val) 2)) | |
156 (setf *foo* (first val)) | |
157 (setf (gsharp::clef (first val)) (gsharp::make-clef :bass)))) | |
158 staff-names) | |
159 (maphash #'(lambda (key events) | 168 (maphash #'(lambda (key events) |
160 (add-music-to-layer key | 169 (add-music-to-layer key |
161 (reverse events) | 170 (reverse events) |
162 (gethash key layer-staves) | 171 (gethash key layer-staves) |
163 composition | 172 composition |
164 (handler-bind ((insufficient-information | 173 (handler-bind ((insufficient-information |
165 #'(lambda (c) | 174 #'(lambda (c) |
166 (declare (ignore c)) | 175 (declare (ignore c)) |
167 (invoke-restart 'guess)))) | 176 (invoke-restart 'guess)))) |
168 (get-applicable-key-signatures composition composition)))) | 177 (get-applicable-key-signatures composition composition)))) |
169 layer-events) | 178 layer-events) |
170 (setf (gsharp::segments buffer) (list segment) | 179 buffer)) |
171 (gsharp::staves buffer) nil) | 180 |
172 (let ((staves)) | 181 (defun %gather-objects-for-gsharp-output (composition buffer) |
173 (maphash #'(lambda (key val) | 182 (let ((layer-names (make-hash-table :test #'equal)) |
174 (declare (ignore key)) | 183 (layer-events (make-hash-table)) |
175 (push (car val) staves)) | 184 (layer-staves (make-hash-table)) |
185 (staff-names (make-hash-table :test #'equal)) | |
186 (staff-name) (staff) (layer-name) (layer) (staves) | |
187 (segment)) | |
188 (sequence::dosequence (event composition) | |
189 ;; can't do percussion parts yet: | |
190 (when (pitchedp event) | |
191 (setf layer-name (gsharp-layer-string event) | |
192 layer (gethash layer-name layer-names) | |
193 staff-name (gsharp-staff-string event) | |
194 staff (gethash staff-name staff-names)) | |
195 (unless staff | |
196 (setf staff (list (%new-gsharp-staff-for-amuse staff-name buffer) | |
197 0 0) | |
198 (gethash staff-name staff-names) staff)) | |
199 ;; Keeping note of whether the mean pitch is above C for clef | |
200 ;; guessing. | |
201 (setf (third staff) (+ (third staff) 1) | |
202 (second staff) (+ (second staff) | |
203 (min (floor (midi-pitch-number event) 60) 1))) | |
204 ;; Check if layer has happened before, if not make it | |
205 (unless layer | |
206 (setf layer (%create-and-record-layer layer-name (first staff) | |
207 segment buffer layer-names | |
208 layer-staves layer-events) | |
209 segment (gsharp::segment layer))) | |
210 ;; Associate new event with layer | |
211 (setf layer-events | |
212 (%add-event-to-layer-hash event (first staff) | |
213 layer layer-events layer-staves)))) | |
214 ;; Guess clefs for staves: bass if most pitches are below middle | |
215 ;; C, otherwise treble. (yes, I know this is stupid) | |
216 (maphash #'(lambda (key val) | |
217 (declare (ignore key)) | |
218 (unless (>= (second val) (/ (third val) 2)) | |
219 (setf (gsharp::clef (first val)) (gsharp::make-clef :bass)))) | |
220 staff-names) | |
221 ;; gather and sort staves | |
222 (maphash #'(lambda (key val) | |
223 (declare (ignore key)) | |
224 (push (car val) staves)) | |
176 staff-names) | 225 staff-names) |
177 (setf staves (sort staves #'stave<)) | 226 (setf staves (sort staves #'stave<) |
178 (setf (gsharp::staves buffer) staves) | 227 (gsharp::staves buffer) staves) |
179 buffer))) | 228 (values layer-events layer-staves))) |
229 | |
230 (defun %new-gsharp-staff-for-amuse (staff-name buffer) | |
231 (let ((staff (gsharp::make-fiveline-staff :name staff-name))) | |
232 (setf (gsharp::buffer staff) buffer) | |
233 staff)) | |
234 | |
235 (defun %add-event-to-layer-hash (event staff layer layer-events layer-staves) | |
236 ;; (unless (find staff (gethash layer layer-staves)) | |
237 (unless (member staff (gethash layer layer-staves)) | |
238 (push staff (gethash layer layer-staves))) | |
239 (push event (gethash layer layer-events)) | |
240 layer-events) | |
241 | |
242 (defun %create-and-record-layer (name staff segment buffer | |
243 layer-names layer-staves layer-events) | |
244 ;; create fresh layer called name and add to all necessary objects | |
245 (let ((layer (gsharp::make-layer (list staff) | |
246 :body (gsharp::make-slice :bars nil) | |
247 :name name | |
248 :segment segment))) | |
249 (if segment | |
250 (setf (gsharp::layers segment) | |
251 (cons layer (gsharp::layers segment))) | |
252 (setf segment (make-instance 'gsharp::segment | |
253 :buffer buffer | |
254 :layers (list layer)) | |
255 (gsharp::segment layer) segment | |
256 (gsharp::segments buffer) (list segment))) | |
257 (setf (gethash name layer-names) layer | |
258 (gethash layer layer-staves) nil | |
259 (gethash layer layer-events) nil) | |
260 layer)) | |
261 | |
180 (defgeneric stave< (staff1 staff2) | 262 (defgeneric stave< (staff1 staff2) |
181 (:method (s1 s2) | 263 (:method (s1 s2) |
182 (let* ((clefs '(:treble :bass)) | 264 (let* ((clefs '(:treble :bass)) |
183 (c1 (gsharp::clef s1)) | 265 (c1 (gsharp::clef s1)) |
184 (c2 (gsharp::clef s2)) | 266 (c2 (gsharp::clef s2)) |
227 (>= beat-time (second bars))) | 309 (>= beat-time (second bars))) |
228 (push (reverse current) starts) | 310 (push (reverse current) starts) |
229 (setf current nil | 311 (setf current nil |
230 bars (cdr bars))) | 312 bars (cdr bars))) |
231 (push beat-time current)))))) | 313 (push beat-time current)))))) |
232 (defun add-music-to-layer (layer events staves composition key-sigs) | 314 |
233 "Creating all the musical objects for the gsharp staves in the | 315 (defgeneric add-music-to-layer (layer events staves composition key-sigs) |
234 provided layer" | 316 (:documentation "Creating all the musical objects for the gsharp staves in the |
317 provided layer")) | |
318 ;; change this into some sort of quantize-please mixin? or switch? or something | |
319 (defmethod add-music-to-layer (layer events staves (composition amuse-midi::unquantized-composition) key-sigs) | |
235 (let* ((bar-moments (bar-starts-2 composition)) | 320 (let* ((bar-moments (bar-starts-2 composition)) |
236 (beat-moments (or (beat-starts-2 bar-moments composition) | 321 (beat-moments (or (beat-starts-2 bar-moments composition) |
237 bar-moments)) | 322 (mapcar #'list bar-moments))) |
238 (body (gsharp::body layer)) | 323 (body (gsharp::body layer)) |
239 (bar-no 0) | 324 (bar-no 0) |
240 (ons) (position) (clusters) (bar)) | 325 (ons) (position) (clusters) (bar)) |
241 ;; this is a cheat to guess timing rounding (quantisation) based | 326 ;; this is a cheat to guess timing rounding (quantisation) based |
242 ;; on onset times - only affects midi-like data where onsets are | 327 ;; on onset times - only affects midi-like data where onsets are |
243 ;; already rounded, but durations are not (as in TC's fantasia | 328 ;; already rounded, but durations are not (as in TC's fantasia |
244 ;; midi files....) | 329 ;; midi files....) |
245 (setf *rounding-factor* (max (guess-rounding-factor events) | 330 (setf *rounding-factor* (max (guess-rounding-factor-smart events) |
246 1/8)) | 331 1/8)) |
247 ;; First create a list of change-points for when events are | 332 ;; First create a list of change-points for when events are |
248 ;; sounding, of the format (time event event event) (time event)) | 333 ;; sounding, of the format (time event event event) (time event)) |
249 (dolist (event events) | 334 (dolist (event events) |
250 (setf ons (add-on-off-pair event ons))) | 335 (setf ons (add-on-off-pair event ons))) |
257 ;; Finally, one problem here is that, in midi, there is often a | 342 ;; Finally, one problem here is that, in midi, there is often a |
258 ;; gap or overlap between consecutive notes or chords. Since | 343 ;; gap or overlap between consecutive notes or chords. Since |
259 ;; rounding happens, but there is no check for bar length here or | 344 ;; rounding happens, but there is no check for bar length here or |
260 ;; within g-sharp, this should verify that everything makes | 345 ;; within g-sharp, this should verify that everything makes |
261 ;; sense. At the moment, it just removes short rests... | 346 ;; sense. At the moment, it just removes short rests... |
262 (setf ons (check-ons ons bar-moments)) | 347 (setf ons (check-ons-2 ons bar-moments)) |
263 ;; Now create the bars and the gsharp clusters | 348 ;; Now create the bars and the gsharp clusters |
264 (when key-sigs | 349 (when key-sigs |
265 (dolist (staff staves) | 350 (dolist (staff staves) |
266 (setf (gsharp::keysig staff) | 351 (setf (gsharp::keysig staff) |
267 (make-gsharp-key-signature (car key-sigs) staff)))) | 352 (make-gsharp-key-signature (car key-sigs) staff)))) |
268 (do ((old-ons nil ons) | 353 (do ((old-ons nil ons) |
269 (ons ons (cdr ons))) | 354 (ons ons (cdr ons))) |
270 ((null (cdr ons))) | 355 ((null (car ons))) |
271 (when (member (caar ons) bar-moments) | 356 (when (member (caar ons) bar-moments) |
272 ;; We're at the beginning of a bar. | 357 ;; We're at the beginning of a bar. |
273 (when bar (check-beams bar)) | 358 (when bar (check-beams bar)) |
274 (setf bar (gsharp::make-melody-bar)) | 359 (setf bar (gsharp::make-melody-bar)) |
275 (gsharp::add-bar bar body bar-no) | 360 (gsharp::add-bar bar body bar-no) |
296 ;; time signature (for example, a note of a tactus beat + a | 381 ;; time signature (for example, a note of a tactus beat + a |
297 ;; quaver in 6/8 will be rendered as a minim this way) - that's | 382 ;; quaver in 6/8 will be rendered as a minim this way) - that's |
298 ;; why I've taken as much of the metrical logic out and put it | 383 ;; why I've taken as much of the metrical logic out and put it |
299 ;; above if there are other straightforward rules, they should, | 384 ;; above if there are other straightforward rules, they should, |
300 ;; I think go there. | 385 ;; I think go there. |
301 (if (cdar ons) | 386 ;; NB now incorporating JF fix (not via version control) |
302 (setf clusters (make-gsharp-clusters-with-duration (- (car (second ons)) | 387 (if (second ons) |
303 (car (car ons))))) | 388 (if (cdar ons) |
304 (setf clusters (make-gsharp-rests-with-duration (- (car (second ons)) | 389 (setf clusters (make-gsharp-clusters-with-duration (- (car (second ons)) |
305 (car (car ons))) | 390 (car (car ons))))) |
306 layer))) | 391 (setf clusters (make-gsharp-rests-with-duration (- (car (second ons)) |
392 (car (car ons))) | |
393 layer))) | |
394 (if (cdar ons) | |
395 (setf clusters (make-gsharp-clusters-with-duration (duration (cadar ons)))) | |
396 (setf clusters (make-gsharp-rests-with-duration (- (timepoint | |
397 (cut-off composition)) | |
398 (caar ons)) | |
399 layer)))) | |
307 (let ((now (caar ons)) (first-p t) (pitches)) | 400 (let ((now (caar ons)) (first-p t) (pitches)) |
308 (do ((clusters clusters (cdr clusters))) | 401 (do ((clusters clusters (cdr clusters))) |
309 ((null clusters)) | 402 ((null clusters)) |
310 (when (member now (car beat-moments)) | 403 (when (member now (car beat-moments)) |
311 (setf (gsharp::lbeams (car clusters)) 0)) | 404 (setf (gsharp::lbeams (car clusters)) 0)) |
330 :staff (staff-for-note (car pitch) staves) | 423 :staff (staff-for-note (car pitch) staves) |
331 :tie-right (if (or (cdr clusters) | 424 :tie-right (if (or (cdr clusters) |
332 (member (car pitch) (second ons))) | 425 (member (car pitch) (second ons))) |
333 t | 426 t |
334 nil) | 427 nil) |
335 :tie-left (if first-p | 428 :tie-left (if (or first-p |
336 (member (car pitch) (first old-ons)) | 429 (member (car pitch) (first old-ons))) |
337 t))))) | 430 t |
431 nil))))) | |
338 (incf now (* (gsharp::duration (car clusters)) 4)) | 432 (incf now (* (gsharp::duration (car clusters)) 4)) |
339 (setf first-p nil) | 433 (setf first-p nil) |
340 (incf position))) | 434 (incf position))) |
341 (when (and (cdr bar-moments) | 435 (when (and (cdr bar-moments) |
342 (= (car (second ons)) | 436 (= (car (second ons)) |
343 (second bar-moments))) | 437 (second bar-moments))) |
344 (setf bar-moments (cdr bar-moments) | 438 (setf bar-moments (cdr bar-moments) |
345 beat-moments (cdr beat-moments)))))) | 439 beat-moments (cdr beat-moments)))))) |
440 | |
441 (defclass amuse-gsharp-note (gsharp::note) | |
442 ((composition :initarg :composition | |
443 :accessor composition) | |
444 (event :initarg :event | |
445 :accessor event) | |
446 (groups :initarg :groups | |
447 :accessor groups))) | |
448 | |
449 (defun make-amuse-gsharp-note (event staves composition | |
450 &key tie-right tie-left groups) | |
451 (destructuring-bind (pitch accidental) | |
452 (pitch-for-gsharp event composition) | |
453 (let ((note (make-instance 'amuse-gsharp-note | |
454 :pitch pitch | |
455 :accidentals accidental | |
456 :staff (staff-for-note event staves) | |
457 :tie-right tie-right | |
458 :tie-left tie-left | |
459 :composition composition | |
460 :event event | |
461 :groups groups)) | |
462 (event-map (get-event-map composition))) | |
463 (setf (gethash event event-map) note) | |
464 note))) | |
465 | |
466 (defun get-event-map (composition) | |
467 (unless (gethash composition *composition-event-maps*) | |
468 (setf (gethash composition *composition-event-maps*) | |
469 (make-hash-table :test 'eq))) | |
470 (gethash composition *composition-event-maps*)) | |
471 | |
472 (defun get-gsharp-note (event composition) | |
473 (gethash event (get-event-map composition))) | |
474 | |
475 (defmethod add-music-to-layer (layer events staves composition key-sigs) | |
476 ;; no beaming yet | |
477 (let* ((scale (duration (crotchet composition))) | |
478 (times (loop for event in events | |
479 collect (timepoint event) | |
480 collect (timepoint (cut-off event)))) | |
481 (event-array) | |
482 (bar-no 0) (slice (gsharp::body layer)) (bar) | |
483 (position 0) (bar-starts) (clusters)) | |
484 (do* ((bar-period (current-bar (make-moment 0) composition) | |
485 (current-bar (cut-off bar-period) composition)) | |
486 (bar-start (when bar-period (timepoint bar-period)) | |
487 (when bar-period (timepoint bar-period)))) | |
488 ((time>= (cut-off bar-period) (cut-off composition)) | |
489 (setf bar-starts (reverse bar-starts))) | |
490 (push bar-start times) | |
491 (push bar-start bar-starts)) | |
492 (setf times (sort (remove-duplicates times) #'<) | |
493 event-array (make-array (list-length times) :initial-element nil)) | |
494 ;; Create an array of which rhythmic clusters each event belongs | |
495 ;; to (notational clusters come later) | |
496 (loop for time in times | |
497 for i from 0 | |
498 do (loop for event in events | |
499 while (<= (timepoint event) time) | |
500 when (> (timepoint (cut-off event)) time) | |
501 do (push event (aref event-array i)))) | |
502 (when (and key-sigs (= (timepoint (first key-sigs)) 0)) | |
503 (mapcar #'(lambda (x) (set-staff-key-signature (first key-sigs) x)) | |
504 staves) | |
505 (setf key-sigs (cdr key-sigs))) | |
506 (do ((times times (cdr times)) | |
507 (i 0 (1+ i))) | |
508 ((not times)) | |
509 (when (and bar-starts (<= (first bar-starts) | |
510 (first times))) | |
511 (setf bar (gsharp::make-melody-bar)) | |
512 (gsharp::add-bar bar slice bar-no) | |
513 (incf bar-no) | |
514 (setf position 0) | |
515 (setf bar-starts (cdr bar-starts))) | |
516 (if (aref event-array i) | |
517 (setf clusters (make-gsharp-clusters-with-exact-duration | |
518 (/ (- (or (second times) | |
519 (timepoint (cut-off composition))) | |
520 (first times)) | |
521 scale))) | |
522 (setf clusters (make-gsharp-rests-with-exact-duration | |
523 (/ (- (or (second times) | |
524 (timepoint (cut-off composition))) | |
525 (first times)) | |
526 scale) | |
527 layer))) | |
528 ;; FIXME: This has possible problem cases for key-sig changes | |
529 ;; mid-note and for multi-staff signatures. Fix this when the | |
530 ;; AMUSE representation is a bit richer. | |
531 (when (and key-sigs (<= (timepoint (first key-sigs)) | |
532 (first times))) | |
533 (gsharp::add-element (make-gsharp-key-signature (car key-sigs) | |
534 (gsharp::staff bar)) | |
535 bar position) | |
536 (incf position) | |
537 (setf key-sigs (cdr key-sigs))) | |
538 (do* ((clusters clusters (cdr clusters)) | |
539 (cluster (car clusters) (car clusters)) | |
540 (firstp t nil)) | |
541 ((not clusters)) | |
542 (gsharp::add-element cluster bar position) | |
543 (incf position) | |
544 ;; There will be trouble with same pitch in same layer, | |
545 ;; but that's a gsharp bug, not an amuse one | |
546 (dolist (event (aref event-array i)) | |
547 (gsharp::add-note | |
548 cluster | |
549 (make-amuse-gsharp-note event staves composition | |
550 :tie-right (or (cdr clusters) | |
551 (and (< (1+ i) (length event-array)) | |
552 (member event (aref event-array (1+ i))))) | |
553 :tie-left (or (not firstp) | |
554 (and (> i 0) | |
555 (member event (aref event-array (1- i)))))))))))) | |
346 | 556 |
347 (defun staff-for-note (event staves) | 557 (defun staff-for-note (event staves) |
348 (find-if #'(lambda (x) (string= (gsharp::name x) (gsharp-staff-string event))) | 558 (find-if #'(lambda (x) (string= (gsharp::name x) (gsharp-staff-string event))) |
349 staves)) | 559 staves)) |
350 | 560 |
368 (setf (gsharp::rbeams mid) 0)) | 578 (setf (gsharp::rbeams mid) 0)) |
369 ((< (gsharp::rbeams left) | 579 ((< (gsharp::rbeams left) |
370 (gsharp::lbeams right)) | 580 (gsharp::lbeams right)) |
371 (setf (gsharp::lbeams mid) (gsharp::rbeams left))) | 581 (setf (gsharp::lbeams mid) (gsharp::rbeams left))) |
372 (t (setf (gsharp::rbeams mid) (gsharp::lbeams right))))))) | 582 (t (setf (gsharp::rbeams mid) (gsharp::lbeams right))))))) |
583 | |
584 (defun set-staff-key-signature (key-sig staff) | |
585 (setf (gsharp::keysig staff) | |
586 (make-gsharp-key-signature key-sig staff))) | |
373 | 587 |
374 (defgeneric make-gsharp-key-signature (key-signature object)) | 588 (defgeneric make-gsharp-key-signature (key-signature object)) |
375 (defmethod make-gsharp-key-signature ((key-signature standard-key-signature) (layer gsharp-buffer::layer)) | 589 (defmethod make-gsharp-key-signature ((key-signature standard-key-signature) (layer gsharp-buffer::layer)) |
376 (let ((alterations (make-array 7 :initial-element :natural)) | 590 (let ((alterations (make-array 7 :initial-element :natural)) |
377 (order-of-sharps #(3 0 4 1 5 2 6)) | 591 (order-of-sharps #(3 0 4 1 5 2 6)) |
477 (- (slot-value e 'amuse::number) 21)))) into result | 691 (- (slot-value e 'amuse::number) 21)))) into result |
478 finally (return (sort result #'sorter :key #'car))))) | 692 finally (return (sort result #'sorter :key #'car))))) |
479 | 693 |
480 ;; Time | 694 ;; Time |
481 | 695 |
696 (defun make-gsharp-clusters-with-exact-duration (duration) | |
697 ;; at least for now | |
698 (make-gsharp-clusters-with-duration duration)) | |
482 (defun make-gsharp-clusters-with-duration (duration) | 699 (defun make-gsharp-clusters-with-duration (duration) |
483 "Returns a list of cluster(s) whose total duration is equal to | 700 "Returns a list of cluster(s) whose total duration is equal to |
484 duration (which is given in crotchets)" | 701 duration (which is given in crotchets)" |
485 (let ((new-durations (gsharp-durations-from-beats duration))) | 702 (let ((new-durations (gsharp-durations-from-beats duration))) |
486 (loop for new-duration in new-durations | 703 (loop for new-duration in new-durations |
487 collect (gsharp::make-cluster :notehead (gsharp-duration-notehead new-duration) | 704 collect (gsharp::make-cluster :notehead (gsharp-duration-notehead new-duration) |
488 :lbeams (gsharp-duration-beams new-duration) | 705 :lbeams (gsharp-duration-beams new-duration) |
489 :rbeams (gsharp-duration-beams new-duration) | 706 :rbeams (gsharp-duration-beams new-duration) |
490 :dots (gsharp-duration-dots new-duration))))) | 707 :dots (gsharp-duration-dots new-duration))))) |
491 | 708 |
709 (defun make-gsharp-rests-with-exact-duration (duration layer) | |
710 ;; at least for now | |
711 (make-gsharp-rests-with-duration duration layer)) | |
492 (defun make-gsharp-rests-with-duration (duration layer) | 712 (defun make-gsharp-rests-with-duration (duration layer) |
493 "Returns a list of rest(s) whose total duration is equal to | 713 "Returns a list of rest(s) whose total duration is equal to |
494 duration (which is given in crotchets)" | 714 duration (which is given in crotchets)" |
495 (let ((new-durations (gsharp-durations-from-beats duration))) | 715 (let ((new-durations (gsharp-durations-from-beats duration))) |
496 (loop for new-duration in new-durations | 716 (loop for new-duration in new-durations |
497 collect(gsharp::make-rest (car (gsharp::staves layer)) | 717 collect (gsharp::make-rest (car (gsharp::staves layer)) |
498 :notehead (gsharp-duration-notehead new-duration) | 718 :notehead (gsharp-duration-notehead new-duration) |
499 :lbeams (gsharp-duration-beams new-duration) | 719 :lbeams (gsharp-duration-beams new-duration) |
500 :rbeams (gsharp-duration-beams new-duration) | 720 :rbeams (gsharp-duration-beams new-duration) |
501 :dots (gsharp-duration-dots new-duration))))) | 721 :dots (gsharp-duration-dots new-duration))))) |
502 | 722 |
668 | 888 |
669 (defun add-on-off-pair (event data) | 889 (defun add-on-off-pair (event data) |
670 "For walking through an ordered event sequence and building up a | 890 "For walking through an ordered event sequence and building up a |
671 list of changes to sounding pitches, this function takes an event and | 891 list of changes to sounding pitches, this function takes an event and |
672 adds the time for which it sounds to the structure." | 892 adds the time for which it sounds to the structure." |
673 (let ((copied-data) | 893 (let* ((copied-data) (rounding (/ *rounding-factor* 2)) |
674 (on (* (round | 894 (on (* (timepoint event) |
895 (duration (crotchet event))) | |
896 #+nil (* (round | |
675 (* (timepoint event) | 897 (* (timepoint event) |
676 (duration (crotchet event))) | 898 (duration (crotchet event))) |
677 *rounding-factor*) *rounding-factor*)) | 899 rounding) rounding)) |
678 (off (* (round | 900 (off (* (round |
679 (* (timepoint (cut-off event)) | 901 (* (timepoint (cut-off event)) |
680 (duration (crotchet event))) | 902 (duration (crotchet event))) |
681 *rounding-factor*) *rounding-factor*))) | 903 rounding) rounding))) |
682 (do ((data data (cdr data))) | 904 (do ((data data (cdr data))) |
683 ((null data) (reverse (cons (list off) | 905 ((null data) (reverse (cons (list off) |
684 (cons (list on event) | 906 (cons (list on event) |
685 copied-data)))) | 907 copied-data)))) |
686 (cond | 908 (cond |
723 notes (cdar ons)) | 945 notes (cdar ons)) |
724 (dolist (note (cdar ons)) | 946 (dolist (note (cdar ons)) |
725 (unless (member note notes) | 947 (unless (member note notes) |
726 (push note notes))))))) | 948 (push note notes))))))) |
727 | 949 |
950 (defun check-ons-2 (ons bar-starts) | |
951 "looks for small rests such as might be created by midi performance | |
952 of tenuto lines" | |
953 (let ((best-time) (found-bar) (new-ons)) | |
954 (do* ((ons ons (cdr ons)) | |
955 (on1 (first ons) (first ons)) | |
956 (on2 (second ons) (second ons)) | |
957 (query nil nil)) | |
958 ((null on2) (reverse new-ons)) | |
959 (unless found-bar | |
960 (cond | |
961 ((member (first on1) bar-starts) | |
962 (setf found-bar t | |
963 best-time (first on1))) | |
964 ((or (not best-time) | |
965 (better-timep (first on1) best-time)) ;; this ought to know about tactus | |
966 (setf best-time (first on1))))) | |
967 (when (>= (- (first on2) (first on1)) | |
968 *rounding-factor*) | |
969 (push (cons best-time (cdr on1)) new-ons) | |
970 (setf best-time nil | |
971 found-bar nil))))) | |
972 | |
973 (defun better-timep (t1 t2) | |
974 (< (or (granularity t1 4) | |
975 (granularity (/ (round t1 1/16) 16) 4)) | |
976 (or (granularity t2 4) | |
977 (granularity (/ (round t2 1/16) 16) 4)))) | |
978 | |
979 (defun granularity (n &optional (max 16)) | |
980 (loop for i from 1 to max | |
981 when (= (rem n (expt 2 (- i))) 0) | |
982 do (return-from granularity i))) | |
983 | |
728 #+nil | 984 #+nil |
729 | 985 |
730 (defun check-ons (ons) | 986 (defun check-ons (ons) |
731 "looks for small rests such as might be created by midi performance | 987 "looks for small rests such as might be created by midi performance |
732 of tenuto lines" | 988 of tenuto lines" |
771 onsets" | 1027 onsets" |
772 (let ((times (map 'list #'(lambda (x) | 1028 (let ((times (map 'list #'(lambda (x) |
773 (denominator (* (timepoint x) | 1029 (denominator (* (timepoint x) |
774 (duration (crotchet x))))) | 1030 (duration (crotchet x))))) |
775 events))) | 1031 events))) |
1032 | |
776 (/ 1 (apply #'lcm times)))) | 1033 (/ 1 (apply #'lcm times)))) |