def _make_melodic_orientation_system(self) -> lily.NOventLine: orientation = lily.NOventLine([]) for tone in self.musdat["transcription"]: if tone.pitch.is_empty: pitch = [] markup = None else: instrument = globals_.INSTRUMENT_NAME2OBJECT[ globals_.PITCH2INSTRUMENT[tone.pitch.normalize()]] pitch = [tone.pitch] markup = attachments.MarkupOnOff("\\small {}".format( instrument.short_name), direction="up") novent = lily.NOvent( pitch=pitch, delay=tone.delay, duration=tone.duration, markup_on_off=markup, ) orientation.append(novent) duration = orientation.duration difference = self.duration - duration if difference > 0: orientation.append( lily.NOvent(pitch=[], delay=difference, duration=difference)) return orientation
def _make_rhythmic_orientation_system(self) -> lily.NOventLine: absolute_positions = self.transcription.spread_metrical_loop.get_all_rhythms( ) absolute_rhythm = tuple(absolute_positions[index] for index in self.rhythmic_orientation_indices) is_first_attack_rest = False if absolute_rhythm[0] != 0: absolute_rhythm = (0, ) + absolute_rhythm is_first_attack_rest = True relative_rhythm = tuple(b - a for a, b in zip( absolute_rhythm, absolute_rhythm[1:] + (self.transcription.spread_metrical_loop.duration, ), )) is_first = True orientation = lily.NOventLine([]) for rhythm in relative_rhythm: if is_first and is_first_attack_rest: pitch = [] is_first = False else: pitch = [ji.r(1, 1)] novent = lily.NOvent(pitch=pitch, delay=rhythm, duration=rhythm) orientation.append(novent) return orientation
def split( nth_event: int, novent_line: lily.NOventLine, *duration_of_splitted_event, change_novent_line: bool = True, set_n_novents2rest: int = 0, ) -> None: n_splits = len(duration_of_splitted_event) if n_splits < set_n_novents2rest: set_n_novents2rest = n_splits is_active_per_novent = tuple( not bool(it) for it in tools.euclid(set_n_novents2rest, n_splits)) duration = sum(duration_of_splitted_event) try: assert duration == novent_line[nth_event].delay except AssertionError: msg = ( "Summed duration of each splitted event has to be as long as the duration " ) msg += "of the event that shall be splitted." raise ValueError(msg) event2split = novent_line[nth_event].copy() if change_novent_line: del novent_line[nth_event] else: splitted_novents = [] for duration, is_active in zip(reversed(duration_of_splitted_event), is_active_per_novent): splitted_novent = event2split.copy() splitted_novent.delay = duration splitted_novent.duration = duration if change_novent_line: novent_line.insert(nth_event, splitted_novent) else: if not is_active: splitted_novent = lily.NOvent(pitch=[], delay=duration, duration=duration) splitted_novents.insert(0, splitted_novent) if not change_novent_line: return tuple(splitted_novents) else: for idx, is_active in enumerate(is_active_per_novent): if not is_active: rest(idx + nth_event, novent_line)
def harmonic_pitches(self) -> tuple: last_pitch = self.bread[0].harmonic_pitch start = self.bread[0].start stop = self.bread[0].stop melody_pitch_starts = [] if self.bread[0].does_slice_start_overlap_with_attack: melody_pitch_starts.append(self.bread[0].start) ns = [] for slice_ in self.bread[1:]: if slice_.harmonic_pitch == last_pitch: stop = slice_.stop if slice_.does_slice_start_overlap_with_attack: melody_pitch_starts.append(slice_.start) else: if last_pitch: ns.append(( lily.NOvent(pitch=[last_pitch], delay=start, duration=stop), tuple(melody_pitch_starts), )) start = slice_.start stop = slice_.stop last_pitch = slice_.harmonic_pitch melody_pitch_starts = [] if slice_.does_slice_start_overlap_with_attack: melody_pitch_starts.append(slice_.start) if last_pitch: ns.append(( lily.NOvent(pitch=[last_pitch], delay=start, duration=stop), tuple(melody_pitch_starts), )) return tuple(ns)
def process_comprovisation_attachments( novent_line: lily.NOventLine) -> lily.NOventLine: new_novent_line = lily.NOventLine([]) for novent in novent_line.copy(): if globals_.ADD_COMPROVISATION and novent.optional: # perhaps it is more likely that an optional tone get played by the musicians # than that it won't get played. if random.random() > 0.38: shall_pass = True else: shall_pass = False else: shall_pass = True if novent.optional_some_pitches: choosen_pitches = [] for pitch_idx, pitch in enumerate(sorted(novent.pitch)): if pitch_idx in novent.optional_some_pitches.optional_pitch_indices: if not globals_.ADD_COMPROVISATION or random.random( ) > 0.4: choosen_pitches.append(pitch) else: choosen_pitches.append(pitch) novent.pitch = choosen_pitches if shall_pass: if isinstance(novent.choose, attachments.ChooseOne): novent.pitch = [random.choice(novent.pitch)] elif isinstance(novent.choose, attachments.Choose): possible_choices = functools.reduce( operator.add, tuple( tuple(itertools.combinations(novent.pitch, n + 1)) for n in range(len(novent.pitch))), ) novent.pitch = list(possible_choices[random.choice( range(len(possible_choices)))]) new_novent_line.append(novent) else: new_novent_line.append( lily.NOvent( pitch=[], tempo=novent.tempo, duration=novent.duration, delay=novent.delay, )) return new_novent_line
def postpone(nth_event: int, value: fractions.Fraction, novent_line: lily.NOventLine) -> None: try: assert novent_line[nth_event].delay > value except AssertionError: msg = "Can't postpone event with value {} ".format(value) msg += "because the event isn't long enough." raise ValueError(msg) novent_line[nth_event].delay -= value novent_line[nth_event].duration -= value if nth_event == 0 or novent_line[nth_event - 1].pitch: novent_line.insert(nth_event, lily.NOvent(pitch=[], delay=value, duration=value)) else: novent_line[nth_event - 1].delay += value novent_line[nth_event - 1].duration += value
def shorten(nth_event: int, value: fractions.Fraction, novent_line: lily.NOventLine) -> None: try: assert novent_line[nth_event].delay > value except AssertionError: msg = "Can't shorten event '{}' by value '{}'. Event is too short!".format( novent_line[nth_event], value) raise ValueError(msg) novent_line[nth_event].delay -= value novent_line[nth_event].duration -= value if nth_event + 1 != len(novent_line): if not novent_line[nth_event + 1].pitch: novent_line[nth_event + 1].delay += value novent_line[nth_event + 1].duration += value return novent_line.insert(nth_event + 1, lily.NOvent(pitch=[], delay=value, duration=value))
def rest(idx: int, novent_line: lily.NOventLine) -> None: previous_is_rest = False if idx != 0: previous_is_rest = not novent_line[idx - 1].pitch try: following_is_rest = not novent_line[idx + 1].pitch except KeyError: following_is_rest = False if previous_is_rest and following_is_rest: added_duration = novent_line[idx].duration + novent_line[idx + 1].duration novent_line[idx - 1].delay += added_duration novent_line[idx - 1].duration += added_duration for _ in range(2): del novent_line[idx] elif previous_is_rest: added_duration = novent_line[idx].duration novent_line[idx - 1].delay += added_duration novent_line[idx - 1].duration += added_duration del novent_line[idx] elif following_is_rest: added_duration = novent_line[idx].duration novent_line[idx + 1].delay += added_duration novent_line[idx + 1].duration += added_duration del novent_line[idx] else: empty_event = lily.NOvent(pitch=[], delay=fractions.Fraction( novent_line[idx].delay)) novent_line[idx] = empty_event