Created
April 6, 2014 12:34
-
-
Save kurogelee/10005408 to your computer and use it in GitHub Desktop.
ポケット・ミクを操作する関数を作ってみる ref: http://qiita.com/kurogelee/items/c5443167b355cd021407
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns pokemiku.core | |
(:import [javax.sound.midi MidiSystem ShortMessage SysexMessage MidiDevice Receiver] | |
[javax.xml.bind DatatypeConverter])) | |
(defn ^MidiDevice get-device [] | |
(some->> (seq (MidiSystem/getMidiDeviceInfo)) | |
(filter #(re-find #"NSX-39" (:name (bean %)))) | |
(filter #(re-find #"External" (:description (bean %)))) | |
first | |
(MidiSystem/getMidiDevice))) | |
(defn note [^Receiver r data1 data2] | |
(.send r (ShortMessage. ShortMessage/NOTE_ON data1 data2) -1)) | |
(defn note-off [^Receiver r data1 data2] | |
(.send r (ShortMessage. ShortMessage/NOTE_OFF data1 data2) -1)) | |
(defn vibrato | |
([^Receiver r] (vibrato r 127)) | |
([^Receiver r vol] (.send r (ShortMessage. ShortMessage/CONTROL_CHANGE 1 vol) -1))) | |
(defn vibrato-off [^Receiver r] (vibrato r 0)) | |
(defn pitch-bend [^Receiver r n] | |
(when (<= -64 n 63) | |
(.send r (ShortMessage. ShortMessage/PITCH_BEND 1 (+ 64 n)) -1))) | |
(defn pitch-bend-off [^Receiver r] (pitch-bend r 0)) | |
(defn- small-char? [x] (re-find #"[ぁぃぅぇぉゃゅょ]" (str x))) | |
(def ^:private base-chars "あいうえおかきくけこがぎぐげごきゃきゅきょぎゃぎゅぎょさすぃすせそざずぃずぜぞしゃししゅしぇしょじゃじじゅじぇじょたてぃとぅてとだでぃどぅでどてゅでゅちゃちちゅちぇちょつぁつぃつつぇつぉなにぬねのにゃにゅにょはひふへほばびぶべぼぱぴぷぺぽひゃひゅひょびゃびゅびょぴゃぴゅぴょふぁふぃふゅふぇふぉまみむめもみゃみゅみょやゆよらりるれろりゃりゅりょわうぃうぇうぉんmNJn") | |
(defn split-chars [s] | |
(let [s (str (apply str s) " ")] | |
(->> (map #(cond (small-char? %2) (str %1 %2) (not (small-char? %1)) (str %1)) s (drop 1 s)) | |
(filter some?)))) | |
(def ^:private char-map | |
(->> (zipmap (split-chars base-chars) (range)) | |
(merge {"づぁ" 26 "づぃ" 27 "づ" 28 "づぇ" 29 "づぉ" 30 "ゐ" 120 "ゑ" 121 "を" 122 "N\\" 123 "ぢ" 37 "ヴ" 78}))) | |
(def ^:private bin-map | |
(->> (mapcat (fn [[k v]] [(keyword k) (DatatypeConverter/parseHexBinary (format "F0437909110A00%02XF7" v))]) char-map) | |
(apply hash-map))) | |
(defn set-char [^Receiver r ch] | |
(when-let [data (bin-map (if (char? ch) (keyword (str ch)) (keyword ch)))] | |
(.send r (SysexMessage. data (count data)) -1))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns pokemiku.util | |
(:require [pokemiku.core :refer :all]) | |
(:import [java.util.concurrent Executors ScheduledExecutorService ScheduledFuture TimeUnit] | |
[javax.sound.midi ShortMessage])) | |
(def base-octave [60 62 64 65 67 69 71]) | |
(defn play [tempo & notes] | |
(let [n (partition 4 notes) | |
base 120 | |
tempo (atom tempo) | |
n (atom n) | |
sum (atom 0) | |
pool (Executors/newScheduledThreadPool 1) | |
f #(if (nil? @n) (.shutdown pool) | |
;; char pitch length volume | |
(let [[c p l v] (first @n)] | |
(if (zero? @sum) | |
(condp = c | |
:V (vibrato % v) | |
:B (pitch-bend % v) | |
:T (reset! tempo v) | |
:R (note-off % p v) | |
(do (set-char % c) (note % p v))) | |
(when (< @sum 2) (set-char % (first (second @n))))) ; set-charを即座に反映するため | |
(swap! sum inc) | |
(when (<= (* base l (/ 60 @tempo)) @sum) | |
(vibrato-off %) (pitch-bend-off %) (reset! sum 0) (swap! n next))))] | |
(with-open [dev (get-device)] | |
(.open dev) | |
(let [r (.getReceiver dev) rate (Math/round (double (/ 1000000 base)))] | |
(doto pool | |
(.scheduleAtFixedRate #(f r) 0 rate TimeUnit/MICROSECONDS) | |
(.awaitTermination 1 TimeUnit/DAYS)))))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(play 60 :ど 72 1 127 :V 1 1 127 :R 72 1/2 0 :れ 74 1/2 127 :B 1 1/5 2 :み 76 1 127 :T 0 0 120 :ど 72 1 127 :V 1 1 127 :れ 74 1/2 127 :B 1 1/5 2 :み 76 1 127) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(apply play 150 (interleave | |
(split-chars (repeat 3 "どれみふぁそらし")) | |
(concat (map #(- % 12) base-octave) base-octave (map #(+ 12 %) base-octave)) | |
(repeat 1) (repeat 127))) | |
(play 150 :ど 84 1/5 127 :V 1 2 127) | |
(apply play 120 | |
(interleave (cycle "みく") | |
(let [c [76 77 74 72]] (concat c (map inc c) (reverse c) (map inc (reverse c) ))) | |
(cycle [1/2 1/3 1 2/3]) (repeat 127))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment