[CM] Rearranging a sequence

Landspeedrecord landspeedrecord@gmail.com
Thu, 19 Apr 2007 18:59:07 -0400


Rick and Michael, thanks for helping me out with your suggestions!  I
wound up taking bits of code from each of your approaches to get
something that worked for me.  It is primitive but it is a start for
me... I will come up with more complicated versions and post them here
if anyone is interested.

Here is what I wound up with... let me know if you have any comments
or suggestions!  I would love any feedback you may have!

;;This function shuffles the times of MIDI notes in a MIDI file with a single
;;function called MIDIShuffler.  I wanted to create variations on Rex
file rhythms
;;to use in Reason, but it could be used anytime you wanted to jumble the notes
;;of a MIDI file up and spit out a new file.

;;This function does 4 things:
;;  1) grabs MIDI info from a file
;;  2) shuffle/rearranges the time slot values of the MIDI events
;;  3) sorts the MIDI events in the sequence
;;  4) exports the sequence to a new MIDI file.

;;An example call to this function might look like this:
;;  (MIDIShuffler "reich8.mid" "testeroony.mid")

(define (MIDIShuffler input-file output-file)
  (let* ((mymidiseq (import-events input-file :meta-exclude true))
         (extracted-time-values (fold-objects #'cons mymidiseq '() :slot 'time))
         (reordered-time-values (shuffle extracted-time-values)))
    (loop for m in (subobjects mymidiseq)
       for k in reordered-time-values
       do (sv m :time k))
    (setf (container-subobjects mymidiseq)
          (sort (subobjects mymidiseq) #'< :key #'(lambda (m) (sv m :time))))
    (events mymidiseq output-file)))

On 4/10/07, Rick Taube <taube@uiuc.edu> wrote:
> dont think you are crazy or stupid, just that doin destructive
> operations isnt a good idea unless you really understand what you are
> doing!
>
> that said, you can use (shuffle ) orr whatever on subobjects to
> scramble them, but if you want to put them back in the seq then you
> will need to sort them first:
>
>         (defparameter mess (shuffle (subobjects myseq)))
>         ...
>         (new seq :subobjects (sort #'< mess :key #'object-time))
>
> alternately  you can simply pass your unsorted list i to events
> because events will schedule, or sort, the objects you pass it:
>
>         (events mess ...)
>
>
> On Apr 10, 2007, at 7:22 PM, Landspeedrecord wrote:
>
> > So you don't think I am crazy/stupid I suppose I should elaborate
> > more.
> >
> > Let's say a Seq has 10 midi notes in it.  Each note is merely an
> > instance of the class "midi".  Each note has slots for time, keynum,
> > duration, amp.  My view of the seq is a like a jar of marbles.  When
> > the seq is called by some function (list-objects or whatever), that
> > function then orders the marbles based on it's time slot.  Or
> > alternately, the ordering happens whenever something happens to any
> > time slot value in a seq, like when a new midi note is inserted at the
> > beginning of the seq.  Then all the marbles are rearranged and the seq
> > is resaved to be called upon later.
> >
> > The point being that the ordering has to happen at some time based on
> > the time slot value and if so, then one should be able to rearrange
> > the time values.
> >
> > Sorry for all the verbage, I just don't want anyone thinking that I am
> > trying to make time reorder.  That is impossible.  I am trying to make
> > the note's time values reorder which is a different thing.
> >
> > Please let me know if I have this all wrong conceptually.
> >
> > Thanks!
> >
> >
> >
> >
> > On 4/10/07, Landspeedrecord <landspeedrecord@gmail.com> wrote:
> >> Thanks Rick!  Using fold-objects in conjunction with cons would have
> >> taken me weeks to figure out so I appreciate your help.
> >>
> >> However, what I want to do is exactly what you are saying I
> >> shouldn't.
> >>  The only thing I want to shuflle/reorder is the midi time.  All the
> >> other midi information (keynum, duration, amp, chan) is supposed to
> >> stay together so that the notes remain the same but just come out
> >> in a
> >> different temporal order.  Why do I want to do this?  Because I am
> >> trying to manipulate midi files that correspond to .rex files
> >> (chopped
> >> up rhythms produced by propellerheads recycle). If I can rearrange
> >> the
> >> midi file I can come up with endless variations of the looped audio
> >> file.
> >>
> >> I am confused.  I thought the midi "time" value was just another
> >> slot/keyword value of the MIDI class (i.e. the same as keynum or
> >> duration).  I figured that it was only until the seq was put into the
> >> scheduler that the midi time became "cemented" in.  Do I have it all
> >> wrong?
> >>
> >> On 4/9/07, Rick Taube <taube@uiuc.edu> wrote:
> >> > you shouldnt "rearrange the time values" of the seq's objects --
> >> the
> >> > purpose of a seq is maintain a time-ordered list of events!
> >> >
> >> > assuming you want to scramble keynumbers or something like that you
> >> > could do this
> >> >
> >> > ;; create a seq of midis
> >> >
> >> > (defparameter myseq
> >> >    (new seq :subobjects (loop for i to 100
> >> >                           collect (new midi :time i :keynum i))))
> >> >
> >> > ;; look at the first ten
> >> >
> >> > (list-objects myseq :end 10)
> >> >
> >> > 0. #i(midi time 0 keynum 0 duration 0.5 amplitude 64 channel 0)
> >> > 1. #i(midi time 1 keynum 1 duration 0.5 amplitude 64 channel 0)
> >> > 2. #i(midi time 2 keynum 2 duration 0.5 amplitude 64 channel 0)
> >> > 3. #i(midi time 3 keynum 3 duration 0.5 amplitude 64 channel 0)
> >> > 4. #i(midi time 4 keynum 4 duration 0.5 amplitude 64 channel 0)
> >> > 5. #i(midi time 5 keynum 5 duration 0.5 amplitude 64 channel 0)
> >> > 6. #i(midi time 6 keynum 6 duration 0.5 amplitude 64 channel 0)
> >> > 7. #i(midi time 7 keynum 7 duration 0.5 amplitude 64 channel 0)
> >> > 8. #i(midi time 8 keynum 8 duration 0.5 amplitude 64 channel 0)
> >> > 9. #i(midi time 9 keynum 9 duration 0.5 amplitude 64 channel 0)
> >> >
> >> > ;; gather the keynumbers
> >> >
> >> > (defparameter seqkeys
> >> >    (fold-objects #'cons myseq '() :slot 'keynum))
> >> >
> >> > ;; now shuffle the keynums and put them back
> >> >
> >> > (let ((mixedup (shuffle seqkeys)))
> >> >    (loop for m in (subobjects myseq)
> >> >       for k in mixedup
> >> >       do (sv m :keynum k))
> >> >    )
> >> >
> >> > ;; look at them again
> >> >
> >> > (list-objects myseq :end 10)
> >> >
> >> > 0. #i(midi time 0 keynum 60 duration 0.5 amplitude 64 channel 0)
> >> > 1. #i(midi time 1 keynum 68 duration 0.5 amplitude 64 channel 0)
> >> > 2. #i(midi time 2 keynum 15 duration 0.5 amplitude 64 channel 0)
> >> > 3. #i(midi time 3 keynum 51 duration 0.5 amplitude 64 channel 0)
> >> > 4. #i(midi time 4 keynum 29 duration 0.5 amplitude 64 channel 0)
> >> > 5. #i(midi time 5 keynum 52 duration 0.5 amplitude 64 channel 0)
> >> > 6. #i(midi time 6 keynum 35 duration 0.5 amplitude 64 channel 0)
> >> > 7. #i(midi time 7 keynum 74 duration 0.5 amplitude 64 channel 0)
> >> > 8. #i(midi time 8 keynum 25 duration 0.5 amplitude 64 channel 0)
> >> > 9. #i(midi time 9 keynum 16 duration 0.5 amplitude 64 channel 0)
> >> > CM>
> >> >
> >> >
> >> >
> >> >
> >> >
> >> >
> >> > On Apr 9, 2007, at 6:52 PM, Landspeedrecord wrote:
> >> >
> >> > > I having been trying to rearrange the time values of a MIDI
> >> file, i.e.
> >> > > rearrange the ordering of the notes while keeping all the
> >> other MIDI
> >> > > information intact.  I can load the MIDI into a seq object but
> >> from
> >> > > there I hit a brick wall.
> >> >
> >>
>