annotate clojure/com/aurellem/music/midi_util.clj @ 242:2e751984b42d

making interesting data insights.
author Dylan Holmes <ocsenave@gmail.com>
date Sun, 25 Mar 2012 02:53:29 -0500
parents
children 5b59c6f17cd5
rev   line source
ocsenave@242 1 (ns com.aurellem.music.midi-util
ocsenave@242 2 ;;(:import javax.sound.sampled)
ocsenave@242 3 (:import (javax.sound.midi MidiSystem
ocsenave@242 4 Sequence
ocsenave@242 5 Track
ocsenave@242 6 MidiEvent
ocsenave@242 7 MetaMessage
ocsenave@242 8
ocsenave@242 9 ShortMessage)
ocsenave@242 10 (com.sun.media.sound FastShortMessage)
ocsenave@242 11 (java.io File))
ocsenave@242 12
ocsenave@242 13 (:use (com.aurellem.gb saves util constants gb-driver vbm items assembly characters))
ocsenave@242 14 (:use (com.aurellem.run title))
ocsenave@242 15 (:use (com.aurellem.exp pokemon item-bridge))
ocsenave@242 16 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@242 17
ocsenave@242 18
ocsenave@242 19 ;;; PURE MIDI MANIPULATION
ocsenave@242 20
ocsenave@242 21 (defn midi-load
ocsenave@242 22 "Takes a path to a MIDI file and returns a Sequence object."
ocsenave@242 23 [path]
ocsenave@242 24 ((fn [file]
ocsenave@242 25 (if (.exists file)
ocsenave@242 26 (MidiSystem/getSequence file)
ocsenave@242 27 nil))
ocsenave@242 28 (File. path)))
ocsenave@242 29
ocsenave@242 30
ocsenave@242 31 (defn midi-play
ocsenave@242 32 "Plays the MIDI file at the given location. The MIDI file runs in
ocsenave@242 33 the current thread until it finishes or is cancelled."
ocsenave@242 34 [path]
ocsenave@242 35 (let [midi (midi-load path)]
ocsenave@242 36 (if (nil? midi) nil
ocsenave@242 37 (let [song
ocsenave@242 38 (doto
ocsenave@242 39 (MidiSystem/getSequencer)
ocsenave@242 40 (.open)
ocsenave@242 41 (.setSequence midi)
ocsenave@242 42 (.start))]
ocsenave@242 43 (try
ocsenave@242 44 (loop []
ocsenave@242 45 (if (. song (isRunning))
ocsenave@242 46 (do
ocsenave@242 47 (Thread/sleep 10)
ocsenave@242 48 (recur))
ocsenave@242 49 (throw (Exception. "Song stopped!"))))
ocsenave@242 50 (finally (.close song)))))))
ocsenave@242 51
ocsenave@242 52
ocsenave@242 53 (defn midi-test-1 []
ocsenave@242 54 (-> (.
ocsenave@242 55 (midi-load
ocsenave@242 56 "/home/ocsenave/bk_robert/sounds/sounds/www.vgmusic.com/console/nintendo/gameboy/PkmRB-Item.mid")
ocsenave@242 57 (getTracks))
ocsenave@242 58
ocsenave@242 59 (vec)
ocsenave@242 60 (second)
ocsenave@242 61
ocsenave@242 62 ((fn[trk]
ocsenave@242 63 (map #(. trk (get %))
ocsenave@242 64 (range 0 (. trk size)))))
ocsenave@242 65
ocsenave@242 66 ((fn [evts]
ocsenave@242 67 (map (juxt #(identity (.getMessage %)) #(vec (.getMessage (.getMessage %))) #(.getTick %) ) evts)
ocsenave@242 68 )
ocsenave@242 69
ocsenave@242 70 )))
ocsenave@242 71
ocsenave@242 72
ocsenave@242 73
ocsenave@242 74
ocsenave@242 75
ocsenave@242 76
ocsenave@242 77 (defn midi-event
ocsenave@242 78 "Creates an event at the given tick, of the given msg-type,
ocsenave@242 79 containing data in coll. msg-type can be :meta, :short. If :meta, x
ocsenave@242 80 is the type of the msg. If :short, x is the status of the message."
ocsenave@242 81 [tick msg-type x coll]
ocsenave@242 82
ocsenave@242 83 (cond (= msg-type :meta)
ocsenave@242 84 (MetaMessage.)
ocsenave@242 85 (= msg-type :short)
ocsenave@242 86 (ShortMessage.))
ocsenave@242 87
ocsenave@242 88 )
ocsenave@242 89
ocsenave@242 90
ocsenave@242 91 (defn midi-test-2 []
ocsenave@242 92 (let [sequence (Sequence. (float 30) 15)] ;; 30 fps, 15 frames per beat
ocsenave@242 93 (doto (. sequence (createTrack))
ocsenave@242 94 (.add (MidiEvent. (MetaMessage.) 0)))))
ocsenave@242 95
ocsenave@242 96
ocsenave@242 97
ocsenave@242 98 [com.sun.media.sound.FastShortMessage [-80 0 0] 0] [com.sun.media.sound.FastShortMessage [-80 7 100] 0] [com.sun.media.sound.FastShortMessage [-80 10 64] 0] [com.sun.media.sound.FastShortMessage [-80 32 0] 0] [com.sun.media.sound.FastShortMessage [-64 80] 0] [com.sun.media.sound.FastShortMessage [-80 101 0] 0] [com.sun.media.sound.FastShortMessage [-80 100 0] 1] [com.sun.media.sound.FastShortMessage [-80 6 2] 2] [com.sun.media.sound.FastShortMessage [-80 38 0] 3] [com.sun.media.sound.FastShortMessage [-32 0 56] 3] [com.sun.media.sound.FastShortMessage [-112 68 100] 3] [com.sun.media.sound.FastShortMessage [-112 68 0] 20] [com.sun.media.sound.FastShortMessage [-112 68 100] 40] [com.sun.media.sound.FastShortMessage [-112 68 0] 60] [com.sun.media.sound.FastShortMessage [-112 68 100] 80] [com.sun.media.sound.FastShortMessage [-112 68 0] 100] [com.sun.media.sound.FastShortMessage [-80 7 100] 120] [com.sun.media.sound.FastShortMessage [-112 76 100] 120] [com.sun.media.sound.FastShortMessage [-80 7 90] 181] [com.sun.media.sound.FastShortMessage [-80 7 80] 209] [com.sun.media.sound.FastShortMessage [-80 7 65] 240] [com.sun.media.sound.FastShortMessage [-80 7 50] 270] [com.sun.media.sound.FastShortMessage [-112 76 0] 300] [com.sun.media.sound.FastShortMessage [-80 7 0] 360] [javax.sound.midi.Track$ImmutableEndOfTrack [-1 47 0] 360])
ocsenave@242 99 com.aurellem.music.midi-util> (midi-test-1)
ocsenave@242 100 ([javax.sound.midi.MetaMessage [-1 3 33 79 114 105 103 105 110 97 108 32 99 111 109 112 111 115 101 114 58 32 74 117 110 105 99 104 105 32 77 97 115 117 100 97] 0] [com.sun.media.sound.FastShortMessage [-80 0 0] 0] [com.sun.media.sound.FastShortMessage [-80 7 100] 0] [com.sun.media.sound.FastShortMessage [-80 10 64] 0] [com.sun.media.sound.FastShortMessage [-80 32 0] 0] [com.sun.media.sound.FastShortMessage [-64 80] 0] [com.sun.media.sound.FastShortMessage [-80 101 0] 0] [com.sun.media.sound.FastShortMessage [-80 100 0] 1] [com.sun.media.sound.FastShortMessage [-80 6 2] 2] [com.sun.media.sound.FastShortMessage [-80 38 0] 3] [com.sun.media.sound.FastShortMessage [-32 0 56] 3] [com.sun.media.sound.FastShortMessage [-112 68 100] 3] [com.sun.media.sound.FastShortMessage [-112 68 0] 20] [com.sun.media.sound.FastShortMessage [-112 68 100] 40] [com.sun.media.sound.FastShortMessage [-112 68 0] 60] [com.sun.media.sound.FastShortMessage [-112 68 100] 80] [com.sun.media.sound.FastShortMessage [-112 68 0] 100] [com.sun.media.sound.FastShortMessage [-80 7 100] 120] [com.sun.media.sound.FastShortMessage [-112 76 100] 120] [com.sun.media.sound.FastShortMessage [-80 7 90] 181] [com.sun.media.sound.FastShortMessage [-80 7 80] 209] [com.sun.media.sound.FastShortMessage [-80 7 65] 240] [com.sun.media.sound.FastShortMessage [-80 7 50] 270] [com.sun.media.sound.FastShortMessage [-112 76 0] 300] [com.sun.media.sound.FastShortMessage [-80 7 0] 360] [javax.sound.midi.Track$ImmutableEndOfTrack [-1 47 0] 360])
ocsenave@242 101
ocsenave@242 102
ocsenave@242 103 ;;; ROM MUSIC MANIPULATION
ocsenave@242 104
ocsenave@242 105 (def songs;; music-headers
ocsenave@242 106 {
ocsenave@242 107 :pallet 0x822E
ocsenave@242 108 :pkmn-center 0x8237
ocsenave@242 109 :gym 0x8240
ocsenave@242 110 :city-1 0x8249 ;;virian, pewter, saffron
ocsenave@242 111 :city-2 0x8255 ;; cerulean, fuchsia
ocsenave@242 112 :celedon 0x825E
ocsenave@242 113 :cinnibar 0x8267
ocsenave@242 114 :vermilion 0x8270
ocsenave@242 115 :lavender 0x827C
ocsenave@242 116 :ss-anne 0x8288
ocsenave@242 117 :meet-prof 0x8291
ocsenave@242 118 :meet-blue 0x829A
ocsenave@242 119 :follow 0x82A3
ocsenave@242 120 :safari 0x82AF
ocsenave@242 121 :sfx-heal 0x82BA
ocsenave@242 122 :route-1 0x82C1 ;; route 1,2
ocsenave@242 123 :route-2 0x82CD ;; route 24, 25
ocsenave@242 124 :route-3 0x82D9 ;; route 3-10,16-22
ocsenave@242 125 :route-4 0x82E5 ;; route 11-15
ocsenave@242 126 :route-5 0x82F1 ;; indigo plateau
ocsenave@242 127
ocsenave@242 128 :title 0x7C249
ocsenave@242 129 :credits 0x7C255
ocsenave@242 130 :hall-of-fame 0x7C25E
ocsenave@242 131 :lab-prof 0x7C267
ocsenave@242 132 :jigglypuff 0x7C270
ocsenave@242 133 :bike 0x7C276
ocsenave@242 134 :surfing 0x7C282
ocsenave@242 135 :casino 0x7C28B
ocsenave@242 136 :intro-battle 0x7C294
ocsenave@242 137 :power-plant 0x7C2A0 ;; power plant, unknown dungeon
ocsenave@242 138 :viridian-forest 0x7C2AC ;;viridian forest, seafoam islands
ocsenave@242 139 :victory-rd 0x7C2B8 ;;mt moon, rock tunnel, victory rd
ocsenave@242 140 :mansion 0x7C2C4
ocsenave@242 141 :pkmn-tower 0x7C2D0
ocsenave@242 142 :silph 0x7C2D9
ocsenave@242 143 :trainer-bad 0x7C2E2
ocsenave@242 144 :trainer-girl 0x7C2EB
ocsenave@242 145 :trainer-angry 0x7C2F4
ocsenave@242 146 })
ocsenave@242 147
ocsenave@242 148
ocsenave@242 149 })
ocsenave@242 150
ocsenave@242 151
ocsenave@242 152 (defn low-high-format
ocsenave@242 153 "Returns the number represented by the bytes."
ocsenave@242 154 [low high]
ocsenave@242 155 (+ low (* 256 high)))
ocsenave@242 156
ocsenave@242 157 (defn rom-tracks
ocsenave@242 158 "Given a valid address to a music header, returns a list of the
ocsenave@242 159 data tracks"
ocsenave@242 160 [address]
ocsenave@242 161 (let [rom (rom (root))
ocsenave@242 162 tracklist
ocsenave@242 163 ((fn extract-tracklist [mem n]
ocsenave@242 164 (if (= (nth mem 2) n)
ocsenave@242 165 (cons (low-high-format (first mem)
ocsenave@242 166 (second mem))
ocsenave@242 167 (extract-tracklist (drop 3 mem) (inc n)))
ocsenave@242 168 '()))
ocsenave@242 169
ocsenave@242 170 (take 12 (drop (inc address) rom))
ocsenave@242 171 1
ocsenave@242 172 )]
ocsenave@242 173
ocsenave@242 174 (map
ocsenave@242 175 (fn [trk] (take-while #(not= 0xFF %) (drop trk rom)))
ocsenave@242 176 tracklist)
ocsenave@242 177
ocsenave@242 178 ))
ocsenave@242 179
ocsenave@242 180
ocsenave@242 181
ocsenave@242 182 (defn parse-track
ocsenave@242 183 "Consumes the list of opcodes, returning a runnable MIDI Sequence object."
ocsenave@242 184 [track]
ocsenave@242 185 (fn [midi track]
ocsenave@242 186 (cond (empty? track) midi)))
ocsenave@242 187
ocsenave@242 188
ocsenave@242 189
ocsenave@242 190
ocsenave@242 191
ocsenave@242 192
ocsenave@242 193
ocsenave@242 194
ocsenave@242 195
ocsenave@242 196
ocsenave@242 197 ;; 8237-823F Pokecenter
ocsenave@242 198 ;; 8240-8248 Gym
ocsenave@242 199 ;; 8249-8254 Viridian / Pewter / Saffron
ocsenave@242 200 ;; 8255-825D Cerulean / Fuchsia
ocsenave@242 201 ;; 825E-8266 Celedon
ocsenave@242 202 ;; 8267-826F Cinnibar
ocsenave@242 203 ;; 8270-827B Vermilion
ocsenave@242 204 ;; 827C-8287 Lavender
ocsenave@242 205 ;; 8288-8290 S.S. Anne
ocsenave@242 206 ;; 8291-8299 Meet Prof. Oak
ocsenave@242 207 ;; 829A-82A2 Meet Rival
ocsenave@242 208 ;; 82A3-82AE Guy Walks you to Museum
ocsenave@242 209 ;; 82AF-82B7 Safari Zone
ocsenave@242 210 ;; 82B8-82C0 Pokemon get healed
ocsenave@242 211 ;; 82C1-82CC Routes 1 / 2
ocsenave@242 212 ;; 82CD-82D8 Routes 24 / 25
ocsenave@242 213 ;; 82D9-82E4 Routes 3 / 4 / 5 / 6 / 7 / 8 / 9 / 10 / 16 / 17 / 18 / 19 / 20 / 21 / 22
ocsenave@242 214 ;; 82E5-82F0 Routes 11 / 12 / 13 / 14 / 15
ocsenave@242 215 ;; 82F1-82FD Route 23 / Indigo Plateau
ocsenave@242 216 ;; 7C249-7C254 Title Screen
ocsenave@242 217 ;; 7C255-7C25D Credits
ocsenave@242 218 ;; 7C25E-7C266 Hall of FAme Registration
ocsenave@242 219 ;; 7C267-7C26F PRof Oak's LAb
ocsenave@242 220 ;; 7C270-7C275 Jigglypuff's Song
ocsenave@242 221 ;; 7C276-7C281 Bike Riding
ocsenave@242 222 ;; 7C282-7C28A Surfing
ocsenave@242 223 ;; 7C28B-7C293 Casino
ocsenave@242 224 ;; 7C294-7C29F Introduction Battle
ocsenave@242 225 ;; 7C2A0-7C2AB Power Plant / Unknown Dungeon
ocsenave@242 226 ;; 7C2AC-7C2B7 Viridian Forest / Seafoam Islands
ocsenave@242 227 ;; 7C2B8-7C2C3 Mt. Moon / Rock Tunnel / Victory Road
ocsenave@242 228 ;; 7C2C4-7C2CF Cinnibar Mansion
ocsenave@242 229 ;; 7C2D0-7C2D8 Pokemon Tower
ocsenave@242 230 ;; 7C2D9-7C2E1 Silph Co
ocsenave@242 231 ;; 7C2E2-7C2EA Meet Bad Trainer
ocsenave@242 232 ;; 7C2EB-7C2F3 Meet Girl Trainer
ocsenave@242 233 ;; 7C2F4-7C2FC Meet Angry Trainer