annotate clojure/com/aurellem/run/final_cut.clj @ 554:37daf1acb212

progress.
author Robert McIntyre <rlm@mit.edu>
date Fri, 31 Aug 2012 00:51:17 -0500
parents 6ce1d5fd4911
children 4503899241e6
rev   line source
rlm@530 1 (ns com.aurellem.run.final-cut
rlm@530 2 (:use (com.aurellem.gb saves gb-driver util constants
rlm@530 3 items vbm characters money
rlm@530 4 rlm-assembly))
rlm@530 5 (:use (com.aurellem.run util sound music title save-corruption
rlm@530 6 bootstrap-0 bootstrap-1
rlm@530 7 ram-display
rlm@530 8 ))
rlm@530 9 (:require clojure.string)
rlm@530 10 (:import [com.aurellem.gb.gb_driver SaveState])
rlm@530 11 (:import java.awt.image.BufferedImage)
rlm@530 12 (:import java.io.File)
rlm@530 13 (:import com.aurellem.gb.WaveWriter))
rlm@530 14
rlm@530 15
rlm@542 16 (def render-dir (File. user-home "proj/vba-clojure/render/test"))
rlm@530 17
rlm@546 18 (defn write-move-image! [move target-file]
rlm@546 19 (let [actual-keys (set move)
rlm@546 20 keys [:a :b :start :select :u :d :l :r]
rlm@546 21 button-on-name ["-size" "5x5" "xc:red"]
rlm@546 22 button-off-name ["-size" "5x5" "xc:white"]]
rlm@546 23 (apply
rlm@546 24 clojure.java.shell/sh
rlm@546 25 (flatten
rlm@546 26 ["convert"
rlm@546 27 "-size" "64x5" "xc:white"
rlm@546 28 (map
rlm@546 29 (fn [index]
rlm@546 30 (let [position ["-geometry"
rlm@546 31 (str "+" (* index 8)
rlm@546 32 "+" "0") "-composite"]]
rlm@546 33 (if (actual-keys (keys index))
rlm@546 34 [button-on-name position]
rlm@546 35 [button-off-name position])))
rlm@546 36 (range (count keys)))
rlm@546 37 (.getCanonicalPath target-file)]))))
rlm@544 38
rlm@530 39 (defn render-files!
rlm@530 40 ([^File target-dir initial-state moves]
rlm@530 41 (let [ram-map-dir (File. target-dir "ram-map")
rlm@530 42 frames-dir (File. target-dir "frames")
rlm@546 43 moves-dir (File. target-dir "moves")
rlm@530 44 audio-file (File. target-dir "audio.wav")
rlm@533 45 _ (.mkdir target-dir)
rlm@533 46 _ (.mkdir ram-map-dir)
rlm@533 47 _ (.mkdir frames-dir)
rlm@546 48 _ (.mkdir moves-dir)
rlm@530 49 wave-writer (WaveWriter. audio-file)
rlm@544 50 moves (vec moves)
rlm@544 51 desired-fps 60
rlm@547 52 seconds-per-frame (/ 1.0 desired-fps)]
rlm@530 53 (set-state! initial-state)
rlm@544 54 ;; clear sound buffer
rlm@544 55 (sound-bytes)
rlm@544 56 (try
rlm@544 57 (dorun
rlm@544 58 (reduce
rlm@544 59 (fn [[total-audio-samples
rlm@544 60 total-video-samples] move]
rlm@544 61 (run-moves @current-state (vector move))
rlm@544 62 (let [sound (sound-bytes)
rlm@544 63 total-audio-samples (+ total-audio-samples
rlm@544 64 (count sound))
rlm@544 65 total-audio-time
rlm@544 66 (*
rlm@544 67 (/ total-audio-samples 4)
rlm@544 68 (/ 44100))
rlm@544 69
rlm@544 70 total-video-time (* total-video-samples
rlm@544 71 seconds-per-frame)
rlm@530 72
rlm@544 73 av-diff (- total-audio-time
rlm@544 74 total-video-time)
rlm@544 75 write-video!
rlm@544 76 (fn [index]
rlm@544 77 ;; write screenshot
rlm@546 78 (write-move-image!
rlm@546 79 move
rlm@546 80 (File. moves-dir (format "%07d.png" index)))
rlm@544 81
rlm@544 82 (write-png!
rlm@544 83 @current-state
rlm@544 84 (File. frames-dir (format "%07d.png" index)))
rlm@544 85
rlm@544 86 ;; write ram-image
rlm@544 87 (write-ram-image!
rlm@544 88 @current-state
rlm@544 89 (File. ram-map-dir (format "%07d.png" index))))]
rlm@544 90 ;;(println "audio-samples:" (count sound))
rlm@544 91
rlm@544 92 ;; record audio
rlm@544 93 (.process wave-writer sound gb-sound-format)
rlm@544 94
rlm@544 95 ;; duplicate or drop frames depending on
rlm@544 96 ;; desired-fps
rlm@544 97 (if (> (Math/abs av-diff) (* 2 seconds-per-frame))
rlm@544 98 (if (< 0 av-diff)
rlm@544 99 ;; audio has gone past video, duplicate video.
rlm@544 100 (do (println
rlm@544 101 "duplicating frame, av-diff is" av-diff)
rlm@544 102 (write-video! (+ 1 total-video-samples))
rlm@544 103 (write-video! (+ 2 total-video-samples))
rlm@544 104 [total-audio-samples
rlm@544 105 (+ 2 total-video-samples)])
rlm@544 106 ;; video has gone past audio, drop frame.
rlm@544 107 (do (println
rlm@544 108 "dropping frame, av-diff is" av-diff)
rlm@544 109 [total-audio-samples
rlm@544 110 total-video-samples]))
rlm@544 111 ;; no frame dropping or duplication required.
rlm@544 112 (do ;;(println "all normal")
rlm@544 113 (write-video! (+ 1 total-video-samples))
rlm@544 114 [total-audio-samples
rlm@544 115 (+ 1 total-video-samples)]))))
rlm@544 116 [0 0 0] moves))
rlm@544 117 (finally
rlm@544 118 (do
rlm@544 119 (println "cleanup audio.")
rlm@544 120 (.cleanup wave-writer))))))
rlm@544 121 ([initial-state moves]
rlm@544 122 (render-files! render-dir initial-state moves))
rlm@544 123 ([moves]
rlm@544 124 (render-files! (root) moves)))
rlm@530 125
rlm@531 126 (defn file-names [#^File dir]
rlm@531 127 (mapv #(.getCanonicalPath %) (next (sort (file-seq dir)))))
rlm@531 128
rlm@531 129 (defn composite-frames-command
rlm@546 130 [move-image screenshot ram-map target]
rlm@546 131 ["convert"
rlm@546 132 "-size" "318x276" "xc:white"
rlm@546 133 move-image "-geometry" "+30+225" "-composite"
rlm@546 134 screenshot "-geometry" "+10+10" "-composite"
rlm@546 135 ram-map "-geometry" "+180+10" "-composite"
rlm@546 136 target])
rlm@531 137
rlm@531 138 (defn generate-composite-frames!
rlm@547 139 [^File rendered-dir]
rlm@532 140 (let [final-frames (File. rendered-dir "final")
rlm@532 141 _ (.mkdir final-frames)
rlm@547 142 move-images (file-names (File. rendered-dir "moves"))
rlm@532 143 screenshots (file-names (File. rendered-dir "frames"))
rlm@532 144 ram-maps (file-names (File. rendered-dir "ram-map"))
rlm@532 145 targets (map #(.getCanonicalPath
rlm@532 146 (File. final-frames (format "%07d.bmp" %)))
rlm@532 147 (range (count screenshots)))]
rlm@532 148 (dorun
rlm@532 149 (map
rlm@532 150 (comp
rlm@532 151 (partial apply clojure.java.shell/sh)
rlm@532 152 flatten
rlm@532 153 (partial apply composite-frames-command)
rlm@547 154 (fn [a b c d] (println d) [a b c d]))
rlm@547 155 move-images screenshots ram-maps targets))))
rlm@531 156
rlm@532 157
rlm@549 158 ;; (defn final-cut! [^File render-dir]
rlm@549 159 ;; (let [movie (File. render-dir "final.ogg")
rlm@549 160 ;; final-audio (File. render-dir "final.wav")
rlm@549 161 ;; final (File. render-dir "final")]
rlm@549 162 ;; (.delete movie)
rlm@549 163 ;; (.delete final-audio)
rlm@549 164 ;; (clojure.java.shell/sh
rlm@549 165 ;; "sox" (.getCanonicalPath (File. render-dir "audio.wav"))
rlm@549 166 ;; (.getCanonicalPath final-audio))
rlm@549 167 ;; (clojure.java.shell/sh
rlm@549 168 ;; "ffmpeg" "-r" "60" ;; maybe 59.7 ???!
rlm@549 169 ;; "-i" (str (.getCanonicalPath final) "/" "%07d.bmp")
rlm@549 170 ;; "-i" (.getCanonicalPath final-audio)
rlm@549 171 ;; "-b:a" "128k"
rlm@549 172 ;; "-b:v" "9000k"
rlm@549 173 ;; "-c:a" "libvorbis"
rlm@549 174 ;; "-f" "webm"
rlm@549 175 ;; "-g" "200"
rlm@549 176 ;; (.getCanonicalPath movie)) nil))
rlm@549 177
rlm@532 178 (defn final-cut! [^File render-dir]
rlm@532 179 (let [movie (File. render-dir "final.ogg")
rlm@544 180 final-audio (File. render-dir "final.wav")
rlm@532 181 final (File. render-dir "final")]
rlm@532 182 (.delete movie)
rlm@547 183 (.delete final-audio)
rlm@532 184 (clojure.java.shell/sh
rlm@544 185 "sox" (.getCanonicalPath (File. render-dir "audio.wav"))
rlm@544 186 (.getCanonicalPath final-audio))
rlm@544 187 (clojure.java.shell/sh
rlm@549 188 "ffmpeg"
rlm@549 189 "-framerate" "60"
rlm@532 190 "-i" (str (.getCanonicalPath final) "/" "%07d.bmp")
rlm@544 191 "-i" (.getCanonicalPath final-audio)
rlm@532 192 "-b:a" "128k"
rlm@532 193 "-b:v" "9000k"
rlm@532 194 "-c:a" "libvorbis"
rlm@549 195 "-c:v" "libtheora"
rlm@549 196 "-r" "60"
rlm@532 197 (.getCanonicalPath movie)) nil))
rlm@549 198
rlm@531 199
rlm@532 200 (comment
rlm@531 201
rlm@532 202 ;; step 1
rlm@532 203
rlm@532 204 (render-files!
rlm@532 205 render-dir (root)
rlm@532 206 (take 9000 (first (control-checkpoint))))
rlm@531 207
rlm@532 208 ;; step 2
rlm@532 209
rlm@532 210 (generate-composite-frames!
rlm@532 211 render-dir
rlm@532 212 (take 9000 (first (control-checkpoint))))
rlm@532 213
rlm@532 214 ;; step 3
rlm@532 215 (final-cut! render-dir)
rlm@532 216 )