def one_case(self, interval_start: float, interval_end: float, buffer_length: int, expected_level_in_output: Optional[float], expected_average: Optional[float]): host = Host() host.sample_rate = 100 unit = Unit(2, 0, 2, 0, host) clips: List[AudioClip] = self.generate_test_clips() mocked_waveform_provider = MockedWaveformProvider() strategy = Sampler(clips, mocked_waveform_provider) strategy.unit = unit interval = TimeInterval() interval.start_in_seconds = interval_start interval.end_in_seconds = interval_end out1 = np.zeros(shape=(buffer_length,), dtype=np.float32) out2 = np.zeros(shape=(buffer_length,), dtype=np.float32) strategy.render(interval, [], [out1, out2], [], []) values_tested: bool = False if expected_level_in_output is not None: expected_buffer = np.zeros(100, ) + expected_level_in_output self.assertTrue((out1 == expected_buffer).all()) values_tested = True if expected_average is not None: self.assertEqual(expected_average, np.mean(out1)) self.assertEquals(expected_average, np.mean(out2)) values_tested = True self.assertTrue(values_tested)
def test_vst_plugin_strategy(self): host = Host() dir_path = os.path.dirname(os.path.realpath(__file__)) path_to_so: str = dir_path + '/../../submodules/cython-vst-loader/tests/test_plugins' \ '/amsynth-vst.x86_64-linux.so' as_bytes = path_to_so.encode('utf-8') unit = Unit(0, 0, 1, 0, host) strategy = VstPlugin(as_bytes, unit) unit.set_processing_strategy(strategy) event_factory = MidiEventFactory() event = event_factory.create_note_on_event(87, 10) event.sample_position = 10 events: List[Event] = [event] def generate(): return np.zeros((host.block_size,), np.float32) left_out = generate() right_out = generate() interval = TimeInterval() interval.start_in_bars = 0 interval.end_in_bars = 1 self.assertTrue(left_out[13] == 0.0) self.assertTrue(right_out[13] == 0.0) strategy.render(interval, [], [left_out, right_out], [events], []) self.assertTrue(left_out[13] != 0.0) self.assertTrue(right_out[13] != 0.0)
def test_chaining_two_stream_units(self): host = Host() unit1 = Unit(0, 0, 1, 0, host, ConstantLevel(np.float32(0.5))) unit2 = Unit(1, 0, 1, 0, host, StreamGain(np.float32(0.5))) Connector(unit1.output_stream_nodes[0], unit2.input_stream_nodes[0]) chain = Chain(unit1, unit2) self.assertEqual(len(chain.input_stream_nodes), 0) self.assertEqual(len(chain.input_event_nodes), 0) self.assertEqual(len(chain.output_stream_nodes), 1) self.assertEqual(len(chain.output_event_nodes), 0) interval = TimeInterval() interval.start_in_bars = 0 interval.end_in_bars = 1 interval.start_in_seconds = 0.0 interval.end_in_seconds = 0.25 interval.num_samples = 44100 * interval.get_length_in_seconds() out_buffer = np.ndarray(shape=(100, ), dtype=np.float32) chain.output_stream_nodes[0].render(interval, out_buffer) for x in range(0, 100): self.assertEqual(0.25, out_buffer[x])
def test_render_one_buffer_with_a_note(self): plugin = DrumSynthPlugin() host = Host() strategy = DrumSynthStrategy(plugin) Unit(0, 0, 1, 0, host, strategy) out_stream_buffer = np.zeros(shape=(100, ), dtype=np.float32) interval = TimeInterval() interval.start_in_bars = 0 interval.end_in_bars = 1 factory = MidiEventFactory() note_event = factory.create_note_on_event(note=65, velocity=70, position=50) strategy.render(interval, [], [out_stream_buffer], [[note_event]], []) zero_sample_indices = [0, 20, 40] non_zero_sample_indices = [60, 80, 99] for idx in zero_sample_indices: self.assertEqual(0, out_stream_buffer[idx]) for idx in non_zero_sample_indices: self.assertNotEqual(0, out_stream_buffer[idx])
def test_fork_and_join(self): # +--------+ +--------+ # | | | | # | level1 +--+--> gain1 +--+ # | | | | | | +--------+ # +--------+ | +--------+ | | | # | +-> mixer | # | | | | # +--------+ | +--------+ | +--------+ # | +--+ | | | # | level2 +-----> gain2 +--+ # | | | | # +--------+ +--------+ gain1_value = np.float32(0.7) gain2_value = np.float32(0.113) level1_value = np.float32(0.63) level2_value = np.float32(0.47) host = Host() level1 = Unit(0, 0, 1, 0, host, ConstantLevel(level1_value)) level2 = Unit(0, 0, 1, 0, host, ConstantLevel(level2_value)) gain1 = Unit(1, 0, 1, 0, host, StreamGain(gain1_value)) gain2 = Unit(1, 0, 1, 0, host, StreamGain(gain2_value)) mixer = Unit(1, 0, 1, 0, host, Transparent()) Connector(level1.output_stream_nodes[0], gain1.input_stream_nodes[0]) Connector(level2.output_stream_nodes[0], gain2.input_stream_nodes[0]) Connector(level2.output_stream_nodes[0], gain1.input_stream_nodes[0]) Connector(gain1.output_stream_nodes[0], mixer.input_stream_nodes[0]) Connector(gain2.output_stream_nodes[0], mixer.input_stream_nodes[0]) interval = TimeInterval() interval.start_in_bars = 0 interval.end_in_bars = 1 interval.start_in_seconds = -0.1 interval.end_in_seconds = 0.333333333 interval.num_samples = 44100 * interval.get_length_in_seconds() out_buffer = np.ndarray(shape=(100, ), dtype=np.float32) mixer.output_stream_nodes[0].render(interval, out_buffer) expected_output_level = (level1_value + level2_value ) * gain1_value + level2_value * gain2_value for x in range(0, 100): self.assertEqual(expected_output_level, out_buffer[x])
def compile(self, project: Project) -> List[StreamNode]: """ Given a project, returns a list of stream nodes (as many nodes as many channels there are - e.g. 2 for stereo. Then the user is expected to iteratively render data from those nodes into buffers. :param project: Project :return: List[StreamNode] """ compiled_tracks: Dict[Track, Unit] = {} host = Host() master_unit = self._compile_internal(host, project, project.master_track, compiled_tracks) return master_unit.output_stream_nodes
def test_smoke(self): host = Host() strategy = ConstantLevel(np.float32(0.50)) unit = Unit(0, 0, 1, 0, host, strategy) all_output_nodes = unit.get_all_output_nodes() self.assertEqual(1, len(all_output_nodes)) output_node = all_output_nodes[0] interval = TimeInterval() interval.start_in_bars = 0 interval.end_in_bars = 1 out_buffer = np.ndarray(shape=(100, ), dtype=np.float32) output_node.render(interval, out_buffer) for x in range(0, 100): self.assertEqual(0.5, out_buffer[x])