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>
spectrogram.c was ~2950 lines holding everything. Break it into cohesive
translation units; spectrogram.c keeps only globals + the main frame loop.
New modules:
- spectrogram_types.h shared types, constants, extern globals, inline math
- fft.c/.h FFT, bit-reverse, twiddle (standalone, no app deps)
- stft.c/.h STFT compute, adaptive resolution, FFT-size LRU cache
- audio.c/.h WAV/ffmpeg load, FreeSignal, bandpass, playback
- render.c/.h UI scaling, colormaps, texture gen, on-screen drawing
- ui.c/.h file browser, sidebar, sliders, PNG export
Also:
- utils.c now includes utils.h instead of re-typedef'ing AudioSignal/
SignalStats (they had to be hand-synced before).
- Remove dead code: ApplyHannWindow and ComputeSTFTHighResRange were never
called (the live high-res path is ComputeNextHighResChunk).
- Delete the unused raylib-template main.c.
- rspektrum.make: build the new units. premake5.lua: glob src/**.c so a
future regen stays correct.
Pure code movement otherwise; no behavior change. Builds clean (-Wshadow).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Create primitives.h/c for waveform visualization (time/amplitude display)
- Scope view draws signal as per-pixel min/max envelope (Audacity-style)
- Add draggable divider between spectrogram and scope (30%-80% range)
- Fix selection bounds to use correct spectrogram area (not full viewport)
- Scope syncs with spectrogram zoom/pan for aligned time axis
Display Duration, Energy, Peak amplitude, RMS amplitude, and PAPR for
the current time/frequency selection. The stats box:
- Appears next to the selection box (right side, or left if not enough room)
- Centers vertically on the selection box
- Uses a semi-transparent dark background with yellow border
- Updates live while dragging the selection
- Computed in utils.c with ComputeSignalStats()
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