many functions added

This commit is contained in:
aprilnightk 2025-09-12 21:16:39 +03:00
parent 60334da61c
commit 4b608b2584
10 changed files with 420 additions and 30 deletions

View file

@ -8,7 +8,20 @@ OPCODES = {
'endtick': 3,
'relay': 4,
'setpos': 5,
'sine': 6,
'setbasefreq': 6,
'setgain': 7,
'setphase': 8,
'sine': 9,
'triangle': 10,
'square': 11,
'sawtooth': 12,
'setskew': 13,
'skewsine': 14,
'slidebasefreq': 15,
'slidegain': 16,
'slidephase': 17,
'slideskew': 18,
'slidepos': 19,
}
class Activity:

37
pysonnum/notes.py Normal file
View file

@ -0,0 +1,37 @@
NOTES_OF_OCTAVE = {
0: ['C', 'B#'],
1: ['C#', 'Db'],
2: ['D'],
3: ['D#', 'Eb'],
4: ['E', 'Fb'],
5: ['F', 'E#'],
6: ['F#', 'Gb'],
7: ['G'],
8: ['G#', 'Ab'],
9: ['A'],
10: ['A#', 'Bb'],
11: ['B', 'Cb']
}
def note_to_freq(note):
note_no = note_to_note_no(note)
return note_no_to_freq(note_no)
def note_to_note_no(note):
octave = int(note[-1])
note = note[:-1]
note_no_oct = 1
for note_no_oct, notelst in NOTES_OF_OCTAVE.items():
if note in notelst:
break
corr_note_no_oct = note_no_oct - 8
return corr_note_no_oct + (octave*12)
def note_no_to_freq(note_no):
return 2**((note_no-49) / 12.0) * 440

View file

@ -1,4 +1,5 @@
from .soundnode import SoundNode
from .notes import *
class Sonnum:
@ -41,6 +42,9 @@ class Sonnum:
def sec(self, seconds):
return seconds * 44100
def note(self, note):
return note_to_freq(note)
def relay(self):
node = self.add_node("")

View file

@ -8,6 +8,7 @@ class SoundNode:
self.name = name
self.properties = dict() # {k: v}
def __repr__(self):
return f'{self.order}:{self.name}'
@ -23,6 +24,44 @@ class SoundNode:
def setpos(self, start_tick, x, y, z):
self.act('setpos', start_tick, start_tick, self, None, [x, y, z])
def sine(self, start_tick, end_tick, freq, r_amp):
self.act('sine', start_tick, end_tick, self, None, [freq, r_amp])
def setbasefreq(self, start_tick, basefreq):
self.act('setbasefreq', start_tick, start_tick, self, None, [basefreq])
def setgain(self, start_tick, gain):
self.act('setgain', start_tick, start_tick, self, None, [gain])
def setphase(self, start_tick, phase):
self.act('setphase', start_tick, start_tick, self, None, [phase])
def sine(self, start_tick, end_tick):
self.act('sine', start_tick, end_tick, self, None, [])
def triangle(self, start_tick, end_tick):
self.act('triangle', start_tick, end_tick, self, None, [])
def square(self, start_tick, end_tick):
self.act('square', start_tick, end_tick, self, None, [])
def sawtooth(self, start_tick, end_tick):
self.act('sawtooth', start_tick, end_tick, self, None, [])
def setskew(self, start_tick, skew):
self.act('setskew', start_tick, start_tick, self, None, [skew])
def skewsine(self, start_tick, end_tick):
self.act('skewsine', start_tick, end_tick, self, None, [])
def slidebasefreq(self, start_tick, end_tick, startfreq, endfreq):
self.act('slidebasefreq', start_tick, end_tick, self, None, [startfreq, endfreq])
def slidegain(self, start_tick, end_tick, startgain, endgain):
self.act('slidegain', start_tick, end_tick, self, None, [startgain, endgain])
def slidephase(self, start_tick, end_tick, startphase, endphase):
self.act('slidephase', start_tick, end_tick, self, None, [startphase, endphase])
def slideskew(self, start_tick, end_tick, startskew, endskew):
self.act('slideskew', start_tick, end_tick, self, None, [startskew, endskew])
def slidepos(self, start_tick, end_tick, sx, sy, sz, ex, ey, ez):
self.act('slidepos', start_tick, end_tick, self, None, [sx, sy, sz, ex, ey, ez])

18
sineex.py Normal file
View file

@ -0,0 +1,18 @@
ln = s.sec(4)
s.endtick(ln)
left = s.relay()
right = s.relay()
left.setpos(0, -0.3, 0, 0)
right.setpos(0, 0.3, 0, 0)
tr1 = s.node()
tr1.setbasefreq(ln, s.note("C4"))
tr1.sine(0, ln)
tr1.setgain(0, 0.3)
tr1.setpos(0, 100, 0, 0)
s.air(tr1, [left])
s.air(tr1, [right])

View file

@ -35,25 +35,26 @@ pub const Activity = struct {
switch (self.opcode) {
4 => { self.relay(); },
5 => { self.setpos(); },
6 => { self.sine(); },
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(); },
else => {},
}
}
pub fn sine(self: *Activity) void {
const current_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick);
const freq = self.operands[0];
const r_amp = self.operands[1];
const phase = self.operands[2];
const amp = r_amp * math.sin(utility.corrected_tau * freq * current_tick - phase * utility.tau);
self.soundnode.fab.add_r_amp(amp);
}
pub fn relay(self: *Activity) void {
pub fn relay_imprecise(self: *Activity) void {
const current_tick: u32 = self.soundnode.fab.current_tick;
@ -88,12 +89,240 @@ pub const Activity = struct {
}
pub fn setpos(self: *Activity) void {
self.soundnode.location.x = @as(f32, @floatCast(self.operands[0]));
self.soundnode.location.y = @as(f32, @floatCast(self.operands[1]));
self.soundnode.location.z = @as(f32, @floatCast(self.operands[2]));
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;
const amp = r_amp * (@abs(2 * (2 * ( tp - @floor(tp + 0.5) ) )) - 1 - (phase * utility.tau));
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;
const amp = r_amp * (2 * (tp - @floor(0.5+tp) - (phase * utility.tau)));
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 freq = utility.interpolate(current_tick, start_tick, end_tick, startfreq, endfreq);
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));
}
};

View file

@ -13,6 +13,13 @@ pub const Pnt = struct {
print("{d} {d} {d}\n", .{self.x, self.y, self.z});
}
pub fn set(self: *Pnt, x: f32, y: f32, z: f32) void {
self.x = x;
self.y = y;
self.z = z;
}
};
pub fn distanceBetweenPoints(pt1: Pnt, pt2: Pnt) f64 {

View file

@ -102,11 +102,11 @@ pub fn main() !void {
while (cursor < buf.len) {
opcode = std.mem.readVarInt(u16, buf[cursor..cursor+2], .big);
print("----\nCURRENT TICK {d}\nOPCODE {d} :: {any}\n", .{tick, opcode, buf[cursor..cursor+2]});
//print("----\nCURRENT TICK {d}\nOPCODE {d} :: {any}\n", .{tick, opcode, buf[cursor..cursor+2]});
cursor += 2;
tick_start = std.mem.readVarInt(u32, buf[cursor..cursor+4], .big);
print("TICKSTART {d} :: {any}\n", .{tick_start, buf[cursor..cursor+4]});
//print("TICKSTART {d} :: {any}\n", .{tick_start, buf[cursor..cursor+4]});
cursor += 4;
if (tick_start > tick) {
@ -117,11 +117,11 @@ pub fn main() !void {
} else {
tick_end = std.mem.readVarInt(u32, buf[cursor..cursor+4], .big);
print("TICKEND {d} :: {any}\n", .{tick_end, buf[cursor..cursor+4]});
//print("TICKEND {d} :: {any}\n", .{tick_end, buf[cursor..cursor+4]});
cursor += 4;
src_node = std.mem.readVarInt(u16, buf[cursor..cursor+2], .big);
print("SRCNODE {d} :: {any}\n", .{src_node, buf[cursor..cursor+2]});
//print("SRCNODE {d} :: {any}\n", .{src_node, buf[cursor..cursor+2]});
cursor += 2;
trg_node = std.mem.readVarInt(u16, buf[cursor..cursor+2], .big);
@ -162,6 +162,11 @@ pub fn main() !void {
const sn = try SoundNode.create(allocator, nodename);
//print("Added node {s} at tick {d}\n", .{nodename, tick});
try soundnodes.append(sn);
try sn.s("basefreq", @as(f64, 440));
try sn.s("gain", @as(f64, 1));
try sn.s("phase", @as(f64, 0));
},
1 => {
@ -196,7 +201,7 @@ pub fn main() !void {
const src = soundnodes.items[src_node];
const a = try Activity.create(allocator, tick_start, tick_end, opcode, src, [6]f64{op1, op2, op3, op4, op5, op6});
print("Set activity {d} for node {d} s at tick {d}\n", .{opcode, src_node, tick});
//print("Set activity {d} for node {d} s at tick {d}\n", .{opcode, src_node, tick});
try src.activities.append(a);
},

View file

@ -23,13 +23,16 @@ pub const SoundNode = struct {
allocator: Allocator,
name: []const u8 = "soundnode",
location: Pnt = Pnt{.x = 0, .y = 0, .z = 0},
air_in: ArrayList(*SoundNode),
wire_in: ArrayList(*SoundNode),
activities: ArrayList(*Activity),
props: StringHashMap(f64),
x: f32 = 0,
y: f32 = 0,
z: f32 = 0,
fab: FreqAmpBuffer,
pub fn create(allocator: Allocator, name: []const u8) !*SoundNode {
@ -50,6 +53,9 @@ pub const SoundNode = struct {
.activities = activities,
.fab = fab,
.props = props,
.x = 0,
.y = 0,
.z = 0,
};
return sn;
@ -72,6 +78,9 @@ pub const SoundNode = struct {
.activities = activities,
.fab = fab,
.props = props,
.x = 0,
.y = 0,
.z = 0,
};
}
@ -92,9 +101,34 @@ pub const SoundNode = struct {
}
pub fn g(self: *SoundNode, key: []const u8) f64 {
const value = self.props.get(key);
if (value) |v| {
return v;
} else {
return @as(f64, 0.0);
}
}
pub fn s(self: *SoundNode, key: []const u8, value: f64) !void {
try self.props.put(key, value);
}
pub fn distance(self: *SoundNode, other: *SoundNode) f64 {
return pnt.distanceBetweenPoints(self.location, other.location);
if ((self.x == other.x) and (self.y == other.y) and (self.z == other.z)) {
return 0;
}
const dx: f32 = self.x - other.x;
const dy: f32 = self.y - other.y;
const dz: f32 = self.z - other.z;
return math.sqrt(dx*dx + dy*dy + dz*dz);
}

View file

@ -7,3 +7,7 @@ pub const corrected_tau: f64 = tau / 44100;
pub fn prnt(s: []const u8) void {
print("{s}\n", .{s});
}
pub fn interpolate(x: f64, x0: f64, x1: f64, y0: f64, y1: f64) f64 {
return y0 + ((y1-y0)*(x-x0) / (x1-x0));
}