diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2021-01-08 13:43:24 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2025-03-02 14:24:49 +0000 |
| commit | 020429ac00fb4827fc528313ad85f6ca87733ebe (patch) | |
| tree | 720d6d9fab2bbaccb8f72602cc5ddb851aeba6a0 | |
| parent | copilot/cli: colorize output linewise (diff) | |
| download | alive-020429ac00fb4827fc528313ad85f6ca87733ebe.tar.gz alive-020429ac00fb4827fc528313ad85f6ca87733ebe.zip | |
lib: various fixes
| -rw-r--r-- | alv-lib/midi.moon | 85 | ||||
| -rw-r--r-- | alv-lib/midi/core.moon | 2 | ||||
| -rw-r--r-- | alv-lib/rhythm.moon | 4 | ||||
| -rw-r--r-- | alv-lib/time.moon | 13 |
4 files changed, 86 insertions, 18 deletions
diff --git a/alv-lib/midi.moon b/alv-lib/midi.moon index a42867e..83fe32f 100644 --- a/alv-lib/midi.moon +++ b/alv-lib/midi.moon @@ -1,5 +1,6 @@ -import Constant, Op, Input, T, sig, evt from require 'alv.base' +import Constant, Op, Input, T, Struct, sig, evt from require 'alv.base' import input, output, port, apply_range from require 'alv-lib.midi.core' +import monotime from require 'system' gate = Constant.meta meta: @@ -81,7 +82,7 @@ cc = Constant.meta meta: name: 'cc' summary: "`num` from cc-change messages." - examples: { '(midi/cc [port] cc [chan [range]])' } + examples: { '(midi/cc [port] cc [range] [chan])' } description: " `range` can be one of: @@ -93,18 +94,19 @@ cc = Constant.meta - (num) [ 0 - num[" value: class extends Op - pattern = -sig['midi/in'] + sig.num + -sig.num + -sig.num + pattern = -sig['midi/in'] + sig.num + -(sig.num / sig.str) + -sig.num setup: (inputs, scope) => - { port, cc, chan, range } = pattern\match inputs + { port, cc, range, chan } = pattern\match inputs super port: Input.cold port or scope\get '*midi*' cc: Input.cold cc - chan: Input.cold chan or Constant.num -1 range: Input.cold range or Constant.str 'uni' + chan: Input.cold chan or Constant.num -1 - internal: Input.hot T.num\mk_sig 0 + internal: Input.hot T.bang\mk_evt! - @out or= T.num\mk_sig! + @state or= 0 + @out or= T.num\mk_sig apply_range @inputs.range, @state poll: => { :port, :cc, :chan, :internal } = @inputs @@ -114,7 +116,8 @@ cc = Constant.meta msg = msgs[i] if msg.a == cc! and (chan! == -1 or msg.chan == chan!) if msg.status == 'control-change' - internal.result\set msg.b + @state = msg.b + internal.result\set true return true false @@ -122,16 +125,72 @@ cc = Constant.meta tick: => { :range, :internal } = @inputs - value = internal! - @state = value / 128 - @out\set apply_range range, value + if internal! + @out\set apply_range range, @state vis: => { type: 'bar' - bar: @state + bar: @state / 128 } +send_notes = Constant.meta + meta: + name: 'send-notes' + summary: "`send MIDI note events." + examples: { '(midi/send-notes [port] [chan] note-events)' } + description: " +`chan` can be +`note-events` is a !-stream of structs with the following keys: + +- `pitch`: MIDI pitch (num) +- `dur`: note duration in seconds (num) +- `vel`: MIDI velocity (num, optional)" + + value: class extends Op + thin = Struct pitch: T.num, dur: T.num + thiq = Struct pitch: T.num, dur: T.num, vel: T.num + pattern = -sig['midi/out'] + -sig.num + (evt(thin) / evt(thiq)) + setup: (inputs, scope) => + { port, chan, notes } = pattern\match inputs + @state = {} + super + port: Input.cold port or scope\get '*midi*' + notes: Input.hot notes + chan: Input.cold chan or Constant.num 0 + + note_off: Input.hot T.num\mk_evt! + + poll: => + time = monotime! + + for pitch, endt in pairs @state + if endt <= time + @inputs.note_off.result\set pitch + return true + + false + + tick: => + { :port, :chan, :notes, :note_off } = @unwrap_all! + + if notes + { :pitch, :dur, :vel } = notes + pitch = math.floor pitch + vel = if vel then math.floor vel else 127 + @state[pitch] = monotime! + dur + port\send 'note-on', chan, pitch, vel + + if pitch = note_off + @state[pitch] = nil + port\send 'note-off', chan, pitch, 0 + + destroy: => + { :port, :chan } = @unwrap_all! + + for pitch, endt in pairs @state + port\send 'note-off', chan, pitch, 0 + Constant.meta meta: name: 'midi' @@ -141,6 +200,8 @@ Constant.meta :input :output :port + :gate :trig :cc + 'send-notes': send_notes diff --git a/alv-lib/midi/core.moon b/alv-lib/midi/core.moon index 03cfcb2..c456a01 100644 --- a/alv-lib/midi/core.moon +++ b/alv-lib/midi/core.moon @@ -134,7 +134,7 @@ apply_range = (range, val) -> when 'deg' then val / 128 * 360 else error Error 'argument', "unknown range '#{range!}'" - elseif range.type == T.num + elseif range\type! == T.num val / 128 * range! else error Error 'argument', "range has to be a string or number" diff --git a/alv-lib/rhythm.moon b/alv-lib/rhythm.moon index 57be9a7..582483f 100644 --- a/alv-lib/rhythm.moon +++ b/alv-lib/rhythm.moon @@ -24,7 +24,7 @@ bjorklund2 = (n, k) -> b, bs = '0', n - k while true - if bs == 1 or bs == 0 + if as < 2 or bs < 2 break elseif as < bs a, b = a .. b, b @@ -64,6 +64,8 @@ When fed a num~ or num! stream, outputs a bang if the corresponding step is on." tick: => { :trig, :n, :k } = @unwrap_all! + n = math.floor n + k = math.floor k if @inputs.trig\type! == T.bang @state += 1 diff --git a/alv-lib/time.moon b/alv-lib/time.moon index f091792..8b3f47d 100644 --- a/alv-lib/time.moon +++ b/alv-lib/time.moon @@ -149,6 +149,7 @@ ramp = Constant.meta tick: => { :clock, :period, :max } = @unwrap_all! max or= period + return if period == 0 @state += clock.dt / period while @state >= 1 @@ -187,7 +188,9 @@ tick = Constant.meta period: Input.cold period tick: => - @state.phase += @inputs.clock!.dt / @inputs.period! + { :clock, :period } = @unwrap_all! + return if period == 0 + @state.phase += clock.dt / period if @state.phase >= 1 @state.phase -= 1 @@ -223,11 +226,13 @@ every = Constant.meta @out = @inputs.evt\type!\mk_evt! tick: => - @state += @inputs.clock!.dt / @inputs.period! + { :clock, :period, :evt } = @unwrap_all! + return if period == 0 + @state += clock.dt / period if @state >= 1 - @state -= 1 - @out\set @inputs.evt! + @state = @state % 1 + @out\set evt val_seq = Constant.meta meta: |
