changeset 426:c03f28aa98d9

completed basic midi parser using midicsv
author Robert McIntyre <rlm@mit.edu>
date Mon, 23 Apr 2012 07:02:39 -0500
parents df4e03672b05
children fbccf46cf34d
files clojure/com/aurellem/run/music.clj
diffstat 1 files changed, 86 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
     1.1 --- a/clojure/com/aurellem/run/music.clj	Mon Apr 23 05:45:25 2012 -0500
     1.2 +++ b/clojure/com/aurellem/run/music.clj	Mon Apr 23 07:02:39 2012 -0500
     1.3 @@ -4,7 +4,9 @@
     1.4                           rlm-assembly))
     1.5    (:use (com.aurellem.run util title save-corruption
     1.6                            bootstrap-0 bootstrap-1))
     1.7 -  (:import [com.aurellem.gb.gb_driver SaveState]))
     1.8 +  (:require clojure.string)
     1.9 +  (:import [com.aurellem.gb.gb_driver SaveState])
    1.10 +  (:import java.io.File))
    1.11  
    1.12  
    1.13  (def music-base new-kernel)
    1.14 @@ -295,9 +297,6 @@
    1.15                               target program)
    1.16             (PC! target)))))
    1.17  
    1.18 -(defn trippy []
    1.19 -  (run-moves (play-music many-notes ) (repeat 8000 [])))
    1.20 -
    1.21  (defn test-timer []
    1.22    (flatten
    1.23     [0x3E
    1.24 @@ -314,3 +313,86 @@
    1.25       500
    1.26       [0xF0
    1.27        0x05])]))
    1.28 +
    1.29 +(def third-kind
    1.30 +  (File. "/home/r/proj/midi/third-kind.mid"))
    1.31 +
    1.32 +(defn raw-midi-text [#^File midi-file]
    1.33 +  (:out 
    1.34 +   (clojure.java.shell/sh
    1.35 +    "midicsv"
    1.36 +    (.getCanonicalPath midi-file)
    1.37 +    "-")))
    1.38 +
    1.39 +(def command-line #"^(\d+), (\d+), ([^,]+)(.*)$")
    1.40 +
    1.41 +(defmulti parse-command :command)
    1.42 +
    1.43 +(defn discard-args [command] (dissoc command :args))
    1.44 +
    1.45 +(defmethod parse-command :Start_track
    1.46 +  [command] (discard-args command))
    1.47 +
    1.48 +(defmethod parse-command :End_track
    1.49 +  [command] (discard-args command))
    1.50 +
    1.51 +(defmethod parse-command :default
    1.52 +  [command] command)
    1.53 +
    1.54 +(defn parse-number-list
    1.55 +  [number-list-str]
    1.56 +  (map #(Integer/parseInt %)
    1.57 +       (clojure.string/split number-list-str #", ")))
    1.58 +
    1.59 +(defmethod parse-command :Tempo
    1.60 +  [command]
    1.61 +  (update-in command [:args] #(Integer/parseInt %)))
    1.62 +
    1.63 +(defn parse-midi-note-list
    1.64 +  [midi-note-list-str]
    1.65 +  (let [[channel note velocity]
    1.66 +        (parse-number-list midi-note-list-str)]
    1.67 +    {:channel channel :note note :velocity velocity}))
    1.68 +  
    1.69 +
    1.70 +(defmethod parse-command :Note_on_c
    1.71 +  [command]
    1.72 +  (update-in command [:args] parse-midi-note-list))
    1.73 +
    1.74 +(defmethod parse-command :Note_off_c
    1.75 +  [command]
    1.76 +  (update-in command [:args] parse-midi-note-list))
    1.77 +
    1.78 +(defmethod parse-command :Header
    1.79 +  [command]
    1.80 +  (let [args (:args command)
    1.81 +        [format num-tracks division] (parse-number-list args)]
    1.82 +    (assoc command :args
    1.83 +           {:format format
    1.84 +            :num-tracks num-tracks
    1.85 +            :division division})))
    1.86 +        
    1.87 +(defmethod parse-command :Program_c
    1.88 +  [command]
    1.89 +  (let [args (:args command)
    1.90 +        [channel program-num] (parse-number-list args)]
    1.91 +    (assoc command :args
    1.92 +           {:channel channel
    1.93 +            :program-num program-num})))
    1.94 +
    1.95 +
    1.96 +(defn parse-midi [#^File midi-file]
    1.97 +  (map
    1.98 +   (comp parse-command
    1.99 +         (fn [line]
   1.100 +           (let [[[_ channel time command args]]
   1.101 +                 (re-seq command-line line)]
   1.102 +             ;;(println (re-seq command-parse-1 line))
   1.103 +             {:channel (Integer/parseInt channel)
   1.104 +              :time (Integer/parseInt time)
   1.105 +              :command (keyword command)
   1.106 +              :args (apply str (drop 2 args))})))
   1.107 +   (drop-last
   1.108 +    (clojure.string/split-lines
   1.109 +     (raw-midi-text midi-file)))))
   1.110 +