Skip to content

Instantly share code, notes, and snippets.

@andrewrk
Last active January 29, 2024 16:05
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewrk/9638b092c1977adb6543de28e2ccb710 to your computer and use it in GitHub Desktop.
Save andrewrk/9638b092c1977adb6543de28e2ccb710 to your computer and use it in GitHub Desktop.
libsoundio zig example. zig build_exe sine.zig --library c --library soundio
const c = @cImport(@cInclude("soundio/soundio.h"));
const std = @import("std");
const io = std.io;
const cstr = std.cstr;
const panic = std.debug.panic;
const math = std.math;
fn sio_err(err: c_int) !void {
switch (@intToEnum(c.SoundIoError, err)) {
c.SoundIoError.None => {},
c.SoundIoError.NoMem => return error.NoMem,
c.SoundIoError.InitAudioBackend => return error.InitAudioBackend,
c.SoundIoError.SystemResources => return error.SystemResources,
c.SoundIoError.OpeningDevice => return error.OpeningDevice,
c.SoundIoError.NoSuchDevice => return error.NoSuchDevice,
c.SoundIoError.Invalid => return error.Invalid,
c.SoundIoError.BackendUnavailable => return error.BackendUnavailable,
c.SoundIoError.Streaming => return error.Streaming,
c.SoundIoError.IncompatibleDevice => return error.IncompatibleDevice,
c.SoundIoError.NoSuchClient => return error.NoSuchClient,
c.SoundIoError.IncompatibleBackend => return error.IncompatibleBackend,
c.SoundIoError.BackendDisconnected => return error.BackendDisconnected,
c.SoundIoError.Interrupted => return error.Interrupted,
c.SoundIoError.Underflow => return error.Underflow,
c.SoundIoError.EncodingString => return error.EncodingString,
}
}
var seconds_offset: f32 = 0;
extern fn write_callback(
maybe_outstream: ?[*]c.SoundIoOutStream,
frame_count_min: c_int,
frame_count_max: c_int,
) void {
const outstream = @ptrCast(*c.SoundIoOutStream, maybe_outstream);
const layout = &outstream.layout;
const float_sample_rate = outstream.sample_rate;
const seconds_per_frame = 1.0 / @intToFloat(f32, float_sample_rate);
var frames_left = frame_count_max;
while (frames_left > 0) {
var frame_count = frames_left;
var areas: [*]c.SoundIoChannelArea = undefined;
sio_err(c.soundio_outstream_begin_write(
maybe_outstream,
@ptrCast([*]?[*]c.SoundIoChannelArea, &areas),
(*[1]c_int)(&frame_count),
)) catch |err| panic("write failed: {}", @errorName(err));
if (frame_count == 0) break;
const pitch = 440.0;
const radians_per_second = pitch * 2.0 * math.pi;
{
var frame: c_int = 0;
while (frame < frame_count) : (frame += 1) {
const sample = math.sin((seconds_offset + @intToFloat(f32, frame) *
seconds_per_frame) * radians_per_second);
{
var channel: usize = 0;
while (channel < @intCast(usize, layout.channel_count)) : (channel += 1) {
const channel_ptr = areas[channel].ptr.?;
const sample_ptr = &channel_ptr[@intCast(usize, areas[channel].step * frame)];
@ptrCast(*f32, @alignCast(@alignOf(f32), sample_ptr)).* = sample;
}
}
}
}
seconds_offset += seconds_per_frame * @intToFloat(f32, frame_count);
sio_err(c.soundio_outstream_end_write(maybe_outstream)) catch |err| panic("end write failed: {}", @errorName(err));
frames_left -= frame_count;
}
}
pub fn main() void {
const soundio = c.soundio_create() orelse panic("out of mem");
defer c.soundio_destroy(soundio);
sio_err(c.soundio_connect(soundio)) catch |err| panic("unable to connect: {}", @errorName(err));
c.soundio_flush_events(soundio);
const default_output_index = c.soundio_default_output_device_index(soundio);
if (default_output_index < 0) panic("no output device found");
const device = c.soundio_get_output_device(soundio, default_output_index) orelse panic("out of mem");
defer c.soundio_device_unref(device);
std.debug.warn("Output device: {s}\n", device[0].name.?);
const outstream = c.soundio_outstream_create(device) orelse panic("out of memory");
defer c.soundio_outstream_destroy(outstream);
outstream[0].format = c.SoundIoFormatFloat32NE;
outstream[0].write_callback = write_callback;
sio_err(c.soundio_outstream_open(outstream)) catch |err| panic("unable to open stream: {}", @errorName(err));
sio_err(c.soundio_outstream_start(outstream)) catch |err| panic("unable to start stream: {}", @errorName(err));
while (true) c.soundio_wait_events(soundio);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment