#!/usr/bin/env python3 from NCO import NCOType, output_type from FixedPoint import FXfamily, FXnum import numpy as np class Summer: def __init__(self, sine_shift: int, square_shift: int, triangle_shift: int, sawtooth_shift: int) -> None: self.shifts = [sine_shift, square_shift, triangle_shift, sawtooth_shift] def next_sample(self, nco_in: NCOType) -> FXnum: sample = FXnum(0, family=output_type) for wave,shift in zip(nco_in, self.shifts): sample = sample + (wave >> shift) return sample class Truncator: def __init__(self, global_gain: int) -> None: self.global_gain = global_gain def next_sample(self, samp_in: FXnum) -> int: samp_gained = samp_in >> self.global_gain sample_bin = samp_gained.toBinaryString().replace('.', '') sample_bin_msbs = sample_bin[:12] #print("Sample bin: ", sample_bin) #print("MSB int val: ", int(sample_bin_msbs, 2)) if sample_bin_msbs[0] == '1': # negative number return (~(-1*int(sample_bin_msbs, 2)) + 1) - 2**11 else: # positive number return int(sample_bin_msbs, 2) + 2**11 if __name__ == "__main__": print("Testing truncator sweep") t = Truncator(0) for x in np.linspace(-8, 7.9, 10): print(t.next_sample(FXnum(x, output_type))) print("Testing truncator critical values") for x in [-8, 0, 8 - 2**-16]: print(t.next_sample(FXnum(x, output_type))) print("Testing summer") s = Summer(0, 32, 32, 32) for sample in np.linspace(-1, 1, 1000): out = s.next_sample([FXnum(sample, output_type), FXnum(-1, output_type), FXnum(-1, output_type), FXnum(-1, output_type)]) assert abs(out - sample) < 1e-4