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)
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 )
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)
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)
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)