Health Tool · Signal Processing · Browser-local · 2026 · Solo — signal processing pipeline architecture (Butterworth filter + adaptive peak detection), iOS permission flow, GPX 1.1 binary writer, TDD (38 tests), Vercel production deployment
Cadence Log
A browser-based step counter and cadence logger: DeviceMotion API → Butterworth LPF (10 Hz cutoff) → adaptive peak detector (RMS noise floor) → EMA cadence computation → GPX 1.1 export. No native app, no backend, no wearable required.
The problem
Runners and physical therapists want accurate cadence data without proprietary wearables or native apps. Every existing web step counter either uses a high-level step-detection API (which abstracts the physics entirely) or is a toy demo with no usable output. Doing real accelerometer signal processing in the browser — filter, peak detect, cadence compute, GPX export — closes that gap.
Architecture
Key decisions
Butterworth filter over simple moving average
A 4th-order Butterworth LPF at 10 Hz preserves the 1–3 Hz stride frequency while removing high-frequency vibration noise. A simple moving average would smear the step peaks and degrade peak detection at lower cadences. The filter coefficients were derived analytically and verified in tests against known frequency response.
Adaptive peak threshold over static threshold
A static minimum peak height breaks during acceleration and deceleration phases. Computing the RMS noise floor over a sliding 2-second window and requiring peaks to exceed 1.5×RMS makes the detector work across walk, jog, and sprint without per-session tuning.
GPX 1.1 with Garmin Training Data extension for cadence
The standard GPX 1.1 <trkpt> element has no cadence field. The Garmin Training Data extension adds <gpxtpx:cad> inside <extensions>, which Strava, Garmin Connect, Wahoo, and Apple Fitness all parse correctly. The GPX writer produces a valid XML Blob URL directly in the browser with no server involvement.
TDD — 38 tests written and confirmed failing before implementation
All engine functions (butterworth_lpf, adaptivePeakDetector, cadenceEma, gpxWriter, iosPermissionFlow, recordingState) were specified as failing tests first. The suite covers filter coefficient correctness, pole placement, frequency response, RMS floor calculation, peak identification, minimum interval enforcement, EMA convergence, GPX XML validity, and iOS permission state transitions.