scritcher/src/custom.zig

193 lines
4.9 KiB
Zig

// Custom plugins
const std = @import("std");
const lv2 = @import("lv2_helpers.zig");
const plugins = @import("plugin.zig");
const image = @import("image.zig");
const log = std.log.scoped(.scritcher_custom);
const c = lv2.c;
const RunBuffers = plugins.RunBuffers;
pub const RandomNoise = struct {
r: std.rand.DefaultPrng,
rand_buf: ?[]f32 = null,
allocator: ?std.mem.Allocator = null,
cnt: usize = 0,
pub fn init(
allocator: std.mem.Allocator,
params: anytype,
) ?RandomNoise {
var r = std.rand.DefaultPrng.init(params.seed);
if (params.fill_bytes > 0) {
var rand_buf = allocator.alloc(f32, params.fill_bytes) catch return null;
for (rand_buf, 0..) |_, idx| {
rand_buf[idx] = r.random().float(f32);
}
return RandomNoise{
.r = r,
.allocator = allocator,
.rand_buf = rand_buf,
};
} else {
return RandomNoise{
.r = r,
};
}
}
pub fn deinit(self: *RandomNoise) void {
if (self.allocator == null) return;
if (self.rand_buf == null) return;
self.allocator.?.free(self.rand_buf.?);
}
pub fn run(self: *RandomNoise, bufs: *RunBuffers) void {
if (self.rand_buf) |rand_buf| {
if (self.cnt >= rand_buf.len) self.cnt = 0;
bufs.out[0] = rand_buf[self.cnt];
self.cnt += 1;
} else {
bufs.out[0] = self.r.random().float(f32);
}
}
};
pub const WildNoise = struct {
r: std.rand.DefaultPrng,
rand_buf: ?[]f32 = null,
allocator: ?std.mem.Allocator = null,
cnt: usize = 0,
pub fn init(
allocator: std.mem.Allocator,
params: anytype,
) ?WildNoise {
var r = std.rand.DefaultPrng.init(params.seed);
if (params.fill_bytes > 0) {
var rand_buf = allocator.alloc(f32, params.fill_bytes) catch return null;
for (rand_buf, 0..) |_, idx| {
rand_buf[idx] = @as(f32, @floatFromInt(r.random().int(u1)));
}
return WildNoise{
.r = r,
.rand_buf = rand_buf,
};
} else {
return WildNoise{
.r = r,
};
}
}
pub fn deinit(self: *WildNoise) void {
if (self.allocator == null) return;
if (self.rand_buf == null) return;
self.allocator.?.free(self.rand_buf.?);
}
pub fn run(self: *WildNoise, bufs: *RunBuffers) void {
if (self.rand_buf) |rand_buf| {
if (self.cnt >= rand_buf.len) self.cnt = 0;
bufs.out[0] = rand_buf[self.cnt];
self.cnt += 1;
} else {
bufs.out[0] = @as(f32, @floatFromInt(self.r.random().int(u1)));
}
}
};
/// Write any float to the image.
/// Keep in mind that the bit representation of the float will clash with
/// the format of BMP pixel data, which means writing 0 everywhere won't give
/// you the black color.
pub const Write = struct {
data: f32,
pub fn init(
allocator: std.mem.Allocator,
params: anytype,
) Write {
_ = allocator;
return Write{
.data = params.data,
};
}
pub fn deinit(self: *Write) void {
_ = self;
}
pub fn run(self: *Write, bufs: *RunBuffers) void {
bufs.out[0] = self.data;
}
};
pub const Embed = struct {
allocator: std.mem.Allocator,
filepath: []const u8,
sndfile: *c.SNDFILE = undefined,
buf: []f32 = undefined,
pub fn init(allocator: std.mem.Allocator, params: anytype) @This() {
return Embed{
.allocator = allocator,
.filepath = params.path,
};
}
pub fn setup(self: *@This()) !void {
var in_fmt = c.SF_INFO{
.frames = @as(c_int, 0),
.samplerate = @as(c_int, 0),
.channels = @as(c_int, 0),
.format = @as(c_int, 0),
.sections = @as(c_int, 0),
.seekable = @as(c_int, 0),
};
self.sndfile = try image.sopen(
self.allocator,
self.filepath,
c.SFM_READ,
&in_fmt,
);
image.sseek(self.sndfile, 0);
self.buf = try self.allocator.alloc(f32, @as(usize, @intCast(in_fmt.channels)));
}
pub fn deinit(self: *@This()) void {
_ = self;
}
pub fn run(self: *@This(), bufs: *RunBuffers) void {
const read_bytes = c.sf_readf_float(self.sndfile, self.buf.ptr, 1);
if (read_bytes == 0) {
bufs.out[0] = bufs.in[0];
return;
}
if (read_bytes < 0) {
const st: i32 = c.sf_error(self.sndfile);
log.debug("Failed to read {s} ({s})", .{
self.filepath,
c.sf_error_number(st),
});
return;
}
bufs.out[0] = bufs.in[0] + self.buf[0];
}
};