diff options
| author | Jake Zerrer <him@jakezerrer.com> | 2025-11-05 15:32:14 -0500 |
|---|---|---|
| committer | Jake Zerrer <him@jakezerrer.com> | 2025-11-05 15:32:55 -0500 |
| commit | 2a4fce4fef775f6661a625303de9b28b446f1877 (patch) | |
| tree | e470e267956b55f3b8260be55d3b74dd0acc0e34 /src/midi.clj | |
| parent | 17ec1243e674e5a211eeb86d7491c63b951e4fd7 (diff) | |
Create keyboard function
Diffstat (limited to 'src/midi.clj')
| -rw-r--r-- | src/midi.clj | 58 |
1 files changed, 40 insertions, 18 deletions
diff --git a/src/midi.clj b/src/midi.clj index e63f811..330402b 100644 --- a/src/midi.clj +++ b/src/midi.clj @@ -233,32 +233,54 @@ [>messages] (m/group-by #(.getChannel ^ShortMessage %) >messages)) +(defn |group-by-data-1 + [>messages] + (m/group-by #(.getData1 ^ShortMessage %) + >messages)) + +(defn |matching-commands + [>messages commands] + (m/eduction (filter (fn [^ShortMessage v] + (contains? commands (.getCommand v)))) >messages)) + (def note-commands #{ShortMessage/NOTE_OFF ShortMessage/NOTE_ON ShortMessage/POLY_PRESSURE}) -(defn |notes - [>messages] - (m/group-by #(.getData1 ^ShortMessage %) - (m/ap - (let [^ShortMessage v (m/?> >messages)] - (if (contains? note-commands (.getCommand v)) - v - (m/amb)))))) - (def control-commands #{ShortMessage/CONTROL_CHANGE}) -;; TODO: |control-changes and |notes combine grouping and filtering, which isn't great -(defn |control-changes - [>messages] - (m/group-by #(.getData1 ^ShortMessage %) - (m/ap - (let [^ShortMessage v (m/?> >messages)] - (if (contains? control-commands (.getCommand v)) - v - (m/amb)))))) +(defn keyboard + [f] + (m/ap + (let [[ch ch-messages] + (m/?> 128 (midi/|channels (midi/|short-messages (m/stream f)))) + ch-messages (m/stream ch-messages)] + (m/amb= + (let [[note note-messages] + (m/?> 128 (-> ch-messages + (midi/|matching-commands note-commands) + (midi/|group-by-data-1)))] + [:key ch note + (m/?< + (m/relieve + (m/reductions + (fn [_prev curr] + (when (some? curr) + (let [cmd (.getCommand ^ShortMessage curr)] + (cond + (= cmd ShortMessage/NOTE_ON) + (.getData2 ^ShortMessage curr) + (= cmd ShortMessage/POLY_PRESSURE) + (.getData2 ^ShortMessage curr) + (= cmd ShortMessage/NOTE_OFF) + nil)))) nil note-messages)))]) + (let [[control-number control-messages] + (m/?> 128 (-> ch-messages + (midi/|matching-commands control-commands) + (midi/|group-by-data-1)))] + [:control ch control-number (.getData2 ^ShortMessage (m/?< control-messages))]))))) #_(defn >ch-stream [>device ch] (m/cp (m/?< (second (get >device ch))))) |
