-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.zig
102 lines (82 loc) · 3.97 KB
/
main.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
const c = @cImport(@cInclude("soundio/soundio.h"));
const std = @import("std");
fn sio_err(err: c_int) !void {
switch (err) {
c.SoundIoErrorNone => {},
c.SoundIoErrorNoMem => return error.NoMem,
c.SoundIoErrorInitAudioBackend => return error.InitAudioBackend,
c.SoundIoErrorSystemResources => return error.SystemResources,
c.SoundIoErrorOpeningDevice => return error.OpeningDevice,
c.SoundIoErrorNoSuchDevice => return error.NoSuchDevice,
c.SoundIoErrorInvalid => return error.Invalid,
c.SoundIoErrorBackendUnavailable => return error.BackendUnavailable,
c.SoundIoErrorStreaming => return error.Streaming,
c.SoundIoErrorIncompatibleDevice => return error.IncompatibleDevice,
c.SoundIoErrorNoSuchClient => return error.NoSuchClient,
c.SoundIoErrorIncompatibleBackend => return error.IncompatibleBackend,
c.SoundIoErrorBackendDisconnected => return error.BackendDisconnected,
c.SoundIoErrorInterrupted => return error.Interrupted,
c.SoundIoErrorUnderflow => return error.Underflow,
c.SoundIoErrorEncodingString => return error.EncodingString,
else => return error.Unknown,
}
}
var seconds_offset: f32 = 0;
fn write_callback(
maybe_outstream: ?[*]c.SoundIoOutStream,
frame_count_min: c_int,
frame_count_max: c_int,
) callconv(.C) void {
_ = frame_count_min;
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),
&frame_count,
)) catch |err| std.debug.panic("write failed: {s}", .{@errorName(err)});
if (frame_count == 0) break;
const pitch = 440.0;
const radians_per_second = pitch * 2.0 * std.math.pi;
var frame: c_int = 0;
while (frame < frame_count) : (frame += 1) {
const sample = std.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| std.debug.panic("end write failed: {s}", .{@errorName(err)});
frames_left -= frame_count;
}
}
pub fn main() !void {
const soundio = c.soundio_create();
defer c.soundio_destroy(soundio);
try sio_err(c.soundio_connect(soundio));
c.soundio_flush_events(soundio);
const default_output_index = c.soundio_default_output_device_index(soundio);
if (default_output_index < 0) return error.NoOutputDeviceFound;
const device = c.soundio_get_output_device(soundio, default_output_index) orelse return error.OutOfMemory;
defer c.soundio_device_unref(device);
std.debug.print("Output device: {s}\n", .{device.*.name});
const outstream = c.soundio_outstream_create(device) orelse return error.OutOfMemory;
defer c.soundio_outstream_destroy(outstream);
outstream.*.format = c.SoundIoFormatFloat32NE;
outstream.*.write_callback = write_callback;
try sio_err(c.soundio_outstream_open(outstream));
try sio_err(c.soundio_outstream_start(outstream));
while (true) c.soundio_wait_events(soundio);
}