Commit Graph

536 Commits

Author SHA1 Message Date
you 2fd0d3e07b Audio Lab: show WHY each parameter has its value
Sound Mapping: 3-column table (Parameter | Value | Formula/Reason)
Note Sequence: payload index + duration/gap derivation formulas
2026-03-22 19:36:07 +00:00
you 7c1132b7cf Audio Lab: real-time playback highlighting
As each note plays, highlights sync across all three views:
- Hex dump: current byte pulses red
- Note table: current row highlights blue
- Byte visualizer: current bar glows and scales up

Timing derived from note duration + gap (same values the voice
module uses), scheduled via setTimeout in parallel with audio.
Clears previous note before highlighting next. Auto-clears at end.
2026-03-22 19:27:35 +00:00
you f523d4f3c4 Audio Lab page (Milestone 1): Packet Jukebox
New #/audio-lab page for understanding and debugging audio sonification.

Server: GET /api/audio-lab/buckets — returns representative packets
bucketed by type (up to 8 per type spanning size range).

Client: Left sidebar with collapsible type sections, right panel with:
- Controls: Play, Loop, Speed (0.25x-4x), BPM, Volume, Voice select
- Packet Data: type, sizes, hops, obs count, hex dump with sampled
  bytes highlighted
- Sound Mapping: computed instrument, scale, filter, volume, voices,
  pan — shows exactly why it sounds the way it does
- Note Sequence: table of sampled bytes → MIDI → freq → duration → gap
- Byte Visualizer: bar chart of payload bytes, sampled ones colored

Enables MeshAudio automatically on first play. Mobile responsive.
2026-03-22 19:19:45 +00:00
you edbaddbd37 Audio Workbench: expand M2 parameter overrides — envelope, filter, limiter, timing 2026-03-22 19:00:48 +00:00
you d5e6481d9b Audio: eliminate pops — proper envelope + per-packet limiter
Three pop sources fixed:
1. setValueAtTime(0) at note start — oscillator starting at exact zero
   causes click. Now starts at 0.0001 with exponentialRamp up.
2. setValueAtTime at noteEnd jumping to sustain level — removed.
   Decay ramp flows naturally into setTargetAtTime release (smooth
   exponential decay, no discontinuities).
3. No amplitude limiting — multiple overlapping packets could spike.
   Added DynamicsCompressor as limiter per packet chain (-6dB
   threshold, 12:1 ratio, 1ms attack).

Also: 20ms lookahead (was 10ms) gives scheduler more headroom.
2026-03-22 18:58:33 +00:00
you 1450bc928b Packets page: O(1) hash dedup via Map index
packets.find(g => g.hash === h) was O(n) and could race with
loadPackets replacing the array. hashIndex Map stays in sync —
rebuilt on API fetch, updated on WS insert. Prevents duplicate
rows for same hash in grouped mode.
2026-03-22 18:55:22 +00:00
you c7f12c72b9 Audio: log2 voice scaling (up to 8), wider detune spread
1 obs = solo, 3 = duo, 8 = trio, 15 = quartet, 30 = quintet, 60 = sextet.
Wider detune (±8, ±13, ±18...) so stacked voices shimmer instead
of sounding like the same oscillator copied.
2026-03-22 18:45:47 +00:00
you 2688f3e63a Audio: pass consolidated observation_count to sonifyPacket
Realistic mode buffers observations then fires once — but was
passing the first packet (obs_count=1). Now passes consolidated
packet with obs_count=packets.length so the voice module gets
the real count for volume + chord voicing.
2026-03-22 18:44:45 +00:00
you 90bd9e12e5 Fix realistic mode: all WS broadcasts include hash + raw_hex
Secondary broadcast paths (ADVERT, GRP_TXT, TXT_MSG, TRACE, API)
were missing hash field. Without hash, realistic mode's buffer
check (if pkt.hash) failed and packets fell through to
animatePacket individually — causing duplicate feed items and
duplicate sonification.

Also added missing addFeedItem call in animateRealisticPropagation
so the feed shows consolidated entries in realistic mode.
2026-03-22 18:37:53 +00:00
you 4e8b1b2584 Audio: fix pop/crackle — exponential ramps + longer release tail
Linear gain ramps + osc.stop() too close to release end caused
waveform discontinuities. Switched to exponentialRamp (natural
decay curve), 0.0001 floor (-80dB), 50ms extra headroom before
oscillator stop.
2026-03-22 18:31:36 +00:00
you 288c1b048b CI: skip deploy on markdown, docs, LICENSE, gitignore changes 2026-03-22 18:28:56 +00:00
you 85ecddd92c Audio Workbench plan — packet jukebox, parameter overrides, A/B comparison 2026-03-22 18:26:49 +00:00
you d0b02b7070 Remove legacy playSound/🔇 button — MeshAudio is the only audio system now 2026-03-22 18:11:55 +00:00
you 08255aeba5 Audio: "Tap to enable audio" overlay when context is suspended
Instead of silently dropping notes or hoping gesture listeners fire,
show a clear overlay on first packet if AudioContext is suspended.
One tap resumes context and removes overlay. Standard pattern used
by every browser game/music site.
2026-03-22 17:31:23 +00:00
you 51df14521b Audio: create context eagerly on restore, gesture listener as fallback 2026-03-22 17:27:54 +00:00
you f3572c646a Audio: unlock on first user gesture after restore
When audio was previously enabled, registers one-shot click/touch/key
listener to init AudioContext on first interaction. Any tap on the
page is enough — no need to toggle the checkbox.
2026-03-22 17:27:00 +00:00
you 0dbe5fd229 Audio: fix inconsistent init — lazy AudioContext, no premature creation
restore() was creating AudioContext without user gesture (on page load
when volume was saved), causing browser to permanently suspend it.
Now restore() only sets flags; AudioContext created lazily on first
sonifyPacket() call or setEnabled() click. Pending volume applied
when context is finally created.
2026-03-22 17:25:42 +00:00
you f206ae48ef Modularize audio: engine + swappable voice modules
audio.js is now the core engine (context, routing, voice mgmt).
Voice modules register via MeshAudio.registerVoice(name, module).
Each module exports { name, play(ctx, master, parsed, opts) }.

Voice selector dropdown appears in audio controls.
Voices persist in localStorage. Adding a new voice = new file +
script tag. Previous voices are never lost.

v1 "constellation" extracted as audio-v1-constellation.js.
2026-03-22 17:06:18 +00:00
you ff0f26293e Audio plan: add percussion layer — kick/hat/snare/rim/crash from packet types 2026-03-22 09:41:04 +00:00
you d0de0770ec Revert audio fixes — restore to initial working audio commit (ddc86a2) 2026-03-22 09:35:18 +00:00
you 6b8e4447c0 Audio: debug logs to trace why packets aren't playing 2026-03-22 09:33:47 +00:00
you a7e8a70c2f Audio: resume suspended AudioContext + sonify realistic propagation path
AudioContext starts suspended until user gesture — now resumes on
setEnabled(). Also added sonifyPacket to animateRealisticPropagation
which is the main code path when Realistic mode is on.
2026-03-22 09:29:54 +00:00
you ddc86a2574 Add mesh audio sonification — raw packet bytes become music
Per AUDIO-PLAN.md:
- payload_type selects instrument (bell/marimba/piano/ethereal),
  scale (major penta/minor penta/natural minor/whole tone), and root key
- sqrt(payload_length) bytes sampled evenly across payload for melody
- byte value → pitch (quantized to scale) + note duration (50-400ms)
- byte-to-byte delta → note spacing (30-300ms)
- hop_count → low-pass filter cutoff (bright nearby, muffled far)
- observation_count → volume + chord voicing (detuned stacked voices)
- origin longitude → stereo pan
- BPM tempo slider scales all timings
- Volume slider for master gain
- ADSR envelopes per instrument type
- Max 12 simultaneous voices with voice stealing
- Pure Web Audio API, no dependencies
2026-03-22 09:19:36 +00:00
you 3f8b8aec79 Audio plan: final — byte-driven timing, BPM tempo control, no fixed spacing 2026-03-22 09:15:14 +00:00
you 73dd0d34d2 Audio plan: header configures voice, payload sings the melody 2026-03-22 09:11:02 +00:00
you fbf1648ae3 Audio plan: payload type as root key, document guaranteed fields 2026-03-22 09:06:15 +00:00
you 36eb04c016 Audio plan: drop SNR/RSSI, use obs count + hops for dynamics 2026-03-22 08:58:05 +00:00
you 7739b7ef71 Add mesh audio sonification plan (AUDIO-PLAN.md) 2026-03-22 08:56:51 +00:00
you 7fbbea11a4 Remove scanline flicker animation — was causing visible pulsing 2026-03-22 08:39:47 +00:00
you 8dfb5c39f7 v2.5.0 "Digital Rain" — Matrix mode, hex flight, matrix rain v2.5.0 2026-03-22 08:38:28 +00:00
you 0116cd38ac Fix replay missing raw_hex — no rain on replayed packets
Replay button builds packets without raw/raw_hex field.
Now includes raw: o.raw_hex || pkt.raw_hex for both
single and multi-observation replays.
2026-03-22 08:19:21 +00:00
you 0255e10746 Rain: vary hop count per observation column (±1 hop)
Each observer sees a different path length in reality. Extra
rain columns now randomly vary ±1 hop from the base, giving
different fall distances for visual variety.
2026-03-22 08:17:18 +00:00
you 3d7c087025 Rain: 4 hops = full screen (was 8), matches median of 3 hops 2026-03-22 08:15:15 +00:00
you 54d453d034 Rain: spawn column per observation for denser rain
Each observation of a packet spawns its own rain column,
staggered 150ms apart. More observers = more rain.
2026-03-22 08:13:22 +00:00
you ca46cc6959 Rain: show all packet bytes, no cap 2026-03-22 08:12:14 +00:00
you a01999c743 Rain: show up to 20 bytes trailing, scroll through all packet bytes
Trail was limited to hops*30px which meant 1-hop packets showed
1 character. Now shows up to 20 visible chars at once, scrolling
through the entire packet byte array as the drop falls.
2026-03-22 08:11:23 +00:00
you a295e5eb9c Rain: fix missing raw_hex in VCR/timeline packets
dbPacketToLive() wasn't including raw_hex from API data.
VCR replay and timeline scrub packets had no raw bytes,
so rain silently dropped them all. Now includes pkt.raw_hex
as 'raw' field. Removed debug log.
2026-03-22 08:09:26 +00:00
you c3e97e6768 Rain: add debug log to diagnose missing drops 2026-03-22 08:06:33 +00:00
you 1ba33d5d04 Rain: only show drops with real raw packet bytes, no faking
Packets from companion bridge (Format 2) have no raw hex —
they arrive as pre-decoded JSON. Skip them entirely instead
of showing fake/random bytes.
2026-03-22 08:03:52 +00:00
you 4b0cc38adb Rain: use packet hash + decoded payload as hex source fallback
Format 2 MQTT packets (companion bridge) have no raw hex field.
Now falls back to pkt.hash, then extracts hex from decoded payload
JSON. Random bytes only as absolute last resort.
2026-03-22 08:02:53 +00:00
you 26fca2677b Rain: fix hex bytes source — check pkt.raw, pkt.raw_hex, pkt.packet.raw_hex 2026-03-22 07:58:52 +00:00
you 3f4077c8e0 Matrix Rain: canvas overlay with falling hex byte columns
New 'Rain' toggle on live map. Each incoming packet spawns a
falling column of hex bytes from its raw data:

- Fall distance proportional to hop count (8+ hops = full screen)
- 5 second fall time for full-height drops, proportional for shorter
- Leading char: bright white with green glow
- Trail chars: green, progressively fading
- Entire column fades out in last 30% of life
- Random x position across screen width
- Canvas-rendered at 60fps (no DOM overhead)
- Works independently of Matrix mode (can combine both)
2026-03-22 07:53:50 +00:00
you 261bb54c38 Matrix: faster trail fadeout (500ms->300ms, delay 300->150ms) 2026-03-22 07:41:39 +00:00
you bbfaded9fb Matrix: 1.1s per hop 2026-03-22 07:38:47 +00:00
you 051d351a01 Matrix: speed up to 1s per hop (was 1.4s) 2026-03-22 07:36:43 +00:00
you 786237e461 Revert "Matrix: CSS transition pooled markers for smoother animation"
This reverts commit 68d2fba54e.
2026-03-22 07:36:10 +00:00
you 68d2fba54e Matrix: CSS transition pooled markers for smoother animation
- Pre-create pool of 6 reusable markers (no create/destroy per frame)
- CSS transition: transform 80ms linear for position, opacity 200ms ease
- will-change: transform, opacity for GPU compositing
- Styles moved from inline to .matrix-char span class
- Marker positions updated via setLatLng, browser interpolates between
- Fade-out via CSS transition instead of rAF opacity loop

Revert to bbaecd6 if this doesn't feel better.
2026-03-22 07:34:39 +00:00
you bbaecd664a Matrix: requestAnimationFrame for smooth 60fps animation
Replaced setInterval(40ms) with rAF + time-based interpolation.
Same 1.4s duration per hop, but buttery smooth movement.
Fade-out also uses rAF instead of setInterval.
2026-03-22 07:31:23 +00:00
you aa8feb3912 Matrix: markers 10% brighter (#008a22, 50% opacity), map 10% darker (1.1) 2026-03-22 07:29:35 +00:00
you 967f4def7e Matrix: speed up animation (35 steps @ 40ms = ~1.4s per hop) 2026-03-22 07:29:06 +00:00