Mercurial > vba-clojure
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 |