sonnum/core/soundnode.py
2025-08-13 22:43:56 +03:00

88 lines
No EOL
2.1 KiB
Python

import math
TAU = 2 * math.pi
class SoundNode:
def __init__(self, name, room):
self.name = name
self.room = room
self.room.nodes.append(self)
self.r_amps = dict() # {tick: {freq: r_amp}}
self.air_in = []
self.wire_in = []
self.start_location = (0, 0, 0)
# Used by the tick cycle to correctly order the nodes.
# Do not touch this.
self.tick_done = False
def distance_to_node(self, other_node, t):
loc = self.location(t)
other_loc = other_node.location(t)
if (loc, other_loc) in self.room.dist_cache:
return self.room.dist_cache[(loc, other_loc)]
if (other_loc, loc) in self.room.dist_cache:
return self.room.dist_cache[(other_loc, loc)]
diff_x = loc[0]-other_loc[0]
diff_y = loc[1]-other_loc[1]
diff_z = loc[2]-other_loc[2]
dist = diff_x*diff_x + diff_y*diff_y + diff_z * diff_z
self.room.dist_cache[(loc, other_loc)] = dist
return dist
return (loc[0]-other_loc[0])**2 + (loc[1]-other_loc[1])**2 + (loc[2]-other_loc[2])**2
def sample_r_amps_by_wire(self, source_node, current_t):
if current_t in source_node.r_amps:
return source_node.r_amps[current_t]
return dict()
def sample_r_amps_by_air(self, source_node, current_t):
dist = self.distance_to_node(source_node, current_t)
#sample_t = current_t - int(dist / self.room.speed_of_sound)
sample_t = current_t - int(128.571428 * dist)
if sample_t in source_node.r_amps:
attenuation = math.exp(-(dist/100.0))
return {f: a * attenuation for f, a in source_node.r_amps[sample_t].items()}
return dict()
def air_to(self, out_node):
if not self in out_node.air_in:
out_node.air_in.append(self)
def wire_to(self, out_node):
if not self in out_node.wire_in:
out_node.wire_in.append(self)
## THE FOLLOWING FUNCTIONS NEED TO BE DEFINED BY CONCRETE NODES
def location(self, t):
# Location of the soundnote (x,y,z) in meters
# at time t.
return self.start_location
def calc_r_amps(self, t):
# Fill the amp_cache for tick t
# {freq: relative_amp}
# relative_amp must be between 0 and 1
self.r_amps[t] = dict()