Example #1
0
    def _generate_rhythmical_data(
        fundamental: pitches.JustIntonationPitch,
        n_periods_of_fundamental_per_beat: int,
        n_repetitions_of_rhythm: int,
        partial: int,
    ) -> typing.Tuple[typing.Any]:
        """Generate rhythmical data for the respective partial.

        The rhythmical data contain the following information:
            1. How often the rhythm get repeated (int)
            2. How many periods one beat last (int)
            3. The respective rhythm with duration values in seconds
               (basic.SequentialEvent[basic.SimpleEvent])
            4. Indispensability of each beat (typing.Tuple[int])
        """

        duration_of_one_period = 1 / (fundamental.frequency * partial)
        duration_of_one_beat = (duration_of_one_period *
                                n_periods_of_fundamental_per_beat)
        rhythm = basic.SequentialEvent(
            [basic.SimpleEvent(duration_of_one_beat) for _ in range(partial)])
        if partial == 1:
            indispensability_for_bar = (0, )
        else:
            indispensability_for_bar = indispensability.indispensability_for_bar(
                (partial, ))

        return (
            n_repetitions_of_rhythm,
            n_periods_of_fundamental_per_beat,
            rhythm,
            indispensability_for_bar,
        )
    def solve(self, a: int, b: int, x: int, mode: modes.Mode,
              rhythm: tuple) -> tuple:
        try:
            assert all((rhythm[0] >= 5, rhythm[1] >= 1))
        except AssertionError:
            msg = "Rhythmical structure has to be bigger than (4, 0)."
            raise ValueError(msg)

        primes = (a, b, x)
        a, b = primes[self.main_prime], primes[self.side_prime]
        x = tuple(p for p in (mode.x, mode.y, mode.z) if p not in (a, b))[0]

        data0 = FlippedEx.detect_data_for_pitches(
            ((x, b), (a, b), (a, x), (b, x), (b, a), (x, a)), mode)
        data1 = FlippedEx.detect_data_for_pitches(
            ((a, x), (a, b), (x, b), (x, a), (b, a), (b, x)), mode)

        if data0[2] > data1[2]:
            data = data0
        else:
            data = data1

        if rhythm[1] == 1:
            rhythms_middle = tools.euclid(rhythm[0], 5)
            rhythms_else = rhythm[0]
            middle = tuple(
                old.Tone(p, r) for p, r in zip((mel.TheEmptyPitch, ) +
                                               data[0], rhythms_middle))
            return ((old.Rest(rhythms_else), ), middle,
                    (old.Rest(rhythms_else), ))
        else:
            complete_duration = rhythm[0] * rhythm[1]
            amount_pitches = len(data[0]) + len(
                data[1]) + 1  # middle + high + rest
            rhythmic_ranking = indispensability.bar_indispensability2indices(
                indispensability.indispensability_for_bar(
                    rhythm))[:amount_pitches]
            positions_middle = rhythmic_ranking[::2]
            positions_high = (0, ) + rhythmic_ranking[1::2]
            low_line = (old.Rest(complete_duration), )

            middle_line = (old.Tone(p, r) for p, r in zip(
                (mel.TheEmptyPitch, ) + data[0],
                (b - a for a, b in zip(
                    positions_middle,
                    positions_middle[1:] + (complete_duration, ),
                )),
            ))

            high_line = (old.Tone(p, r) for p, r in zip(
                (mel.TheEmptyPitch, ) + data[1],
                (b - a
                 for a, b in zip(positions_high, positions_high[1:] +
                                 (complete_duration, ))),
            ))

            return (low_line, middle_line, high_line)
Example #3
0
    def _calculate_metricity_per_beat(self) -> tuple:
        primes = list(globals_.TIME_SIGNATURES2COMPOSITION_STRUCTURES[
            abjad.TimeSignature((self.numerator, self.denominator))])
        duration = self.duration

        while (duration / functools.reduce(operator.mul, primes) >
               self._smallest_expected_unit):
            primes.append(2)

        return tools.scale(
            indispensability.indispensability_for_bar(tuple(primes)), 0, 1)
    def _generate_potential_meters() -> tuple:
        """Return tuple filled with subtuples where one subtuple represents one meter.

        Each subtuple is composed of (TIME_SIGNATURE, INDISPENSABILITY_PER_BEAT).
        """
        return tuple(
            (
                abjad.TimeSignature(ts),
                tools.scale(indispensability.indispensability_for_bar(primes), 0, 1),
            )
            for ts, primes in globals_.AVAILABLE_TIME_SIGNATURES
        )
Example #5
0
    def _get_position_metricity_pairs(
        time_signature: tuple, smallest_unit: fractions.Fraction
    ) -> tuple:
        ts = fractions.Fraction(
            time_signature[0].numerator, time_signature[0].denominator
        )
        current_unit_size = ts / functools.reduce(operator.mul, time_signature[1])
        smallest_unit = min((smallest_unit, current_unit_size))
        factors = tuple(time_signature[1])
        if smallest_unit < current_unit_size:
            factors += (int(current_unit_size / smallest_unit),)

        metricities = tools.scale(
            indispensability.indispensability_for_bar(factors), 0, 1
        )
        return tuple((smallest_unit, metricity) for metricity in metricities)
Example #6
0
 def find_weight_per_beat(prime: int) -> tuple:
     weights = indispensability.indispensability_for_bar(
         tuple(prime_factors.factorise(prime)))
     maxima = max(weights)
     return tuple(w / maxima for w in weights)
Example #7
0
        def rhythm_maker(self) -> tuple:
            n_bars = self._n_bars
            # for first attack every voice should have a theoretical attack
            # (rests are explicitly controlled through the start_harmony argument)
            distribution_for_first_attack_per_bar = ((0, 1, 2), )
            distribution_for_first_attack_per_bar += tuple(
                next(distribution_function_for_first_attack_per_bar)
                for i in range(n_bars - 1))
            rhythm_per_voice = []
            max_attacks_per_bar = min(self._metrical_numbers)
            for voice_idx, metrical_prime, density, curve in zip(
                    range(3), self._metrical_numbers, density_per_voice,
                    curve_per_voice):

                rhythm = []

                # if density between 0 and 1 understand as percentage
                # for density 1 only understand it as percentage if type is
                # float
                if (density >= 0
                        and density < 1) or (density == 1
                                             and type(density) is float):
                    n_attacks_per_bar = int(density * max_attacks_per_bar)

                # else use it as an absolute number
                else:
                    assert density <= max_attacks_per_bar
                    n_attacks_per_bar = int(density)

                for (distribution_for_first_attack
                     ) in distribution_for_first_attack_per_bar:
                    has_first_attack = voice_idx in distribution_for_first_attack
                    n_attacks = n_attacks_per_bar + has_first_attack

                    if rhythmic_function == "euclid":
                        current_rhythm = tools.euclid(metrical_prime,
                                                      n_attacks)

                    elif rhythmic_function == "barlow":
                        if metrical_prime == 10:
                            divided = (2, 5)
                        else:
                            divided = tuple(
                                prime_factors.factorise(metrical_prime))

                        ranking = indispensability.bar_indispensability2indices(
                            indispensability.indispensability_for_bar(divided))
                        choosen_attacks = sorted(ranking[:n_attacks])
                        current_rhythm = tuple(b - a for a, b in zip(
                            choosen_attacks, choosen_attacks[1:] +
                            [metrical_prime]))

                    else:
                        msg = "Unknown rhythmic function {}.".format(
                            rhythmic_function)
                        raise NotImplementedError(msg)

                    if not has_first_attack:
                        rhythm[-1] += current_rhythm[0]
                        current_rhythm = current_rhythm[1:]

                    rhythm.extend(current_rhythm)

                rhythm_per_voice.append(binr.Compound(rhythm))

            return tuple(rhythm_per_voice)