summaryrefslogtreecommitdiff
path: root/src/unheard/instrument/util.clj
blob: 0faa5b52f7fe713195d38a65943ca6864ddfca70 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
(ns unheard.instrument.util
  (: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]
    ;; TODO: Should be signal
    (m/stream
     (m/reductions {} init
                   (m/eduction
                    (comp
                     matching-control-change
                     (matching-channel ch)
                     (matching-data-1 k)
                     get-data-2
                     ;; TODO git-bug f109911
                     (dedupe))
                    f)))))