rlm@530: (ns com.aurellem.run.final-cut rlm@530: (:use (com.aurellem.gb saves gb-driver util constants rlm@530: items vbm characters money rlm@530: rlm-assembly)) rlm@530: (:use (com.aurellem.run util sound music title save-corruption rlm@530: bootstrap-0 bootstrap-1 rlm@530: ram-display rlm@530: )) rlm@530: (:require clojure.string) rlm@530: (:import [com.aurellem.gb.gb_driver SaveState]) rlm@530: (:import java.awt.image.BufferedImage) rlm@530: (:import java.io.File) rlm@530: (:import com.aurellem.gb.WaveWriter)) rlm@530: rlm@530: rlm@542: (def render-dir (File. user-home "proj/vba-clojure/render/test")) rlm@530: rlm@544: rlm@530: (defn render-files! rlm@599: ([^File target-dir rlm@599: moves-render-fn rlm@599: render-ram-map? rlm@599: initial-state rlm@599: moves rlm@599: rlm@599: ] rlm@530: (let [ram-map-dir (File. target-dir "ram-map") rlm@530: frames-dir (File. target-dir "frames") rlm@546: moves-dir (File. target-dir "moves") rlm@530: audio-file (File. target-dir "audio.wav") rlm@533: _ (.mkdir target-dir) rlm@533: _ (.mkdir ram-map-dir) rlm@533: _ (.mkdir frames-dir) rlm@546: _ (.mkdir moves-dir) rlm@530: wave-writer (WaveWriter. audio-file) rlm@544: moves (vec moves) rlm@544: desired-fps 60 rlm@547: seconds-per-frame (/ 1.0 desired-fps)] rlm@530: (set-state! initial-state) rlm@544: ;; clear sound buffer rlm@544: (sound-bytes) rlm@544: (try rlm@544: (dorun rlm@544: (reduce rlm@544: (fn [[total-audio-samples rlm@544: total-video-samples] move] rlm@544: (run-moves @current-state (vector move)) rlm@544: (let [sound (sound-bytes) rlm@544: total-audio-samples (+ total-audio-samples rlm@544: (count sound)) rlm@544: total-audio-time rlm@544: (* rlm@544: (/ total-audio-samples 4) rlm@544: (/ 44100)) rlm@544: rlm@544: total-video-time (* total-video-samples rlm@544: seconds-per-frame) rlm@530: rlm@544: av-diff (- total-audio-time rlm@544: total-video-time) rlm@544: write-video! rlm@544: (fn [index] rlm@544: ;; write screenshot rlm@599: (moves-render-fn rlm@546: move rlm@546: (File. moves-dir (format "%07d.png" index))) rlm@544: rlm@544: (write-png! rlm@544: @current-state rlm@544: (File. frames-dir (format "%07d.png" index))) rlm@544: rlm@544: ;; write ram-image rlm@599: (if render-ram-map? rlm@599: (write-ram-image! rlm@599: @current-state rlm@599: (File. ram-map-dir (format "%07d.png" index)))))] rlm@544: ;;(println "audio-samples:" (count sound)) rlm@544: rlm@544: ;; record audio rlm@544: (.process wave-writer sound gb-sound-format) rlm@544: rlm@544: ;; duplicate or drop frames depending on rlm@544: ;; desired-fps rlm@544: (if (> (Math/abs av-diff) (* 2 seconds-per-frame)) rlm@544: (if (< 0 av-diff) rlm@544: ;; audio has gone past video, duplicate video. rlm@544: (do (println rlm@544: "duplicating frame, av-diff is" av-diff) rlm@544: (write-video! (+ 1 total-video-samples)) rlm@544: (write-video! (+ 2 total-video-samples)) rlm@544: [total-audio-samples rlm@544: (+ 2 total-video-samples)]) rlm@544: ;; video has gone past audio, drop frame. rlm@544: (do (println rlm@544: "dropping frame, av-diff is" av-diff) rlm@544: [total-audio-samples rlm@544: total-video-samples])) rlm@544: ;; no frame dropping or duplication required. rlm@544: (do ;;(println "all normal") rlm@544: (write-video! (+ 1 total-video-samples)) rlm@544: [total-audio-samples rlm@544: (+ 1 total-video-samples)])))) rlm@544: [0 0 0] moves)) rlm@544: (finally rlm@544: (do rlm@544: (println "cleanup audio.") rlm@544: (.cleanup wave-writer)))))) rlm@544: ([initial-state moves] rlm@544: (render-files! render-dir initial-state moves)) rlm@544: ([moves] rlm@544: (render-files! (root) moves))) rlm@530: rlm@531: (defn file-names [#^File dir] rlm@531: (mapv #(.getCanonicalPath %) (next (sort (file-seq dir))))) rlm@531: rlm@531: rlm@532: rlm@549: ;; (defn final-cut! [^File render-dir] rlm@549: ;; (let [movie (File. render-dir "final.ogg") rlm@549: ;; final-audio (File. render-dir "final.wav") rlm@549: ;; final (File. render-dir "final")] rlm@549: ;; (.delete movie) rlm@549: ;; (.delete final-audio) rlm@549: ;; (clojure.java.shell/sh rlm@549: ;; "sox" (.getCanonicalPath (File. render-dir "audio.wav")) rlm@549: ;; (.getCanonicalPath final-audio)) rlm@549: ;; (clojure.java.shell/sh rlm@549: ;; "ffmpeg" "-r" "60" ;; maybe 59.7 ???! rlm@549: ;; "-i" (str (.getCanonicalPath final) "/" "%07d.bmp") rlm@549: ;; "-i" (.getCanonicalPath final-audio) rlm@549: ;; "-b:a" "128k" rlm@549: ;; "-b:v" "9000k" rlm@549: ;; "-c:a" "libvorbis" rlm@549: ;; "-f" "webm" rlm@549: ;; "-g" "200" rlm@549: ;; (.getCanonicalPath movie)) nil)) rlm@549: rlm@532: (defn final-cut! [^File render-dir] rlm@532: (let [movie (File. render-dir "final.ogg") rlm@544: final-audio (File. render-dir "final.wav") rlm@532: final (File. render-dir "final")] rlm@532: (.delete movie) rlm@547: (.delete final-audio) rlm@532: (clojure.java.shell/sh rlm@544: "sox" (.getCanonicalPath (File. render-dir "audio.wav")) rlm@544: (.getCanonicalPath final-audio)) rlm@544: (clojure.java.shell/sh rlm@549: "ffmpeg" rlm@549: "-framerate" "60" rlm@532: "-i" (str (.getCanonicalPath final) "/" "%07d.bmp") rlm@544: "-i" (.getCanonicalPath final-audio) rlm@532: "-b:a" "128k" rlm@532: "-b:v" "9000k" rlm@532: "-c:a" "libvorbis" rlm@549: "-c:v" "libtheora" rlm@549: "-r" "60" rlm@532: (.getCanonicalPath movie)) nil)) rlm@549: rlm@531: rlm@532: (comment rlm@531: rlm@532: ;; step 1 rlm@532: rlm@532: (render-files! rlm@532: render-dir (root) rlm@532: (take 9000 (first (control-checkpoint)))) rlm@531: rlm@532: ;; step 2 rlm@532: rlm@532: (generate-composite-frames! rlm@532: render-dir rlm@532: (take 9000 (first (control-checkpoint)))) rlm@532: rlm@532: ;; step 3 rlm@532: (final-cut! render-dir) rlm@532: )