Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
- name: Install Zig
uses: mlugg/setup-zig@v2
with:
version: 0.14.0
version: 0.16.0

- name: Show Zig version
run: |
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Install Zig
uses: mlugg/setup-zig@v2
with:
version: 0.14.0
version: 0.16.0

- name: Show Zig version
run: |
Expand All @@ -54,7 +54,7 @@ jobs:
- name: Install Zig
uses: mlugg/setup-zig@v2
with:
version: 0.14.0
version: 0.16.0

- name: Install kcov
run: |
Expand Down Expand Up @@ -86,7 +86,7 @@ jobs:
- name: Install Zig
uses: mlugg/setup-zig@v2
with:
version: 0.14.0
version: 0.16.0

- name: Check formatting
run: zig fmt --check .
2 changes: 1 addition & 1 deletion .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- name: Install Zig
uses: mlugg/setup-zig@v2
with:
version: 0.14.0
version: 0.16.0

- name: Show Zig version
run: |
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
zig-cache/
.zig-cache/
zig-out/
zig-pkg/
build/
build-*/
docgen_tmp/
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM eloitor/zig:0.14.0 as builder
FROM eloitor/zig:0.16.0 as builder

Check warning on line 1 in Dockerfile

View workflow job for this annotation

GitHub Actions / Docker Build and Push

The 'as' keyword should match the case of the 'from' keyword

FromAsCasing: 'as' and 'FROM' keywords' casing do not match More info: https://docs.docker.com/go/dockerfile/rule/from-as-casing/
RUN apk update
RUN apk add --no-cache git
WORKDIR /app
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@

#### Prerequisites

- [Zig](https://ziglang.org/download/) (`0.14`)
- [Zig](https://ziglang.org/download/) (`0.16`)

#### Instructions

Expand Down
6 changes: 3 additions & 3 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.name = .linuxwave,
.version = "0.1.5",
.fingerprint = 0x217eafdf4732b5f9,
.minimum_zig_version = "0.14.0",
.minimum_zig_version = "0.16.0",
.paths = .{
"build.zig",
"build.zig.zon",
Expand All @@ -12,8 +12,8 @@
},
.dependencies = .{
.clap = .{
.url = "https://github.com/Hejsil/zig-clap/archive/refs/tags/0.10.0.tar.gz",
.hash = "clap-0.10.0-oBajB434AQBDh-Ei3YtoKIRxZacVPF1iSwp3IX_ZB8f0",
.url = "https://github.com/Hejsil/zig-clap/archive/fc1e5cc3f6d9d3001112385ee6256d694e959d2f.tar.gz",
.hash = "clap-0.11.0-oBajB7foAQC3Iyn4IVCkUdYaOVVng5IZkSncySTjNig1",
},
},
}
22 changes: 13 additions & 9 deletions src/file.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,34 @@ const std = @import("std");

/// Reads the given file and returns a byte array with the length of `len`.
pub fn readBytes(
io: std.Io,
allocator: std.mem.Allocator,
path: []const u8,
len: usize,
) ![]u8 {
const file = try std.fs.cwd().openFile(path, .{});
defer file.close();
var list = try std.ArrayList(u8).initCapacity(allocator, len);
var buffer = list.allocatedSlice();
const bytes_read = try file.read(buffer);
return buffer[0..bytes_read];
const file = try std.Io.Dir.cwd().openFile(io, path, .{});
defer file.close(io);
var read_buffer: [1024]u8 = undefined;
var file_reader = file.reader(io, &read_buffer);
const reader = &file_reader.interface;
return reader.readAlloc(allocator, len);
}

test "read bytes from the file" {
const allocator = std.testing.allocator;
const io = std.testing.io;

// Get the current directory.
var cwd_buffer: [std.fs.max_path_bytes]u8 = undefined;
const cwd = try std.posix.getcwd(&cwd_buffer);
const cwd_len = try std.process.currentPath(io, &cwd_buffer);
const cwd = cwd_buffer[0..cwd_len];

// Concatenate the current directory with the builder file.
const allocator = std.testing.allocator;
const path = try std.fs.path.join(allocator, &.{ cwd, "build.zig" });
defer allocator.free(path);

// Read the contents of the file and compare.
const bytes = try readBytes(allocator, path, 9);
const bytes = try readBytes(io, allocator, path, 9);
try std.testing.expectEqualStrings("const std", bytes);
defer allocator.free(bytes);
}
6 changes: 3 additions & 3 deletions src/gen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub const Generator = struct {
///
/// Returns an array that contains the amplitudes of the sound wave at a given point in time.
pub fn generate(self: Generator, allocator: std.mem.Allocator, sample: u8) ![]u8 {
var buffer = std.ArrayList(u8).init(allocator);
var buffer: std.ArrayList(u8) = .empty;
var i: usize = 0;
while (i < sample_count) : (i += 1) {
// Calculate the frequency according to the equal temperament.
Expand All @@ -45,9 +45,9 @@ pub const Generator = struct {
// Apply the volume control.
const volume: f32 = @floatFromInt(self.config.volume);
amp = amp * volume / 100;
try buffer.append(@intFromFloat(amp));
try buffer.append(allocator, @trunc(amp));
}
return buffer.toOwnedSlice();
return buffer.toOwnedSlice(allocator);
}
};

Expand Down
89 changes: 53 additions & 36 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,37 @@ const build_options = @import("build_options");
const clap = @import("clap");

/// Runs `linuxwave`.
fn run(allocator: std.mem.Allocator, output: anytype) !void {
fn run(io: std.Io, allocator: std.mem.Allocator, output: *std.Io.Writer, argv: std.process.Args) !void {
// Parse command-line arguments.
const cli = try clap.parse(clap.Help, &args.params, args.parsers, .{ .allocator = allocator });
const cli = try clap.parse(clap.Help, &args.params, args.parsers, argv, .{ .allocator = allocator });
defer cli.deinit();
if (cli.args.help != 0) {
try output.print("{s}\n", .{args.banner});
return clap.help(output, clap.Help, &args.params, args.help_options);
} else if (cli.args.version != 0) {
try clap.help(output, clap.Help, &args.params, args.help_options);
try output.flush();
return;
}
if (cli.args.version != 0) {
try output.print("{s} {s}\n", .{ build_options.exe_name, build_options.version });
try output.flush();
return;
}

// Create encoder configuration.
const encoder_config = wav.EncoderConfig{
const encoder_config: wav.EncoderConfig = .{
.num_channels = if (cli.args.channels) |channels| channels else defaults.channels,
.sample_rate = if (cli.args.rate) |rate| @intFromFloat(rate) else defaults.sample_rate,
.format = if (cli.args.format) |format| format else defaults.format,
};

// Create generator configuration.
const scale = s: {
var scale = std.ArrayList(u8).init(allocator);
var scale: std.ArrayList(u8) = .empty;
var splits = std.mem.splitAny(u8, if (cli.args.scale) |s| s else defaults.scale, ",");
while (splits.next()) |chunk| {
try scale.append(try std.fmt.parseInt(u8, chunk, 0));
try scale.append(allocator, try std.fmt.parseInt(u8, chunk, 0));
}
break :s try scale.toOwnedSlice();
break :s try scale.toOwnedSlice(allocator);
};
defer allocator.free(scale);
const generator_config = gen.GeneratorConfig{
Expand All @@ -50,63 +54,76 @@ fn run(allocator: std.mem.Allocator, output: anytype) !void {
const buffer = b: {
if (std.mem.eql(u8, input_file, "-")) {
try output.print("Reading {d} bytes from stdin\n", .{data_len});
var list = try std.ArrayList(u8).initCapacity(allocator, data_len);
const buffer = list.allocatedSlice();
const stdin = std.io.getStdIn().reader();
try stdin.readNoEof(buffer);
break :b buffer;
} else {
try output.print("Reading {d} bytes from {s}\n", .{ data_len, input_file });
break :b try file.readBytes(allocator, input_file, data_len);
try output.flush();
var read_buffer: [1024]u8 = undefined;
var stdin_reader = std.Io.File.stdin().reader(io, &read_buffer);
const stdin = &stdin_reader.interface;
break :b try stdin.readAlloc(allocator, data_len);
}

try output.print("Reading {d} bytes from {s}\n", .{ data_len, input_file });
try output.flush();
break :b try file.readBytes(io, allocator, input_file, data_len);
};
defer allocator.free(buffer);

// Generate music.
const generator = gen.Generator.init(generator_config);
var data = std.ArrayList(u8).init(allocator);
const generator: gen.Generator = .init(generator_config);
var data: std.ArrayList(u8) = .empty;
for (buffer) |v| {
const gen_data = try generator.generate(allocator, v);
defer allocator.free(gen_data);
try data.appendSlice(gen_data);
try data.appendSlice(allocator, gen_data);
}

// Encode WAV.
const out = if (cli.args.output) |out| out else defaults.output;
const writer = w: {
var write_buffer: [1024]u8 = undefined;
var fhandle: ?std.Io.File = null;
defer if (fhandle) |f| {
f.close(io);
};
var file_writer = w: {
if (std.mem.eql(u8, out, "-")) {
try output.print("Writing to stdout\n", .{});
break :w std.io.getStdOut().writer();
} else {
try output.print("Saving to {s}\n", .{out});
const out_file = try std.fs.cwd().createFile(out, .{});
break :w out_file.writer();
try output.flush();
break :w std.Io.File.stdout().writer(io, &write_buffer);
}

try output.print("Saving to {s}\n", .{out});
try output.flush();
fhandle = try std.Io.Dir.cwd().createFile(io, out, .{});
break :w fhandle.?.writer(io, &write_buffer);
};
const wav_data = try data.toOwnedSlice();
const wav_data = try data.toOwnedSlice(allocator);
defer allocator.free(wav_data);
try wav.Encoder(@TypeOf(writer)).encode(writer, wav_data, encoder_config);
try wav.encode(&file_writer.interface, wav_data, encoder_config);
}

/// Entry-point.
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
const stderr = std.io.getStdErr().writer();
run(allocator, stderr) catch |err| {
pub fn main(init: std.process.Init) !void {
const allocator = init.gpa;
const io = init.io;
var stderr_buffer: [1024]u8 = undefined;
var stderr_writer = std.Io.File.stderr().writer(io, &stderr_buffer);
const stderr = &stderr_writer.interface;
run(io, allocator, stderr, init.minimal.args) catch |err| {
try stderr.print("Error occurred: {}\n", .{err});
try stderr.flush();
};
}

test "run" {
const allocator = std.testing.allocator;
var buffer = std.ArrayList(u8).init(allocator);
const output = buffer.writer();
run(allocator, output) catch |err| {
const io = std.testing.io;

const fake_args: std.process.Args = .{ .vector = &[_][*:0]const u8{} };
var allocating: std.Io.Writer.Allocating = .init(allocator);
run(io, allocator, &allocating.writer, fake_args) catch |err| {
std.debug.print("Error occurred: {s}\n", .{@errorName(err)});
return;
};
const result = buffer.toOwnedSlice() catch |err| {
const result = allocating.toOwnedSlice() catch |err| {
std.debug.print("Error occurred: {s}\n", .{@errorName(err)});
return;
};
Expand Down
Loading
Loading