352 lines
No EOL
10 KiB
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);
|
|
|
|
}
|
|
}; |