diff --git a/build.zig b/build.zig index 659af323f..b58e90e4a 100644 --- a/build.zig +++ b/build.zig @@ -7,6 +7,8 @@ pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const module = b.addModule("mach-flac", .{ .source_file = .{ .path = "src/lib.zig" } }); + const sysaudio_dep = b.dependency("mach_sysaudio", .{ .target = target, .optimize = optimize }); + const main_test = b.addTest(.{ .root_source_file = .{ .path = "src/lib.zig" }, .target = target, @@ -25,10 +27,7 @@ pub fn build(b: *std.Build) void { .optimize = optimize, }); example.addModule("mach-flac", module); - example.addModule("mach-sysaudio", b.dependency("mach_sysaudio", .{ - .target = target, - .optimize = optimize, - }).module("mach-sysaudio")); + example.addModule("mach-sysaudio", sysaudio_dep.module("mach-sysaudio")); link(b, example); sysaudio.link(b, example); b.installArtifact(example); @@ -41,8 +40,6 @@ pub fn build(b: *std.Build) void { } pub fn link(b: *std.Build, step: *std.build.CompileStep) void { - step.linkLibrary(b.dependency("flac", .{ - .target = step.target, - .optimize = step.optimize, - }).artifact("flac")); + const libflac_dep = b.dependency("flac", .{ .target = step.target, .optimize = step.optimize }); + step.linkLibrary(libflac_dep.artifact("flac")); } diff --git a/build.zig.zon b/build.zig.zon index 0221e4e7b..59ca9733e 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -13,16 +13,16 @@ }, .dependencies = .{ .flac = .{ - .url = "https://pkg.machengine.org/flac/158f9c75675f36f50fe1e17537194ee592920b1f.tar.gz", - .hash = "1220a94ab7ce73640614765e10e13a028ad9119d254b6117bd824db4d924d6c1d7cc", + .url = "https://pkg.machengine.org/flac/6df11b8a314fed1946be9f803f9af6cbb60c21e6.tar.gz", + .hash = "1220d42b299ce867c859cba01d4b4c4d539b460d522d80af84b2a71e3f0f49394013", }, .mach_sysaudio = .{ - .url = "https://pkg.machengine.org/mach-sysaudio/f987d55fefbb7b7ef5c742ad2e64db68a5a2110d.tar.gz", - .hash = "1220539dbe43f4651bac0495175d5567661c8b9c323fb4fbea9aa1de67a2a7b26566", + .url = "https://pkg.machengine.org/mach-sysaudio/7736b88a31cfc9eb59cde3f97d76658eeaa81dd2.tar.gz", + .hash = "1220e298a52bb47dfb17ca01db57e0432da7968b38fcb92922145377560d76b6eada", }, .linux_audio_headers = .{ - .url = "https://pkg.machengine.org/linux-audio-headers/6b182ff9d51009ca903f3bac63777fbfa654e5f5.tar.gz", - .hash = "122052c4415f4d5be98e3324083939af644d5f8eddd2e6a1a544596645eda8cf411a", + .url = "https://pkg.machengine.org/linux-audio-headers/a239b310fe45bfc974c121be2c9908e51a0c027d.tar.gz", + .hash = "1220ceab34e6617e3ff7be14477b1aea34b6e091c1e4316406ce474fca2293af831a", }, }, } diff --git a/examples/play.zig b/examples/play.zig index 8a30cbc95..2293b9f34 100644 --- a/examples/play.zig +++ b/examples/play.zig @@ -53,12 +53,14 @@ pub fn main() !void { } var i: usize = 0; -fn writeCallback(_: ?*anyopaque, frames: usize) void { - for (0..frames) |fi| { - if (i >= file_decoded.samples.len) i = 0; - for (0..file_decoded.channels) |ch| { - player.write(player.channels()[ch], fi, file_decoded.samples[i]); - i += 1; - } - } +fn writeCallback(_: ?*anyopaque, output: []u8) void { + if (i >= file_decoded.samples.len) i = 0; + const to_write = @min(output.len / player.format().size(), file_decoded.samples.len - i); + sysaudio.convertTo( + i32, + file_decoded.samples[i..][0..to_write], + player.format(), + output[0 .. to_write * player.format().size()], + ); + i += to_write; } diff --git a/src/lib.zig b/src/lib.zig index b805187a1..b78c1ba22 100644 --- a/src/lib.zig +++ b/src/lib.zig @@ -202,55 +202,23 @@ pub const EncodeError = error{ InvalidSampleRate, }; -/// TODO: encoder is super buggy and doesn't work yet -pub fn encode( - allocator: std.mem.Allocator, - channels: u8, - bits_per_sample: u8, - sample_rate: u24, - samples: []const i32, - compression_level: ?u4, -) EncodeError![]const u8 { - std.debug.assert(std.io.FixedBufferStream(u8).WriteError == error{NoSpaceLeft}); - var buffer = try allocator.alloc(u8, samples.len); - errdefer allocator.free(buffer); - var fbs = std.io.fixedBufferStream(buffer); - encodeStream( - std.io.StreamSource{ .buffer = fbs }, - channels, - bits_per_sample, - sample_rate, - samples, - compression_level, - ) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - error.SeekingFailed => return error.SeekingFailed, - error.InvalidSampleRate => return error.InvalidSampleRate, - error.NoSpaceLeft => unreachable, - else => unreachable, - }; - buffer = try allocator.realloc(buffer, fbs.pos); - return buffer; -} - -/// TODO: encoder is super buggy and doesn't work yet +/// TODO: encoder is buggy and doesn't work yet (UB?) pub fn encodeStream( stream: std.io.StreamSource, channels: u8, bits_per_sample: u8, sample_rate: u24, samples: []const i32, - compression_level: ?u4, + compression_level: ?u8, ) (EncodeError || std.io.StreamSource.WriteError)!void { - std.debug.assert(bits_per_sample >= 4 and bits_per_sample <= 32); - var data = Encoder{ .stream = stream }; var encoder = c.FLAC__stream_encoder_new() orelse return error.OutOfMemory; + defer _ = c.FLAC__stream_encoder_delete(encoder); _ = c.FLAC__stream_encoder_set_channels(encoder, channels); - _ = c.FLAC__stream_encoder_set_bits_per_sample(encoder, 32); + _ = c.FLAC__stream_encoder_set_bits_per_sample(encoder, bits_per_sample); _ = c.FLAC__stream_encoder_set_sample_rate(encoder, sample_rate); - _ = c.FLAC__stream_encoder_set_total_samples_estimate(encoder, samples.len / channels); + _ = c.FLAC__stream_encoder_set_total_samples_estimate(encoder, samples.len); if (compression_level) |level| { std.debug.assert(level <= 8); _ = c.FLAC__stream_encoder_set_compression_level(encoder, level); @@ -293,6 +261,8 @@ pub fn encodeStream( else => unreachable, } } + + _ = c.FLAC__stream_encoder_finish(encoder); } const Encoder = struct {