LabSoundC is a minimalist C binding for the LabSound audio engine, designed for real-time game and synth environments. All objects are opaque handles owned by the context -- zero memory management overhead for the host. The pin-centric graph model exposes inputs, outputs, and parameters uniformly, making it ideal for visual node-graph editors. Wraps ~30 WebAudio-derived node types. Bindings for Python and Zig included.
- ~68 C functions covering the full LabSound API
- Opaque handle system (Node, Pin, Conn, Bus) with generational IDs
- Hybrid pin model: unified
ls_Pinfor enumeration + typedls_Output/ls_Input/ls_ParamInputfor connection safety - Complete parameter automation (
setValueAtTime,linearRamp,exponentialRamp,setTarget) - Audio-rate parameter modulation (connect oscillator output to filter frequency)
- Normalized name matching (case-insensitive, space-insensitive)
- 30 node types: oscillators, filters, delays, compressors, noise, ADSR, spatial audio, recording, custom DSP
- Python (ctypes) and Zig bindings
- Shared + static library builds
cd LabSoundC
cmake -B build .
cmake --build build
./build/labsoundc_demo # plays 4 procedural effectsC:
ls_ContextDesc desc = {0};
ls_Context* ctx = ls_context_create(&desc);
ls_Node osc = ls_node_create(ctx, "Oscillator");
ls_Node gain = ls_node_create(ctx, "Gain");
ls_Node dest = ls_destination_node(ctx);
ls_param_set_value(ctx, ls_node_param(ctx, gain, "gain").pin, 0.25f);
ls_connect(ctx, ls_node_output(ctx, osc, 0), ls_node_input(ctx, gain, 0));
ls_connect(ctx, ls_node_output(ctx, gain, 0), ls_node_input(ctx, dest, 0));
ls_node_start(ctx, osc, 0.0);Python:
with Context() as ctx:
osc = ctx.create_node("Oscillator")
gain = ctx.create_node("Gain")
gain.param("gain").value = 0.25
connect(osc.output(0), gain.input(0))
connect(gain.output(0), ctx.destination_node.input(0))
osc.start()
time.sleep(1)Zig:
var ctx = try Context.init(null);
defer ctx.deinit();
const osc = ctx.createNode("Oscillator");
const gain_node = ctx.createNode("Gain");
const dest = ctx.destinationNode();
gain_node.param(ctx, "gain").setValue(ctx, 0.25);
ctx.connect(osc.output(ctx, 0), gain_node.input(ctx, 0));
ctx.connect(gain_node.output(ctx, 0), dest.input(ctx, 0));
osc.start(ctx, 0.0);- BUILDING.md -- build instructions for C, Python, and Zig
- docs/manual.md -- full user's manual, API reference, and audio cookbook
The demo app (examples/demo.c) plays four procedural sound effects built entirely through the C API:
- Red Alert Warble -- FM sweep through a resonant filter bank with delay chorus
- Twittering Bird -- rapid FM chirps with randomized timing and envelope shaping
- Marble in a Tin Can -- noise bursts through tuned resonant filters simulating metal resonance
- Passing Train -- rhythmic chug with stereo panning sweep and simulated Doppler shift
Run a single demo with ./build/labsoundc_demo [1-4], or all four sequentially with no argument.
LabSoundC/
include/LabSoundC/LabSoundC.h C API header
src/LabSoundC.cpp Implementation
examples/ C smoke test + demo
bindings/python/ Python ctypes bindings
bindings/zig/ Zig idiomatic bindings
docs/manual.md User's manual
BSD-2-Clause. Copyright 2022-2026 Nick Porcino and the LabSound Authors.