summaryrefslogtreecommitdiff
path: root/src/unheard
diff options
context:
space:
mode:
Diffstat (limited to 'src/unheard')
-rw-r--r--src/unheard/clock.clj51
1 files changed, 48 insertions, 3 deletions
diff --git a/src/unheard/clock.clj b/src/unheard/clock.clj
index 42e7930..89f18c7 100644
--- a/src/unheard/clock.clj
+++ b/src/unheard/clock.clj
@@ -24,7 +24,8 @@
;; TODO: Make part of public API
(defonce mono-clock-freq (atom 120)) ;; hz
(defonce >mono-clock-freq
- (m/watch mono-clock-freq))
+ (m/signal
+ (m/watch mono-clock-freq)))
(def >mono-clock
"This is the base monotonic clock used for driving playback.
@@ -55,15 +56,17 @@
(cancel))
(defonce bpm (atom 120))
-(defonce >bpm (m/watch bpm))
+(defonce >bpm
+ (m/signal
+ (m/watch bpm)))
(def >beat-clock
+ "Counts beats at `bpm`. Guaranteed not to lose or gain time."
(m/signal
(m/relieve
(let [init-beat 1]
(m/reductions {} init-beat
(m/ap
- ;; Doesn't need to be atom
(let [state (object-array 2)
_ (aset state 0 (System/nanoTime))
_ (aset state 1 init-beat)
@@ -95,3 +98,45 @@
(let [clock (atom 0)
>clock (m/signal (m/watch clock))]
[>clock clock]))
+
+(defonce numerator (atom 4))
+(defonce >numerator
+ (m/signal
+ (m/watch numerator)))
+
+(def >measure-clock
+ "Emits measure count. Increases at the end of the current measure.
+ Follows changes to numerator."
+ (m/signal
+ (m/relieve
+ (let [init-measure 1]
+ (m/reductions {} init-measure
+ (m/ap
+ (let [state (object-array 2)
+ last-measure-idx 0
+ last-downbeat-idx 1
+ _ (aset state last-measure-idx init-measure)
+ _ (aset state last-downbeat-idx init-measure)
+ [beat numerator] (m/?< (m/latest vector >beat-clock >numerator))
+ last-measure (aget state last-measure-idx)
+ last-downbeat (aget state last-downbeat-idx)
+ next-downbeat (+ last-downbeat numerator)]
+ (if (<= next-downbeat beat)
+ (do (aset state last-measure-idx (inc last-measure))
+ (aset state last-downbeat-idx next-downbeat)
+ (inc last-measure))
+ (m/amb)))))))))
+
+(comment
+ (def cancel
+ ((m/reduce prn nil (m/latest vector >beat-clock >measure-clock)) prn prn))
+
+ (reset! mono-clock-freq 120)
+ (reset! bpm 120)
+ (reset! bpm -120)
+ (reset! bpm 160)
+ (reset! numerator 2)
+ (reset! numerator 3)
+ (reset! numerator 4)
+
+ (cancel))