j@253
|
1 (cl:in-package #:amuse-charm)
|
j@253
|
2
|
j@253
|
3 (defun make-charm-property-list (&rest properties)
|
j@253
|
4 (make-instance 'charm-property-list
|
j@253
|
5 :%data properties))
|
j@253
|
6
|
j@253
|
7 (defun make-charm-constituent-identifier (id)
|
j@253
|
8 (make-instance 'charm-constituent-identifier
|
j@253
|
9 :constituent-id id))
|
j@253
|
10
|
j@253
|
11 (defun make-standard-charm-constituent (particles parent
|
j@253
|
12 extrinsic-properties
|
j@253
|
13 intrinsic-properties &key
|
j@253
|
14 start duration
|
j@253
|
15 constituent-identifier owner
|
j@253
|
16 version creation-timestamp
|
j@253
|
17 deletion-timestamp)
|
j@253
|
18 "Properties should be charm-property-lists. FIXME: enforce this?
|
j@253
|
19 What about time? Should we be using implementation time data-types?
|
j@253
|
20 Particles by definition are identifiers - BUT this seemed to cause
|
j@253
|
21 unnecessary pain, so particales are now either events or
|
j@253
|
22 constituents. This could be made to call a backend specific
|
j@253
|
23 constructor specialised on the parent-identifier."
|
j@253
|
24 (make-instance 'standard-charm-constituent
|
j@253
|
25 :identifier constituent-identifier
|
j@253
|
26 :parent parent
|
j@253
|
27 :time start ; FIXME: naming conventions?
|
j@253
|
28 :interval duration
|
j@253
|
29 :extrinsic-properties extrinsic-properties
|
j@253
|
30 :intrinsic-properties intrinsic-properties
|
j@253
|
31 :%data particles
|
j@253
|
32 :owner owner
|
j@253
|
33 :version version
|
j@253
|
34 :creation-timestamp creation-timestamp
|
j@253
|
35 :deletion-timestamp deletion-timestamp))
|
j@253
|
36
|
j@253
|
37 (defun make-standard-charm-event-constituent (particles parent
|
j@253
|
38 extrinsic-properties
|
j@253
|
39 intrinsic-properties
|
j@253
|
40 &key start duration
|
j@253
|
41 constituent-identifier
|
j@253
|
42 owner version
|
j@253
|
43 creation-timestamp
|
j@253
|
44 deletion-timestamp)
|
j@255
|
45 (let ((constituent-class (cond
|
j@255
|
46 ((every #'amuse-utils:pitchedp particles)
|
j@255
|
47 'standard-charm-pitched-event-constituent)
|
j@255
|
48 ((every #'amuse-utils:unpitchedp particles)
|
j@255
|
49 'standard-charm-unpitched-event-constituent)
|
j@255
|
50 (t 'standard-charm-event-constituent))))
|
j@255
|
51 (make-instance constituent-class
|
j@255
|
52 :identifier constituent-identifier
|
j@255
|
53 :parent parent
|
j@255
|
54 :time start ; FIXME: naming conventions?
|
j@255
|
55 :interval duration
|
j@255
|
56 :extrinsic-properties extrinsic-properties
|
j@255
|
57 :intrinsic-properties intrinsic-properties
|
j@255
|
58 :%data particles
|
j@255
|
59 :owner owner
|
j@255
|
60 :version version
|
j@255
|
61 :creation-timestamp creation-timestamp
|
j@255
|
62 :deletion-timestamp deletion-timestamp)))
|
j@253
|
63
|
j@253
|
64 (defun composition->charm-constituent (composition
|
j@253
|
65 extrinsic-properties
|
j@253
|
66 intrinsic-properties)
|
j@253
|
67 "This is currently the bridge that takes us from AMuSE compositions
|
j@253
|
68 to Charm constituents."
|
j@253
|
69 (make-standard-charm-event-constituent (%list-slot-sequence-data
|
j@253
|
70 composition) composition
|
j@253
|
71 extrinsic-properties
|
j@253
|
72 intrinsic-properties
|
j@253
|
73 :start (timepoint
|
j@253
|
74 composition)
|
j@253
|
75 :duration (duration
|
j@253
|
76 composition)))
|
j@253
|
77
|
j@253
|
78 (defun make-onset-segment-constituent (composition)
|
j@253
|
79 "So this makes a constituent for each set of events with the same
|
j@253
|
80 onset, and adds all of those as particles to a parent constituent. To
|
j@253
|
81 two levels are created, maybe it's better to only return a list of
|
j@253
|
82 onset-constituents, and the user can group them together within
|
j@253
|
83 another constituent if necessary?"
|
j@253
|
84 (let ((grouped-events (group-by-onset composition))
|
j@253
|
85 (parent-constituent
|
j@253
|
86 (make-standard-charm-constituent nil composition
|
j@253
|
87 (make-charm-property-list
|
j@253
|
88 'sequence-class)
|
j@253
|
89 (make-charm-property-list
|
j@253
|
90 'sequence-class)
|
j@253
|
91 :start (timepoint
|
j@253
|
92 composition)
|
j@253
|
93 :duration (duration
|
j@253
|
94 composition))))
|
j@253
|
95 (loop for beat-events in grouped-events
|
j@253
|
96 collect (make-standard-charm-event-constituent
|
j@253
|
97 beat-events
|
j@253
|
98 parent-constituent
|
j@253
|
99 (make-charm-property-list 'segment)
|
j@253
|
100 (make-charm-property-list 'onset-segment))
|
j@253
|
101 into constituents
|
j@253
|
102 finally (progn
|
j@253
|
103 (setf (%list-slot-sequence-data parent-constituent)
|
j@253
|
104 constituents)
|
j@253
|
105 (return parent-constituent)))))
|
j@253
|
106
|
j@253
|
107 (defun group-by-onset (composition)
|
j@253
|
108 (loop for event in (reverse (%list-slot-sequence-data composition))
|
j@253
|
109 with grouped-events
|
j@253
|
110 do (if (and grouped-events
|
j@253
|
111 (time= (onset event) (onset (car (car grouped-events)))))
|
j@253
|
112 (push event (car grouped-events))
|
j@253
|
113 (push (list event) grouped-events))
|
j@253
|
114 finally (return grouped-events)))
|
j@253
|
115
|
j@253
|
116 (defun segment-at-bar (composition)
|
j@253
|
117 "Returns a list of bar-constituents."
|
j@255
|
118 (loop with current-bar = (current-bar (elt composition 0) composition)
|
j@255
|
119 and current-events
|
j@253
|
120 for event in (%list-slot-sequence-data composition)
|
j@253
|
121 if (time= current-bar (current-bar event composition))
|
j@253
|
122 do (push event current-events)
|
j@253
|
123 else
|
j@253
|
124 collect (make-standard-charm-event-constituent
|
j@253
|
125 (reverse current-events)
|
j@253
|
126 composition
|
j@253
|
127 (make-charm-property-list)
|
j@253
|
128 (make-charm-property-list 'segment 'bar))
|
j@253
|
129 into constituents
|
j@253
|
130 and do (setf current-bar (current-bar event composition))
|
j@253
|
131 and do (setf current-events nil)
|
j@253
|
132 finally (return constituents)))
|