Skip to content
Projects

zig-gamedev/zaudio has 45 GitHub stars and 20 forks. GitHot measured 0 stars in 24 hours. Last checked 2026-11-15 01:40 UTC. Last push 2026-11-03.

How these counts are measured

What you can do

  • ResourceManager (missing methods)
  • Log (missing methods)
  • custom data sources
  • LpfNode // Low-Pass Filter

Measured star growth

in 24h
0
in 7 days
Collecting history
in 15 days
Collecting history
in 1 month
Collecting history

Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.

About

Zig build package and wrapper for https://github.com/mackron/miniaudio

Creative & Media

README.md

Original

zaudio

Zig build package and wrapper for miniaudio v0.11.25

As an example program please see audio experiments (wgpu).

Features

Provided structs:

  • Device
  • Engine
  • Sound
  • SoundGroup
  • NodeGraph
  • Fence
  • Context
  • ResourceManager (missing methods)
  • Log (missing methods)
  • DataSource
    • Waveform
    • Noise
    • custom data sources
  • Node
    • DataSourceNode
    • SplitterNode
    • BiquadNode
    • LpfNode // Low-Pass Filter
    • HpfNode // High-Pass Filter
    • NotchNode
    • PeakNode
    • LoshelfNode // Low Shelf Filter
    • HishelfNode // High Shelf Filter
    • DelayNode
    • custom nodes
  • Decoder (missing methods)
  • Encoder (missing methods)
  • DataConverter

Getting started

Add this package to build.zig.zon:

zig fetch --save git+https://github.com/zig-gamedev/zaudio.git

In your build.zig add:

pub fn build(b: *std.Build) void {
    const exe = b.addExecutable(.{ ... });

    const zaudio = b.dependency("zaudio", .{});
    exe.root_module.addImport("zaudio", zaudio.module("root"));
    exe.root_module.linkLibrary(zaudio.artifact("miniaudio"));
}

Now in your code you may import and use the high level API of zaudio:

const zaudio = @import("zaudio");

pub fn main() !void {
    ...
    zaudio.init(allocator);
    defer zaudio.deinit();

    const engine = try zaudio.Engine.create(null);
    defer engine.destroy();

    const music = try engine.createSoundFromFile(
        content_dir ++ "Broke For Free - Night Owl.mp3",
        .{ .flags = .{ .stream = true } },
    );
    defer music.destroy();
    try music.start();
    ...
}

Or use the low level API which is similar to the original miniaudio library, but because the callback function is bridged from the original C library, you must explicitly handle the errors at the callback level:

const zaudio = @import("zaudio");

pub fn main() !void {
  ...
  zaudio.init(std.heap.smp_allocator);
  defer zaudio.deinit();

  const decoder_config = zaudio.Decoder.Config.initDefault();
  var mp3_decoder = try zaudio.Decoder.createFromFile("testing_media/Accipiter Supersaw Demo.mp3", decoder_config);
  defer mp3_decoder.destroy();

  // device
  var device_config = zaudio.Device.Config.init(.playback);
  device_config.playback.format = zaudio.Format.float32;
  device_config.playback.channels = 2;
  device_config.sample_rate = SAMPLE_RATE;
  device_config.data_callback = data_callback; // we will fill that with actual signal source
  device_config.user_data = mp3_decoder;

  const device = zaudio.Device.create(null, device_config) catch {
      @panic("Failed to open playback device");
  };
  defer device.destroy();

  zaudio.Device.start(device) catch {
      zaudio.Device.destroy(device);
      @panic("Failed to start playback device");
  };
  ...
}

fn data_callback(device: *zaudio.Device, pOutput: ?*anyopaque, _: ?*const anyopaque, frame_count: u32) callconv(.c) void {
    const decoder_opt: ?*zaudio.Decoder = @ptrCast(device.getUserData());

    if (decoder_opt) |decoder| {
        var frames_read: u64 = 0;

        _ = try decoder.readPCMFrames(pOutput.?, frame_count) catch |err| {
            std.debug.print("ERROR: {any}", .{err});
            return;
        };

        if (frames_read < frame_count) {
            decoder.seekToPCMFrames(0) catch {
                @panic("cannot seek");
            };
        }
    } else {
        return;
    }
}