comparison implementations/midi/midifile-import.lisp @ 36:ad321ce17e3e

Moving some functionality from specialised geerdes area. Also added mcsv output darcs-hash:20070511120916-f76cc-d6f1b566eea7115c5de1d3aad285c84b304730b7.gz
author David Lewis <d.lewis@gold.ac.uk>
date Fri, 11 May 2007 13:09:16 +0100
parents 1d757c33e00e
children cf198383852d
comparison
equal deleted inserted replaced
35:1d757c33e00e 36:ad321ce17e3e
27 (or (< (midi:message-time x) 27 (or (< (midi:message-time x)
28 (midi:message-time y)) 28 (midi:message-time y))
29 (and (= (midi:message-time x) 29 (and (= (midi:message-time x)
30 (midi:message-time y)) 30 (midi:message-time y))
31 (typep x 'midi:note-off-message)))))) 31 (typep x 'midi:note-off-message))))))
32 (let ((ons (make-array '(17 128) :initial-element nil)) 32 (let ((ons (make-array '(16 128) :initial-element nil))
33 (offs) 33 (offs)
34 (patches (make-array 17 :initial-element 0))) 34 (patches (make-array 16 :initial-element 0)))
35 (dolist (event track) 35 (dolist (event track)
36 (when (> (midi:message-time event) last-time) 36 (when (> (midi:message-time event) last-time)
37 (setf last-time (midi:message-time event))) 37 (setf last-time (midi:message-time event)))
38 (cond 38 (cond
39 ((or (typep event 'midi:note-off-message) 39 ((or (typep event 'midi:note-off-message)
40 (and (typep event 'midi:note-on-message) 40 (and (typep event 'midi:note-on-message)
41 (= (midi:message-velocity event) 0))) 41 (= (midi:message-velocity event) 0)))
42 (let ((pitch (midi:message-key event)) 42 (let ((pitch (midi:message-key event))
43 (channel (1+ (midi:message-channel event))) 43 (channel (midi:message-channel event))
44 (t-off (midi:message-time event))) 44 (t-off (midi:message-time event)))
45 (if (aref ons channel pitch) 45 (if (aref ons channel pitch)
46 (push (make-event-from-on-off-pair (aref ons channel pitch) 46 (push (make-event-from-on-off-pair (aref ons channel pitch)
47 t-off 47 t-off
48 division 48 division
52 ;; if there's no matching on, wait until the beat 52 ;; if there's no matching on, wait until the beat
53 ;; is done. 53 ;; is done.
54 (push event offs)))) 54 (push event offs))))
55 ((typep event 'midi:note-on-message) 55 ((typep event 'midi:note-on-message)
56 (let ((pitch (midi:message-key event)) 56 (let ((pitch (midi:message-key event))
57 (channel (1+ (midi:message-channel event))) 57 (channel (midi:message-channel event))
58 (t-off (midi:message-time event))) 58 (t-off (midi:message-time event)))
59 (when (aref ons channel pitch) 59 (when (aref ons channel pitch)
60 ;; there's a note already sounding. End it. 60 ;; there's a note already sounding. End it.
61 (push (make-event-from-on-off-pair (aref ons channel pitch) 61 (push (make-event-from-on-off-pair (aref ons channel pitch)
62 t-off 62 t-off
75 (timepoint (car time-sigs))))) 75 (timepoint (car time-sigs)))))
76 (push (make-instance 'basic-time-signature 76 (push (make-instance 'basic-time-signature
77 :time (/ (midi:message-time event) 77 :time (/ (midi:message-time event)
78 division) 78 division)
79 :numerator (midi:message-numerator event) 79 :numerator (midi:message-numerator event)
80 :denominator (midi:message-denominator event)) 80 :denominator (expt 2 (midi:message-denominator event)))
81 time-sigs)) 81 time-sigs))
82 ((typep event 'midi:tempo-message) 82 ((typep event 'midi:tempo-message)
83 (when tempi 83 (when tempi
84 (setf (duration (car tempi)) 84 (setf (duration (car tempi))
85 (- (/ (midi:message-time event) 85 (- (/ (midi:message-time event)
89 :time (/ (midi:message-time event) 89 :time (/ (midi:message-time event)
90 division) 90 division)
91 :bpm (microsecond-per-crotchet-to-bpm (midi:message-tempo event))) 91 :bpm (microsecond-per-crotchet-to-bpm (midi:message-tempo event)))
92 tempi)) 92 tempi))
93 ((typep event 'midi:program-change-message) 93 ((typep event 'midi:program-change-message)
94 (setf (aref patches (1+ (midi:message-channel event))) 94 (setf (aref patches (midi:message-channel event))
95 (midi:message-program event))) 95 (midi:message-program event)))
96 (t (incf misses)))))) 96 (t (incf misses))))))
97 (when tempi 97 (when tempi
98 (setf (duration (car tempi)) (- (/ last-time division) (timepoint (car tempi))))) 98 (setf (duration (car tempi)) (- (/ last-time division) (timepoint (car tempi)))))
99 (when time-sigs 99 (when time-sigs
100 (setf (duration (car time-sigs)) (- (/ last-time division) (timepoint (car time-sigs))))) 100 (setf (duration (car time-sigs)) (- (/ last-time division) (timepoint (car time-sigs)))))
101 ;; make a midi object from notes, etc. 101 ;; make a midi object from notes, etc.
102 (let ((composition (make-instance 'midi-composition 102 (let ((composition (make-instance 'midi-composition
103 :time 0 103 :time 0
104 :interval (/ last-time division) 104 :interval (/ last-time division)
105 :time-signatures (sort time-sigs #'time<) 105 :time-signatures (if time-sigs
106 (sort time-sigs #'time<)
107 (list (make-instance 'basic-time-signature
108 :time 0
109 :interval (/ last-time division)
110 :numerator 4
111 :denominator 4)))
106 :tempi (sort tempi #'time<)))) 112 :tempi (sort tempi #'time<))))
107 (sequence:adjust-sequence composition 113 (sequence:adjust-sequence composition
108 (length notes) 114 (length notes)
109 :initial-contents (sort notes #'time<))))) 115 :initial-contents (sort notes #'time<)))))
110 116
111 (defparameter *short* nil)
112
113 (defun make-event-from-on-off-pair (note-on cut-off divisions track patch) 117 (defun make-event-from-on-off-pair (note-on cut-off divisions track patch)
114 (when (< (/ (- cut-off (midi:message-time note-on)) divisions) 1/8)
115 (push (cons note-on cut-off) *short*))
116 (cond 118 (cond
117 ((or (= (midi:message-channel note-on) 9) 119 ((or (= (midi:message-channel note-on) 9)
118 (> patch 111)) 120 (> patch 111))
119 ;; percussive 121 ;; percussive
120 (make-instance 'midi-percussive-event 122 (make-instance 'midi-percussive-event