From 2a4fce4fef775f6661a625303de9b28b446f1877 Mon Sep 17 00:00:00 2001 From: Jake Zerrer Date: Wed, 5 Nov 2025 15:32:14 -0500 Subject: Create keyboard function --- src/midi.clj | 58 +++++++++++++++++++++++++++++++++++++++------------------ src/scratch.clj | 31 +++--------------------------- 2 files changed, 43 insertions(+), 46 deletions(-) (limited to 'src') 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))))) diff --git a/src/scratch.clj b/src/scratch.clj index 63d54a3..80baa83 100644 --- a/src/scratch.clj +++ b/src/scratch.clj @@ -1,41 +1,16 @@ (ns scratch (:require [midi :refer [print-all-midi-devices >bus 128 (midi/|channels (midi/|short-messages (m/stream f)))) - ch-messages (m/stream ch-messages)] - (println - (m/amb= - (let [[note note-messages] (m/?> 128 (midi/|notes ch-messages))] - [:key ch note - (m/?< - (m/relieve - (m/reductions - (fn [_prev curr] - (when (some? curr) - (cond - (= (.getCommand ^ShortMessage curr) ShortMessage/NOTE_ON) - (.getData2 ^ShortMessage curr) - (= (.getCommand ^ShortMessage curr) ShortMessage/POLY_PRESSURE) - (.getData2 ^ShortMessage curr) - (= (.getCommand ^ShortMessage curr) ShortMessage/NOTE_OFF) - nil))) nil note-messages)))]) - (let [[control-number control-messages] (m/?> 128 (midi/|control-changes ch-messages))] - [:control ch control-number (.getData2 ^ShortMessage (m/?< control-messages))])))))))) + (midi/