(ns unheard.instrument.minilab3 (:require [missionary.core :as m]) (:import [javax.sound.midi ShortMessage])) (def matching-control-change (filter (fn [^ShortMessage m] (= (.getCommand m) ShortMessage/CONTROL_CHANGE)))) (defn matching-channel [ch] (filter (fn [^ShortMessage m] (= (.getChannel m) ch)))) (defn matching-data-1 [d1] (filter (fn [^ShortMessage m] (= (.getData1 m) d1)))) (def get-data-2 (map (fn [^ShortMessage m] (.getData2 m)))) (defn matching-control "Returns a function filtering flow of ShortMessage `f` down to control change messages where channel is `ch` and data-1 is `k`, and then returning a signal of values for data-2. Initial value of signal will be `init`. Though a little esoteric sounding, this is actually quite useful. The signal returned by this is useful for representing knobs, faders, and pads on a midi controller. " [init ch k] (fn [f] (m/signal (m/reductions {} init (m/eduction (comp matching-control-change (matching-channel ch) (matching-data-1 k) get-data-2) f))))) (def minilab3 {:knob {1 (matching-control 0 0 74) 2 (matching-control 0 0 71) 3 (matching-control 0 0 76) 4 (matching-control 0 0 77) 5 (matching-control 0 0 93) 6 (matching-control 0 0 18) 7 (matching-control 0 0 19) 8 (matching-control 0 0 16)} :fader {1 (matching-control 0 0 82) 2 (matching-control 0 0 83) 3 (matching-control 0 0 85) 4 (matching-control 0 0 17)} :pad {1 (matching-control 0 9 36) 2 (matching-control 0 9 37) 3 (matching-control 0 9 38) 4 (matching-control 0 9 39) 5 (matching-control 0 9 40) 6 (matching-control 0 9 41) 7 (matching-control 0 9 42) 8 (matching-control 0 9 43)}})