sysaudio: access sample rate from field (except for jack) and add media role option
This commit is contained in:
parent
bb6a654c90
commit
7315d1ab62
6 changed files with 41 additions and 44 deletions
|
|
@ -422,11 +422,11 @@ pub const Context = struct {
|
||||||
.mixer = mixer.?,
|
.mixer = mixer.?,
|
||||||
.selem = selem.?,
|
.selem = selem.?,
|
||||||
.mixer_elm = mixer_elm.?,
|
.mixer_elm = mixer_elm.?,
|
||||||
.sample_rate = sample_rate,
|
|
||||||
.writeFn = writeFn,
|
.writeFn = writeFn,
|
||||||
.user_data = options.user_data,
|
.user_data = options.user_data,
|
||||||
.channels = device.channels,
|
.channels = device.channels,
|
||||||
.format = format,
|
.format = format,
|
||||||
|
.sample_rate = sample_rate,
|
||||||
.write_step = format.frameSize(device.channels.len),
|
.write_step = format.frameSize(device.channels.len),
|
||||||
};
|
};
|
||||||
return .{ .alsa = player };
|
return .{ .alsa = player };
|
||||||
|
|
@ -446,10 +446,10 @@ pub const Player = struct {
|
||||||
mixer_elm: *c.snd_mixer_elem_t,
|
mixer_elm: *c.snd_mixer_elem_t,
|
||||||
writeFn: main.WriteFn,
|
writeFn: main.WriteFn,
|
||||||
user_data: ?*anyopaque,
|
user_data: ?*anyopaque,
|
||||||
sample_rate: u24,
|
|
||||||
|
|
||||||
channels: []main.Channel,
|
channels: []main.Channel,
|
||||||
format: main.Format,
|
format: main.Format,
|
||||||
|
sample_rate: u24,
|
||||||
write_step: u8,
|
write_step: u8,
|
||||||
|
|
||||||
pub fn deinit(self: *Player) void {
|
pub fn deinit(self: *Player) void {
|
||||||
|
|
@ -557,10 +557,6 @@ pub const Player = struct {
|
||||||
|
|
||||||
return @intToFloat(f32, vol) / @intToFloat(f32, max_vol - min_vol);
|
return @intToFloat(f32, vol) / @intToFloat(f32, max_vol - min_vol);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sampleRate(self: Player) u24 {
|
|
||||||
return self.sample_rate;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn freeDevice(allocator: std.mem.Allocator, device: main.Device) void {
|
fn freeDevice(allocator: std.mem.Allocator, device: main.Device) void {
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,6 @@ const main = @import("main.zig");
|
||||||
const backends = @import("backends.zig");
|
const backends = @import("backends.zig");
|
||||||
const util = @import("util.zig");
|
const util = @import("util.zig");
|
||||||
|
|
||||||
pub const min_sample_rate = 8_000; // Hz
|
|
||||||
pub const max_sample_rate = 5_644_800; // Hz
|
|
||||||
|
|
||||||
const dummy_playback = main.Device{
|
const dummy_playback = main.Device{
|
||||||
.id = "dummy-playback",
|
.id = "dummy-playback",
|
||||||
.name = "Dummy Device",
|
.name = "Dummy Device",
|
||||||
|
|
@ -13,8 +10,8 @@ const dummy_playback = main.Device{
|
||||||
.channels = undefined,
|
.channels = undefined,
|
||||||
.formats = std.meta.tags(main.Format),
|
.formats = std.meta.tags(main.Format),
|
||||||
.sample_rate = .{
|
.sample_rate = .{
|
||||||
.min = min_sample_rate,
|
.min = main.min_sample_rate,
|
||||||
.max = max_sample_rate,
|
.max = main.max_sample_rate,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -25,8 +22,8 @@ const dummy_capture = main.Device{
|
||||||
.channels = undefined,
|
.channels = undefined,
|
||||||
.formats = std.meta.tags(main.Format),
|
.formats = std.meta.tags(main.Format),
|
||||||
.sample_rate = .{
|
.sample_rate = .{
|
||||||
.min = min_sample_rate,
|
.min = main.min_sample_rate,
|
||||||
.max = max_sample_rate,
|
.max = main.max_sample_rate,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -61,16 +58,15 @@ pub const Context = struct {
|
||||||
|
|
||||||
try self.devices_info.list.append(self.allocator, dummy_playback);
|
try self.devices_info.list.append(self.allocator, dummy_playback);
|
||||||
try self.devices_info.list.append(self.allocator, dummy_capture);
|
try self.devices_info.list.append(self.allocator, dummy_capture);
|
||||||
self.devices_info.list.items[0].channels = try self.allocator.alloc(main.Channel, 1);
|
|
||||||
self.devices_info.list.items[0].channels[0] = .{
|
|
||||||
.id = .front_center,
|
|
||||||
};
|
|
||||||
self.devices_info.list.items[1].channels = try self.allocator.alloc(main.Channel, 1);
|
|
||||||
self.devices_info.list.items[1].channels[0] = .{
|
|
||||||
.id = .front_center,
|
|
||||||
};
|
|
||||||
self.devices_info.setDefault(.playback, 0);
|
self.devices_info.setDefault(.playback, 0);
|
||||||
self.devices_info.setDefault(.capture, 1);
|
self.devices_info.setDefault(.capture, 1);
|
||||||
|
|
||||||
|
self.devices_info.list.items[0].channels = try self.allocator.alloc(main.Channel, 1);
|
||||||
|
self.devices_info.list.items[1].channels = try self.allocator.alloc(main.Channel, 1);
|
||||||
|
|
||||||
|
self.devices_info.list.items[0].channels[0] = .{ .id = .front_center };
|
||||||
|
self.devices_info.list.items[1].channels[0] = .{ .id = .front_center };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn devices(self: Context) []const main.Device {
|
pub fn devices(self: Context) []const main.Device {
|
||||||
|
|
@ -86,11 +82,11 @@ pub const Context = struct {
|
||||||
var player = try self.allocator.create(Player);
|
var player = try self.allocator.create(Player);
|
||||||
player.* = .{
|
player.* = .{
|
||||||
.allocator = self.allocator,
|
.allocator = self.allocator,
|
||||||
.sample_rate = options.sample_rate,
|
|
||||||
.is_paused = false,
|
.is_paused = false,
|
||||||
.vol = 1.0,
|
.vol = 1.0,
|
||||||
.channels = device.channels,
|
.channels = device.channels,
|
||||||
.format = options.format,
|
.format = options.format,
|
||||||
|
.sample_rate = options.sample_rate,
|
||||||
.write_step = 0,
|
.write_step = 0,
|
||||||
};
|
};
|
||||||
return .{ .dummy = player };
|
return .{ .dummy = player };
|
||||||
|
|
@ -99,12 +95,12 @@ pub const Context = struct {
|
||||||
|
|
||||||
pub const Player = struct {
|
pub const Player = struct {
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
sample_rate: u24,
|
|
||||||
is_paused: bool,
|
is_paused: bool,
|
||||||
vol: f32,
|
vol: f32,
|
||||||
|
|
||||||
channels: []main.Channel,
|
channels: []main.Channel,
|
||||||
format: main.Format,
|
format: main.Format,
|
||||||
|
sample_rate: u24,
|
||||||
write_step: u8,
|
write_step: u8,
|
||||||
|
|
||||||
pub fn deinit(self: *Player) void {
|
pub fn deinit(self: *Player) void {
|
||||||
|
|
@ -134,10 +130,6 @@ pub const Player = struct {
|
||||||
pub fn volume(self: Player) !f32 {
|
pub fn volume(self: Player) !f32 {
|
||||||
return self.vol;
|
return self.vol;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sampleRate(self: Player) u24 {
|
|
||||||
return self.sample_rate;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn freeDevice(allocator: std.mem.Allocator, device: main.Device) void {
|
fn freeDevice(allocator: std.mem.Allocator, device: main.Device) void {
|
||||||
|
|
|
||||||
|
|
@ -206,10 +206,12 @@ pub const Player = struct {
|
||||||
|
|
||||||
fn processCallback(n_frames: c.jack_nframes_t, self_opaque: ?*anyopaque) callconv(.C) c_int {
|
fn processCallback(n_frames: c.jack_nframes_t, self_opaque: ?*anyopaque) callconv(.C) c_int {
|
||||||
const self = @ptrCast(*Player, @alignCast(@alignOf(*Player), self_opaque.?));
|
const self = @ptrCast(*Player, @alignCast(@alignOf(*Player), self_opaque.?));
|
||||||
|
|
||||||
for (self.channels) |*ch, i| {
|
for (self.channels) |*ch, i| {
|
||||||
ch.*.ptr = @ptrCast([*]u8, c.jack_port_get_buffer(self.ports[i], n_frames));
|
ch.*.ptr = @ptrCast([*]u8, c.jack_port_get_buffer(self.ports[i], n_frames));
|
||||||
}
|
}
|
||||||
self.writeFn(self.user_data, n_frames);
|
self.writeFn(self.user_data, n_frames);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ const backends = @import("backends.zig");
|
||||||
|
|
||||||
pub const default_sample_rate = 44_100; // Hz
|
pub const default_sample_rate = 44_100; // Hz
|
||||||
pub const default_latency = 500 * std.time.us_per_ms; // μs
|
pub const default_latency = 500 * std.time.us_per_ms; // μs
|
||||||
|
pub const min_sample_rate = 8_000; // Hz
|
||||||
|
pub const max_sample_rate = 5_644_800; // Hz
|
||||||
|
|
||||||
pub const Backend = backends.Backend;
|
pub const Backend = backends.Backend;
|
||||||
pub const DeviceChangeFn = *const fn (self: ?*anyopaque) void;
|
pub const DeviceChangeFn = *const fn (self: ?*anyopaque) void;
|
||||||
|
|
@ -104,9 +106,18 @@ pub const Player = struct {
|
||||||
pub const Options = struct {
|
pub const Options = struct {
|
||||||
format: Format = .f32,
|
format: Format = .f32,
|
||||||
sample_rate: u24 = default_sample_rate,
|
sample_rate: u24 = default_sample_rate,
|
||||||
|
media_role: MediaRole = .default,
|
||||||
user_data: ?*anyopaque = null,
|
user_data: ?*anyopaque = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const MediaRole = enum {
|
||||||
|
default,
|
||||||
|
game,
|
||||||
|
music,
|
||||||
|
movie,
|
||||||
|
communication,
|
||||||
|
};
|
||||||
|
|
||||||
data: backends.BackendPlayer,
|
data: backends.BackendPlayer,
|
||||||
|
|
||||||
pub fn deinit(self: Player) void {
|
pub fn deinit(self: Player) void {
|
||||||
|
|
@ -185,7 +196,7 @@ pub const Player = struct {
|
||||||
|
|
||||||
pub fn write(self: Player, channel: Channel, frame: usize, sample: anytype) void {
|
pub fn write(self: Player, channel: Channel, frame: usize, sample: anytype) void {
|
||||||
switch (@TypeOf(sample)) {
|
switch (@TypeOf(sample)) {
|
||||||
f32, u8, i8, i16, i24, i32 => {},
|
u8, i8, i16, i24, i32, f32 => {},
|
||||||
else => @compileError(
|
else => @compileError(
|
||||||
\\invalid sample type. supported types are:
|
\\invalid sample type. supported types are:
|
||||||
\\u8, i8, i16, i24, i32, f32
|
\\u8, i8, i16, i24, i32, f32
|
||||||
|
|
@ -239,8 +250,11 @@ pub const Player = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sampleRate(self: Player) u24 {
|
pub fn sampleRate(self: Player) u24 {
|
||||||
return switch (self.data) {
|
return if (@hasField(Backend, "jack")) switch (self.data) {
|
||||||
inline else => |b| b.sampleRate(),
|
.jack => |b| b.sampleRate(),
|
||||||
|
inline else => |b| b.sample_rate,
|
||||||
|
} else switch (self.data) {
|
||||||
|
inline else => |b| b.sample_rate,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -282,11 +282,11 @@ pub const Context = struct {
|
||||||
.stream = stream.?,
|
.stream = stream.?,
|
||||||
.write_ptr = undefined,
|
.write_ptr = undefined,
|
||||||
.vol = 1.0,
|
.vol = 1.0,
|
||||||
.sample_rate = sample_rate,
|
|
||||||
.writeFn = writeFn,
|
.writeFn = writeFn,
|
||||||
.user_data = options.user_data,
|
.user_data = options.user_data,
|
||||||
.channels = device.channels,
|
.channels = device.channels,
|
||||||
.format = format,
|
.format = format,
|
||||||
|
.sample_rate = sample_rate,
|
||||||
.write_step = format.frameSize(device.channels.len),
|
.write_step = format.frameSize(device.channels.len),
|
||||||
};
|
};
|
||||||
return .{ .pulseaudio = player };
|
return .{ .pulseaudio = player };
|
||||||
|
|
@ -329,24 +329,25 @@ pub const Player = struct {
|
||||||
stream: *c.pa_stream,
|
stream: *c.pa_stream,
|
||||||
write_ptr: [*]u8,
|
write_ptr: [*]u8,
|
||||||
vol: f32,
|
vol: f32,
|
||||||
sample_rate: u24,
|
|
||||||
writeFn: main.WriteFn,
|
writeFn: main.WriteFn,
|
||||||
user_data: ?*anyopaque,
|
user_data: ?*anyopaque,
|
||||||
|
|
||||||
channels: []main.Channel,
|
channels: []main.Channel,
|
||||||
format: main.Format,
|
format: main.Format,
|
||||||
|
sample_rate: u24,
|
||||||
write_step: u8,
|
write_step: u8,
|
||||||
|
|
||||||
pub fn deinit(self: *Player) void {
|
pub fn deinit(self: *Player) void {
|
||||||
c.pa_threaded_mainloop_lock(self.main_loop);
|
c.pa_threaded_mainloop_lock(self.main_loop);
|
||||||
defer c.pa_threaded_mainloop_unlock(self.main_loop);
|
|
||||||
|
|
||||||
c.pa_stream_set_write_callback(self.stream, null, null);
|
c.pa_stream_set_write_callback(self.stream, null, null);
|
||||||
c.pa_stream_set_state_callback(self.stream, null, null);
|
c.pa_stream_set_state_callback(self.stream, null, null);
|
||||||
c.pa_stream_set_underflow_callback(self.stream, null, null);
|
c.pa_stream_set_underflow_callback(self.stream, null, null);
|
||||||
c.pa_stream_set_overflow_callback(self.stream, null, null);
|
c.pa_stream_set_overflow_callback(self.stream, null, null);
|
||||||
_ = c.pa_stream_disconnect(self.stream);
|
_ = c.pa_stream_disconnect(self.stream);
|
||||||
c.pa_stream_unref(self.stream);
|
c.pa_stream_unref(self.stream);
|
||||||
|
c.pa_threaded_mainloop_unlock(self.main_loop);
|
||||||
|
|
||||||
|
self.allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(self: *Player) !void {
|
pub fn start(self: *Player) !void {
|
||||||
|
|
@ -475,10 +476,6 @@ pub const Player = struct {
|
||||||
|
|
||||||
self.vol = @intToFloat(f32, info.*.volume.values[0]) / @intToFloat(f32, c.PA_VOLUME_NORM);
|
self.vol = @intToFloat(f32, info.*.volume.values[0]) / @intToFloat(f32, c.PA_VOLUME_NORM);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sampleRate(self: Player) u24 {
|
|
||||||
return self.sample_rate;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn freeDevice(allocator: std.mem.Allocator, device: main.Device) void {
|
fn freeDevice(allocator: std.mem.Allocator, device: main.Device) void {
|
||||||
|
|
|
||||||
|
|
@ -112,9 +112,9 @@ pub const Context = struct {
|
||||||
.is_paused = false,
|
.is_paused = false,
|
||||||
.writeFn = writeFn,
|
.writeFn = writeFn,
|
||||||
.user_data = options.user_data,
|
.user_data = options.user_data,
|
||||||
.sample_rate = options.sample_rate,
|
|
||||||
.channels = device.channels,
|
.channels = device.channels,
|
||||||
.format = .f32,
|
.format = .f32,
|
||||||
|
.sample_rate = options.sample_rate,
|
||||||
.write_step = @sizeOf(f32),
|
.write_step = @sizeOf(f32),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -138,10 +138,10 @@ pub const Player = struct {
|
||||||
is_paused: bool,
|
is_paused: bool,
|
||||||
writeFn: main.WriteFn,
|
writeFn: main.WriteFn,
|
||||||
user_data: ?*anyopaque,
|
user_data: ?*anyopaque,
|
||||||
sample_rate: u24,
|
|
||||||
|
|
||||||
channels: []main.Channel,
|
channels: []main.Channel,
|
||||||
format: main.Format,
|
format: main.Format,
|
||||||
|
sample_rate: u24,
|
||||||
write_step: u8,
|
write_step: u8,
|
||||||
|
|
||||||
pub fn deinit(self: *Player) void {
|
pub fn deinit(self: *Player) void {
|
||||||
|
|
@ -221,10 +221,6 @@ pub const Player = struct {
|
||||||
defer gain.deinit();
|
defer gain.deinit();
|
||||||
return @floatCast(f32, gain.get("value").view(.num));
|
return @floatCast(f32, gain.get("value").view(.num));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sampleRate(self: Player) u24 {
|
|
||||||
return self.sample_rate;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn freeDevice(allocator: std.mem.Allocator, device: main.Device) void {
|
fn freeDevice(allocator: std.mem.Allocator, device: main.Device) void {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue