Skip to content

Instantly share code, notes, and snippets.

@ul
Created September 27, 2018 15:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ul/707fa1df7174a8cda343e98d8e7f3931 to your computer and use it in GitHub Desktop.
Save ul/707fa1df7174a8cda343e98d8e7f3931 to your computer and use it in GitHub Desktop.
const sio = @cImport({
@cInclude("soundio/soundio.h");
});
const warn = @import("std").debug.warn;
const panic = @import("std").debug.panic;
const math = @import("std").math;
const PI = 3.14159265358979323846264338328;
const pitch = 440.0;
const radians_per_second = pitch * 2.0 * PI;
var seconds_offset: f64 = 0.0;
extern fn writeCallback(outstream: ?[*]sio.SoundIoOutStream, frame_count_min: c_int, frame_count_max: c_int) void {
if (outstream) |stream| {
const layout = stream.*.layout;
const channel_count = @intCast(usize, layout.channel_count);
const float_sample_rate = stream.*.sample_rate;
const seconds_per_frame = 1.0 / @intToFloat(f64, float_sample_rate);
var areas: [*]sio.SoundIoChannelArea = undefined;
var err: c_int = 0;
var frames_left = frame_count_max;
while (true) {
var frame_count = frames_left;
err = sio.soundio_outstream_begin_write(
outstream,
@ptrCast(?[*]?[*]sio.SoundIoChannelArea, &areas),
@ptrCast(?[*]c_int, &frame_count));
if (err > 0) {
panic("unrecoverable stream error: {s}", sio.soundio_strerror(err));
}
if (frame_count == 0) { break; }
var frame: c_int = 0;
while (frame < frame_count) : (frame += 1) {
const sample = math.sin((seconds_offset + @intToFloat(f64, frame) * seconds_per_frame) * radians_per_second);
var channel: usize = 0;
while (channel < channel_count) : (channel += 1) {
@intToPtr(
*f32,
@ptrToInt(areas[channel].ptr) +
@intCast(usize, frame * areas[channel].step)
).* = @floatCast(f32, sample);
}
}
seconds_offset = @mod(seconds_offset + seconds_per_frame * @intToFloat(f64, frame_count), 1.0);
err = sio.soundio_outstream_end_write(stream);
if (err > 0 and err != @enumToInt(sio.SoundIoErrorUnderflow)) {
panic("unrecoverable stream error: {s}", sio.soundio_strerror(err));
}
frames_left -= frame_count;
if (frames_left <= 0) { break; }
}
}
}
pub fn main() u8 {
const soundio = sio.soundio_create() orelse {
warn("out of memory");
return 1;
};
defer sio.soundio_destroy(soundio);
var err = sio.soundio_connect(soundio);
if (err > 0) {
warn("unable to connect to backend: {s}", sio.soundio_strerror(err));
return 1;
}
const backend_name = sio.soundio_backend_name(soundio.*.current_backend) orelse c"<Unknown>";
warn("Backend: {s}\n", backend_name);
sio.soundio_flush_events(soundio);
const dev_id = sio.soundio_default_output_device_index(soundio);
if (dev_id < 0) {
warn("output device not found");
return 1;
}
const device = sio.soundio_get_output_device(soundio, dev_id) orelse {
warn("out of memory");
return 1;
};
defer sio.soundio_device_unref(device);
const device_name = device.*.name;
warn("Output device: {s}\n", device_name);
if (device.*.probe_error > 0) {
warn("cannot probe device");
return 1;
}
const outstream = sio.soundio_outstream_create(device) orelse {
warn("out of memory");
return 1;
};
defer sio.soundio_outstream_destroy(outstream);
outstream.*.write_callback = writeCallback;
outstream.*.format = sio.SoundIoFormatFloat32NE;
err = sio.soundio_outstream_open(outstream);
if (err > 0) {
warn("unable to open device: {s}", sio.soundio_strerror(err));
return 1;
}
if (outstream.*.layout_error > 0) {
warn("unable to set channel layout: {s}", sio.soundio_strerror(err));
return 1;
}
err = sio.soundio_outstream_start(outstream);
if (err > 0) {
warn("unable to start device: {s}", sio.soundio_strerror(err));
return 1;
}
sio.soundio_wait_events(soundio);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment