diff options
-rw-r--r-- | examples/hrtf.zig | 3 | ||||
-rw-r--r-- | examples/play.zig | 5 | ||||
-rw-r--r-- | src/al.zig | 73 | ||||
-rw-r--r-- | src/sf.zig | 1 | ||||
-rw-r--r-- | src/zeal.zig | 41 |
5 files changed, 89 insertions, 34 deletions
diff --git a/examples/hrtf.zig b/examples/hrtf.zig index d90adff..2db3d78 100644 --- a/examples/hrtf.zig +++ b/examples/hrtf.zig @@ -56,7 +56,8 @@ pub fn main() !void { const source = try Source.init(); defer source.deinit() catch unreachable; try source.setSpatialize(al.TRUE); - try source.play(buffer); + try source.bind(buffer); + try source.play(); defer print("\n", .{}); while (try source.isPlaying()) { const offset = try source.getSecOffset(); diff --git a/examples/play.zig b/examples/play.zig index 2ad1db9..210972c 100644 --- a/examples/play.zig +++ b/examples/play.zig @@ -49,10 +49,11 @@ pub fn main() !void { const source = try Source.init(); defer source.deinit() catch unreachable; - try source.play(buffer); + try source.bind(buffer); + try source.play(); defer print("\n", .{}); while (try source.isPlaying()) { sleep(10_000_000); - defer print("\r{d:.1} s", .{ source.getSecOffset() }); + print("\r{d:.1} s", .{ source.getSecOffset() }); } } diff --git a/src/al.zig b/src/al.zig index bbde02e..a5164d6 100644 --- a/src/al.zig +++ b/src/al.zig @@ -16,7 +16,9 @@ // You should have received a copy of the GNU Lesser General Public License // along with zeal. If not, see <https://www.gnu.org/licenses/>. -const Child = @import("std").meta.Child; +const Child = meta.Child; +const Tag = meta.Tag; +const meta = @import("std").meta; usingnamespace @cImport({ @cInclude("AL/al.h"); @@ -36,21 +38,23 @@ pub const Error = error { OutOfMemory, }; +// FIXME: turn into enum pub const FALSE = AL_FALSE; pub const TRUE = AL_TRUE; pub const AUTO = AL_AUTO_SOFT; -pub const BUFFER = AL_BUFFER; -pub const POSITION = AL_POSITION; -pub const ORIENTATION = AL_ORIENTATION; -pub const PLAYING = AL_PLAYING; -pub const SEC_OFFSET = AL_SEC_OFFSET; -pub const SOURCE_STATE = AL_SOURCE_STATE; -pub const SOURCE_SPATIALIZE = AL_SOURCE_SPATIALIZE_SOFT; - pub const listener = struct { + const Property = enum(ALenum) { + gain = AL_GAIN, + position = AL_POSITION, + velocity = AL_VELOCITY, + orientation = AL_ORIENTATION, + meters_per_unit = AL_METERS_PER_UNIT, + }; + /// Set a property for the listener. - pub fn set(param: ALenum, value: anytype) Error!void { + pub fn set(property: Property, value: anytype) Error!void { + const param = @enumToInt(property); const T = @TypeOf(value); switch (T) { f32 => alListenerf(param, value), @@ -165,17 +169,42 @@ pub const source = struct { } } + const Property = enum(ALenum) { + pitch = AL_PITCH, + gain = AL_GAIN, + position = AL_POSITION, + velocity = AL_VELOCITY, + direction = AL_DIRECTION, + relative = AL_SOURCE_RELATIVE, + looping = AL_LOOPING, + buffer = AL_BUFFER, + state = AL_SOURCE_STATE, + sec_offset = AL_SEC_OFFSET, + spatialize = AL_SOURCE_SPATIALIZE_SOFT, + }; + + pub const State = enum(i32) { + initial = AL_INITIAL, + playing = AL_PLAYING, + paused = AL_PAUSED, + stopped = AL_STOPPED, + }; + /// Set a property for the source. - pub fn set(reference: u32, param: ALenum, value: anytype) Error!void { + pub fn set(reference: u32, property: Property, value: anytype) Error!void { + const param = @enumToInt(property); const T = @TypeOf(value); switch (T) { f32 => alSourcef(reference, param, value), i32 => alSourcei(reference, param, value), - else => switch (Child(T)) { - f32 => alSourcefv(reference, param, value[0..]), - i32 => alSourceiv(reference, param, value[0..]), - else => unreachable, - } + else => switch (@typeInfo(T)) { + .Enum => alSourcei(reference, param, @enumToInt(value)), + else => switch (Child(T)) { + f32 => alSourcefv(reference, param, value[0..]), + i32 => alSourceiv(reference, param, value[0..]), + else => unreachable, + }, + }, } switch (alGetError()) { @@ -189,12 +218,20 @@ pub const source = struct { } /// Get a scalar property from the source. - pub fn get(comptime T: type, reference: u32, param: ALenum) Error!T { + pub fn get(comptime T: type, reference: u32, property: Property) Error!T { + const param = @enumToInt(property); var value: T = undefined; switch (T) { f32 => alGetSourcef(reference, param, &value), i32 => alGetSourcei(reference, param, &value), - else => unreachable, + else => switch (@typeInfo(T)) { + .Enum => { + var raw: i32 = undefined; + alGetSourcei(reference, param, &raw); + value = @intToEnum(T, raw); + }, + else => unreachable, + }, } return switch (alGetError()) { diff --git a/src/sf.zig b/src/sf.zig index dca1cec..80cfd9e 100644 --- a/src/sf.zig +++ b/src/sf.zig @@ -78,6 +78,7 @@ pub const SndFile = struct { frames: usize) Error![]const i16 { const items = frames * @intCast(usize, self.channels); const memory = try allocator.alloc(i16, items); + errdefer allocator.free(memory); const n = sf_read_short(self.pimpl, memory.ptr, @intCast(i64, items)); return try allocator.realloc(memory, @intCast(usize, n)); } diff --git a/src/zeal.zig b/src/zeal.zig index 1749e28..b3126ec 100644 --- a/src/zeal.zig +++ b/src/zeal.zig @@ -80,13 +80,21 @@ pub const Context = struct { }; pub const listener = struct { + pub fn setMetersPerUnit(factor: f32) Error!void { + try al.listener.set(.meters_per_unit, factor); + } + pub fn setPosition(position: [3]f32) Error!void { - try al.listener.set(al.POSITION, position); + try al.listener.set(.position, position); + } + + pub fn setVelocity(velocity: [3]f32) Error!void { + try al.listener.set(.velocity, velocity); } pub fn setOrientation(at: [3]f32, up: [3]f32) Error!void { const orientation = [_]f32{ at[0], at[1], at[2], up[0], up[1], up[2] }; - try al.listener.set(al.ORIENTATION, orientation); + try al.listener.set(.orientation, orientation); } }; @@ -125,6 +133,7 @@ pub const Buffer = struct { pub fn init(audio: Audio) Error!Buffer { const reference = try al.buffer.create(); + errdefer al.buffer.destroy(&reference) catch unreachable; try al.buffer.fill(reference, audio.data, audio.frequency); return Buffer{ .reference = reference }; } @@ -146,30 +155,36 @@ pub const Source = struct { try al.source.destroy(&self.reference); } + pub fn bind(self: Source, buffer: Buffer) Error!void { + try al.source.set(self.reference, .buffer, + @intCast(i32, buffer.reference)); + } + /// Specify if the source always has 3D spatialization features (al.ON), /// never has 3D spatialization features (al.OFF), or if spatialization /// is enabled based on playing a mono sound or not (al.AUTO, default). pub fn setSpatialize(self: Source, value: i32) Error!void { - try al.source.set(self.reference, al.SOURCE_SPATIALIZE, value); + try al.source.set(self.reference, .spatialize, value); } - pub fn setPosition(self: Source, position: [3]f32) Error!void { - try al.source.set(self.reference, al.POSITION, position); + fn getState(self: Source) Error!al.source.State { + return try al.source.get(al.source.State, self.reference, .state); } pub fn isPlaying(self: Source) Error!bool { - const state = try al.source.get(i32, self.reference, al.SOURCE_STATE); - return state == al.PLAYING; + return (try self.getState()) == .playing; } - pub fn getSecOffset(self: Source) Error!f32 { - return try al.source.get(f32, self.reference, al.SEC_OFFSET); + pub fn play(self: Source) Error!void { + try al.source.play(self.reference); } - pub fn play(self: Source, buffer: Buffer) Error!void { - try al.source.set(self.reference, al.BUFFER, - @intCast(i32, buffer.reference)); - try al.source.play(self.reference); + pub fn setPosition(self: Source, position: [3]f32) Error!void { + try al.source.set(self.reference, .position, position); + } + + pub fn getSecOffset(self: Source) Error!f32 { + return try al.source.get(f32, self.reference, .sec_offset); } }; |