Пример #1
0
    def estimate_best_meter(self, melody: old.Melody) -> tuple:
        """Return (Melody, TimeSignature) - pair."""
        meter_fitness_pairs = []
        for meter in self.potential_meters:
            n_potential_upbeats = int(
                fractions.Fraction(meter[0].numerator, meter[0].denominator)
                / fractions.Fraction(1, 8)
            )
            for n_upbeats in range(n_potential_upbeats):
                adadpted_melody = melody.copy()
                if n_upbeats:
                    adadpted_melody.insert(
                        0, old.Rest(n_upbeats * fractions.Fraction(1, 8))
                    )
                metricity = self._calculate_metricity_of_melody(meter, adadpted_melody)
                meter_fitness_pairs.append((adadpted_melody, meter[0], metricity))

        return max(meter_fitness_pairs, key=operator.itemgetter(2))[:2]
Пример #2
0
    def __call__(self, melody: old.Melody) -> old.Melody:
        new_melody = melody.copy()
        melody_size = len(melody)

        for idx, tone in enumerate(new_melody):
            halved_duration = tone.duration * 0.5

            # only add ornamentation if there isn't any glissando yet
            if (not tone.glissando and not tone.pitch.is_empty
                    and halved_duration > self.__minima_gissando_duration):
                previous = None
                following = None
                previous_distance = None
                following_distance = None

                if idx != 0 and not melody[idx - 1].pitch.is_empty:
                    previous = melody[idx - 1]
                    previous_distance = previous.pitch.cents - tone.pitch.cents

                if idx + 1 != melody_size and not melody[idx +
                                                         1].pitch.is_empty:
                    following = melody[idx + 1]
                    following_distance = following.pitch.cents - tone.pitch.cents

                beginning_and_end_glissando = (
                    previous is not None
                    and abs(previous_distance) > self.__minima_gissando_size,
                    following is not None
                    and abs(following_distance) > self.__minima_gissando_size,
                )

                if any(beginning_and_end_glissando):

                    if next(self.__al):
                        if all(beginning_and_end_glissando):
                            glissando_type = next(
                                self.__glissando_type_generator)
                        else:
                            glissando_type = beginning_and_end_glissando.index(
                                True)

                        glissando_type = ((True, False), (False, True),
                                          (True, True))[glissando_type]

                        glissando_line = []
                        is_first = True
                        for is_allowed, distance in zip(
                                glissando_type,
                            (previous_distance, following_distance)):
                            if is_allowed:
                                data = self.get_glissando_values(
                                    halved_duration, distance)
                                remaining_time = halved_duration - data[1]
                                if is_first:
                                    data = (
                                        old.PitchInterpolation(
                                            data[1],
                                            mel.SimplePitch(0, data[0])),
                                        old.PitchInterpolation(
                                            remaining_time,
                                            mel.SimplePitch(0, 0)),
                                    )
                                else:
                                    data = (
                                        old.PitchInterpolation(
                                            remaining_time,
                                            mel.SimplePitch(0, 0)),
                                        old.PitchInterpolation(
                                            data[1], mel.SimplePitch(0, 0)),
                                        old.PitchInterpolation(
                                            0, mel.SimplePitch(0, data[0])),
                                    )
                            else:
                                data = [
                                    old.PitchInterpolation(
                                        halved_duration, mel.SimplePitch(0, 0))
                                ]
                                if not is_first:
                                    data.append(
                                        old.PitchInterpolation(
                                            0, mel.SimplePitch(0, 0)))

                            glissando_line.extend(data)
                            is_first = False

                        new_melody[idx].glissando = old.GlissandoLine(
                            interpolations.InterpolationLine(glissando_line))

        return new_melody
Пример #3
0
    def transform_melody(
        self,
        melody: old.Melody,
        mapping: dict = {
            instr: prime
            for prime, instr in zip(globals_.METRICAL_PRIMES, ("violin",
                                                               "viola",
                                                               "cello"))
        },
    ) -> tuple:
        prime_number_per_event = []
        for tone in melody:
            if tone.pitch.is_empty:
                if prime_number_per_event:
                    prime_number_per_event.append(prime_number_per_event[-1])

                else:
                    prime_number_per_event.append(None)

            else:
                prime_number_per_event.append(
                    mapping[globals_.PITCH2INSTRUMENT[tone.pitch.normalize()]])

        if prime_number_per_event[0] is None:
            prime_number_per_event[0] = int(prime_number_per_event[1])

        # as high metricity as possible / as low deviation as possible
        hof = crosstrainer.MultiDimensionalRating(size=2, fitness=[1, -1])

        n_possible_offsets = len(
            self._rhythm_and_metricity_per_prime[prime_number_per_event[0]][0])
        for n_offsets in range(n_possible_offsets):
            if n_offsets > 0:
                adapted_melody = melody.copy()
                offset_duration = sum(self._rhythm_and_metricity_per_prime[
                    prime_number_per_event[0]][0][:n_offsets])
                adapted_melody.insert(
                    0, old.Tone(mel.TheEmptyPitch, delay=offset_duration))
                adapted_prime_number_per_event = (
                    prime_number_per_event[0],
                ) + tuple(prime_number_per_event)

            else:
                adapted_melody = melody.copy()
                adapted_prime_number_per_event = tuple(prime_number_per_event)

            expected_distances = tuple(
                fractions.Fraction(d) for d in adapted_melody.delay)

            positions = [
                Point(
                    adapted_prime_number_per_event[0],
                    0,
                    0,
                    self._absolute_rhythm_and_metricity_per_prime,
                    self.duration,
                )
            ]
            for expected_distance, prime_number in zip(
                    expected_distances,
                    adapted_prime_number_per_event[1:] +
                (adapted_prime_number_per_event[-1], ),
            ):
                positions.append(positions[-1].find_next_position(
                    prime_number, expected_distance))

            absolute_rhythm = tuple(p.position for p in positions)
            complete_duration = (positions[-1].nth_loop + 1) * self.duration

            if absolute_rhythm[-1] != complete_duration:
                absolute_rhythm += ((positions[-1].nth_loop + 1) *
                                    self.duration, )
                adapted_melody.append(old.Tone(mel.TheEmptyPitch, delay=1))

            relative_rhythm = tuple(
                b - a for a, b in zip(absolute_rhythm, absolute_rhythm[1:]))
            new_melody = old.Melody([
                old.Tone(pitch=t.pitch, volume=t.volume, delay=r, duration=r)
                for t, r in zip(adapted_melody, relative_rhythm)
            ])

            summed_metricity = sum(p.metricity
                                   for p in positions[:-1]) / len(positions)
            summed_deviation = sum(
                abs(exp - real)
                for exp, real in zip(expected_distances, relative_rhythm))
            hof.append(
                (new_melody, positions[-1].nth_loop + 1),
                summed_metricity,
                summed_deviation,
            )

        best = hof.convert2list()[-1]
        return (best[0][0], lambda: self.spread(best[0][-1], mapping)), best[1]