diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-02-16 11:47:24 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-02-16 11:47:24 +0000 |
| commit | 2953f1e56b408fc26eb54fa65935505dd128ce82 (patch) | |
| tree | 8c7c513ccf03df06c4e9e2e70ba68031d2d0b7a5 /lib/midi | |
| parent | add ==, mod (diff) | |
| download | alive-2953f1e56b408fc26eb54fa65935505dd128ce82.tar.gz alive-2953f1e56b408fc26eb54fa65935505dd128ce82.zip | |
major refactoring: Const, Stream + ResultNode
Diffstat (limited to 'lib/midi')
| -rw-r--r-- | lib/midi/core.moon | 17 | ||||
| -rw-r--r-- | lib/midi/init.moon | 44 | ||||
| -rw-r--r-- | lib/midi/launchctl.moon | 99 |
3 files changed, 114 insertions, 46 deletions
diff --git a/lib/midi/core.moon b/lib/midi/core.moon index ea49a2c..891de0a 100644 --- a/lib/midi/core.moon +++ b/lib/midi/core.moon @@ -51,8 +51,10 @@ class Input -- register a handler -- mask is { :status, :chan, :a } (all keys optional) + -- returns mask for op convenience attach: (mask, handler) => @listeners[mask] = handler + mask detach: (mask) => @listeners[mask] = nil @@ -83,8 +85,23 @@ class InOut detach: (...) => @inp\detach ... send: (...) => @out\send ... +apply_range = (range, val) -> + if range.type == 'str' + switch range\unwrap! + when 'raw' then val + when 'uni' then val / 128 + when 'bip' then val / 64 - 1 + when 'rad' then val / 64 * math.pi + else + error "unknown range #{@range}" + elseif range.type == 'num' + val / 128 * range\unwrap! + else + error "range has to be a string or number" + { :Input :Output :InOut + :apply_range } diff --git a/lib/midi/init.moon b/lib/midi/init.moon index f522b6c..c9e2476 100644 --- a/lib/midi/init.moon +++ b/lib/midi/init.moon @@ -1,29 +1,29 @@ -import Const, Op from require 'core' -import Input from require 'lib.midi.core' +import Stream, Const, Op from require 'core' +import Input, apply_range from require 'lib.midi.core' -dispatch = Input 'system:midi_capture_6' +dispatch = Input 'system:midi_capture_4' class gate extends Op @doc: "(midi/gate note [chan]) - gate from note-on and note-off messages" - new: (...) => - super ... - destroy: => dispatch\detach @mask if @mask setup: (note, chan) => dispatch\detach @mask if @mask - note = note\getc 'num' - chan = chan and chan\getc 'num' + note = note\const!\unwrap 'num' + chan = chan and chan\const!\unwrap 'num' @value = false @mask = dispatch\attach { :chan, a: note }, (status) -> if status == 'note-on' - @value = true + @out\set true else if status == 'note-off' - @value = false + @out\set false + + @out = Stream 'bool', false + @out update: (dt) => dispatch\tick! @@ -43,26 +43,16 @@ range can be one of: setup: (cc, chan, @range=Const.str'uni') => dispatch\detach @mask if @mask - cc = cc\getc 'num' - chan = chan and chan\getc 'num' + cc = cc\const!\unwrap 'num' + chan = chan and chan\const!\unwrap 'num' - @mask = dispatch\attach { status: 'control-change', :chan, a: cc }, (_, _, _, val) -> @apply val + @mask = dispatch\attach { status: 'control-change', :chan, a: cc }, (_, _, _, val) -> + @out\set apply_range @range, val - update: (dt) => dispatch\tick! + @out = Stream 'num', 0 + @out - apply: (val) => - @value = if @range.type == 'str' - switch @range\get! - when 'raw' then val - when 'uni' then val / 128 - when 'bip' then val / 64 - 1 - when 'rad' then val / 64 * math.pi - else - error "unknown range #{@range}" - elseif @range.type == 'num' - val / 128 * @range\get! - else - error "range has to be a string or number" + update: (dt) => dispatch\tick! { :gate diff --git a/lib/midi/launchctl.moon b/lib/midi/launchctl.moon index c7d7b06..778a724 100644 --- a/lib/midi/launchctl.moon +++ b/lib/midi/launchctl.moon @@ -1,66 +1,127 @@ -import Const, Op from require 'core' -import InOut from require 'lib.midi.core' +import Stream, Const, Op from require 'core' +import InOut, apply_range from require 'lib.midi.core' import bor, lshift from require 'bit32' -launch = InOut 'system:midi_capture_6', 'system:midi_playback_6' +launch = InOut 'system:midi_capture_4', 'system:midi_playback_4' color = (r, g) -> bor 12, r, (lshift g, 4) +class cc_seq extends Op + @doc: "(launctl/cc-seq i start chan [steps [range]]) - CC-Sequencer + +returns the value for the i-th step steps (buttons starting from start). +steps defaults to 8. + +range can be one of: +- 'raw' [ 0 - 128[ +- 'uni' [ 0 - 1[ (default) +- 'bip' [-1 - 1[ +- 'rad' [ 0 - tau[ +- (num) [ 0 - num[" + + destroy: => + launch\detach @mask if @mask + + new: => + @steps = {} + @out = Stream 'num' + + setup: (@i, start, chan, steps=(Const.num 8), @range=Const.str 'uni') => + launch\detach @mask if @mask + + @start = start\const!\unwrap 'num' + @chan = chan\const!\unwrap 'num' + steps = steps\const!\unwrap 'num' + + while steps > #@steps + table.insert @steps, 0 + while steps < #@steps + table.remove @steps + + @mask = launch\attach { status: 'control-change', chan: @chan }, (_, _, cc, val) -> @change cc, val + @out + + change: (cc, val) => + i = cc - @start + if i < #@steps + @steps[i+1] = val + + update: (dt) => + launch\tick! + + curr_i = (@i\unwrap 'num') % #@steps + + @out\set apply_range @range, @steps[curr_i+1] + + class gate_seq extends Op @doc: "(launctl/gate-seq i start chan [steps]) - Gate-Sequencer -returns true or false for the i-th step steps (buttons starting from start)." +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: => @steps = {} - @value = false + @out = Stream 'bool' setup: (@i, start, chan, steps=(Const.num 8)) => launch\detach @mask if @mask - @start = start\getc 'num' - @chan = chan\getc 'num' - steps = steps\getc 'num' + 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 - @mask = launch\attach { status: 'note-on', chan: @chan }, (_, _, note, _) -> @toggle note + 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\get 'num') % #@steps - launch\send 'note-on', @chan, note, light @steps[i+1], i == curr_i + curr_i = (@i\unwrap 'num') % #@steps + @display i, i == curr_i + + display: (i, active) => + launch\send 'note-on', @chan, (@start + i), light @steps[i+1], active light = (set, active) -> set = if set then 'S' else ' ' active = if active then 'A' else ' ' color switch set .. active when ' ' then 0, 0 - when ' A' then 1, 0 - when 'S ' then 0, 1 - when 'SA' then 0, 3 + when ' A' then 1, 1 + when 'S ' then 1, 0 + when 'SA' then 3, 1 update: (dt) => launch\tick! - @i\update dt - curr_i = (@i\get 'num') % #@steps + curr_i = (@i\unwrap 'num') % #@steps prev_i = (curr_i - 1) % #@steps - launch\send 'note-on', @chan, (@start + curr_i), light @steps[curr_i+1], true - launch\send 'note-on', @chan, (@start + prev_i), light @steps[prev_i+1], false + @display curr_i, true + @display prev_i, false - @value = @steps[curr_i+1] + @out\set @steps[curr_i+1] { 'gate-seq': gate_seq + 'cc-seq': cc_seq } |
