Commit Graph

8 Commits

Author SHA1 Message Date
tyler 40623feadc feat: web file upload, axis-locked grid, averaged cursor readout
**File loading on the web.** The browser build's filesystem is an in-memory
sandbox, so the file browser could only ever list what the page itself had
written — useless for opening a capture off the user's disk. Adds
Platform_NeedsFileUpload / RequestFileUpload / TakeUploadedFile: no-ops on
desktop, and on web they drive a real <input type="file">, copy the chosen
bytes into MEMFS, and hand the path back through a callback the main loop
polls. The ordinary load path takes it from there, so mLnL parsing and
collision detection work identically.

All three entry points (the O key, File -> Open, and the empty-state
button) route through the same place, so they can't disagree about what
"open" means. ccall/cwrap/FS and the callback symbol needed explicit
export — recent emscripten omits them by default and the failure is
silent until someone clicks the button.

The empty-state banner was centred with the old 320px sidebar's width
hardcoded and never measured its text, so it sat well off-centre once the
rail shrank to 46px. It now measures and centres against the area right of
the rail, and says something useful on web.

**Grid was not locked to the axes.** It drew a fixed 10x8 even divisions of
the viewport rectangle, with no idea what time or frequency those lines
fell on — so they marked arbitrary values and slid continuously while
panning, never coinciding with the labels. Both axes now draw at real
values from a 1-2-5 ladder, and the time labels moved onto that same
ladder (they were at 11 fixed fractions of the view, printing values like
"3.47s" that matched no gridline). Grid and labels share one set of
spacing helpers so they cannot drift apart again.

**Cursor dB readout was a single bin.** On an OFDM burst that swings ~30 dB
between adjacent subcarriers and symbols, so the number reported where the
cursor landed rather than the level of the signal under it. Now averaged
over +/-3 segments x +/-6 bins (~76 Hz x 300 ms at 12 kHz / 2048, under a
third of the narrowest mLink channel, so it stays inside one signal).
Simulated against Rayleigh-distributed subcarriers this cuts the standard
deviation from 5.6 dB to 0.44 dB.

The mean is taken over power and converted afterwards: averaging dB values
is a geometric mean of power and read ~2 dB low. The window is sized in
STFT cells rather than screen pixels, which would otherwise mean something
different at every zoom — one pixel spans hundreds of segments zoomed out
and a fraction of a bin zoomed in.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V8ZWfr5XZyyDttvkhJUgHN
2026-08-12 16:23:26 -07:00
tyler 398be34aaf build: document system deps, add check-deps, auto-glob web modules
- README: rewrite Build section for the hand-written Makefile (make /
  make DEBUG=1 / run / test / bench). Add a "System dependencies" table
  with the X11+GL dev packages per distro (apt/dnf/pacman/zypper/apk),
  since a clone won't build without them and the error is otherwise
  cryptic. Fix stale ./bin/Debug paths to ./bin/Release.
- Makefile: add `make check-deps` — probes for the required X11/GL dev
  headers and prints the install command for the detected distro on
  failure (via /etc/os-release).
- build_web.sh: auto-discover app modules from src/*.c (drop the
  hardcoded APP_MODULES list that had to be hand-synced), matching the
  desktop Makefile. Excludes the desktop platform backends. Remove the
  stale rspektrum.make reference.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 21:19:23 -07:00
tyler ac262505c1 feat: headless PNG render, mLnL annotations, and per-frame sched offset
Commit the accumulated working-tree changes as one snapshot.

- Headless render: `--render OUT.png INPUT.wav` draws the spectrogram
  (full window, or `--pane` for the spectrogram pane only) to a PNG
  with no visible window. Options: `--annotations`/`--no-annotations`,
  `--annotation-opacity`, `--width`/`--height`.
- mLnL annotations: parse the optional `mLnL` RIFF chunk (schema v2)
  and render tx_frame/assertion/control overlays, a timeline lane, and
  a waveform-scope echo, with hover tooltips on the spectrogram,
  timeline, and scope.
- sched_offset_ms: parse the per-frame intent->air latency and surface
  it in the hover tooltips (boxes stay air-anchored upstream).
- Supporting: build wiring (rspektrum.make), shared types/headers,
  web-build and capture-script tweaks, and removal of the old
  synchrosqueezing LaTeX doc.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 12:19:37 -07:00
tyler cef7619833 feat(web): proper viewport scaling, instant load, and file downloads
Make the Emscripten build behave like the desktop app for loading, window
scaling, and exporting. All changes are #ifdef __EMSCRIPTEN__-gated or no-op on
desktop, so native behavior is unchanged.

Scaling:
- Drop FLAG_WINDOW_HIGHDPI on web. The emscripten-GLFW shim forces a fixed
  pixel canvas style (!important) when HiDPI-aware, overriding the shell's
  100vw/100vh CSS so the canvas can't fill the page; raylib's own resize/window
  callbacks also disagree about dividing by devicePixelRatio, desyncing the
  framebuffer from the reported screen size.
- Sync raylib's window size to window.innerWidth/innerHeight each frame via
  SetWindowSize (guarded against no-op churn). This keeps screen size, GL
  viewport, and projection consistent, so the UI fills the viewport and reflows
  on resize like the desktop window.

Loading:
- Compute the full-resolution STFT synchronously when a file loads instead of
  the desktop overview-then-deferred-high-res path, which relied on many
  main-loop iterations yielding to the browser and appeared to stall partway.
- Allow the wasm heap to grow (INITIAL_MEMORY + ALLOW_MEMORY_GROWTH) so longer
  recordings fit now that everything is computed up front.

Exports:
- Add Platform_OfferFileToUser(): no-op on desktop (file is already on disk);
  on web it reads the just-written file from MEMFS and triggers a browser
  download, then unlinks the temp copy. Wired into PNG and WAV export, which
  now show just the filename in the status message.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 11:48:47 -07:00
tyler 6347eb172e fix(web): repair Emscripten build after module split + font move
The web build had bit-rotted since the last successful build (Apr 12):

- build_web.sh only compiled spectrogram.c + platform_web.c, but commit
  3a8f20b split the code into 9 modules — link failed with undefined
  symbols. Now compiles all app modules (kept in sync with rspektrum.make,
  swapping platform_linux -> platform_web).
- Dropped -DPLATFORM_WEB from the app-module compile/link: the platform
  refactor (b6942d8) added a `Platform` enum whose PLATFORM_WEB enumerator
  collides with the macro. Web behavior is selected by linking
  platform_web.c, not the macro, so the define was never needed by our code
  (raylib still gets it in its own build).
- Removed the stale `fonts/DejaVuSansMono.ttf` preload (font moved to
  resources/fonts/); resources@resources already bundles it and the runtime
  loads it relative to the resources dir.
- platform_web.c: include <errno.h> for ENOSYS (this stub had never compiled).
- build_web.sh: skip the slow raylib rebuild when libraylib.a already exists.

Verified: `./build_web.sh release` exits 0 and produces html/js/wasm/data;
font is packaged; all artifacts serve 200 via python http.server and the
wasm has valid magic bytes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 11:15:31 -07:00
tyler b6942d8577 Refactor: extract platform abstraction for subprocess spawning
Move all Unix-specific syscalls (fork, execvp, waitpid, strerror, /tmp)
into a platform layer so the same spectrogram.c can target Windows
(CreateProcess) and WebAssembly (stubs). Key changes:

- src/platform.h: public API with spawn handle, error codes, path helpers
- src/platform_linux.c: fork/execvp implementation, /tmp, strerror
- src/platform_win32.c: CreateProcess implementation, temp dir lookup
- src/platform_web.c: stub implementations (no subprocess support on web)
- src/spectrogram.c: consume only platform.h; replace pid_t/fork/execvp
  with Platform_SpawnChild/WaitForChild; use Platform_GetTempDir() for
  /tmp path; replace strdup with malloc/memcpy for portability
- Build: add platform_*.c to gmake, Premake, and build_web.sh
2026-05-14 18:16:21 -07:00
tyler 4331d010e5 Add incremental loading progress, auto-scaled amplitude, DPI-aware TTF fonts, and better file browser scaling
- Add incremental STFT processing with loading overlay and progress bar
- Add auto-scaling amplitude (max dB, max-40dB floor) for low-signal files
- Replace fixed bitmap text with TTF font scaled by window size for crisp rendering at any resolution
- Fix command-line file path resolution relative to original working directory
- Scale file browser dialog dimensions by GetUIScale() to prevent text overlap
- Disable ESC key closing the window
- Fix FFT size changes to restart STFT computation
2026-05-14 16:01:22 -07:00
tyler da37cecb59 Add web build support with custom shell HTML
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-04-12 21:28:18 -07:00