d@158
|
1 ;;; Tools for simile, melconv and melfeature
|
d@158
|
2
|
d@158
|
3 (cl:in-package #:amuse-utils)
|
d@158
|
4
|
d@158
|
5 ;; Basic tools and variables for mcsv output
|
d@158
|
6
|
d@158
|
7 (defgeneric get-timebase (constituent)
|
d@158
|
8 (:method (c)
|
d@158
|
9 (apply #'lcm
|
d@158
|
10 (nconc (map 'list #'(lambda (x)
|
d@158
|
11 (denominator
|
d@158
|
12 (timepoint x)))
|
d@158
|
13 c)
|
d@158
|
14 (map 'list #'(lambda (x)
|
d@158
|
15 (denominator
|
d@158
|
16 (timepoint (cut-off x))))
|
d@158
|
17 c)))))
|
d@158
|
18
|
d@158
|
19 (defparameter *default-field-list*
|
d@158
|
20 '(:onset :onsetics :takt :beat :ticks :pitch :durs :durtic :dur16))
|
d@158
|
21
|
d@158
|
22 (defparameter *mcsv-field-functions*
|
d@158
|
23 '((:onset mcsv-real-time-onset)
|
d@158
|
24 (:onsetics mcsv-tick-onset)
|
d@158
|
25 (:takt mcsv-bar-number)
|
d@158
|
26 (:beat mcsv-beat-in-bar)
|
d@158
|
27 (:ticks mcsv-ticks-in-beat)
|
d@158
|
28 (:pitch mcsv-pitch)
|
d@158
|
29 (:durs mcsv-seconds-duration)
|
d@158
|
30 (:durtic mcsv-ticks-duration)
|
d@158
|
31 (:dur16 mcsv-quarter-beat-duration)))
|
d@158
|
32
|
d@158
|
33 ;; method or function?
|
d@158
|
34 (defgeneric write-mcsv (filename constituent fieldlist ticks)
|
d@158
|
35 (:method (fn c fl ticks)
|
d@158
|
36 (with-open-file (file fn :direction :output :if-exists :supersede)
|
d@158
|
37 (let ((time-sig (car (get-applicable-time-signatures c c)))
|
d@158
|
38 (timebase (or ticks (get-timebase c)))
|
d@158
|
39 (fieldlist (or fl *default-field-list*)))
|
d@158
|
40 (format file "Signature: ~D/~D, Ticks per Beat: ~D~%"
|
d@158
|
41 (if time-sig
|
d@158
|
42 (time-signature-numerator time-sig)
|
d@158
|
43 4)
|
d@158
|
44 (if time-sig
|
d@158
|
45 (time-signature-denominator time-sig)
|
d@158
|
46 4)
|
d@158
|
47 timebase)
|
d@158
|
48 (dolist (field fieldlist (format file "~%"))
|
d@158
|
49 (format file "~D;" field))
|
d@158
|
50 (write-mcsv-to-stream file c fieldlist timebase)))))
|
d@158
|
51
|
d@158
|
52 (defun write-mcsv-to-stream (stream composition fieldlist ticks)
|
d@158
|
53 (sequence:dosequence (event composition)
|
d@158
|
54 (dolist (field fieldlist (format stream "~%"))
|
d@158
|
55 (format stream "~D;" (get-mcsv-data field event composition ticks)))))
|
d@158
|
56
|
d@158
|
57 (defun get-mcsv-data (field event composition ticks)
|
d@158
|
58 (funcall (second (assoc field *mcsv-field-functions*))
|
d@158
|
59 event composition ticks))
|
d@158
|
60
|
d@158
|
61 ;; mcsv data functions
|
d@158
|
62
|
d@158
|
63 (defun mcsv-real-time-onset (event composition ticks)
|
d@158
|
64 (declare (ignore ticks))
|
d@158
|
65 (fraction-to-comma-string
|
d@158
|
66 (beats-to-seconds (onset event) composition)))
|
d@158
|
67
|
d@158
|
68 (defun mcsv-tick-onset (event composition ticks)
|
d@158
|
69 (declare (ignore composition))
|
d@158
|
70 (round (* ticks (timepoint event))))
|
d@158
|
71
|
d@158
|
72 (defun mcsv-bar-number (event composition ticks)
|
d@158
|
73 (declare (ignore ticks))
|
d@158
|
74 (bar-number event composition))
|
d@158
|
75
|
d@158
|
76 (defun mcsv-beat-in-bar (event composition ticks)
|
d@158
|
77 ;; FIXME: broken if beat!= crotchet
|
d@158
|
78 (declare (ignore ticks))
|
d@158
|
79 (1+ (floor (- (timepoint event)
|
d@158
|
80 (timepoint (bar-onset (bar-number event composition)
|
d@158
|
81 composition))))))
|
d@158
|
82
|
d@158
|
83 (defun mcsv-ticks-in-beat (event composition ticks)
|
d@158
|
84 ;; FIXME: broken if beat!= crotchet
|
d@158
|
85 (declare (ignore composition))
|
d@158
|
86 (round (* ticks
|
d@158
|
87 (rem (timepoint event) 1))))
|
d@158
|
88
|
d@158
|
89 (defun mcsv-pitch (event composition ticks)
|
d@158
|
90 (declare (ignore composition ticks))
|
d@158
|
91 (midi-pitch-number event))
|
d@158
|
92
|
d@158
|
93 (defun mcsv-seconds-duration (event composition ticks)
|
d@158
|
94 (declare (ignore ticks))
|
d@158
|
95 (fraction-to-comma-string (beats-to-seconds event composition)))
|
d@158
|
96
|
d@158
|
97 (defun mcsv-ticks-duration (event composition ticks)
|
d@158
|
98 (declare (ignore composition))
|
d@158
|
99 (round (* ticks (duration event))))
|
d@158
|
100
|
d@158
|
101 (defun mcsv-quarter-beat-duration (event composition ticks)
|
d@158
|
102 (declare (ignore ticks composition))
|
d@158
|
103 (round (* 4 (duration event))))
|
d@158
|
104
|
d@158
|
105 (defun fraction-to-comma-string (number)
|
d@158
|
106 (multiple-value-bind (int rem)
|
d@158
|
107 (floor number)
|
d@158
|
108 (concatenate 'string
|
d@158
|
109 (princ-to-string int)
|
d@158
|
110 ","
|
d@158
|
111 (princ-to-string (floor (* 10000 rem))))))
|