comparison clojure/com/aurellem/run/music.clj @ 428:476f7da175a4

correctly handle silent spaces in midi files.
author Robert McIntyre <rlm@mit.edu>
date Mon, 23 Apr 2012 09:22:07 -0500
parents fbccf46cf34d
children a69c4d0c1a3b
comparison
equal deleted inserted replaced
427:fbccf46cf34d 428:476f7da175a4
331 331
332 ;; have: clock-pulses 332 ;; have: clock-pulses
333 ;; want: seconds 333 ;; want: seconds
334 334
335 335
336 336 (defn silence [length]
337 {:frequency 1
338 :duration length
339 :volume 0})
337 340
338 (defn midi->mini-midi [#^File midi-file] 341 (defn midi->mini-midi [#^File midi-file]
339 (let [midi-events (parse-midi midi-file) 342 (let [midi-events (parse-midi midi-file)
340 343
341 note-on-events 344 note-on-events
354 357
355 358
356 tempo (:args (first (filter #(= :Tempo (:command %)) midi-events))) 359 tempo (:args (first (filter #(= :Tempo (:command %)) midi-events)))
357 division (:division 360 division (:division
358 (:args (first (filter #(= :Header (:command %)) midi-events)))) 361 (:args (first (filter #(= :Header (:command %)) midi-events))))
362
363 notes
364 (map
365 (fn [note-on note-off]
366 {:frequency (midi-code->frequency (:note (:args note-on)))
367 :duration
368 (/ (* (/ tempo division)
369 (- (:time note-off) (:time note-on)))
370 1e6) ;; convert clock-pulses into seconds
371 :volume (int (/ (:velocity (:args note-on)) 10))
372 :time-stamp (/ (* (/ tempo division)
373 (:time note-on)) 1e6)})
374 channel-1-on channel-1-off)
375
376 silences
377 (map (fn [note-1 note-2]
378 (let [note-1-space (- (:time-stamp note-2)
379 (:time-stamp note-1))
380 note-1-length (:duration note-1)]
381 (silence (- note-1-space note-1-length))))
382 ;; to handle silence at the beginning.
383 (concat [(assoc (silence 0)
384 :time-stamp 0)] notes)
385 notes)
386
387 notes-with-silence
388 (filter (comp not zero? :duration) (interleave silences notes))
359 ] 389 ]
360 390
361 (map 391 (map
362 (fn [note-event] 392 (fn [note-event]
363 (note-codes (:frequency note-event) 393 (note-codes (:frequency note-event)
364 (:volume note-event) 394 (:volume note-event)
365 (int (* (:duration note-event) 0x100)))) 395 (int (* (:duration note-event) 0x100))))
396 notes-with-silence)))
397
398
366 399
367 (map 400
368 (fn [note-on note-off] 401
369 {:frequency (midi-code->frequency (:note (:args note-on)))
370 :duration
371 (/ (* (/ tempo division)
372 (- (:time note-off) (:time note-on)))
373 1e6) ;; convert clock-pulses into seconds
374 :volume (int (/ (:velocity (:args note-on)) 10))
375 :time-stamp (/ (* (/ tempo division)
376 (:time note-on)) 1e6)})
377 channel-1-on channel-1-off))))
378 402
379 403
380 404
381 405
382 406