# HG changeset patch # User Robert McIntyre # Date 1335182559 18000 # Node ID c03f28aa98d90c157de8925c509fdc02c748f484 # Parent df4e03672b05d64eed37e763bff9d475e2193700 completed basic midi parser using midicsv diff -r df4e03672b05 -r c03f28aa98d9 clojure/com/aurellem/run/music.clj --- a/clojure/com/aurellem/run/music.clj Mon Apr 23 05:45:25 2012 -0500 +++ b/clojure/com/aurellem/run/music.clj Mon Apr 23 07:02:39 2012 -0500 @@ -4,7 +4,9 @@ rlm-assembly)) (:use (com.aurellem.run util title save-corruption bootstrap-0 bootstrap-1)) - (:import [com.aurellem.gb.gb_driver SaveState])) + (:require clojure.string) + (:import [com.aurellem.gb.gb_driver SaveState]) + (:import java.io.File)) (def music-base new-kernel) @@ -295,9 +297,6 @@ target program) (PC! target))))) -(defn trippy [] - (run-moves (play-music many-notes ) (repeat 8000 []))) - (defn test-timer [] (flatten [0x3E @@ -314,3 +313,86 @@ 500 [0xF0 0x05])])) + +(def third-kind + (File. "/home/r/proj/midi/third-kind.mid")) + +(defn raw-midi-text [#^File midi-file] + (:out + (clojure.java.shell/sh + "midicsv" + (.getCanonicalPath midi-file) + "-"))) + +(def command-line #"^(\d+), (\d+), ([^,]+)(.*)$") + +(defmulti parse-command :command) + +(defn discard-args [command] (dissoc command :args)) + +(defmethod parse-command :Start_track + [command] (discard-args command)) + +(defmethod parse-command :End_track + [command] (discard-args command)) + +(defmethod parse-command :default + [command] command) + +(defn parse-number-list + [number-list-str] + (map #(Integer/parseInt %) + (clojure.string/split number-list-str #", "))) + +(defmethod parse-command :Tempo + [command] + (update-in command [:args] #(Integer/parseInt %))) + +(defn parse-midi-note-list + [midi-note-list-str] + (let [[channel note velocity] + (parse-number-list midi-note-list-str)] + {:channel channel :note note :velocity velocity})) + + +(defmethod parse-command :Note_on_c + [command] + (update-in command [:args] parse-midi-note-list)) + +(defmethod parse-command :Note_off_c + [command] + (update-in command [:args] parse-midi-note-list)) + +(defmethod parse-command :Header + [command] + (let [args (:args command) + [format num-tracks division] (parse-number-list args)] + (assoc command :args + {:format format + :num-tracks num-tracks + :division division}))) + +(defmethod parse-command :Program_c + [command] + (let [args (:args command) + [channel program-num] (parse-number-list args)] + (assoc command :args + {:channel channel + :program-num program-num}))) + + +(defn parse-midi [#^File midi-file] + (map + (comp parse-command + (fn [line] + (let [[[_ channel time command args]] + (re-seq command-line line)] + ;;(println (re-seq command-parse-1 line)) + {:channel (Integer/parseInt channel) + :time (Integer/parseInt time) + :command (keyword command) + :args (apply str (drop 2 args))}))) + (drop-last + (clojure.string/split-lines + (raw-midi-text midi-file))))) +