changeset 428:476f7da175a4

correctly handle silent spaces in midi files.
author Robert McIntyre <rlm@mit.edu>
date Mon, 23 Apr 2012 09:22:07 -0500
parents fbccf46cf34d
children a69c4d0c1a3b
files clojure/com/aurellem/run/music.clj
diffstat 1 files changed, 37 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
     1.1 --- a/clojure/com/aurellem/run/music.clj	Mon Apr 23 08:26:23 2012 -0500
     1.2 +++ b/clojure/com/aurellem/run/music.clj	Mon Apr 23 09:22:07 2012 -0500
     1.3 @@ -333,7 +333,10 @@
     1.4  ;; want: seconds
     1.5  
     1.6  
     1.7 -
     1.8 +(defn silence [length]
     1.9 +  {:frequency 1
    1.10 +   :duration length
    1.11 +   :volume 0})
    1.12  
    1.13  (defn midi->mini-midi [#^File midi-file]
    1.14    (let [midi-events (parse-midi midi-file)
    1.15 @@ -356,25 +359,46 @@
    1.16          tempo (:args (first (filter #(= :Tempo (:command %)) midi-events)))
    1.17          division (:division
    1.18                    (:args (first (filter #(= :Header (:command %)) midi-events))))
    1.19 +
    1.20 +        notes
    1.21 +        (map
    1.22 +         (fn [note-on note-off]
    1.23 +           {:frequency (midi-code->frequency (:note (:args note-on)))
    1.24 +            :duration
    1.25 +            (/ (* (/ tempo division)
    1.26 +                  (- (:time note-off) (:time note-on)))
    1.27 +               1e6) ;; convert clock-pulses into seconds
    1.28 +            :volume (int (/ (:velocity (:args note-on)) 10))
    1.29 +            :time-stamp (/ (* (/ tempo division)
    1.30 +                              (:time note-on)) 1e6)})
    1.31 +         channel-1-on channel-1-off)
    1.32 +
    1.33 +        silences
    1.34 +        (map (fn [note-1 note-2]
    1.35 +               (let [note-1-space (- (:time-stamp note-2)
    1.36 +                                     (:time-stamp note-1))
    1.37 +                     note-1-length (:duration note-1)]
    1.38 +                 (silence (- note-1-space note-1-length))))
    1.39 +             ;; to handle silence at the beginning.
    1.40 +             (concat [(assoc (silence 0)
    1.41 +                        :time-stamp 0)] notes)
    1.42 +             notes)
    1.43 +        
    1.44 +        notes-with-silence
    1.45 +        (filter (comp not zero? :duration) (interleave silences notes))
    1.46          ]
    1.47 -  
    1.48 +
    1.49      (map
    1.50       (fn [note-event]
    1.51         (note-codes (:frequency note-event)
    1.52                     (:volume note-event)
    1.53                     (int (* (:duration note-event) 0x100))))
    1.54 +     notes-with-silence)))
    1.55 +
    1.56 +
    1.57       
    1.58 -     (map
    1.59 -      (fn [note-on note-off]
    1.60 -        {:frequency (midi-code->frequency (:note (:args note-on)))
    1.61 -         :duration
    1.62 -         (/ (* (/ tempo division)
    1.63 -               (- (:time note-off) (:time note-on)))
    1.64 -            1e6) ;; convert clock-pulses into seconds
    1.65 -         :volume (int (/ (:velocity (:args note-on)) 10))
    1.66 -         :time-stamp (/ (* (/ tempo division)
    1.67 -                           (:time note-on)) 1e6)})
    1.68 -      channel-1-on channel-1-off))))
    1.69 +      
    1.70 +     
    1.71             
    1.72  
    1.73