changeset 467:ac0ed5c1a1c4

working on drums.
author Robert McIntyre <rlm@mit.edu>
date Fri, 04 May 2012 05:17:18 -0500
parents b31cd6651375
children 85d9fa354f0b
files clojure/com/aurellem/run/music.clj music/Friendship is Magic (MLP Theme Song).rg music/drum-test.mid music/drum-test.rg music/pony-title.mid
diffstat 5 files changed, 82 insertions(+), 21 deletions(-) [+]
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))
     2.1 Binary file music/Friendship is Magic (MLP Theme Song).rg has changed
     3.1 Binary file music/drum-test.mid has changed
     4.1 Binary file music/drum-test.rg has changed
     5.1 Binary file music/pony-title.mid has changed