pulp

PULP

Pretty Unweildy Linking Parts

or

Piled Up Lego Pieces

Nobody likes the pulp…

Web Interface

The official interactive web interface and interactive tutorials for Skred have been moved to their own dedicated repository.

Architecture

See parts/ARCHITECTURE.md for the runtime model, real-time boundaries, generated-source workflow, adoption options, and a guide to navigating the codebase.

For external C/C++ hosts, see parts/API_INTEGRATION.md for the generated distribution layout, compile/link examples, lifecycle, logging, feature, audio device, recording, and scope APIs.

Skode documentation:

Build

Most development happens from the parts directory:

cd parts

Features

Most synthesis and routing features (ADSR, FM, FILT, RECORD, TRACKS, etc.) are now permanent, non-optional parts of the core Skred engine.

The following system-level integrations can still be optionally toggled via CMake options (they are ON by default):

SKRED_KSYNTH # synchronous k-synth evaluation
SKRED_SCOPE  # shared-memory live audio publication
SKRED_UDP    # receive skode on UDP

API Releases

Changing VERSION on main publishes Linux x86-64, universal macOS, and Windows x86-64 maxed API packages to the matching v<version> GitHub Release. The release is created only after all three packages build and pass archive checks. Platform-qualified archives and SHA256SUMS are intended for external consumers such as ro-totem; see the API integration guide for asset names, download URLs, and static-link dependencies.

Native Build

make native
./build_native/mini-skred

Runtime builds default to Release; use make native BUILD_TYPE=Debug when an unoptimized debugging build is intentional.

To disable specific integrations manually with CMake:

cmake -B build_native -S . -DCMAKE_BUILD_TYPE=Release \
  -DSKRED_SCOPE=OFF -DSKRED_UDP=OFF
cmake --build build_native
./build_native/mini-skred

Windows Without NMake

On Windows, the easiest build path is CMake’s Ninja generator with Zig’s C compiler. This avoids NMake and does not require Visual Studio Build Tools. Install zig, cmake, and ninja, make sure they are on PATH, then run:

cd parts
cmake --preset windows-zig-ninja
cmake --build --preset windows-zig-ninja
.\build_windows_zig\mini-skred.exe

For a feature-rich Windows build, use the Windows maxed preset:

cmake --preset windows-zig-maxed
cmake --build --preset windows-zig-maxed
.\build_windows_zig_maxed\mini-skred.exe

windows-zig-maxed enables the portable maxed features, including Ksynth, MIDI, recording, and track-aligned delays. It intentionally omits SCOPE=1; the current CMake configuration rejects that feature on Windows even though scope-ipc.c contains a named-file-mapping backend.

If Zig reports cache or filesystem permission errors, point its caches at a writable directory before configuring:

$env:ZIG_LOCAL_CACHE_DIR = "$env:TEMP\pulp-zig-local-cache"
$env:ZIG_GLOBAL_CACHE_DIR = "$env:TEMP\pulp-zig-global-cache"

If your CMake is too old for presets, the equivalent manual command is:

cmake -G Ninja -B build_windows_zig -S . `
  -DCMAKE_TOOLCHAIN_FILE=cmake/zig-cc.cmake `
  -DCMAKE_BUILD_TYPE=Release
cmake --build build_windows_zig

Cross-Build Windows From Linux

Zig can also build the Windows executable from Linux without a Windows SDK. Simply run the Windows cross preset:

cd parts
cmake --preset cross-windows-zig-ninja
cmake --build --preset cross-windows-zig-ninja --target mini-skred
file build_cross_windows_zig/mini-skred.exe

For the portable feature-rich cross-build:

make -C parts cross-windows-zig-maxed

The same SCOPE=1 exclusion applies to the Windows cross maxed preset.


To keep the Windows executable in a stable repo-local directory, run:

```sh
make -C parts mini-skred-windows

This writes parts/out/windows-x86_64/mini-skred.exe; parts/out/ is ignored by Git.

To build a Windows API distribution from Linux:

make -C parts dist-api-windows

This installs the Windows headers, static library, DLL/import library, and mini-skred.exe under dist/windows-x86_64/skred-<version>-maxed/, then creates dist/windows-x86_64/skred-<version>-maxed.zip.

Multichannel WAV and Scope

The maxed build enables both RECORD and SCOPE:

cd parts
make maxed
./build_maxed/mini-skred

In the Mini-Skred REPL, route voices to optional stereo stems and start a ten-channel WAV recording:

v0 r1 w0 f440 a0 t.01,.2,.7,.3
v1 r2 w1 f660 a0 t.01,.2,.6,.3
[take.wav]/rg
v0 l1
v1 l1
/r?
/rs

take.wav contains interleaved 32-bit float audio at the active engine/device sample rate (44.1 kHz by default):

0 master L    1 master R
2 stem 1 L    3 stem 1 R
4 stem 2 L    5 stem 2 R
6 stem 3 L    7 stem 3 R
8 stem 4 L    9 stem 4 R

Stems 1 through 4 also own track-aligned delay lines. r1 through r4 select the stem and delay identity for a voice; ds amount sets how much of that voice feeds the selected track delay. Delay returns are heard in the master mix and included in the matching recording/scope stem.

For live scope publication, enter:

/sg
/s?

Then run this in another terminal:

cd parts
./build_maxed/scope_reader skred-scope 2048

Stop publication with /ss. A named, master-only, 250 ms ring can be started with [my-scope]/sg3,.25 and read with ./build_maxed/scope_reader my-scope 2048. WAV recording and scope publication may run at the same time.

Audio Latency and Real-Time Performance

Skred’s audio engine is built for extreme low-latency performance. By default, it bypasses safety buffers and OS-level resampling to give you the lowest possible latency between a command and sound output.

Because the engine runs “on the razor’s edge,” you might occasionally hear audio glitches or clicks if your Operating System fails to schedule the audio thread in time (which is common on desktop Linux). If you experience glitching or sequence-step lag, you can balance latency and stability using the following OS-specific tips:

1. Increase the Hardware Frame Buffer

You can manually increase the requested frame size at startup using the -r flag (no space):

./mini-skred -r512

A larger frame buffer (e.g., 512 or 1024) gives the OS significantly more time to wake up the audio thread, eliminating glitches at the cost of slightly higher interactive latency (e.g. playing a MIDI keyboard). Note that the internal sequencer is sample-accurate and its timing is completely unaffected by the frame buffer size.

2. Linux (ALSA / PulseAudio)

Standard Linux kernels are notoriously bad at real-time thread scheduling. If you run Skred directly on ALSA and hear dropouts:

3. WebAssembly (WASM)

WASM builds automatically use the WebAudio interactive latency hint and bypass internal buffers. For the absolute lowest WASM latency, ensure your browser is not heavily throttled and consider compiling Skred with Emscripten’s AUDIO_WORKLET support in the future to move audio processing off the main UI thread.

Validation

make test   # build and run the default test suite
make warn   # -Wall -Wextra -Wpedantic -Werror
make warn-maxed # strict canonical maxed-preset build and tests

To measure the synthesis portion of a 128-frame audio callback:

cmake --build build_native --target synth_callback_bench
./build_native/synth_callback_bench 32 5000

The report includes average and worst callback time, the callback deadline, average deadline load, and the number of measured deadline overruns.

WASM Build

make wasm

This builds the WASM binaries and places skred_api.js and skred_api.wasm inside build_wasm/.

Cross Compile

ARM 32-bit Linux:

make pi

This writes Zig cache data under /tmp.

If you want to invoke Zig directly with CMake, the equivalent compiler flag looks like:

cmake -B build_pi -S . \
  -DCMAKE_C_COMPILER="zig;cc;-target;arm-linux-gnueabihf" \
  -DUSE_EXTERNAL_KIT=ON \
cmake --build build_pi