def test_create_relative_ahdsr_envelope( duration: float, velocity: float, frame_rate: int, attack_to_ahds_ratio: float, attack_degree: float, hold_to_ahds_ratio: float, decay_to_ahds_ratio: float, decay_degree: float, sustain_level: float, max_release_duration: float, release_duration_on_velocity_order: float, release_degree: float, peak_value: float, ratio_at_zero_velocity: float, envelope_values_on_velocity_order: float, expected: np.ndarray ) -> None: """Test `create_relative_ahdsr_envelope` function.""" event = Event( instrument='any_instrument', start_time=0, duration=duration, frequency=440, velocity=velocity, effects='', frame_rate=frame_rate ) result = create_relative_ahdsr_envelope( event, attack_to_ahds_ratio, attack_degree, hold_to_ahds_ratio, decay_to_ahds_ratio, decay_degree, sustain_level, max_release_duration, release_duration_on_velocity_order, release_degree, peak_value, ratio_at_zero_velocity, envelope_values_on_velocity_order ) np.testing.assert_almost_equal(result, expected)
def convert_tsv_to_events( input_path: str, settings: Dict[str, Any] ) -> List[Event]: """ Collect sound events (loosely speaking, played notes) from a TSV file. :param input_path: path to TSV file with rows representing events :param settings: global settings for the output track :return: sound events """ raw_events = [] with open(input_path) as input_file: column_names = input_file.readline().rstrip(os.linesep).split('\t') for line in input_file.readlines(): raw_events.append(dict(zip(column_names, line.rstrip(os.linesep).split('\t')))) raw_events = set_types(raw_events) events = [] fields_to_use = [ 'instrument', 'start_time', 'duration', 'frequency', 'velocity', 'effects' ] for raw_event in raw_events: raw_event = {k: v for k, v in raw_event.items() if k in fields_to_use} event = Event(frame_rate=settings['frame_rate'], **raw_event) events.append(event) return events
def test_filter_relative_frequencies( frequencies: List[float], frame_rate: int, min_frequency_ratio: float, max_frequency_ratio: float, invert: bool, order: int, spectrogram_params: Dict[str, Any], expected: np.ndarray ) -> None: """Test `filter_relative_frequencies` function.""" waves = [ generate_mono_wave( 'sine', frequency, np.ones(frame_rate), frame_rate ) for frequency in frequencies ] sound = sum(waves) sound = np.vstack((sound, sound)) event = Event( instrument='any_instrument', start_time=0, duration=1, frequency=min(frequencies), velocity=1, effects='', frame_rate=frame_rate ) sound = filter_relative_frequencies( sound, event, min_frequency_ratio, max_frequency_ratio, invert, order ) spc = spectrogram(sound[0], frame_rate, **spectrogram_params)[2] result = spc.sum(axis=1)[:len(expected)] np.testing.assert_almost_equal(result, expected)
def test_create_constant_envelope(duration: float, frame_rate: int, value: float, expected: np.ndarray) -> None: """Test `create_constant_envelope` function.""" event = Event(instrument='any_instrument', start_time=0.0, duration=duration, frequency=440, velocity=1.0, effects='', frame_rate=frame_rate) result = create_constant_envelope(event, value) np.testing.assert_equal(result, expected)
def test_apply_overdrive(sound: np.ndarray, frame_rate: int, fraction_to_clip: float, strength: float, expected: np.ndarray) -> None: """Test `apply_overdrive` function.""" event = Event(instrument='any_instrument', start_time=0, duration=1, frequency=440, velocity=1, effects='', frame_rate=frame_rate) result = apply_overdrive(sound, event, fraction_to_clip, strength) np.testing.assert_almost_equal(result, expected)
def test_apply_tremolo(sound: np.ndarray, frame_rate: int, sound_frequency: float, kind: str, kwargs: Dict[str, Any], expected: np.ndarray) -> None: """Test `apply_tremolo` function.""" event = Event(instrument='any_instrument', start_time=0, duration=1, frequency=sound_frequency, velocity=1, effects='', frame_rate=frame_rate) result = apply_tremolo(sound, event, kind, **kwargs) np.testing.assert_almost_equal(result, expected)
def test_apply_chorus(sound: np.ndarray, frame_rate: int, original_sound_gain: float, copies_params: List[Dict[str, Any]], expected: np.ndarray) -> None: """Test `apply_chorus` function.""" event = Event(instrument='any_instrument', start_time=0, duration=1, frequency=1, velocity=1, effects='', frame_rate=frame_rate) result = apply_chorus(sound, event, original_sound_gain, copies_params) np.testing.assert_equal(result, expected)
def test_apply_compressor(sound: np.ndarray, frame_rate: int, frequency: float, threshold: float, quantile: float, chunk_size_in_cycles: float, expected: np.ndarray) -> None: """Test `apply_compressor` function.""" event = Event(instrument='any_instrument', start_time=0, duration=sound.shape[1] / frame_rate, frequency=frequency, velocity=1, effects='', frame_rate=frame_rate) result = apply_compressor(sound, event, threshold, quantile, chunk_size_in_cycles) np.testing.assert_almost_equal(result, expected)
def test_create_user_defined_envelope(duration: float, velocity: float, frame_rate: int, parts: List[Dict[str, Any]], ratio_at_zero_velocity: float, envelope_values_on_velocity_order: float, expected: np.ndarray) -> None: """Test `create_user_defined_envelope` function.""" event = Event(instrument='any_instrument', start_time=0, duration=duration, frequency=440, velocity=velocity, effects='', frame_rate=frame_rate) result = create_user_defined_envelope(event, parts, ratio_at_zero_velocity, envelope_values_on_velocity_order) np.testing.assert_almost_equal(result, expected)
def test_apply_phaser(frequency: float, frame_rate: int, kind: str) -> None: """Test that `apply_phaser` function runs without failures.""" sound = generate_mono_wave( 'sine', frequency, np.ones(frame_rate), frame_rate ) sound = np.vstack((sound, sound)) event = Event( instrument='any_instrument', start_time=0, duration=1, frequency=frequency, velocity=1, effects='', frame_rate=frame_rate ) result = apply_phaser(sound, event, kind) assert np.all(np.isfinite(result))
def test_apply_amplitude_normalization(sound: np.ndarray, velocity: float, value_at_max_velocity: float, quantile: float, value_on_velocity_order: float, value_at_zero_velocity: float, expected: np.ndarray) -> None: """Test `apply_amplitude_normalization` function.""" event = Event(instrument='any_instrument', start_time=0, duration=1, frequency=440, velocity=velocity, effects='', frame_rate=8) result = apply_amplitude_normalization(sound, event, value_at_max_velocity, quantile, value_on_velocity_order, value_at_zero_velocity) np.testing.assert_equal(result, expected)
def test_apply_envelope_shaper(sound: np.ndarray, frame_rate: int, frequency: float, envelope_params: Dict[str, Any], quantile: float, chunk_size_in_cycles: float, initial_rescaling_ratio: float, forced_fading_ratio: float, expected: np.ndarray) -> None: """Test `apply_envelope_shaper` function.""" event = Event(instrument='any_instrument', start_time=0, duration=sound.shape[1] / frame_rate, frequency=frequency, velocity=1, effects='', frame_rate=frame_rate) result = apply_envelope_shaper(sound, event, envelope_params, quantile, chunk_size_in_cycles, initial_rescaling_ratio, forced_fading_ratio) np.testing.assert_almost_equal(result, expected)
def convert_midi_to_events(midi_path: str, settings: Dict[str, Any]) -> List[Event]: """ Collect sound events (loosely speaking, played notes) from a MIDI file. :param midi_path: path to source MIDI file :param settings: global settings for the output track :return: sound events """ midi_settings = settings['midi'] if 'track_name_to_instrument' in midi_settings: instruments_mapping = midi_settings['track_name_to_instrument'] effects_mapping = midi_settings.get('track_name_to_effects', {}) key_fn = lambda instrument: instrument.name elif 'program_to_instrument' in midi_settings: instruments_mapping = midi_settings['program_to_instrument'] effects_mapping = midi_settings.get('program_to_effects', {}) key_fn = lambda instrument: instrument.program else: raise RuntimeError("MIDI config file lacks required sections.") midi_data = pretty_midi.PrettyMIDI(midi_path) events = [] for pretty_midi_instrument in midi_data.instruments: key = key_fn(pretty_midi_instrument) sinethesizer_instrument = instruments_mapping.get(key) if sinethesizer_instrument is None: continue for note in pretty_midi_instrument.notes: event = Event(instrument=sinethesizer_instrument, start_time=note.start, duration=note.end - note.start, frequency=pretty_midi.note_number_to_hz(note.pitch), velocity=note.velocity / MAX_MIDI_VALUE, effects=effects_mapping.get(key, ''), frame_rate=settings['frame_rate']) events.append(event) return events
def test_apply_equalizer(frequencies: List[float], frame_rate: int, kind: str, kwargs: Dict[str, Any], spectrogram_params: Dict[str, Any], expected: np.ndarray) -> None: """Test `apply_equalizer` function.""" waves = [ generate_mono_wave('sine', frequency, np.ones(frame_rate), frame_rate) for frequency in frequencies ] sound = sum(waves) sound = np.vstack((sound, sound)) event = Event(instrument='any_instrument', start_time=0, duration=1, frequency=min(frequencies), velocity=1, effects='', frame_rate=frame_rate) sound = apply_equalizer(sound, event, kind, **kwargs) spc = spectrogram(sound[0], frame_rate, **spectrogram_params)[2] result = spc.sum(axis=1)[:len(expected)] np.testing.assert_almost_equal(result, expected)
def test_create_exponentially_decaying_envelope( duration: float, frame_rate: int, attack_to_ad_max_ratio: float, max_attack_duration: float, attack_degree: float, decay_half_life: Optional[float], decay_half_life_ratio: Optional[float], max_release_duration: float, release_duration_on_velocity_order: float, release_degree: float, peak_value: float, ratio_at_zero_velocity: float, envelope_values_on_velocity_order: float, expected: np.ndarray) -> None: """Test `create_exponentially_decaying_envelope` function.""" event = Event(instrument='any_instrument', start_time=0.0, duration=duration, frequency=440, velocity=1.0, effects='', frame_rate=frame_rate) result = create_exponentially_decaying_envelope( event, attack_to_ad_max_ratio, max_attack_duration, attack_degree, decay_half_life, decay_half_life_ratio, max_release_duration, release_duration_on_velocity_order, release_degree, peak_value, ratio_at_zero_velocity, envelope_values_on_velocity_order) np.testing.assert_almost_equal(result, expected)
def test_create_trapezoid_envelope( duration: float, velocity: float, frame_rate: int, attack_share: float, attack_degree: float, decay_share: float, decay_degree: float, peak_value: float, ratio_at_zero_velocity: float, envelope_values_on_velocity_order: float, expected: np.ndarray ) -> None: """Test `create_trapezoid_envelope` function.""" event = Event( instrument='any_instrument', start_time=0, duration=duration, frequency=440, velocity=velocity, effects='', frame_rate=frame_rate ) result = create_trapezoid_envelope( event, attack_share, attack_degree, decay_share, decay_degree, peak_value, ratio_at_zero_velocity, envelope_values_on_velocity_order ) np.testing.assert_almost_equal(result, expected)
@pytest.mark.parametrize( "sound, event, automated_effect_name, break_points, expected", [ ( # `sound` np.array([ [1.0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], ]), # `event` Event(instrument='any_instrument', start_time=0, duration=1, frequency=440, velocity=1, effects='', frame_rate=8), # `automated_effect_name` 'panning', # `break_points` [ { 'relative_position': 0, 'left_amplitude_ratio': 1.0, 'right_amplitude_ratio': 1.0, }, { 'relative_position': 0.25, 'left_amplitude_ratio': 0.25,
from sinethesizer.synth.event_to_amplitude_factor import ( compute_amplitude_factor_as_power_of_velocity) @pytest.mark.parametrize( "timeline, event, instruments_registry, frame_rate, expected", [ ( # `timeline` np.array([[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, -4, -5, -6, -7, -8, -9]]), # `event` Event(instrument='sine', start_time=2, duration=1, frequency=1, velocity=1, effects='', frame_rate=4), # `instruments_registry` { 'sine': Instrument(partials=[ Partial(wave=ModulatedWave( waveform='sine', amplitude_envelope_fn=functools.partial( create_constant_envelope, value=1), phase=0, amplitude_modulator=None, phase_modulator=None, quasiperiodic_bandwidth=0,
@pytest.mark.parametrize( "sound, event, left_amplitude_ratio, right_amplitude_ratio, expected", [ ( # `sound` np.array([ [1.0, 2, 3], [2, 3, 4], ]), # `event` Event(instrument='any_instrument', start_time=0.0, duration=1.0, frequency=440.0, velocity=0.0, effects='', frame_rate=20), # `left_amplitude_ratio` 0.5, # `right_amplitude_ratio` 0.1, # `expected` np.array([ [0.5, 1.0, 1.5], [0.2, 0.3, 0.4], ]), ), ]) def test_apply_panning(sound: np.ndarray, event: Event,
from sinethesizer.synth.core import Event @pytest.mark.parametrize("tsv_content, settings, expected", [ ([ "instrument\tstart_time\tduration\tfrequency\tvelocity\teffects", "sine\t1\t1\tA0\t1\t", 'sine\t2\t1\t1\t1\t[{"name": "tremolo", "frequency": 1}]' ], { 'frame_rate': 4, 'trailing_silence': 1, }, [ Event(instrument='sine', start_time=1.0, duration=1.0, frequency=27.5, velocity=1.0, effects='', frame_rate=4), Event(instrument='sine', start_time=2.0, duration=1.0, frequency=1.0, velocity=1.0, effects='[{"name": "tremolo", "frequency": 1}]', frame_rate=4), ]), ([ "instrument\tstart_time\tduration\tfrequency\tvelocity\teffects\textra_column", "sine\t1\t1\tA0\t1\t\tsomething", 'sine\t2\t1\t1\t1\t[{"name": "tremolo", "frequency": 1}]\tsomething'
], # `settings` { 'frame_rate': 4, 'trailing_silence': 1, 'midi': { 'program_to_instrument': {0: 'sine'} }, }, # `expected` [ Event( instrument='sine', start_time=1.0, duration=1.0, frequency=27.5, # A0 velocity=1.0, effects='', frame_rate=4 ), Event( instrument='sine', start_time=2.0, duration=1.0, frequency=34.64782887210901, # C#1 velocity=1.0, effects='', frame_rate=4 ), ] ),