def get_temporal(self, fs: Hz, start: Frames, end: Frames): source_buffer = self.get_buffer(fs) lower, upper = self.get_range(fs) out = np.zeros(end - start) if start > upper: return out # TODO: upsample source buffer to near-integer period # compute the sampleable range of the signal sample_end = to_frames(end if upper is None else min(upper, end)) sample_start = to_frames(start if lower is None else max(lower, start)) # tile the buffer enough to cover the sampleable range n_tiles = ceil( abs(sample_end - sample_start - start) / len(source_buffer)) # rotate the tiled buffer into the same index space as the output tiled_buffer = np.roll(np.tile(source_buffer, n_tiles + 1), -start) output_start = sample_start - start output_end = sample_end - start out[output_start:output_end] = tiled_buffer[output_start:output_end] return out
def get_range(self) -> FrameRange: """ For bounded child and bounded parameter, sample the parameter to compute the lower and upper extent. """ child_lower, child_upper = self.child.get_range() return self.calculate_extent(to_frames(child_lower), to_frames(child_upper))
def get_valid_range(period: Partial, frame_range: FrameRange) -> (Frames, Frames): lower, upper = frame_range bufsize = to_bufsize(period) if lower is not None: return to_frames(lower), to_frames(lower) + bufsize elif upper is not None: return to_frames(upper) - bufsize, to_frames(upper) else: return 0, bufsize
def get_temporal(self, start: Frames, end: Frames): output = np.zeros(end - start) lower, upper = self.get_range() sample_start = to_frames(min(max(start, lower), upper)) sample_end = to_frames(min(max(end, lower), upper)) sample_size = sample_end - sample_start if sample_size <= 0: return output internal = self.get_temporal_checked(sample_start, sample_end) offset = sample_start - start output[offset:offset + sample_size] = internal return output
def play_signal(signal: Signal, fs: int, start: Optional[Frames] = None, end: Optional[Frames] = None): start = to_frames(start if start is not None else 0) end = to_frames(end if end is not None else signal.get_range(fs)[1]) buffer = signal.get_temporal(fs, start, end) # Ensure that highest value is in 16-bit range audio = buffer / np.max(np.abs(buffer)) * (2 ** 15 - 1) # Convert to 16-bit data audio = audio.astype(np.int16) # Start playback play_obj = sa.play_buffer(audio, 1, 2, fs) # Wait for playback to finish before exiting play_obj.wait_done()
def get_temporal(self, start: Frames, end: Frames): offset_frames = to_frames(self.get_offset_frames()) return self.child.get_temporal(start-offset_frames, end-offset_frames)
workspace = Workspace("resources/signals.json", manager, graph, registry) workspace.initialize() signals = manager.signals restored_signal = manager.get_signal('dilated:2') dilated_signal = manager.get_signal('dilated:0.5') offset_signal = manager.get_signal('offset:2') base_signal = manager.get_signal('wav') var_offset_signal = manager.get_signal('var_offset') sine_signal = manager.get_signal('sine') selected_signal = var_offset_signal dur = to_frames(offset_signal.get_range(fs)[1]) diff = np.abs(np.subtract( base_signal.get_temporal(fs, 0, dur), restored_signal.get_temporal(fs, 0, dur), )) PLOT = True if PLOT: extras = 1 fig, (ax) = plt.subplots(len(signals)+extras, 1) ax[0].plot(diff) for i, signal in zip(range(len(signals)), signals.values()): sub_ax = ax[i+extras] print(f"plotting {signal.data.uuid}")
def get_range(self, fs: Hz) -> FrameRange: return to_frames(self.lower*fs), to_frames(self.upper*fs)
def get_centered_sample(signal: Signal): lower, upper = signal.get_range() lower_frames = to_frames(lower) upper_frames = to_frames(upper) return np.roll(signal.get_temporal(lower_frames, upper_frames), lower_frames)