Some GLSL-Fun

The visualizer video for Moonchild’s “The Other Side” caught me the first time I saw it: calm music, and a scene just as calm, a boat on a night sea under an aurora. I was deep into Shadertoy back then, so I tried to rebuild that scene from techniques I picked up in other shaders. It got somewhere, but never to a state I wanted to publish.

AI-assisted development got me past the point where I had given up, and I could finally finish what I had in mind for that shader. The workflow was fun enough that I went straight on to a second one: an animated version of “imperfection”, an image I once made with generative AI.

Continue reading “Some GLSL-Fun”

go-whistle: Whistle speech-to-text in pure Go, rebuilt from the weights

Whistle is a speech-to-text model from Cactus Compute: 55 million parameters and 16.9 MB on disk, covering seven languages (English, German, French, Spanish, Italian, Dutch and Polish). The weights are published under Apache-2.0, but the code that runs them is not. Upstream, in cactus-compute/needle, Whistle is a thin Python wrapper around a prebuilt, closed-source C++ engine. go-whistle is my pure-Go port: no cgo, no Python, no ONNX. It does transcription with language detection, keyword biasing, word timestamps, live streaming and embeddings, from a CLI, an HTTP/WebSocket server, a Go library, or a WebAssembly page in the browser.

Continue reading “go-whistle: Whistle speech-to-text in pure Go, rebuilt from the weights”

Pocket-sized speech, in Go

Kyutai’s PocketTTS is a text-to-speech model small enough to run on a CPU. Its reference implementation is Python and PyTorch. go-pocket-tts runs the same model as a single Go binary: it reads the safetensors weights directly and needs neither Python nor ONNX Runtime.

It got one sentence in Audio on Linux, in Go. It deserves more than that, because upstream has moved on since then: a September model, German, a 24-layer variant and a new kind of sampler. This weekend I brought the port up to upstream v3.3.0. That came to 25 pull requests and 116 commits in two days, and German is part of it.

Continue reading “Pocket-sized speech, in Go”

PixelParade: a music video, computed

PixelParade is an 86-second chiptune instrumental generated with Suno: a bright pulse arpeggio in G major at 105 BPM, with a band that comes and goes around it. On Saturday I wanted a music video for it. I left the work to Codex and Claude and tried to give them as few instructions as possible. By the evening there were three. Every frame is computed from the song itself, and nothing in the picture is improvised by a browser FFT at playback time.

Continue reading “PixelParade: a music video, computed”

go-signal: Signal on the command line, in pure Go

I wanted to send and read Signal messages from a script, and let an AI agent do the same, without running a Java runtime next to it. signal-cli is the established tool, but it needs a JVM. So on 25 September I started go-signal, a Signal client for the command line written in Go. It ships as a single static binary for Linux, macOS and Windows, and since the second release it contains no Rust or C either.

Continue reading “go-signal: Signal on the command line, in pure Go”

qmc: evenly spread points for Go

Many programs need random points: to estimate an integral, to sample a parameter space, or to send rays through a room. Random points are easy to make, but they clump and leave gaps. Quasi-Monte Carlo sequences such as Sobol and Halton place points so that they fill the space evenly, and for many problems that gives the same accuracy with far fewer points. qmc is a small Go library for these sequences, with no dependencies. I started it in August and have just given it a thorough review.

Continue reading “qmc: evenly spread points for Go”

go-sofa and go-hdf5: how a head hears, in pure Go

A SOFA file describes how a head hears. SOFA (Spatially Oriented Format for Acoustics, standardised as AES69) stores head-related transfer functions: for hundreds or thousands of directions, the impulse response from a loudspeaker at that direction to a microphone in each ear. With such a set you can place any sound anywhere around a listener on headphones. I wrote my first SOFA reader, PasSofa, in Object Pascal in 2017, and ported it to JavaScript as WebSofa. Now there is go-sofa, which reads and writes SOFA files in pure Go, on top of my fork of a pure-Go HDF5 library, go-hdf5. Both started in February. On the last weekend of September they got about 230 commits and 39,000 added lines. Every figure in this post was made by a Go program that reads the files with go-sofa or go-hdf5.

Continue reading “go-sofa and go-hdf5: how a head hears, in pure Go”

WaterColorMap: painting Hanover from OpenStreetMap, a work in progress

For years, one of the nicest maps on the web looked hand-painted: Stamen’s Watercolor tiles, OpenStreetMap rendered with paper texture, soft washes and frayed edges. WaterColorMap is my attempt to rebuild that look in Go, from raw OpenStreetMap data. It is a work in progress. The tiles come out and fit together, but there is no map yet that you could simply visit. This is where it stands, painted over Hanover, the city all its tests are run against.

Continue reading “WaterColorMap: painting Hanover from OpenStreetMap, a work in progress”