diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-02-23 22:16:25 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-02-28 12:22:25 +0000 |
| commit | 0b284ac60916142cadb8b65fa5ca9f9cffcfc200 (patch) | |
| tree | 07fc75330d813d54751f42a2f55b979398929814 | |
| parent | merge Const and Stream into Value; Dataflow logic (diff) | |
| download | alive-0b284ac60916142cadb8b65fa5ca9f9cffcfc200.tar.gz alive-0b284ac60916142cadb8b65fa5ca9f9cffcfc200.zip | |
lots of fixes
| -rw-r--r-- | core/base.moon | 4 | ||||
| -rw-r--r-- | core/builtin.moon | 4 | ||||
| -rw-r--r-- | core/invoke.moon | 4 | ||||
| -rw-r--r-- | core/parsing.moon | 2 | ||||
| -rw-r--r-- | core/value.moon | 1 | ||||
| -rw-r--r-- | lib/math.moon | 44 | ||||
| -rw-r--r-- | lib/midi/init.moon | 4 | ||||
| -rw-r--r-- | lib/midi/launchctl.moon | 101 | ||||
| -rw-r--r-- | lib/osc.moon | 7 | ||||
| -rw-r--r-- | lib/sc.moon | 37 | ||||
| -rw-r--r-- | lib/time.moon | 16 | ||||
| -rw-r--r-- | lib/util.moon | 12 |
12 files changed, 141 insertions, 95 deletions
diff --git a/core/base.moon b/core/base.moon index 60ee460..422e631 100644 --- a/core/base.moon +++ b/core/base.moon @@ -34,6 +34,10 @@ class Op assert_types: (...) => num = select '#', ... assert #@inputs >= num, "argument count mismatch" + @assert_first_types ... + + assert_first_types: (...) => + num = select '#', ... for i = 1, num expect = select i, ... assert @inputs[i].type == expect, "expected argument #{i} of #{@} to be of type #{expect} but found #{@inputs[i]}" diff --git a/core/builtin.moon b/core/builtin.moon index 6abcbd9..5dd296a 100644 --- a/core/builtin.moon +++ b/core/builtin.moon @@ -12,9 +12,9 @@ prints the docstring for sym in the console" eval: (scope, tail) => assert #tail == 1, "'doc' takes exactly one parameter" - def = L\push tail[1]\eval, scope + result = L\push tail[1]\eval, scope with Result children: { def } - def = def.value\const!\unwrap! + def = result\const!\unwrap! L\print "(doc #{tail[1]\stringify!}):\n#{def.doc}\n" class def extends Action diff --git a/core/invoke.moon b/core/invoke.moon index a3932f8..da82d00 100644 --- a/core/invoke.moon +++ b/core/invoke.moon @@ -10,13 +10,15 @@ class op_invoke extends Action def = head\unwrap 'opdef', "cant op-invoke #{@head}" @head, @op = head, def! + @first = true true eval: (scope, tail) => children = L\push -> [L\push expr\eval, scope for expr in *tail] @op\setup [child.value for child in *children] - @op\tick true + @op\tick @first + @first = nil Result :children, value: @op.out, op: @op diff --git a/core/parsing.moon b/core/parsing.moon index 03ef85c..0123469 100644 --- a/core/parsing.moon +++ b/core/parsing.moon @@ -24,7 +24,7 @@ str = strd + strq int = digit^1 float = (digit^1 * '.' * digit^0) + (digit^0 * '.' * digit^1) -num = (float + int) / Value\parse 'num' +num = ((P '-')^-1 * (float + int)) / Value\parse 'num' atom = num + sym + str diff --git a/core/value.moon b/core/value.moon index 986c846..6fbda65 100644 --- a/core/value.moon +++ b/core/value.moon @@ -98,6 +98,7 @@ class Value -- @value - Lua value - access through :unwrap() new: (@type, @value, @raw) => @updated = 0 + pcall @\set, @value dirty: => @updated == Registry.active!.tick diff --git a/lib/math.moon b/lib/math.moon index 68dae3a..ca965be 100644 --- a/lib/math.moon +++ b/lib/math.moon @@ -1,23 +1,21 @@ -import Stream, Op, Const from require 'core' +import Op, Value from require 'core' unpack or= table.unpack class BinOp extends Op - new: (...) => - super ... - @out = Stream 'num', 0 + new: => + super 'num', 0 - setup: (...) => - @children = { ... } - assert #@children >= 2, "#{@} needs at least two parameters" - @out + setup: (params) => + super params + assert #@inputs >= 2, "#{@} needs at least two parameters" class add extends BinOp @doc: "(+ a b [c]...) (add a b [c]...) - add values" - update: (dt) => + tick: => value = 0 - for child in *@children + for child in *@inputs value += child\unwrap 'num' @out\set value @@ -27,9 +25,9 @@ class sub extends BinOp subtracts all other arguments from a" - update: (dt) => - value = @children[1]\unwrap 'num' - for child in *@children[2,] + tick: => + value = @inputs[1]\unwrap 'num' + for child in *@inputs[2,] value -= child\unwrap 'num' @out\set value @@ -37,9 +35,9 @@ class mul extends BinOp @doc: "(* a b [c]...) (mul a b [c]...) - multiply values" - update: (dt) => + tick: => value = 1 - for child in *@children + for child in *@inputs value *= child\unwrap 'num' @out\set value @@ -49,9 +47,9 @@ class div extends BinOp divides a by all other arguments" - update: (dt) => - value = @children[1]\unwrap 'num' - for child in *@children[2,] + tick: => + value = @inputs[1]\unwrap 'num' + for child in *@inputs[2,] value /= child\unwrap 'num' @out\set value @@ -61,7 +59,7 @@ evenodd_op = (name, remainder) -> @out = Stream 'bool' @out - update: (dt) => + tick: => a, divi = (@a\unwrap 'num'), @div\unwrap 'num' @out\set (a % divi) == remainder @@ -73,15 +71,15 @@ div defaults to 2" func_op = (name, arity, func) -> k = class extends Op + new: => + super 'num' + setup: (...) => @params = { ... } if arity != '*' assert #@params == arity, "#{@} needs exactly #{arity} parameters" - @out = Stream 'num' - @out - - update: (dt) => + tick: => @out\set func unpack [p\unwrap 'num' for p in *@params] k.__name = name diff --git a/lib/midi/init.moon b/lib/midi/init.moon index 03f5115..b0f2f6a 100644 --- a/lib/midi/init.moon +++ b/lib/midi/init.moon @@ -44,7 +44,9 @@ range can be one of: super params @inputs[3] or= Value.num -1 @inputs[4] or= Value.str 'uni' - @assert_types 'midi/port', 'num', 'num', 'str' + assert #@inputs == 4 + assert @inputs[4].type == 'num' or @inputs[4].type == 'str' + @assert_types 'midi/port', 'num', 'num' @impulses = { @inputs[1]\unwrap! } if not @out\unwrap! diff --git a/lib/midi/launchctl.moon b/lib/midi/launchctl.moon index c0d5e24..aab20bd 100644 --- a/lib/midi/launchctl.moon +++ b/lib/midi/launchctl.moon @@ -27,28 +27,36 @@ range can be one of: @inputs[5] or= Value.num 8 @inputs[6] or= Value.str 'uni' - @assert_types 'midi/port', 'num', 'num', 'num', 'num', 'str' + assert #@inputs == 6 + assert @inputs[6].type == 'num' or @inputs[6].type == 'str' + @assert_first_types 'midi/port', 'num', 'num', 'num', 'num' @impulses = { @inputs[1]\unwrap! } if not @out\unwrap! @out\set apply_range @inputs[6], 0 - tick: => - port, i, start, chan, steps = unpack [i\unwrap! for i in *@inputs] + tick: (first) => port = @inputs[1]\unwrap! _, i, start, chan, steps = unpack @inputs + if first or @inputs[5]\dirty! + steps = @inputs[5]! + while steps > #@steps + table.insert @steps, 0 + while steps < #@steps + table.remove @steps + curr_i = i\unwrap! % #@steps changed = false for msg in port\receive! - if msg.status == 'control-change' and msg.chan == chan - i = msg.a - start - if i < #@steps - @steps[i+1] = msg.b - changed = i == curr_i + if msg.status == 'control-change' and msg.chan == chan! + rel_i = msg.a - start! + if rel_i >= 0 and rel_i < #@steps + @steps[rel_i+1] = msg.b + changed = rel_i == curr_i - if changed or i\dirty! or start\dirty! or chan\dirty! or steps\diry! + if changed or i\dirty! or start\dirty! or chan\dirty! or steps\dirty! @out\set apply_range @inputs[6], @steps[curr_i+1] class gate_seq extends Op @@ -57,46 +65,17 @@ class gate_seq extends Op returns true or false for the i-th step steps (buttons starting from start). steps defaults to 8." - destroy: => - launch\detach @mask if @mask - new: => + super 'bool', false @steps = {} - @out = Stream 'bool' - - setup: (@i, start, chan, steps=(Const.num 8)) => - launch\detach @mask if @mask - - for i=1, #@steps - launch\send 'note-on', @chan, (@start+i), 0, color 0, 0 - - @start = start\const!\unwrap 'num' - @chan = chan\const!\unwrap 'num' - steps = steps\const!\unwrap 'num' - while steps > #@steps - table.insert @steps, false - while steps < #@steps - table.remove @steps - - for i=1, steps - @display i - - @mask = launch\attach { status: 'note-on', chan: @chan }, (_, _, note, _) -> - @toggle note - - @out - - toggle: (note) => - i = note - @start - val = @steps[i+1] - if val != nil - @steps[i+1] = not val - curr_i = (@i\unwrap 'num') % #@steps - @display i, i == curr_i + setup: (params) => + super params - display: (i, active) => - launch\send 'note-on', @chan, (@start + i), light @steps[i+1], active + @inputs[5] or= Value.num 8 + @inputs[6] or= Value.str 'uni' + @assert_types 'midi/port', 'num', 'num', 'num', 'num', 'str' + @impulses = { @inputs[1]\unwrap! } light = (set, active) -> set = if set then 'S' else ' ' @@ -106,17 +85,35 @@ steps defaults to 8." when ' A' then 1, 1 when 'S ' then 1, 0 when 'SA' then 3, 1 + display: (i, active) => + port, _, start, chan = @unwrap_inputs! + port\send 'note-on', chan, (start + i), light @steps[i+1], active + + tick: (first) => + port, curr_i, start, chan, steps = @unwrap_inputs! + + if first or @inputs[5]\dirty! + while steps > #@steps + table.insert @steps, false + while steps < #@steps + table.remove @steps - update: (dt) => - launch\tick! + curr_i = curr_i % #@steps + + for msg in port\receive! + if msg.status == 'note-on' and msg.chan == chan + rel_i = msg.a - start + if rel_i >= 0 and rel_i < #@steps + @steps[rel_i+1] = not @steps[rel_i+1] + @display rel_i, rel_i == curr_i - curr_i = (@i\unwrap 'num') % #@steps - prev_i = (curr_i - 1) % #@steps + if @inputs[2]\dirty! + prev_i = (curr_i - 1) % #@steps - @display curr_i, true - @display prev_i, false + @display curr_i, true + @display prev_i, false - @out\set @steps[curr_i+1] + @out\set @steps[curr_i+1] { 'gate-seq': gate_seq diff --git a/lib/osc.moon b/lib/osc.moon index 3bac3f1..bced72f 100644 --- a/lib/osc.moon +++ b/lib/osc.moon @@ -1,4 +1,4 @@ -import Stream, Op from require 'core' +import Op from require 'core' import pack, unpack from require 'osc' import dns, udp from require 'socket' @@ -19,7 +19,7 @@ class addr extends Op @out\set { :ip, :port } class out extends Op - @doc: "(out host port path val) - send a value via OSC" + @doc: "(out remote path val) - send a value via OSC" new: (...) => @@udp or= udp! @@ -29,8 +29,9 @@ class out extends Op assert @inputs[3], "need a value" @assert_types 'udp/remote', 'str', @inputs[3].type - update: (dt) => + tick: => remote, path, value = @unwrap_inputs! + { :ip, :port } = remote msg = pack path, value @@udp\sendto msg, ip, port diff --git a/lib/sc.moon b/lib/sc.moon new file mode 100644 index 0000000..7ffd16c --- /dev/null +++ b/lib/sc.moon @@ -0,0 +1,37 @@ +import Op, Value, Scope from require 'core' +import pack from require 'osc' +import dns, udp from require 'socket' + +class play extends Op + @doc: "(sc/play remote synth trigger [name-str val]...) - play a SC SynthDef" + + new: => + super! + @@udp or= udp! + + setup: (params) => + super params + @assert_first_types 'udp/remote', 'str', 'bool' + + assert #@inputs % 2 == 1, "parameters need to be specified as pairs" + for key in *@inputs[4,,2] + assert key.type == 'str', "ony strings are supported as control names" + for val in *@inputs[5,,2] + assert val.type == 'num', "only numbers are supported as control values" + + tick: => + { remote, synth, trig, p } = @inputs + + if trig\dirty! and trig! + controls = {} + for i = 4, #@inputs, 2 + table.insert controls, @inputs[i]! + table.insert controls, @inputs[i+1]! + msg = pack '/s_new', synth!, -1, 0, 1, unpack controls + + { :ip, :port } = remote! + @@udp\sendto msg, ip, port + +{ + :play +} diff --git a/lib/time.moon b/lib/time.moon index c49a7d7..a726af3 100644 --- a/lib/time.moon +++ b/lib/time.moon @@ -87,19 +87,22 @@ class tick extends Op counts upwards by one every period seconds and returns the number of completed ticks." new: => - super 'num' + super 'num', 0 @phase = 0 setup: (params) => + super params @assert_types 'num', 'num' - update: (dt) => + tick: (first) => -- if clock is dirty - if @inputs[1].dirty + if first or @inputs[1].dirty dt, period = @unwrap_inputs! @phase += dt / period - @out\set math.floor @phase + next_num = math.floor @phase + if next_num != @.out! + @out\set next_num class every extends Op @doc: "(every clock period) - trigger every period seconds @@ -110,11 +113,12 @@ returns true once every period seconds." @phase = 0 setup: (@period) => + super params @assert_types 'num', 'num' - update: (dt) => + tick: (first) => -- if clock is dirty - if @inputs[1].dirty + if first or @inputs[1].dirty dt, period = @unwrap_inputs! @phase += dt / period diff --git a/lib/util.moon b/lib/util.moon index 04d012f..747cb0d 100644 --- a/lib/util.moon +++ b/lib/util.moon @@ -1,4 +1,4 @@ -import Op from require 'core' +import Value, Op from require 'core' class switch_ extends Op @doc: "(switch i v0 [v1 v2...]) - switch between multiple inputs @@ -15,9 +15,9 @@ when i is a num, it is (floor)ed and the matching argument (starting from 0) is for inp in *@inputs[3,] assert inp.type == first.type, "not all values have the same type: #{first.type} != #{inp.type}" - @out = Stream first.type + @out = Value first.type, first! - update: (dt) => + tick: => i = @inputs[1]\unwrap! active = switch i when true @@ -44,7 +44,7 @@ when i is a num, it is (floor)ed and the matching argument (starting from 0) is -- @out = Stream typ -- @out -- --- update: (dt) => +-- tick: => -- i = @i\unwrap! -- active = switch i -- when true @@ -68,7 +68,7 @@ class edge extends Op super params @assert_types 'bool' - update: (dt) => + tick: => now = @params[1]\unwrap! if now and not @last @out\set true @@ -85,7 +85,7 @@ default defaults to zero." { i, init } = @inputs @out = Value i.type, default and init\unwrap! - tick => + tick: => if next = @params[1]\unwrap! @out\set next |
