aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-05-21 13:48:20 +0000
committers-ol <s+removethis@s-ol.nu>2025-03-02 14:24:49 +0000
commitc54b33d9c6b06316d9cd5547622720b4306f42ec (patch)
treeb390e164972da42aadd6988de8924b99b4666f49
parentalv-fltk: clear log option, autoclear option (diff)
downloadalive-c54b33d9c6b06316d9cd5547622720b4306f42ec.tar.gz
alive-c54b33d9c6b06316d9cd5547622720b4306f42ec.zip
add lib/rhythm
-rw-r--r--alv-lib/rhythm.moon80
1 files changed, 80 insertions, 0 deletions
diff --git a/alv-lib/rhythm.moon b/alv-lib/rhythm.moon
new file mode 100644
index 0000000..35d57ae
--- /dev/null
+++ b/alv-lib/rhythm.moon
@@ -0,0 +1,80 @@
+import Constant, Op, Input, T, val, evt from require 'alv.base'
+
+-- slower reference implementation
+bjorklund = (n, k) ->
+ full = ['1' for i=1,k]
+ rest = ['0' for i=k,n-1]
+ while #rest > 1
+ next_full = {}
+ while full[1] and rest[1]
+ a = table.remove full
+ b = table.remove rest
+ table.insert next_full, a .. b
+ while rest[1]
+ table.insert full, table.remove rest
+ full, rest = next_full, full
+
+ if rest[1]
+ table.insert full, rest[1]
+ table.concat full, ''
+
+-- faster implementation
+bjorklund2 = (n, k) ->
+ a, as = '1', k
+ b, bs = '0', n - k
+
+ while true
+ if bs == 1 or bs == 0
+ break
+ elseif as < bs
+ a, b = a .. b, b
+ as, bs = as, bs - as
+ else
+ a, b = a .. b, a
+ as, bs = bs, as - bs
+
+ (string.rep a, as) .. (string.rep b, bs)
+
+euclid = Constant.meta
+ meta:
+ name: 'euclid'
+ summary: "Generate euclidean rhythms."
+ examples: { '(euclid i n k)', '(euclid trigger! n k)' }
+ description: "Generates bangs according to the Euclidean algorithm.
+
+When fed a bang! trigger, steps forward to the next step on each trigger.
+When fed a num~ or num! stream, outputs a bang if the corresponding step is on."
+
+ value: class extends Op
+ pattern = (evt.bang / val.num / evt.num) + val.num + val.num
+ setup: (inputs) =>
+ { trig, n, k } = pattern\match inputs
+
+ @out or= T.bang\mk_evt!
+
+ super
+ trig: Input.hot trig
+ n: Input.cold n
+ k: Input.cold k
+
+ if @inputs.trig\type! == T.bang
+ @state or= 1
+ else
+ @state = nil
+
+ tick: =>
+ { :trig, :n, :k } = @unwrap_all!
+
+ if @inputs.trig\type! == T.bang
+ @state += 1
+ if @state > n
+ @state -= n
+
+ i = 1 + (@state or trig % n)
+ pat = bjorklund2 n, k
+ if '1' == pat\sub i, i
+ @out\set true
+
+{
+ :euclid
+}