Mercurial > vba-clojure
diff clojure/com/aurellem/run/music.clj @ 467:ac0ed5c1a1c4
working on drums.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 04 May 2012 05:17:18 -0500 |
parents | b31cd6651375 |
children | 85d9fa354f0b |
line wrap: on
line diff
1.1 --- a/clojure/com/aurellem/run/music.clj Fri May 04 04:13:13 2012 -0500 1.2 +++ b/clojure/com/aurellem/run/music.clj Fri May 04 05:17:18 2012 -0500 1.3 @@ -216,12 +216,17 @@ 1.4 (concat switch play-note))))) 1.5 1.6 (defn play-noise 1.7 - "read [noise-code, duration] and play the noise. Duration is left in 1.8 + "read [noise-code, volume, duration] and play the noise. Duration is left in 1.9 A, and HL is advanced appropraitely." 1.10 ([] 1.11 [0x2A ;; load noise-code into A 1.12 0xE0 1.13 0x22 ;; write noise-code 1.14 + 1.15 + 0x2A ;; load volume 1.16 + 0xE0 1.17 + 0x21 ;; write volume 1.18 + 1.19 0x2A] ;; load duration into A 1.20 )) 1.21 1.22 @@ -453,8 +458,9 @@ 1.23 channel-nums (map (comp :channel track-order) (range 3))] 1.24 channel-nums)) 1.25 1.26 -(defn midi-track->mini-midi [#^File midi-file track-num] 1.27 - (let [midi-events (parse-midi midi-file) 1.28 +(defn midi-track->abstract-mini-midi 1.29 + [#^File midi-file track-num] 1.30 + (let [midi-events (parse-midi midi-file) 1.31 1.32 note-on-events (commands :Note_on_c midi-events) 1.33 note-off-events (commands :Note_off_c midi-events) 1.34 @@ -476,6 +482,7 @@ 1.35 (map 1.36 (fn [note-on note-off] 1.37 {:frequency (midi-code->frequency (:note (:args note-on))) 1.38 + :midi-code (:note (:args note-on)) 1.39 :duration 1.40 (/ (* (/ tempo division) 1.41 (- (:time note-off) (:time note-on))) 1.42 @@ -501,35 +508,60 @@ 1.43 (filter (comp not zero? :duration) 1.44 (interleave silences notes)) 1.45 [(silence 3)])] 1.46 - 1.47 + notes-with-silence)) 1.48 + 1.49 +(defn midi-track->mini-midi-voice [#^File midi-file track-num] 1.50 + (let [abstract-mini-midi 1.51 + (midi-track->abstract-mini-midi midi-file track-num)] 1.52 (map 1.53 (fn [note-event] 1.54 (note-codes (:frequency note-event) 1.55 (:volume note-event) 1.56 (int (* (:duration note-event) 0x100)))) 1.57 - notes-with-silence))) 1.58 - 1.59 + abstract-mini-midi))) 1.60 + 1.61 +(defn noise-codes [code volume duration] 1.62 + (assert (<= 0 volume 0xF)) 1.63 + (if (<= duration 0xFF) 1.64 + [(if (nil? code) 0xFF code) 1.65 + (bit-shift-left volume 4) 1.66 + duration] 1.67 + (vec 1.68 + (flatten 1.69 + [(noise-codes code volume 0xFF) 1.70 + (noise-codes code volume (- duration 0xFF))])))) 1.71 + 1.72 +(defn midi-track->mini-midi-noise [#^File midi-file track-num] 1.73 + (let [abstract-mini-midi 1.74 + (midi-track->abstract-mini-midi midi-file track-num)] 1.75 + (map 1.76 + (fn [noise-event] 1.77 + (noise-codes (:midi-code noise-event) 1.78 + (:volume noise-event) 1.79 + (int (* (:duration noise-event) 0x100)))) 1.80 + abstract-mini-midi))) 1.81 + 1.82 + 1.83 (defn midi->mini-midi [#^File midi-file] 1.84 (let [targets (target-tracks midi-file) 1.85 - get-track (fn [n] 1.86 - (if (not (nil? n)) 1.87 - (midi-track->mini-midi midi-file n) 1.88 - [])) 1.89 duty-info (keys (track-info midi-file))] 1.90 1.91 - {:voice-1 (get-track (nth targets 0)) 1.92 - :voice-2 (get-track (nth targets 1)) 1.93 - :noise (get-track (nth targets 2)) 1.94 + {:voice-1 (midi-track->mini-midi-voice midi-file (nth targets 0)) 1.95 + :voice-2 (midi-track->mini-midi-voice midi-file (nth targets 1)) 1.96 + :noise (midi-track->mini-midi-noise midi-file (nth targets 2)) 1.97 :duty (zipmap (map :out duty-info) 1.98 (map #(get % :duty 0) duty-info))})) 1.99 1.100 (defn play-midi [#^File midi-file] 1.101 - (let [track-1-target 0xA000 1.102 - track-2-target 0xB000 1.103 + (let [voice-1-target 0xA000 1.104 + voice-2-target 0xB000 1.105 + noise-target 0xA900 1.106 program-target 0xC000 1.107 mini-midi (midi->mini-midi midi-file) 1.108 - long-silence (flatten (note-codes 20 0 9001)) 1.109 - 1.110 + long-silence (flatten (note-codes 20 0 20001)) 1.111 + long-noise-silence 1.112 + (interleave (range 500) (repeat 0x00) (repeat 255)) 1.113 + 1.114 voice-1 (flatten (:voice-1 mini-midi)) 1.115 wave-duty-1 ((:duty mini-midi) 0 0) 1.116 1.117 @@ -540,15 +572,44 @@ 1.118 ] 1.119 1.120 (-> (second (music-base)) 1.121 - (set-memory-range track-1-target long-silence) 1.122 - (set-memory-range track-2-target long-silence) 1.123 - (set-memory-range track-1-target voice-1) 1.124 - (set-memory-range track-2-target voice-2) 1.125 + (set-memory-range voice-1-target long-silence) 1.126 + (set-memory-range voice-2-target long-silence) 1.127 + (set-memory-range noise-target long-noise-silence) 1.128 + (set-memory-range voice-1-target voice-1) 1.129 + (set-memory-range voice-2-target voice-2) 1.130 + (set-memory-range noise-target noise) 1.131 (set-memory-range 1.132 program-target 1.133 (music-kernel wave-duty-1 wave-duty-2)) 1.134 (PC! program-target)))) 1.135 1.136 + 1.137 +(defn test-noise [] 1.138 + (let [noise-pattern 1.139 + (concat (interleave (range 0x100) (repeat 0xF0) (repeat 255)) 1.140 + (interleave (range 10) (repeat 0x00) (repeat 255)))] 1.141 + 1.142 + (-> (second (music-base)) 1.143 + (set-memory-range 0xA900 (flatten noise-pattern)) 1.144 + (set-memory-range 0xC000 (music-kernel 0 0)) 1.145 + (PC! 0xC000)))) 1.146 + 1.147 +(defn test-play-noise [noise-code] 1.148 + (println "playing-noise" noise-code) 1.149 + (run-moves 1.150 + (let [noise-pattern 1.151 + (interleave (repeat 10 noise-code) (repeat 0xF0) (repeat 255))] 1.152 + (-> (second (music-base)) 1.153 + (set-memory-range 0xA900 (flatten noise-pattern)) 1.154 + (set-memory-range 0xC000 (music-kernel 0 0)) 1.155 + (PC! 0xC000))) 1.156 + (repeat 128 []))) 1.157 + 1.158 +(defn test-all-noises [] 1.159 + (dorun (map test-play-noise (range 0x100)))) 1.160 + 1.161 + 1.162 + 1.163 (def C4 (partial note-codes 261.63)) 1.164 (def D4 (partial note-codes 293.66)) 1.165 (def E4 (partial note-codes 329.63))