예제 #1
0
    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
예제 #2
0
    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
예제 #3
0
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)
예제 #4
0
    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)
예제 #5
0
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
예제 #6
0
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
예제 #7
0
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))
예제 #8
0
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