diff options
-rw-r--r-- | src/al.zig | 57 | ||||
-rw-r--r-- | src/main.zig | 58 |
2 files changed, 102 insertions, 13 deletions
diff --git a/src/al.zig b/src/al.zig index e806e90..bfb93b6 100644 --- a/src/al.zig +++ b/src/al.zig @@ -1,4 +1,4 @@ -// Audio Library wrapper +// OpenAL wrapper // Copyright (C) 2021 Nguyễn Gia Phong // // This file is part of zeal. @@ -20,11 +20,26 @@ const Child = @import("std").meta.Child; usingnamespace @cImport(@cInclude("AL/al.h")); +pub const Error = error { + /// Bad name (ID) passed to an OpenAL function. + InvalidName, + /// Invalid enum parameter passed to an OpenAL function. + InvalidEnum, + /// Invalid value parameter passed to an OpenAL function. + InvalidValue, + /// Requested operation invalid. + InvalidOperation, + /// Requested operation resulted in OpenAL running out of memory. + OutOfMemory, +}; + pub const POSITION = AL_POSITION; pub const ORIENTATION = AL_ORIENTATION; pub const listener = struct { - pub fn set(comptime T: type, param: ALenum, value: T) void { + /// Set a property for the listener. + pub fn set(param: ALenum, value: anytype) !void { + const T = @TypeOf(value); switch (T) { f32 => alListenerf(param, value), i32 => alListeneri(param, value), @@ -34,12 +49,48 @@ pub const listener = struct { else => unreachable, } } + + switch (alGetError()) { + AL_NO_ERROR => {}, + AL_INVALID_VALUE => return Error.InvalidValue, + AL_INVALID_ENUM => return Error.InvalidEnum, + AL_INVALID_OPERATION => return Error.InvalidOperation, + else => unreachable, + } } }; +/// Generate one buffer for audio data and return its reference. +pub fn genBuffer() !u32 { + var reference: u32 = undefined; + alGenBuffers(1, &reference); + return switch (alGetError()) { + AL_NO_ERROR => reference, + AL_INVALID_VALUE => Error.InvalidValue, + AL_OUT_OF_MEMORY => Error.OutOfMemory, + else => unreachable, + }; +} + +// TODO: genBuffers + +/// Free resources used by one buffer. +/// Buffers attached to a source cannot be deleted. +pub fn deleteBuffer(reference: *const u32) !void { + alDeleteBuffers(1, reference); + switch (alGetError()) { + AL_NO_ERROR => {}, + AL_INVALID_OPERATION => return Error.InvalidOperation, + AL_INVALID_NAME => return Error.InvalidName, + AL_INVALID_VALUE => return Error.InvalidValue, + else => unreachable, + } +} + +// TODO: deleteBuffers + // alBufferData // alDeleteSources -// alGenBuffers // alGenSources // alGetSourcei // alSourcef diff --git a/src/main.zig b/src/main.zig index fc13fa8..21e4f3a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -18,7 +18,7 @@ const al = @import("al.zig"); const alc = @import("alc.zig"); -const expect = std.testing.expect; +const expectEqual = std.testing.expectEqual; const eql = std.meta.eql; const std = @import("std"); @@ -73,34 +73,72 @@ pub const Listener = struct { pub fn setPosition(self: Listener, position: [3]f32) !void { try checkContext(self.context); - al.listener.set([3]f32, al.POSITION, position); + try al.listener.set(al.POSITION, position); } pub fn setOrientation(self: Listener, at: [3]f32, up: [3]f32) !void { try checkContext(self.context); const orientation = [_]f32{ at[0], at[1], at[2], up[0], up[1], up[2] }; - al.listener.set(@TypeOf(orientation), al.ORIENTATION, orientation); + try al.listener.set(al.ORIENTATION, orientation); } }; -test "temporary" { +pub const Buffer = struct { + context: Context, + reference: u32, + + pub fn init(context: Context, name: []const u8) !Buffer { + try checkContext(context); + const reference = try al.genBuffer(); + return Buffer{ .context = context, .reference = reference }; + } + + pub fn deinit(self: Buffer) !void { + try checkContext(self.context); + try al.deleteBuffer(&self.reference); + } +}; + +test "Device" { const device = try Device.init("OpenAL Soft"); + try device.deinit(); +} + +test "Context" { + const device = try Device.init(null); defer device.deinit() catch unreachable; const context = try Context.init(device, &.{ alc.HRTF, alc.TRUE }); defer context.deinit() catch unreachable; - try expect(null == try currentContext()); - if (checkContext(context)) |_| unreachable else |err| switch (err) { + try expectEqual(try currentContext(), null); + if (checkContext(context)) unreachable else |err| switch (err) { error.UncurrentContext => {}, } try useContext(context); const current_context = (try currentContext()).?; - try expect(eql(current_context, context)); - try expect(eql(current_context.device, device)); + try expectEqual(current_context, context); + try expectEqual(current_context.device, device); try checkContext(context); +} + +test "Listener" { + const context = try Context.init(try Device.init(null), &.{}); + defer context.device.deinit() catch unreachable; + defer context.deinit() catch unreachable; + try useContext(context); const listener = Listener{ .context = context }; - try listener.setPosition(.{ 0, 0, 0 }); - try listener.setOrientation(.{ 0, 0, 0 }, .{ 0, 0, 0 }); + try listener.setPosition(.{ 1, 2, 3 }); + try listener.setOrientation(.{ 4, 5, 6 }, .{ 7, 8, 9 }); +} + +test "Buffer" { + const context = try Context.init(try Device.init(null), &.{}); + defer context.device.deinit() catch unreachable; + defer context.deinit() catch unreachable; + + try useContext(context); + const buffer = try Buffer.init(context, ""); + defer buffer.deinit() catch unreachable; } |