comparison utils/meltools.lisp @ 158:49b418a68acb

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