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))))