Projects

Things I build outside of published work. All of these run entirely in the browser – nothing is uploaded, nothing is installed, and no account is required.

EEG State Simulator

A generator of synthetic multichannel EEG for various arousal states – waking with eyes open and closed, N1 through N3, and REM – on a standard 19-electrode montage. Everything it draws is parametrically manufactured: no sample is data recorded from a brain; nothing is from a generative model.

The scalp topographies come from a three-shell boundary-element head model, with each rhythm defined as a set of named cortical regions in a published anatomical atlas and projected to the electrodes through the volume conductor. Where a rhythm appears largest on the scalp is therefore an output of the anatomy and the physics, not a number arbitrarily chosen or generated.

The controls: the reference montage, the display sensitivity in microvolts per millimetre, the paper speed, a high-pass and low-pass filter with adjustable order and a live spectrum showing what each one removes. Changing the sensitivity does not autoscale, so the amplitude difference between N3 delta and waking alpha survives on screen. Respiration and ECG run in their own lanes below the montage, with both heart rate and the EEG’s spectral tilt rising and falling with the breath.

The head model is fsaverage, distributed with MNE-Python and derived from FreeSurfer; portions are used under licence from The General Hospital Corporation, whose terms note that clinical applications are neither recommended nor advised. Cortical regions follow the Desikan-Killiany parcellation. Parameters were fitted against two open PhysioNet collections – EEG During Mental Arithmetic Tasks, and the Haaglanden Medisch Centrum sleep staging database – and the spindle and aperiodic measurements use YASA and specparam.

Open the simulator

Audio Signal Generator

A dependency-free audio synthesis tool built on the Web Audio API. It is two generators that run independently, together or on their own, each with its own transport and volume.

The tone generator plays steady tones and modulates them at an exact low rate, using a different mechanism depending on what you select: a frequency offset between the ears, a loudness pulse, an opposite phase wobble in each ear, or a level swing between the ears. Carriers run from 30 Hz – low enough to be felt as much as heard – up to 700. Every parameter is stated in the interface: interaural phase excursion, monaural frequency deviation, peak interaural delay. It generates and measures signals, and makes no claims about what listening to them does.

The noise generator is the part I find most interesting. Past the ordinary noise colours there are six beds drawn from complex dynamics: avalanches with no typical size, turbulent intermittency, a sandpile held at its critical slope, bubble resonances, tunable 1/f noise, and Xenakis’s dynamic stochastic synthesis. Each is scale-free – no characteristic timescale – which is what keeps it from competing with the signal being measured.

Each generator has its own visualizer measuring the live output, so you can watch the spectrum, the interaural phase and the modulation rate as they are actually produced rather than as intended, and see the noise mechanisms at work: the avalanche size distribution, the sandpile itself, the cascade of multipliers.

Headphones are needed for the modes that depend on each ear receiving a different signal.

Open the generator

Seven small pieces, each drawn live in the browser by its own engine: iterated maps, woven current, a grid made cloth, a night given a voice, a dish taught to grow, a duet of rooms, and a finale that plays all of them from a single seed. Deterministic and self-contained – the same seed always draws the same image.

Open the gallery