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