import wave import math from .soundnode import * from .nodes.sink import * TAU = 2 * math.pi def stb(i: int, bytelen: int) -> bytes: return i.to_bytes(bytelen, byteorder='little', signed=True) class Room: def __init__(self): self.nodes = [] self.sample_rate = 44100 self.speed_of_sound = 343 / float(self.sample_rate) # m/tick self.set_bit_depth(24) self.left_sink = SinkNode('left', self) self.left_sink.start_location = (-0.3, 0, 0) self.right_sink = SinkNode('right', self) self.right_sink.start_location = (0.3, 0, 0) self.sine_multiplier = TAU / self.sample_rate self.running_program = None def set_bit_depth(self, bit_depth): self.bit_depth = bit_depth self.max_amp = int((2**bit_depth) / 2.0 - 1) self.min_amp = -int((2**bit_depth) / 2.0) self.sample_width = int(self.bit_depth / 8.0) def generate_frame(self, t): for node in self.nodes: node.tick_done = False updates = True order_of_passage = [] if not order_of_passage: while updates: updates = False for node in self.nodes: if not (t in node.r_amps): has_unprocessed_inputs = False for in_node in node.air_in: if not in_node.tick_done: has_unprocessed_inputs = True break if not has_unprocessed_inputs: for in_node in node.wire_in: if not in_node.tick_done: has_unprocessed_inputs = True break if not has_unprocessed_inputs: node.calc_r_amps(t) node.tick_done = True updates = True order_of_passage.append(node) else: for node in order_of_passage: node.calc_r_amps(t) left_total_amp = self.max_amp * sum([vol * math.sin(self.sine_multiplier * freq * t) for freq, vol in self.left_sink.r_amps[t].items()]) right_total_amp = self.max_amp * sum([vol * math.sin(self.sine_multiplier * freq * t) for freq, vol in self.right_sink.r_amps[t].items()]) if left_total_amp > self.max_amp: left_total_amp = self.max_amp if left_total_amp < self.min_amp: left_total_amp = self.min_amp if right_total_amp > self.max_amp: right_total_amp = self.max_amp if right_total_amp < self.min_amp: right_total_amp = self.min_amp return stb(int(left_total_amp), self.sample_width), stb(int(right_total_amp), self.sample_width)