summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJake Zerrer <him@jakezerrer.com>2025-12-01 15:38:37 -0500
committerJake Zerrer <him@jakezerrer.com>2025-12-01 15:39:11 -0500
commit2d1418040bac7bec0ebac8b9c6d89ced3af7faeb (patch)
treee6da9a133b60659fabfc980667ab7115d16c3736 /src
parentf48bd390a2d25bab6f7202941c5eb3a4149ab5a3 (diff)
Add replicate function
Diffstat (limited to 'src')
-rw-r--r--src/unheard/cycles.clj34
1 files changed, 33 insertions, 1 deletions
diff --git a/src/unheard/cycles.clj b/src/unheard/cycles.clj
index acf1900..eb53c57 100644
--- a/src/unheard/cycles.clj
+++ b/src/unheard/cycles.clj
@@ -74,6 +74,21 @@
[weight node]
{:v node :weight weight :type :elongate})
+(defn rep
+ "Replication modifier: repeats an element N times, subdividing its time equally.
+
+ The element is repeated the specified number of times within the same
+ time duration it would normally occupy. Each repetition gets an equal
+ time slice.
+
+ Equivalent to TidalCycles/Strudel '!' operator.
+
+ Examples:
+ (l (rep 3 :a) :b) - :a repeats 3x in first half, :b in second half
+ (l :x (rep 2 :y) :z) - :y repeats 2x in middle third"
+ [times node]
+ {:v node :times times :type :rep})
+
(defn scalar? [x]
(not (and (map? x) (:type x))))
@@ -116,6 +131,11 @@
(= :elongate (:type node))
;; Elongation doesn't change the cycle count - it just affects time division
;; The parent sees the same cycle count as the child
+ (compute-cycle (:v node))
+
+ (= :rep (:type node))
+ ;; Replication doesn't change the cycle count - it just subdivides time
+ ;; The parent sees the same cycle count as the child
(compute-cycle (:v node))))
(defn unfold-node [node start end iteration]
@@ -167,7 +187,19 @@
(= :elongate (:type node))
;; Elongate just wraps a child - unfold the child with the same time bounds
- (unfold-node (:v node) start end iteration))))
+ (unfold-node (:v node) start end iteration)
+
+ (= :rep (:type node))
+ ;; Rep subdivides the time span into N equal parts and repeats the child
+ (let [times (:times node)
+ child (:v node)
+ slice-duration (/ duration times)]
+ (vec (mapcat (fn [i]
+ (unfold-node child
+ (+ start (* i slice-duration))
+ (+ start (* (inc i) slice-duration))
+ iteration))
+ (range times)))))))
(defn unfold
"Unfolds a pattern tree into concrete time intervals.