diff --git a/pysonnum/activity.py b/pysonnum/activity.py index 4a79f62..057281c 100644 --- a/pysonnum/activity.py +++ b/pysonnum/activity.py @@ -23,6 +23,9 @@ OPCODES = { 'slideskew': 18, 'slidepos': 19, 'pulse': 20, + 'setfmsettings': 21, + 'fm': 22, + 'am': 23, } class Activity: diff --git a/pysonnum/soundnode.py b/pysonnum/soundnode.py index d35f528..292bfb8 100644 --- a/pysonnum/soundnode.py +++ b/pysonnum/soundnode.py @@ -67,4 +67,13 @@ class SoundNode: self.act('slidepos', start_tick, end_tick, self, None, [sx, sy, sz, ex, ey, ez]) def pulse(self, start_tick, end_tick): - self.act('pulse', start_tick, end_tick, self, None, []) \ No newline at end of file + self.act('pulse', start_tick, end_tick, self, None, []) + + def setfmsettings(self, start_tick, fmbasefreq, fmq): + self.act('setfmsettings', start_tick, start_tick, self, None, [fmbasefreq, fmq]) + + def fm(self, start_tick, end_tick): + self.act('fm', start_tick, end_tick, self, None, []) + + def am(self, start_tick, end_tick): + self.act('am', start_tick, end_tick, self, None, []) \ No newline at end of file diff --git a/sineex.py b/sineex.py index e51ae21..c2c2e38 100644 --- a/sineex.py +++ b/sineex.py @@ -1,4 +1,4 @@ -ln = s.sec(2) +ln = s.sec(6); s.endtick(ln) @@ -9,18 +9,18 @@ left.setpos(0, -0.3, 0, 0) right.setpos(0, 0.3, 0, 0) tr1 = s.node() + +tr1.setbasefreq(0, 11) +tr1.setgain(0, 0.45) +tr1.triangle(0, ln) + tr2 = s.node() -tr1.setbasefreq(0, s.note("E4")) -tr1.setgain(0, 0.45) -tr1.setskew(0, 0.3) -tr1.square(0, ln) - tr2.setbasefreq(0, s.note("E4")) -tr2.setgain(0, 0.4) -tr2.setphase(0, 0.4) -tr1.setskew(0, 0.3) +tr2.am(0, ln) tr2.square(0, ln) -s.wire(tr1, left) + +s.wire(tr1, tr2) +s.wire(tr2, left) s.wire(tr2, right) \ No newline at end of file diff --git a/zigsonnum/activity.zig b/zigsonnum/activity.zig index 7425fe8..278b947 100644 --- a/zigsonnum/activity.zig +++ b/zigsonnum/activity.zig @@ -50,6 +50,9 @@ pub const Activity = struct { 18 => { try self.slideskew(); }, 19 => { self.slidepos(); }, 20 => { self.pulse(); }, + 21 => { try self.setfmsettings(); }, + 22 => { try self.fm(); }, + 23 => { try self.am(); }, else => {}, } } @@ -136,7 +139,6 @@ pub const Activity = struct { pub fn setbasefreq(self: *Activity) !void { try self.soundnode.s("basefreq", self.operands[0]); - } pub fn setgain(self: *Activity) !void { @@ -255,7 +257,7 @@ pub const Activity = struct { 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; @@ -264,6 +266,29 @@ pub const Activity = struct { } + pub fn slidebasefreq_iterative(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 instfreq = utility.interpolate(current_tick, start_tick, end_tick, startfreq, endfreq); + const c = current_tick / 44100; + + const prevphase = self.soundnode.g("phase"); + const prevfreq = self.soundnode.g("basefreq"); + + const pp = prevphase + c*(instfreq - prevfreq) + @floor(c * prevfreq - prevphase); + const newphase = pp - @floor(pp); + + try self.soundnode.s("phase", newphase); + try self.soundnode.s("basefreq", instfreq); + + } + pub fn slidegain(self: *Activity) !void { const current_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick); @@ -349,4 +374,141 @@ pub const Activity = struct { self.soundnode.fab.add_r_amp(final_amp); } + + pub fn setfmsettings(self: *Activity) !void { + try self.soundnode.s("fmbasefreq", self.operands[0]); + try self.soundnode.s("instfreq", self.operands[0]); + try self.soundnode.s("fmq", self.operands[1]); + } + + + pub fn fm(self: *Activity) !void { + + const current_tick: u32 = self.soundnode.fab.current_tick; + const fcurrent_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick); + + var fprev_tick: f64 = 0; + + if (fcurrent_tick > 0) { + fprev_tick = @floatFromInt(current_tick - 1); + } + + const fmq = self.soundnode.g("fmq"); + const fmbasefreq = self.soundnode.g("fmbasefreq"); + + const prevphase = self.soundnode.g("phase"); + const prevfreq = self.soundnode.g("basefreq"); + + var srcamp: f64 = 0; + + for (self.soundnode.wire_in.items, 0..) |wired_sn, i| { + + const relayed_r_amp = wired_sn.fab.get_r_amp(current_tick); + srcamp += 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; + + srcamp += relayed_r_amp; + + } + + _ = i; + + } + + if (srcamp > 1) { + srcamp = 1; + } else if (srcamp < -1) { + srcamp = -1; + } + + const instfreq = fmbasefreq + (fmbasefreq * fmq * srcamp); + const c = fcurrent_tick / 44100; + + const pp = prevphase + c*(instfreq - prevfreq) + @floor(c * prevfreq - prevphase); + const newphase = pp - @floor(pp); + + try self.soundnode.s("phase", newphase); + try self.soundnode.s("basefreq", instfreq); + + + } + + pub fn am(self: *Activity) !void { + + const current_tick: u32 = self.soundnode.fab.current_tick; + + var srcamp: f64 = 0; + + for (self.soundnode.wire_in.items, 0..) |wired_sn, i| { + + const relayed_r_amp = wired_sn.fab.get_r_amp(current_tick); + srcamp += 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; + + srcamp += relayed_r_amp; + + } + + _ = i; + + } + + if (srcamp > 1) { + srcamp = 1; + } else if (srcamp < -1) { + srcamp = -1; + } + + try self.soundnode.s("gain", srcamp); + + + } }; \ No newline at end of file