[CM] append seq one after the other in cm

Rick Taube taube@uiuc.edu
Sun, 9 Apr 2006 10:50:14 -0500


> i want to output each seq one after the other in
> midifile or whatever.
>
> thanks stf

ok, say you have a few seqs contaings time sorted objects but you dont 
know how long or many their are. the most flexible way to "time append" 
these is to simply shift each seq by the amount of time the previos seq 
claims including an optional "pad" value that you can add to the actual 
end time of each seq to shift it forward or backward relative to the 
previos seq's end. first you need a little function that returns the 
"time length" of a seq. this is easy since the last object in the seq 
has the last time value:

(defun seq-time-length (seq &optional (pad 0))
   (let ((last-event (first (last (subobjects seq)))))
     (if last-event
	(+ (object-time last-event) pad)
	pad)))

given this function you can write another little function that takes a 
sereies of sequences and optional pad values and increments the start 
time of each seq by the amount claimed by the previos seq + any pad 
between them:

(defun seq-time-append (&rest seqs-and-pads)
   (let ((time 0))
     (loop for s in seqs-and-pads
        if (numberp s) do (incf time s)
        else do (progn (sv s :time time)
                       (incf time (seq-time-length s)))
        and collect s)))

Here is a test

;;;--------------------------

(defun ranmidis (n r)
   (loop with x = 0 repeat n
         collect (new midi :time x :keynum (between 60 90))
         do (incf x r)))

(defparameter seq1 (new seq :subobjects (ranmidis 4 .25)))
(list-objects seq1)
(seq-time-length seq1)

(defparameter seq2 (new seq :subobjects (ranmidis 4 .25)))
(list-objects seq2)
(seq-time-length seq2)

(defparameter seq3 (new seq :subobjects (ranmidis 4 .25)))
(list-objects seq2)
(seq-time-length seq3)

(cd )

(events (seq-time-append seq1 seq2 1 seq3) "test.mid")

(events (seq-time-append seq1 .25 seq2 -.5 seq3) "test.mid")