Mercurial > vba-clojure
view clojure/com/aurellem/music/midi_util.clj @ 306:2873f50b7291
beginning to work on cry data
author | Dylan Holmes <ocsenave@gmail.com> |
---|---|
date | Sat, 31 Mar 2012 01:27:46 -0500 |
parents | 5b59c6f17cd5 |
children | e6a5dfd31230 |
line wrap: on
line source
1 (ns com.aurellem.music.midi-util2 ;;(:import javax.sound.sampled)3 (:import (javax.sound.midi MidiSystem4 Sequence5 Track6 MidiEvent7 MetaMessage9 ShortMessage)10 (com.sun.media.sound FastShortMessage)11 (java.io File))13 (:use (com.aurellem.gb saves util constants gb-driver vbm items assembly characters))14 (:use (com.aurellem.run title))15 (:use (com.aurellem.exp pokemon item-bridge))16 (:use (com.aurellem.world practice))17 (:import [com.aurellem.gb.gb_driver SaveState]))20 ;;; PURE MIDI MANIPULATION22 (defn midi-load23 "Takes a path to a MIDI file and returns a Sequence object."24 [path]25 ((fn [file]26 (if (.exists file)27 (MidiSystem/getSequence file)28 nil))29 (File. path)))33 (defn midi-play-seq34 "Plays the MIDI Sequence. The MIDI runs in35 the current thread until it finishes or is cancelled."36 [midi]37 (if (nil? midi) nil38 (let [song39 (doto40 (MidiSystem/getSequencer)41 (.open)42 (.setSequence midi)43 (.start))]44 (try45 (loop []46 (if (. song (isRunning))47 (do48 (Thread/sleep 10)49 (recur))50 ))51 (finally (.close song))))))54 (def midi-play-file55 "Plays the MIDI file at the given location. The MIDI file runs in56 the current thread until it finishes or is cancelled."57 (comp midi-play-seq midi-load))62 (defn midi-test-1 []63 (-> (.64 (midi-load65 "/home/ocsenave/bk_robert/sounds/sounds/www.vgmusic.com/console/nintendo/gameboy/PkmRB-Item.mid")66 (getTracks))68 (vec)69 (nth 1)71 ((fn[trk]72 (map #(. trk (get %))73 (range 0 (. trk size)))))75 ((fn [evts]76 (map (juxt #(.getTick %) #(vec (.getMessage (.getMessage77 %))) #(.getMessage %) ) evts)78 )80 )))86 (defn midi-short87 "Creates a MIDI event containing a ShortMessage."88 [tick [status & ns]]89 (MidiEvent.90 (apply91 (fn92 ([x] (doto (ShortMessage.) (.setMessage x)))93 ([x y] (doto (ShortMessage.) (.setMessage x y 0)))94 ([x y z] (doto (ShortMessage.) (.setMessage x y z)))95 ([x y z w] (doto (ShortMessage.) (.setMessage x y z w))))96 status97 ns)98 tick))100 (defn midi-meta101 "Creates a MIDI event containing a MetaMessage"102 [tick type ns]103 (MidiEvent.104 (doto (MetaMessage.)105 (.setMessage type106 (byte-array (map byte ns))107 (count ns)))108 tick))112 (defn sign113 "Interpret the bits of n as a signed two's-complement byte"114 [n]115 (if (>= n 128) (- n 256)116 n))118 (defn unsign119 "Interpret the bits as an unsigned byte."120 [n]121 (if (neg? n) (+ n 256) n))126 (defn midi-test-2 []127 (let [sequence (Sequence. (float 30) 12)] ;; 30 fps, 10 frames per beat128 (doto (. sequence (createTrack))129 (.add (midi-meta 0 3 [-1 3 33 79 114 105 103 105 110 97 108 32130 99 111 109 112 111 115 101 114 58 32 74 117 110 105 99 104 105 32 77131 97 115 117 100 97]))133 (.add (midi-short 0 [-80 0 0])) ;; control change = -80134 (.add (midi-short 0 [-80 7 100])) ;; control change, volume, 100135 (.add (midi-short 0 [-80 10 64])) ;; control change, pan, 64 (middle?)136 (.add (midi-short 0 [-80 32 0])) ;; ctrl chg, LSB ctrl 0 = bank 0137 (.add (midi-short 0 [-64 01])) ;; program/instrument change = -64138 (.add (midi-short 0 [-80 101 0]))139 (.add (midi-short 1 [-80 100 0]))140 (.add (midi-short 2 [-80 6 2]))141 (.add (midi-short 3 [-80 38 0]))142 (.add (midi-short 3 [-32 0 56])) ;; pitch bend?! = -32143 (.add (midi-short 3 [-112 68 100])) ;; note on = -112144 (.add (midi-short 20 [-112 68 0]))145 (.add (midi-short 40 [-112 68 100]))146 (.add (midi-short 60 [-112 68 0]))147 (.add (midi-short 80 [-112 68 100]))148 (.add (midi-short 100 [-112 68 0]))149 (.add (midi-short 120 [-80 7 100])) ;; control change150 (.add (midi-short 120 [-112 76 100])) ;; note-on151 (.add (midi-short 181 [-80 7 90])) ;; control change152 (.add (midi-short 209 [-80 7 80])) ;; control change153 (.add (midi-short 240 [-80 7 65])) ;; control change154 (.add (midi-short 270 [-80 7 50])) ;; control change155 (.add (midi-short 300 [-112 76 0])) ;; note on = -112156 (.add (midi-short 360 [-80 7 0])))157 ;;(.add (midi-short 360 [-1 47 0])) ;; system reset = -1159 sequence160 ))165 (defn read-memory166 ([mem start length]167 (take length168 (drop start169 mem)))170 ([start length]171 (read-memory (rom(root)) start length)))173 ;;; ROM MUSIC MANIPULATION175 (def songs;; music-headers176 {177 :pallet 0x822E178 :pkmn-center 0x8237179 :gym 0x8240180 :city-1 0x8249 ;;virian, pewter, saffron181 :city-2 0x8255 ;; cerulean, fuchsia182 :celedon 0x825E183 :cinnibar 0x8267184 :vermilion 0x8270185 :lavender 0x827C186 :ss-anne 0x8288187 :meet-prof 0x8291188 :meet-blue 0x829A189 :follow 0x82A3190 :safari 0x82AF191 :sfx-heal 0x82BA192 :route-1 0x82C1 ;; route 1,2193 :route-2 0x82CD ;; route 24, 25194 :route-3 0x82D9 ;; route 3-10,16-22195 :route-4 0x82E5 ;; route 11-15196 :route-5 0x82F1 ;; indigo plateau198 :title 0x7C249199 :credits 0x7C255200 :hall-of-fame 0x7C25E201 :lab-prof 0x7C267202 :jigglypuff 0x7C270203 :bike 0x7C276204 :surfing 0x7C282205 :casino 0x7C28B206 :intro-battle 0x7C294207 :power-plant 0x7C2A0 ;; power plant, unknown dungeon208 :viridian-forest 0x7C2AC ;;viridian forest, seafoam islands209 :victory-rd 0x7C2B8 ;;mt moon, rock tunnel, victory rd210 :mansion 0x7C2C4211 :pkmn-tower 0x7C2D0212 :silph 0x7C2D9213 :trainer-bad 0x7C2E2214 :trainer-girl 0x7C2EB215 :trainer-angry 0x7C2F4216 })219 (defn low-high-format220 "Returns the number represented by the bytes."221 [low high]222 (+ low (* 256 high)))223 (defn high-low-format224 "Returns the number represented by the bytes."225 [high low]226 (+ low (* 256 high)))229 (defn rom-tracks230 "Given a valid address to a music header, returns a list of the231 data tracks"232 [address]233 (let [rom (rom (root))234 tracklist235 ((fn extract-tracklist [mem n]236 (if (= (nth mem 2) n)237 (cons (low-high-format (first mem)238 (second mem))239 (extract-tracklist (drop 3 mem) (inc n)))240 '()))242 (take 12 (drop (inc address) rom))243 1244 )]246 tracklist247 (map248 (fn [trk] (take-while #(not= 0xFF %) (drop trk rom)))249 tracklist)251 ))256 ;; (defn note?257 ;; "Does the given byte correspond to a note?"258 ;; [n])260 ;; (comment defn parse-ops261 ;; "Consumes the list of opcodes, returning a runnable MIDI Sequence object."262 ;; [ops]263 ;; (264 ;; (fn [midi ops]265 ;; (let [x (first ops)]266 ;; (cond (empty? ops) midi267 ;; (= x 0xDA)268 ;; ;; set tempo (high-low (nth ops 1)(nth ops 2))269 ;; (recur (identity midi) (drop 3 ops))271 ;; (note? x)274 ;; )276 ;; (doto (Sequence. (float 30) 15) ;; 30 fps, 15 frames per beat277 ;; (.createTrack))278 ;; ops279 ;; ))))287 ;; 8237-823F Pokecenter288 ;; 8240-8248 Gym289 ;; 8249-8254 Viridian / Pewter / Saffron290 ;; 8255-825D Cerulean / Fuchsia291 ;; 825E-8266 Celedon292 ;; 8267-826F Cinnibar293 ;; 8270-827B Vermilion294 ;; 827C-8287 Lavender295 ;; 8288-8290 S.S. Anne296 ;; 8291-8299 Meet Prof. Oak297 ;; 829A-82A2 Meet Rival298 ;; 82A3-82AE Guy Walks you to Museum299 ;; 82AF-82B7 Safari Zone300 ;; 82B8-82C0 Pokemon get healed301 ;; 82C1-82CC Routes 1 / 2302 ;; 82CD-82D8 Routes 24 / 25303 ;; 82D9-82E4 Routes 3 / 4 / 5 / 6 / 7 / 8 / 9 / 10 / 16 / 17 / 18 / 19 / 20 / 21 / 22304 ;; 82E5-82F0 Routes 11 / 12 / 13 / 14 / 15305 ;; 82F1-82FD Route 23 / Indigo Plateau306 ;; 7C249-7C254 Title Screen307 ;; 7C255-7C25D Credits308 ;; 7C25E-7C266 Hall of FAme Registration309 ;; 7C267-7C26F PRof Oak's LAb310 ;; 7C270-7C275 Jigglypuff's Song311 ;; 7C276-7C281 Bike Riding312 ;; 7C282-7C28A Surfing313 ;; 7C28B-7C293 Casino314 ;; 7C294-7C29F Introduction Battle315 ;; 7C2A0-7C2AB Power Plant / Unknown Dungeon316 ;; 7C2AC-7C2B7 Viridian Forest / Seafoam Islands317 ;; 7C2B8-7C2C3 Mt. Moon / Rock Tunnel / Victory Road318 ;; 7C2C4-7C2CF Cinnibar Mansion319 ;; 7C2D0-7C2D8 Pokemon Tower320 ;; 7C2D9-7C2E1 Silph Co321 ;; 7C2E2-7C2EA Meet Bad Trainer322 ;; 7C2EB-7C2F3 Meet Girl Trainer323 ;; 7C2F4-7C2FC Meet Angry Trainer