100 lines
2.4 KiB
Python
100 lines
2.4 KiB
Python
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.dist_cache = dict() # {((x,y,z),(x,y,z)) : dist}
|
|
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)
|
|
|