sysaudio: improve backend selection; remove i8 sample support (#767)

* sysaudio: fix compilation errors
* re-order backend selection
* remove i8 samples support from backends and disable signedToSigned convertion for now
* update sine-wave example
This commit is contained in:
Ali Chraghi 2023-04-30 16:36:39 -07:00 committed by GitHub
parent 8fbc36999f
commit ed05166348
Failed to generate hash of commit
8 changed files with 64 additions and 89 deletions

View file

@ -44,14 +44,13 @@ pub fn main() !void {
const pitch = 440.0; const pitch = 440.0;
const radians_per_second = pitch * 2.0 * std.math.pi; const radians_per_second = pitch * 2.0 * std.math.pi;
var seconds_offset: f32 = 0.0; var seconds_offset: f32 = 0.0;
fn writeCallback(_: ?*anyopaque, n_frame: usize) void { fn writeCallback(_: ?*anyopaque, frames: usize) void {
const seconds_per_frame = 1.0 / @intToFloat(f32, player.sampleRate()); const seconds_per_frame = 1.0 / @intToFloat(f32, player.sampleRate());
var frame: usize = 0; for (0..frames) |fi| {
while (frame < n_frame) : (frame += 1) { const sample = std.math.sin((seconds_offset + @intToFloat(f32, fi) * seconds_per_frame) * radians_per_second);
const sample = std.math.sin((seconds_offset + @intToFloat(f32, frame) * seconds_per_frame) * radians_per_second); player.writeAll(fi, sample);
player.writeAll(frame, sample);
} }
seconds_offset = @mod(seconds_offset + seconds_per_frame * @intToFloat(f32, n_frame), 1.0); seconds_offset = @mod(seconds_offset + seconds_per_frame * @intToFloat(f32, frames), 1.0);
} }
fn deviceChange(_: ?*anyopaque) void { fn deviceChange(_: ?*anyopaque) void {

View file

@ -16,7 +16,9 @@ pub fn Sdk(comptime deps: anytype) type {
_module = b.createModule(.{ _module = b.createModule(.{
.source_file = .{ .path = sdkPath("/src/main.zig") }, .source_file = .{ .path = sdkPath("/src/main.zig") },
.dependencies = &.{ .dependencies = &.{
.{ .name = "sysjs", .module = deps.sysjs.module(b) }, .{ .name = "sysjs", .module = b.createModule(.{
.source_file = .{ .path = "libs/mach-sysjs/src/main.zig" },
}) },
}, },
}); });
return _module.?; return _module.?;

View file

@ -17,7 +17,7 @@ const lib = struct {
var snd_pcm_state: *const fn (?*c.snd_pcm_t) callconv(.C) c.snd_pcm_state_t = undefined; var snd_pcm_state: *const fn (?*c.snd_pcm_t) callconv(.C) c.snd_pcm_state_t = undefined;
var snd_pcm_pause: *const fn (?*c.snd_pcm_t, c_int) callconv(.C) c_int = undefined; var snd_pcm_pause: *const fn (?*c.snd_pcm_t, c_int) callconv(.C) c_int = undefined;
var snd_pcm_writei: *const fn (?*c.snd_pcm_t, ?*const anyopaque, c.snd_pcm_uframes_t) callconv(.C) c.snd_pcm_sframes_t = undefined; var snd_pcm_writei: *const fn (?*c.snd_pcm_t, ?*const anyopaque, c.snd_pcm_uframes_t) callconv(.C) c.snd_pcm_sframes_t = undefined;
var snd_pcm_recover: *const fn (?*c.snd_pcm_t, c_int, c_int) callconv(.C) c_int = undefined; var snd_pcm_prepare: *const fn (?*c.snd_pcm_t) callconv(.C) c_int = undefined;
var snd_pcm_info_set_device: *const fn (?*c.snd_pcm_info_t, c_uint) callconv(.C) void = undefined; var snd_pcm_info_set_device: *const fn (?*c.snd_pcm_info_t, c_uint) callconv(.C) void = undefined;
var snd_pcm_info_set_subdevice: *const fn (?*c.snd_pcm_info_t, c_uint) callconv(.C) void = undefined; var snd_pcm_info_set_subdevice: *const fn (?*c.snd_pcm_info_t, c_uint) callconv(.C) void = undefined;
var snd_pcm_info_get_name: *const fn (?*const c.snd_pcm_info_t) callconv(.C) [*c]const u8 = undefined; var snd_pcm_info_get_name: *const fn (?*const c.snd_pcm_info_t) callconv(.C) [*c]const u8 = undefined;
@ -71,7 +71,7 @@ const lib = struct {
snd_pcm_state = handle.lookup(@TypeOf(snd_pcm_state), "snd_pcm_state") orelse return error.SymbolLookup; snd_pcm_state = handle.lookup(@TypeOf(snd_pcm_state), "snd_pcm_state") orelse return error.SymbolLookup;
snd_pcm_pause = handle.lookup(@TypeOf(snd_pcm_pause), "snd_pcm_pause") orelse return error.SymbolLookup; snd_pcm_pause = handle.lookup(@TypeOf(snd_pcm_pause), "snd_pcm_pause") orelse return error.SymbolLookup;
snd_pcm_writei = handle.lookup(@TypeOf(snd_pcm_writei), "snd_pcm_writei") orelse return error.SymbolLookup; snd_pcm_writei = handle.lookup(@TypeOf(snd_pcm_writei), "snd_pcm_writei") orelse return error.SymbolLookup;
snd_pcm_recover = handle.lookup(@TypeOf(snd_pcm_recover), "snd_pcm_recover") orelse return error.SymbolLookup; snd_pcm_prepare = handle.lookup(@TypeOf(snd_pcm_prepare), "snd_pcm_prepare") orelse return error.SymbolLookup;
snd_pcm_info_set_device = handle.lookup(@TypeOf(snd_pcm_info_set_device), "snd_pcm_info_set_device") orelse return error.SymbolLookup; snd_pcm_info_set_device = handle.lookup(@TypeOf(snd_pcm_info_set_device), "snd_pcm_info_set_device") orelse return error.SymbolLookup;
snd_pcm_info_set_subdevice = handle.lookup(@TypeOf(snd_pcm_info_set_subdevice), "snd_pcm_info_set_subdevice") orelse return error.SymbolLookup; snd_pcm_info_set_subdevice = handle.lookup(@TypeOf(snd_pcm_info_set_subdevice), "snd_pcm_info_set_subdevice") orelse return error.SymbolLookup;
snd_pcm_info_get_name = handle.lookup(@TypeOf(snd_pcm_info_get_name), "snd_pcm_info_get_name") orelse return error.SymbolLookup; snd_pcm_info_get_name = handle.lookup(@TypeOf(snd_pcm_info_get_name), "snd_pcm_info_get_name") orelse return error.SymbolLookup;
@ -402,10 +402,7 @@ pub const Context = struct {
var fmt_arr = std.ArrayList(main.Format).init(self.allocator); var fmt_arr = std.ArrayList(main.Format).init(self.allocator);
inline for (std.meta.tags(main.Format)) |format| { inline for (std.meta.tags(main.Format)) |format| {
if (lib.snd_pcm_format_mask_test( if (lib.snd_pcm_format_mask_test(fmt_mask, toAlsaFormat(format)) != 0) {
fmt_mask,
toAlsaFormat(format) catch unreachable,
) != 0) {
try fmt_arr.append(format); try fmt_arr.append(format);
} }
} }
@ -465,7 +462,7 @@ pub const Context = struct {
if ((lib.snd_pcm_set_params( if ((lib.snd_pcm_set_params(
pcm, pcm,
toAlsaFormat(format) catch unreachable, toAlsaFormat(format),
c.SND_PCM_ACCESS_RW_INTERLEAVED, c.SND_PCM_ACCESS_RW_INTERLEAVED,
@intCast(c_uint, device.channels.len), @intCast(c_uint, device.channels.len),
sample_rate, sample_rate,
@ -584,19 +581,16 @@ pub const Player = struct {
ch.*.ptr = self.sample_buffer.ptr + self.format.frameSize(i); ch.*.ptr = self.sample_buffer.ptr + self.format.frameSize(i);
} }
var underrun = false;
while (!self.aborted.load(.Unordered)) { while (!self.aborted.load(.Unordered)) {
var frames_left = self.period_size; if (!underrun) {
while (frames_left > 0) { self.writeFn(self.user_data, self.period_size);
self.writeFn(self.user_data, frames_left); }
const n = lib.snd_pcm_writei(self.pcm, self.sample_buffer.ptr, frames_left); underrun = false;
if (n < 0) { const n = lib.snd_pcm_writei(self.pcm, self.sample_buffer.ptr, self.period_size);
if (lib.snd_pcm_recover(self.pcm, @intCast(c_int, n), 1) < 0) { if (n < 0) {
if (std.debug.runtime_safety) unreachable; _ = lib.snd_pcm_prepare(self.pcm);
return; underrun = true;
}
return;
}
frames_left -= @intCast(c_uint, n);
} }
} }
} }
@ -676,10 +670,9 @@ pub fn modeToStream(mode: main.Device.Mode) c_uint {
}; };
} }
pub fn toAlsaFormat(format: main.Format) !c.snd_pcm_format_t { pub fn toAlsaFormat(format: main.Format) c.snd_pcm_format_t {
return switch (format) { return switch (format) {
.u8 => c.SND_PCM_FORMAT_U8, .u8 => c.SND_PCM_FORMAT_U8,
.i8 => c.SND_PCM_FORMAT_S8,
.i16 => if (is_little) c.SND_PCM_FORMAT_S16_LE else c.SND_PCM_FORMAT_S16_BE, .i16 => if (is_little) c.SND_PCM_FORMAT_S16_LE else c.SND_PCM_FORMAT_S16_BE,
.i24 => if (is_little) c.SND_PCM_FORMAT_S24_3LE else c.SND_PCM_FORMAT_S24_3BE, .i24 => if (is_little) c.SND_PCM_FORMAT_S24_3LE else c.SND_PCM_FORMAT_S24_3BE,
.i24_4b => if (is_little) c.SND_PCM_FORMAT_S24_LE else c.SND_PCM_FORMAT_S24_BE, .i24_4b => if (is_little) c.SND_PCM_FORMAT_S24_LE else c.SND_PCM_FORMAT_S24_BE,

View file

@ -4,16 +4,16 @@ const std = @import("std");
pub const Backend = std.meta.Tag(BackendContext); pub const Backend = std.meta.Tag(BackendContext);
pub const BackendContext = switch (builtin.os.tag) { pub const BackendContext = switch (builtin.os.tag) {
.linux => union(enum) { .linux => union(enum) {
pulseaudio: *@import("pulseaudio.zig").Context,
jack: *@import("jack.zig").Context,
pipewire: *@import("pipewire.zig").Context,
alsa: *@import("alsa.zig").Context, alsa: *@import("alsa.zig").Context,
pipewire: *@import("pipewire.zig").Context,
jack: *@import("jack.zig").Context,
pulseaudio: *@import("pulseaudio.zig").Context,
dummy: *@import("dummy.zig").Context, dummy: *@import("dummy.zig").Context,
}, },
.freebsd, .netbsd, .openbsd, .solaris => union(enum) { .freebsd, .netbsd, .openbsd, .solaris => union(enum) {
pulseaudio: *@import("pulseaudio.zig").Context,
jack: *@import("jack.zig").Context,
pipewire: *@import("pipewire.zig").Context, pipewire: *@import("pipewire.zig").Context,
jack: *@import("jack.zig").Context,
pulseaudio: *@import("pulseaudio.zig").Context,
dummy: *@import("dummy.zig").Context, dummy: *@import("dummy.zig").Context,
}, },
.macos, .ios, .watchos, .tvos => union(enum) { .macos, .ios, .watchos, .tvos => union(enum) {
@ -39,16 +39,16 @@ pub const BackendContext = switch (builtin.os.tag) {
}; };
pub const BackendPlayer = switch (builtin.os.tag) { pub const BackendPlayer = switch (builtin.os.tag) {
.linux => union(enum) { .linux => union(enum) {
pulseaudio: *@import("pulseaudio.zig").Player,
jack: *@import("jack.zig").Player,
pipewire: *@import("pipewire.zig").Player,
alsa: *@import("alsa.zig").Player, alsa: *@import("alsa.zig").Player,
pipewire: *@import("pipewire.zig").Player,
jack: *@import("jack.zig").Player,
pulseaudio: *@import("pulseaudio.zig").Player,
dummy: *@import("dummy.zig").Player, dummy: *@import("dummy.zig").Player,
}, },
.freebsd, .netbsd, .openbsd, .solaris => union(enum) { .freebsd, .netbsd, .openbsd, .solaris => union(enum) {
pulseaudio: *@import("pulseaudio.zig").Player,
jack: *@import("jack.zig").Player,
pipewire: *@import("pipewire.zig").Player, pipewire: *@import("pipewire.zig").Player,
jack: *@import("jack.zig").Player,
pulseaudio: *@import("pulseaudio.zig").Player,
dummy: *@import("dummy.zig").Player, dummy: *@import("dummy.zig").Player,
}, },
.macos, .ios, .watchos, .tvos => union(enum) { .macos, .ios, .watchos, .tvos => union(enum) {

View file

@ -337,7 +337,7 @@ pub const Context = struct {
return error.OpeningDevice; return error.OpeningDevice;
} }
const stream_desc = createStreamDesc(options.format, options.sample_rate, device.channels.len); const stream_desc = try createStreamDesc(options.format, options.sample_rate, device.channels.len);
if (c.AudioUnitSetProperty( if (c.AudioUnitSetProperty(
audio_unit, audio_unit,
c.kAudioUnitProperty_StreamFormat, c.kAudioUnitProperty_StreamFormat,
@ -487,7 +487,6 @@ fn createStreamDesc(format: main.Format, sample_rate: u24, ch_count: usize) !c.A
.mSampleRate = @intToFloat(f64, sample_rate), .mSampleRate = @intToFloat(f64, sample_rate),
.mFormatID = c.kAudioFormatLinearPCM, .mFormatID = c.kAudioFormatLinearPCM,
.mFormatFlags = switch (format) { .mFormatFlags = switch (format) {
.i8 => c.kAudioFormatFlagIsSignedInteger,
.i16 => c.kAudioFormatFlagIsSignedInteger, .i16 => c.kAudioFormatFlagIsSignedInteger,
.i24 => c.kAudioFormatFlagIsSignedInteger, .i24 => c.kAudioFormatFlagIsSignedInteger,
.i32 => c.kAudioFormatFlagIsSignedInteger, .i32 => c.kAudioFormatFlagIsSignedInteger,
@ -500,7 +499,6 @@ fn createStreamDesc(format: main.Format, sample_rate: u24, ch_count: usize) !c.A
.mBytesPerFrame = format.frameSize(ch_count), .mBytesPerFrame = format.frameSize(ch_count),
.mChannelsPerFrame = @intCast(c_uint, ch_count), .mChannelsPerFrame = @intCast(c_uint, ch_count),
.mBitsPerChannel = switch (format) { .mBitsPerChannel = switch (format) {
.i8 => 8,
.i16 => 16, .i16 => 16,
.i24 => 24, .i24 => 24,
.i32 => 32, .i32 => 32,

View file

@ -213,24 +213,17 @@ pub const Player = struct {
f32 => floatToUnsigned(u8, sample), f32 => floatToUnsigned(u8, sample),
else => unreachable, else => unreachable,
}, },
.i8 => std.mem.bytesAsValue(i8, ptr[0..@sizeOf(i8)]).* = switch (@TypeOf(sample)) {
i8 => sample,
u8 => unsignedToSigned(i8, sample),
i16, i24, i32 => signedToSigned(i8, sample),
f32 => floatToSigned(i8, sample),
else => unreachable,
},
.i16 => std.mem.bytesAsValue(i16, ptr[0..@sizeOf(i16)]).* = switch (@TypeOf(sample)) { .i16 => std.mem.bytesAsValue(i16, ptr[0..@sizeOf(i16)]).* = switch (@TypeOf(sample)) {
i16 => sample, i16 => sample,
u8 => unsignedToSigned(i16, sample), u8 => unsignedToSigned(i16, sample),
i8, i24, i32 => signedToSigned(i16, sample), // i8, i24, i32 => signedToSigned(i16, sample),
f32 => floatToSigned(i16, sample), f32 => floatToSigned(i16, sample),
else => unreachable, else => unreachable,
}, },
.i24 => std.mem.bytesAsValue(i24, ptr[0..@sizeOf(i24)]).* = switch (@TypeOf(sample)) { .i24 => std.mem.bytesAsValue(i24, ptr[0..@sizeOf(i24)]).* = switch (@TypeOf(sample)) {
i24 => sample, i24 => sample,
u8 => unsignedToSigned(i24, sample), u8 => unsignedToSigned(i24, sample),
i8, i16, i32 => signedToSigned(i24, sample), // i8, i16, i32 => signedToSigned(i24, sample),
f32 => floatToSigned(i24, sample), f32 => floatToSigned(i24, sample),
else => unreachable, else => unreachable,
}, },
@ -238,7 +231,7 @@ pub const Player = struct {
.i32 => std.mem.bytesAsValue(i32, ptr[0..@sizeOf(i32)]).* = switch (@TypeOf(sample)) { .i32 => std.mem.bytesAsValue(i32, ptr[0..@sizeOf(i32)]).* = switch (@TypeOf(sample)) {
i32 => sample, i32 => sample,
u8 => unsignedToSigned(i32, sample), u8 => unsignedToSigned(i32, sample),
i8, i16, i24 => signedToSigned(i32, sample), // i8, i16, i24 => signedToSigned(i32, sample),
f32 => floatToSigned(i32, sample), f32 => floatToSigned(i32, sample),
else => unreachable, else => unreachable,
}, },
@ -377,7 +370,6 @@ pub const Channel = struct {
pub const Format = enum { pub const Format = enum {
u8, u8,
i8,
i16, i16,
i24, i24,
i24_4b, i24_4b,
@ -386,7 +378,7 @@ pub const Format = enum {
pub fn size(self: Format) u8 { pub fn size(self: Format) u8 {
return switch (self) { return switch (self) {
.u8, .i8 => 1, .u8 => 1,
.i16 => 2, .i16 => 2,
.i24 => 3, .i24 => 3,
.i24_4b, .i32, .f32 => 4, .i24_4b, .i32, .f32 => 4,
@ -395,7 +387,7 @@ pub const Format = enum {
pub fn validSize(self: Format) u8 { pub fn validSize(self: Format) u8 {
return switch (self) { return switch (self) {
.u8, .i8 => 1, .u8 => 1,
.i16 => 2, .i16 => 2,
.i24, .i24_4b => 3, .i24, .i24_4b => 3,
.i32, .f32 => 4, .i32, .f32 => 4,

View file

@ -327,7 +327,7 @@ pub const Context = struct {
const sample_rate = device.sample_rate.clamp(options.sample_rate); const sample_rate = device.sample_rate.clamp(options.sample_rate);
const sample_spec = c.pa_sample_spec{ const sample_spec = c.pa_sample_spec{
.format = toPAFormat(format) catch unreachable, .format = toPAFormat(format),
.rate = sample_rate, .rate = sample_rate,
.channels = @intCast(u5, device.channels.len), .channels = @intCast(u5, device.channels.len),
}; };
@ -459,33 +459,28 @@ pub const Player = struct {
var self = @ptrCast(*Player, @alignCast(@alignOf(*Player), user_data.?)); var self = @ptrCast(*Player, @alignCast(@alignOf(*Player), user_data.?));
var frames_left = nbytes; var frames_left = nbytes;
while (frames_left > 0) { if (lib.pa_stream_begin_write(
var chunk_size = frames_left; self.stream,
if (lib.pa_stream_begin_write( @ptrCast(
self.stream, [*c]?*anyopaque,
@ptrCast( @alignCast(@alignOf([*c]?*anyopaque), &self.write_ptr),
[*c]?*anyopaque, ),
@alignCast(@alignOf([*c]?*anyopaque), &self.write_ptr), &frames_left,
), ) != 0) {
&chunk_size, if (std.debug.runtime_safety) unreachable;
) != 0) { return;
if (std.debug.runtime_safety) unreachable; }
return;
}
for (self.channels, 0..) |*ch, i| { for (self.channels, 0..) |*ch, i| {
ch.*.ptr = self.write_ptr + self.format.frameSize(i); ch.*.ptr = self.write_ptr + self.format.frameSize(i);
} }
const frames = chunk_size / self.format.frameSize(self.channels.len); const frames = frames_left / self.format.frameSize(self.channels.len);
self.writeFn(self.user_data, frames); self.writeFn(self.user_data, frames);
if (lib.pa_stream_write(self.stream, self.write_ptr, chunk_size, null, 0, c.PA_SEEK_RELATIVE) != 0) { if (lib.pa_stream_write(self.stream, self.write_ptr, frames_left, null, 0, c.PA_SEEK_RELATIVE) != 0) {
if (std.debug.runtime_safety) unreachable; if (std.debug.runtime_safety) unreachable;
return; return;
}
frames_left -= chunk_size;
} }
} }
@ -616,7 +611,7 @@ pub fn fromPAChannelPos(pos: c.pa_channel_position_t) !main.Channel.Id {
c.PA_CHANNEL_POSITION_SIDE_RIGHT => .side_right, c.PA_CHANNEL_POSITION_SIDE_RIGHT => .side_right,
// TODO: .front_center? // TODO: .front_center?
c.PA_CHANNEL_POSITION_AUX0...c.PA_CHANNEL_POSITION_AUX31 => error.Invalid, c.PA_CHANNEL_POSITION_AUX0...c.PA_CHANNEL_POSITION_AUX31 => .front_center,
c.PA_CHANNEL_POSITION_TOP_CENTER => .top_center, c.PA_CHANNEL_POSITION_TOP_CENTER => .top_center,
c.PA_CHANNEL_POSITION_TOP_FRONT_LEFT => .top_front_left, c.PA_CHANNEL_POSITION_TOP_FRONT_LEFT => .top_front_left,
@ -630,7 +625,7 @@ pub fn fromPAChannelPos(pos: c.pa_channel_position_t) !main.Channel.Id {
}; };
} }
pub fn toPAFormat(format: main.Format) !c.pa_sample_format_t { pub fn toPAFormat(format: main.Format) c.pa_sample_format_t {
return switch (format) { return switch (format) {
.u8 => c.PA_SAMPLE_U8, .u8 => c.PA_SAMPLE_U8,
.i16 => if (is_little) c.PA_SAMPLE_S16LE else c.PA_SAMPLE_S16BE, .i16 => if (is_little) c.PA_SAMPLE_S16LE else c.PA_SAMPLE_S16BE,
@ -638,8 +633,6 @@ pub fn toPAFormat(format: main.Format) !c.pa_sample_format_t {
.i24_4b => if (is_little) c.PA_SAMPLE_S24_32LE else c.PA_SAMPLE_S24_32BE, .i24_4b => if (is_little) c.PA_SAMPLE_S24_32LE else c.PA_SAMPLE_S24_32BE,
.i32 => if (is_little) c.PA_SAMPLE_S32LE else c.PA_SAMPLE_S32BE, .i32 => if (is_little) c.PA_SAMPLE_S32LE else c.PA_SAMPLE_S32BE,
.f32 => if (is_little) c.PA_SAMPLE_FLOAT32LE else c.PA_SAMPLE_FLOAT32BE, .f32 => if (is_little) c.PA_SAMPLE_FLOAT32LE else c.PA_SAMPLE_FLOAT32BE,
.i8 => error.Invalid,
}; };
} }

View file

@ -327,7 +327,7 @@ pub const Context = struct {
var fmt_arr = std.ArrayList(main.Format).init(self.allocator); var fmt_arr = std.ArrayList(main.Format).init(self.allocator);
var closest_match: ?*win32.WAVEFORMATEX = null; var closest_match: ?*win32.WAVEFORMATEX = null;
for (std.meta.tags(main.Format)) |format| { for (std.meta.tags(main.Format)) |format| {
setWaveFormatFormat(wf, format) catch continue; setWaveFormatFormat(wf, format);
if (audio_client.?.IsFormatSupported( if (audio_client.?.IsFormatSupported(
.SHARED, .SHARED,
@ptrCast(?*const win32.WAVEFORMATEX, @alignCast(@alignOf(*win32.WAVEFORMATEX), wf)), @ptrCast(?*const win32.WAVEFORMATEX, @alignCast(@alignOf(*win32.WAVEFORMATEX), wf)),
@ -417,7 +417,7 @@ pub const Context = struct {
}; };
} }
fn setWaveFormatFormat(wf: *win32.WAVEFORMATEXTENSIBLE, format: main.Format) !void { fn setWaveFormatFormat(wf: *win32.WAVEFORMATEXTENSIBLE, format: main.Format) void {
switch (format) { switch (format) {
.u8, .i16, .i24, .i24_4b, .i32 => { .u8, .i16, .i24, .i24_4b, .i32 => {
wf.SubFormat = win32.CLSID_KSDATAFORMAT_SUBTYPE_PCM.*; wf.SubFormat = win32.CLSID_KSDATAFORMAT_SUBTYPE_PCM.*;
@ -425,7 +425,6 @@ pub const Context = struct {
.f32 => { .f32 => {
wf.SubFormat = win32.CLSID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT.*; wf.SubFormat = win32.CLSID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT.*;
}, },
.i8 => return error.Invalid,
} }
wf.Format.wBitsPerSample = format.sizeBits(); wf.Format.wBitsPerSample = format.sizeBits();
wf.Samples.wValidBitsPerSample = format.validSizeBits(); wf.Samples.wValidBitsPerSample = format.validSizeBits();
@ -488,7 +487,7 @@ pub const Context = struct {
.wValidBitsPerSample = format.validSizeBits(), .wValidBitsPerSample = format.validSizeBits(),
}, },
.dwChannelMask = toChannelMask(device.channels), .dwChannelMask = toChannelMask(device.channels),
.SubFormat = toSubFormat(format) catch return error.OpeningDevice, .SubFormat = toSubFormat(format),
}; };
if (!self.is_wine and audio_client3 != null) { if (!self.is_wine and audio_client3 != null) {
@ -608,7 +607,7 @@ pub const Context = struct {
return .{ .wasapi = player }; return .{ .wasapi = player };
} }
fn toSubFormat(format: main.Format) !win32.Guid { fn toSubFormat(format: main.Format) win32.Guid {
return switch (format) { return switch (format) {
.u8, .u8,
.i16, .i16,
@ -617,7 +616,6 @@ pub const Context = struct {
.i32, .i32,
=> win32.CLSID_KSDATAFORMAT_SUBTYPE_PCM.*, => win32.CLSID_KSDATAFORMAT_SUBTYPE_PCM.*,
.f32 => win32.CLSID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT.*, .f32 => win32.CLSID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT.*,
else => error.Invalid,
}; };
} }