sonnum/zigsonnum/activity.zig

352 lines
No EOL
10 KiB
Zig

const std = @import("std");
const math = std.math;
const print = std.debug.print;
const Allocator = std.mem.Allocator;
const SoundNode = @import("soundnode.zig").SoundNode;
const FreqAmpBuffer = @import("freqamp.zig").FreqAmpBuffer;
const FreqAmpList = @import("freqamp.zig").FreqAmpList;
const utility = @import("utility.zig");
pub const Activity = struct {
start_tick: u32,
end_tick: u32,
opcode: u16,
soundnode: *SoundNode,
operands: [6]f64 = std.mem.zeroes([6]f64),
pub fn create(allocator: Allocator, start_tick: u32, end_tick: u32, opcode: u16, soundnode: *SoundNode, operands: [6]f64) !*Activity {
const a = try allocator.create(Activity);
a.* = .{
.start_tick = start_tick,
.end_tick = end_tick,
.opcode = opcode,
.soundnode = soundnode,
.operands = operands,
};
return a;
}
pub fn do(self: *Activity) !void {
switch (self.opcode) {
4 => { self.relay(); },
5 => { self.setpos(); },
6 => { try self.setbasefreq(); },
7 => { try self.setgain(); },
8 => { try self.setphase(); },
9 => { self.sine(); },
10 => { self.triangle(); },
11 => { self.square(); },
12 => { self.sawtooth(); },
13 => { try self.setskew(); },
14 => { self.skewsine(); },
15 => { try self.slidebasefreq(); },
16 => { try self.slidegain(); },
17 => { try self.slidephase(); },
18 => { try self.slideskew(); },
19 => { self.slidepos(); },
20 => { self.pulse(); },
else => {},
}
}
pub fn relay_imprecise(self: *Activity) void {
const current_tick: u32 = self.soundnode.fab.current_tick;
for (self.soundnode.wire_in.items, 0..) |wired_sn, i| {
const relayed_r_amp = wired_sn.fab.get_r_amp(current_tick);
self.soundnode.fab.add_r_amp(relayed_r_amp);
_ = i;
}
for (self.soundnode.air_in.items, 0..) |aired_sn, i| {
const dist: f64 = self.soundnode.distance(aired_sn);
var sample_tick: u32 = 0;
const tck = @as(f64, @floatFromInt(current_tick)) - (128.571428 * dist);
if (tck > 0) {
sample_tick = @intFromFloat( @floor(tck) );
const attenuation: f64 = @as(f64, std.math.exp(-(dist / 100.0)));
const relayed_r_amp = aired_sn.fab.get_r_amp(sample_tick) * attenuation;
self.soundnode.fab.add_r_amp(relayed_r_amp);
}
_ = i;
}
}
pub fn relay(self: *Activity) void {
const current_tick: u32 = self.soundnode.fab.current_tick;
for (self.soundnode.wire_in.items, 0..) |wired_sn, i| {
const relayed_r_amp = wired_sn.fab.get_r_amp(current_tick);
self.soundnode.fab.add_r_amp(relayed_r_amp);
_ = i;
}
for (self.soundnode.air_in.items, 0..) |aired_sn, i| {
const dist: f64 = self.soundnode.distance(aired_sn);
var b_sample_tick: u32 = 0;
var n_sample_tick: u32 = 0;
const tck = @as(f64, @floatFromInt(current_tick)) - (128.571428 * dist);
if (tck > 0) {
b_sample_tick = @intFromFloat( @floor(tck) );
n_sample_tick = b_sample_tick + 1;
const attenuation: f64 = @as(f64, std.math.exp(-(dist / 100.0)));
const b_r_amp = aired_sn.fab.get_r_amp(b_sample_tick);
const n_r_amp = aired_sn.fab.get_r_amp(n_sample_tick);
const tick_diff = tck - @as(f64, @floatFromInt(b_sample_tick));
const relayed_r_amp = (b_r_amp + (tick_diff * (n_r_amp - b_r_amp))) * attenuation;
self.soundnode.fab.add_r_amp(relayed_r_amp);
}
_ = i;
}
}
pub fn setbasefreq(self: *Activity) !void {
try self.soundnode.s("basefreq", self.operands[0]);
}
pub fn setgain(self: *Activity) !void {
try self.soundnode.s("gain", self.operands[0]);
}
pub fn setphase(self: *Activity) !void {
try self.soundnode.s("phase", self.operands[0]);
}
pub fn setpos(self: *Activity) void {
self.soundnode.x = @as(f32, @floatCast(self.operands[0]));
self.soundnode.y = @as(f32, @floatCast(self.operands[1]));
self.soundnode.z = @as(f32, @floatCast(self.operands[2]));
}
pub fn sine(self: *Activity) void {
const current_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick);
const freq = self.soundnode.g("basefreq");
const r_amp = self.soundnode.g("gain");
const phase = self.soundnode.g("phase");
const amp = r_amp * math.sin(utility.corrected_tau * freq * current_tick - phase * utility.tau);
self.soundnode.fab.add_r_amp(amp);
}
pub fn triangle(self: *Activity) void {
const current_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick);
const freq = self.soundnode.g("basefreq");
const r_amp = self.soundnode.g("gain");
const phase = self.soundnode.g("phase");
const period = 44100 / freq;
const tp = (current_tick - (period * phase)) / period;
const amp = r_amp * (@abs(2 * (2 * ( tp - @floor(tp + 0.5) ) )) - 1);
self.soundnode.fab.add_r_amp(amp);
}
pub fn square(self: *Activity) void {
const current_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick);
const freq = self.soundnode.g("basefreq");
const r_amp = self.soundnode.g("gain");
const phase = self.soundnode.g("phase");
const sin = math.sin(utility.corrected_tau * freq * current_tick - phase * utility.tau);
if (sin > 0) {
self.soundnode.fab.add_r_amp(r_amp);
} else {
self.soundnode.fab.add_r_amp(-r_amp);
}
}
pub fn sawtooth(self: *Activity) void {
const current_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick);
const freq = self.soundnode.g("basefreq");
const r_amp = self.soundnode.g("gain");
const phase = self.soundnode.g("phase");
const period = 44100 / freq;
const tp = (current_tick - (period * phase)) / period;
const amp = r_amp * (2 * (tp - @floor(0.5+tp)));
self.soundnode.fab.add_r_amp(amp);
}
pub fn setskew(self: *Activity) !void {
try self.soundnode.s("skew", self.operands[0]);
}
pub fn skewsine(self: *Activity) void {
const current_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick);
const freq = self.soundnode.g("basefreq");
const r_amp = self.soundnode.g("gain");
const phase = self.soundnode.g("phase");
const skew = self.soundnode.g("skew");
if (skew == 0) {
const amp = r_amp * math.sin(utility.corrected_tau * freq * current_tick - phase * utility.tau);
self.soundnode.fab.add_r_amp(amp);
} else if (skew > 0) {
const m = (utility.corrected_tau * freq * current_tick);
const sincos = skew * math.sin(m) / (1 - skew*math.cos(m));
const amp = r_amp * ((1/skew) * math.atan(sincos) - (phase * utility.tau));
self.soundnode.fab.add_r_amp(amp);
} else if (skew < 0) {
const m = (utility.corrected_tau * freq * current_tick);
const sincos = skew * math.cos(m) / (1 + skew*math.sin(m));
const amp = r_amp * ((1/skew) * math.atan(sincos) - (phase * utility.tau));
self.soundnode.fab.add_r_amp(amp);
}
}
pub fn slidebasefreq(self: *Activity) !void {
const current_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick);
const start_tick: f64 = @floatFromInt(self.start_tick);
const end_tick: f64 = @floatFromInt(self.end_tick);
const startfreq = self.operands[0];
const endfreq = self.operands[1];
const x = (current_tick * (current_tick / 2)) - (start_tick*current_tick);
const xx = ((endfreq - startfreq) / (end_tick - start_tick)) * x;
const freq = ((startfreq * current_tick) + xx) / current_tick;
try self.soundnode.s("basefreq", freq);
}
pub fn slidegain(self: *Activity) !void {
const current_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick);
const start_tick: f64 = @floatFromInt(self.start_tick);
const end_tick: f64 = @floatFromInt(self.end_tick);
const startgain = self.operands[0];
const endgain = self.operands[1];
const gain = utility.interpolate(current_tick, start_tick, end_tick, startgain, endgain);
try self.soundnode.s("gain", gain);
}
pub fn slidephase(self: *Activity) !void {
const current_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick);
const start_tick: f64 = @floatFromInt(self.start_tick);
const end_tick: f64 = @floatFromInt(self.end_tick);
const startphase = self.operands[0];
const endphase = self.operands[1];
const phase = utility.interpolate(current_tick, start_tick, end_tick, startphase, endphase);
try self.soundnode.s("phase", phase);
}
pub fn slideskew(self: *Activity) !void {
const current_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick);
const start_tick: f64 = @floatFromInt(self.start_tick);
const end_tick: f64 = @floatFromInt(self.end_tick);
const startskew = self.operands[0];
const endskew = self.operands[1];
const skew = utility.interpolate(current_tick, start_tick, end_tick, startskew, endskew);
try self.soundnode.s("skew", skew);
}
pub fn slidepos(self: *Activity) void {
const current_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick);
const start_tick: f64 = @floatFromInt(self.start_tick);
const end_tick: f64 = @floatFromInt(self.end_tick);
const start_x = self.operands[0];
const start_y = self.operands[1];
const start_z = self.operands[2];
const end_x = self.operands[3];
const end_y = self.operands[4];
const end_z = self.operands[5];
const x = utility.interpolate(current_tick, start_tick, end_tick, start_x, end_x);
const y = utility.interpolate(current_tick, start_tick, end_tick, start_y, end_y);
const z = utility.interpolate(current_tick, start_tick, end_tick, start_z, end_z);
self.soundnode.x = @as(f32, @floatCast(x));
self.soundnode.y = @as(f32, @floatCast(y));
self.soundnode.z = @as(f32, @floatCast(z));
}
pub fn pulse(self: *Activity) void {
const current_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick);
const freq = self.soundnode.g("basefreq");
const r_amp = self.soundnode.g("gain");
const phase = self.soundnode.g("phase");
const period = 44100 / freq;
const tp = current_tick / period;
const tp_detract = (current_tick - (period * phase)) / period;
const amp =2 * (tp - @floor(0.5+tp));
const amp_detract = 2 * (tp_detract - @floor(0.5+tp_detract));
const final_amp = r_amp * (amp - amp_detract);
self.soundnode.fab.add_r_amp(final_amp);
}
};