Add /launch/quant selector (0.5/1/4/8 beats, default 1 mes)
to the LIVE tab. Update /armed/ handler to read 4-state int
(0=off 1=playing 2=queued-launch 3=queued-stop), apply .armed
and .queued classes accordingly, sync clipState map. Pad tap
now toggles based on last-known state. CSS blink animation for
.queued (600 ms ease-in-out infinite).
Move ~lp[\clipGen] increment inside the four transitions that
schedule or cancel a closure (s==0 launch, s==3 cancel-stop,
s==1 stop, s==2 cancel-launch). No-op re-taps (s==1/2 on launch,
s==0/3 on stop) no longer clobber the pending generation counter.
Also clamp /launch/quant to clip(0.125, 64) instead of max(0.125)
to prevent a runaway large value from locking out launches.
~toscArmedPush now iterates all 16 pads plus melseq and rhythmseq,
sending 0/1/2/3 (off/playing/queued-launch/queued-stop) from clipState
with fallback to armed membership for concert-driven clips. Test
extended with clipState in dummy ~lp and clipState read assertion.
Add 4-state machine (off/playing/queued-launch/queued-stop) to ~lpArm.
Launch and stop are quantized to ~lp[\quant] beats (default 4) via
clock.schedAbs(clock.nextTimeOnGrid(q)). Per-clip generation counter
cancels superseded callbacks on re-tap. New env fields: ~lp[\quant],
~lp[\clipState], ~lp[\clipGen]. New /launch/quant OSCdef. ~lp[\armed]
semantics preserved so /launch/clear and concert logic keep working.
iPhone Vision hands (on-device, .right upright, y already
top-left, rotation-invariant) are stored in a dedicated state
field and used by the strike detector when fresh (FINGER_SOURCE
auto/iphone/mediapipe). More stable than MediaPipe on the
rotated downscaled video. Adds FINGER_DEBUG strike logging.
Reorganize control surface into LIVE / FX-HARMONIE-CONCERT /
SEQUENCEURS tabs with pure CSS/JS tab switching.
Default tab is LIVE.
Add engine feedback rendering via WS onmessage:
- /armed/<name>: reconcile armed CSS class from engine state
- /sync/beat: 80 ms flash on beat-dot indicator in header
- /sync/rms: drive master VU bar width from float 0..1
- /seq/rhythm/state: load k/s/h step grid + preset name; guard
suppressEmit to prevent echo back as /seq/rhythm/set
- /seq/melody/state: load degree inputs; same no-echo guard
All pre-existing OSC sends preserved unchanged.
data-only boot does not load palette/scales.scd, so
~scaleMinorPent was nil and ~fpResolve crashed on wrapAt.
Embed fallback scale arrays so notes resolve headless.
Add a second osc.UDPPort bound to FEEDBACK_PORT_IN (default
9000, matches ~toscPort in SC) that receives engine feedback
OSC (/armed/*, /sync/beat, /sync/rms, /seq/*/state) from SC
and relays each message to all WS clients using the existing
{address,args} JSON shape. Does not update the snapshot cache
(feedback is transient). Existing data port, control-send
path, and WS logic are untouched.
node --check: SYNTAX OK.
Replace single ~tosc NetAddr with ~toscClients Dictionary
(keyed by ip) so feedback OSC reaches all connected clients
(web bridge + iPad) simultaneously. ~toscTouch deduplicates
by IP and logs only on first connection. ~toscSend iterates
the dictionary; no-op when empty.
Test: add assertion that two distinct IPs produce size==2.
Balance: P:0 B:0 on both files. Headless TEST PASS.
Add /control/fp (on/off/scale/inst/sens/octave/debug) so the
air-piano is controllable on a headless sclang, plus a debug
strike log gated by ~fpDebug.
Move /armed/<name> receive msg from arm BUTTON to parent GROUP so
pad.lua onReceiveOSC fires on the node that owns the message (FIX 1).
Remove feedback.lua from master RMS fader; native receive already
drives the VU, onFrame decay was pure downside (FIX 3).
Add Lua 5.1/LuaJIT compat shim for table.unpack in melody_faders
(FIX 2). Document deferred sequencer playhead in README (FIX 4).
Regression test: 16 pad GROUPs carry /armed/* receive; 21 tests pass.
Rebuild dist/av-live-control.tosc.
Rotate the iPhone/webcam frame before MediaPipe and display
so detection, skeleton overlay and the shown video stay
aligned after the phone is physically rotated. ARKit 3D
world joints are orientation-invariant and untouched.
Adds sound_algo/data_only/touchosc_feedback.scd: captures the
controlling client IP from inbound /launch* OSC traffic, pushes
/armed/<name> for all 16 pads, /sync/beat each beat on ~lp[clock],
/sync/rms at 20 Hz (server-only, guarded), and echoes
/seq/rhythm/state + /seq/melody/state on preset select. Additive,
nil-guarded, safe to load headless without a booted audio server.
Also adds test/test_touchosc_feedback.scd: headless harness that
builds a dummy ~lp env, loads the feature, asserts the three public
API functions are wired, exercises ~toscArmedPush with nil ~tosc,
and prints TEST PASS.
Pre-existing failure: test_pose_bridge_hands builds the
bridge via __new__, so _vj raised AttributeError on _vdmx.
Defensive getattr makes the full suite green.
Wire finger_piano.scd into both data-only boot paths so
OSCdef /pose/finger and ~fp* API are available at runtime.
Call ~fpModTick on every /pose/hands frame (~30 Hz) for
continuous air-piano modulation. Document FINGER_PIANO env
vars in CLAUDE.md.
Three-page pager (LIVE / FX-HARM-CONCERT / SEQ) with corrected
OSC mapping: scale sends string name not index, octave is absolute
(0/1/2), body-play is /control/doScene "play", arm-mel/rhy send
/launch "melseq"/"rhythmseq". Per-voice VU strip deliberately
omitted (engine sums to bus 0 only). Lua scripts embedded from
gen/lua/*.lua. Dist file committed as the deliverable.
18 tests pass.
Add consti/constf/vali/valf to schema.py so numeric OSC args
carry the right wire type. Partial already supported scale_min/
scale_max; helpers expose them cleanly. Existing API unchanged.
Strengthen test_send_finger_emits_expected_osc to verify all seven OSC
arguments by value (z, tipx, tipy) and their types. Ensures OSC tags and
SC ~fpResolve reader get correct int/float types.
Hybrid architecture: Python detects finger strikes from
iPhone hand joints, SC owns musicality (scale, octave,
instrument) and continuous modulation from hand spacing.
Add melseq (1 Pdef, 8 melodic sequences, /seq/melody) and rhythmseq
(3 sub-Pdefs rsk/rss/rsh, 8 16-step patterns, /seq/rhythm) to the
launchpad OSC bank. ~lpArm special-cases "rhythmseq" to arm/disarm
all three voices together. Web surface gets a Séquenceurs section
with arm pads, selector rows (.sel highlight), and vol sliders.