Repository navigation
Releases
v0.1.0
The first release of Ramdac: indexed colour as an FFGL effect for Resolume Arena and Avenue, SW Ramdac (RM01). It forces a clip into the 4, 8 or 16 colours of a real machine (the Commodore 64, CGA, the ZX Spectrum, the Amstrad CPC, the NES, the Game Boy, PICO-8, teletext, the Amiga's Workbench), a palette you type, or one chosen from the clip. Then it does what indexed displays could do and nothing else could: swap the palette, fade it, and cycle it the way Deluxe Paint did.
The one idea. An indexed display worked by numbers. Every pixel held an index, and a chip, the RAMDAC, turned the index into a colour by looking it up in a small table. The plugin does the same to your clip: it averages it into cells, gives each cell the number of the nearest palette entry, judged in OKLab so that nearest is what your eye would pick, and shows you the table looked up by those numbers. Swaps, fades and colour cycling are writes to the table, so the numbers never move: the shapes, the edges and the dither stay exactly where they were while the colours change under them.
The controls. Palette: Palette (13: Adaptive, Custom, Teletext, CGA Mode 4, CGA 16, Commodore 64, ZX Spectrum, Amstrad CPC, NES, Game Boy, PICO-8, Workbench 1.3, Workbench 2.0), Colours (Adaptive's, 2–16), Adapt (how fast Adaptive follows the clip), Custom (hex colours you type), Order (Lightness, Native), DAC (24, 18, 12 or 9 bits). Dither: Dither (None, Bayer 2, 4 and 8, Blue Noise, Dot Diffusion: Knuth's error diffusion done in parallel on the GPU), Dither Amount, Pixel Size (1–16). Swap: Swap To, Swap, Swap Style (Cut, Fade in OKLab, or Ripple an entry at a time). Cycle: Cycle (Off, Forward, Reverse, Ping-Pong), Cycle Rate, Cycle Sync (Free, Beat, Bar), Cycle Start, Cycle Length, Cycle Blend (Step, Smooth). Output: Freeze (holds the numbers while the table carries on), Alpha (Keep, Opaque), Mix. The defaults are PICO-8 through Bayer 4 at Pixel Size 2, with a Fade to the Commodore 64 waiting on Swap.
Downloads: a universal macOS build (Apple silicon and Intel) as a .dmg or .zip, and a Windows x64 installer (-setup.exe) or .zip. Every archive carries ATTRIBUTIONS.md. The macOS build is Developer ID-signed and notarised minutes after publication; if macOS refuses a download, it's from before that, so download it again. The Windows build isn't signed, so SmartScreen warns once. The installer puts it in Documents\Resolume Arena\Extra Effects; point it at Avenue's folder if that's what you use, and quit Resolume first.
What is measured (offline, by tools/verify.sh on an Apple Silicon Mac under macOS 26, driving the plugin's own class in a headless GL context, at 1280×720 and 320×180 and again on Apple's software renderer):
- The quantiser. Every pixel is one of the table's entries, across all 11 fixed palettes, every dither, Adaptive and Custom, mid-cycle and mid-fade: 0 pixels outside it. With no dither, each cell's index is the OKLab-nearest entry by the harness's own route in double: 0 of 918 827 wrong on PICO-8 (2 773 near-ties, whose decision the input's own rounding could flip, counted and not judged). Bayer and Blue Noise put each cell exactly where Knoll's rule and its rank say (0 wrong); Dot Diffusion follows Knuth's recurrence cell by cell (0 off). On a still clip, all six dithers are still, bit for bit.
- The table. A Cut keeps all 921 600 indices; mid-Fade, no index shows two colours and none is off the OKLab line by more than a code; Ripple runs in index order. Cycling is the still picture with its table rotated, 0 of 100 frames wrong, and a period on it's the same bit for bit; a step a beat and a bar at 120 bpm, 0 of 87 wrong. A host clock 499 million ms into its session renders the same take as one at 0. Every channel lands on its DAC's grid.
- Adaptive settles inside the one-pole's own bound after a cut; under two codes of noise on every pixel no entry moves more than 0.0014 in OKLab a frame (a tenth of a just-noticeable difference); its k-means never ends worse than its median cut.
- The checks can fail. Eleven deliberately wrong models each fail their check, and 35 one-character mutants of the shipped GLSL and C++ are all caught. All 21 controls change the picture. The eleven tables match their published sources. The bundle is universal, and
oxbowreadsSW Ramdac/RM01/ effect with 26 parameters and renders 120 frames through it.
On Windows it has been in Resolume. The fleet's Arena gate ran this release workflow's own Windows build in Arena 7.27.1 on win-lab (software rendering, no GPU), twice: the DLL loads, registers as RM01 (an effect) and appears in Arena's list, all 27 controls (Arena's Opacity and the plugin's 26) match their names, order, types, ranges and defaults, it renders, and Arena's log stays clean: 9 passed, 0 failed, 1 skipped. Against a still, 15 of the plugin's controls changed the picture, seven of them once Adaptive, a swap or a cycle gave them something to act on. Adapt, Cycle Rate and Cycle Sync only set a pace, Freeze holds what a still already holds and Alpha needs a clip with coverage below 1, so a still can't measure those five; Custom, a text control, wasn't probed.
What isn't verified, or is a limit. It's never been loaded into Resolume on macOS. Nobody has watched Cycle Sync follow Arena's transport, run it on a GPU other than one Mac's, or measured what Resolume's own clips do to the frame rate at 4K. Dot Diffusion's tone runs light on a two-colour palette over flat dark greys (a 0.03 grey comes out at 0.12 in linear light); on real clips through PICO-8 or the C64 its mean light is within 2% of the clip's. Adaptive follows the clip at Adapt seconds, so a flash shorter than that is never fully reached: set Adapt to 0 for a strobing clip.
Cost, GPU time on an Apple Silicon Mac at Pixel Size 2: at the defaults (Bayer 4) 1.32 ms a frame at 1080p and 2.37 ms at 4K; no dither 0.42 and 1.52; Dot Diffusion about 3.7 ms at every size; Adaptive with Bayer 4, 3.12 and 6.09. Nothing was timed inside Resolume.
Not done. No presets and no OpenFX port.
- User guide: https://stoatworks-labs.com/software/ramdac/guide/
- Project page: https://stoatworks-labs.com/software/ramdac/
- Browser demo: https://ramdac-demo.stoatworks-labs.com/ (the plugin's own shaders over a JavaScript port of its CPU half; Cycle Sync counts a steady 120 BPM there)