def mk_harmonics_melodies(origin_melodies: tuple,
                          n_voices: int = 5,
                          max_harmonic: int = MAX_HARMONIC) -> tuple:
    """Make polyphonic movement of common (sub-)harmonics from the origin melodies.

    The resulting tuple contains as many melodies as previously declared with the
    n_voices argument.

    The n_voices argument may be helpful for making sure not having too many
    resulting voices what could happen when voices occasionally contain octaves
    or primes.
    """
    poly_per_interlocking = []
    origin_melodies = tuple(m.discard_rests().tie() for m in origin_melodies)
    for comb in itertools.combinations(origin_melodies, 2):
        cadence = old.Polyphon(comb).chordify(add_longer=True)
        harmonics_per_pitch = tuple(
            functools.reduce(
                operator.add,
                tuple(
                    find_common_harmonics(
                        p[0], p[1], gender=gender, border=max_harmonic)
                    for gender in (True, False)),
            ) if len(p) == 2 else tuple([]) for p in tuple(
                tuple(h) for h in cadence.pitch))
        poly = [[old.Rest(chord.delay) for chord in cadence]
                for n in range(n_voices)]
        for h_idx, harmonics in enumerate(harmonics_per_pitch):
            for p_idx, p in enumerate(harmonics[:n_voices]):
                poly[p_idx][h_idx] = p.convert2tone(cadence.delay[h_idx])

        poly = [old.Melody(melody) for melody in poly]
        poly_per_interlocking.append(old.Polyphon(poly))

    return tuple(poly_per_interlocking)
Example #2
0
    def test_find_exact_simultan_events(self):
        poly2 = old.Polyphon(
            (
                old.Melody([old.Tone(ji.r(1, 1), 2), old.Tone(ji.r(1, 1), 3)]),
                old.Melody([old.Tone(ji.r(3, 2), 3), old.Tone(ji.r(3, 2), 2)]),
                old.Melody([old.Tone(ji.r(4, 3), 1), old.Tone(ji.r(4, 3), 2)]),
            )
        )
        simultan_events4 = poly2.find_exact_simultan_events(0, 1)
        simultan_events4_expected = (
            old.Tone(ji.r(3, 2), 1, 1),
            old.Tone(ji.r(3, 2), 2, 2),
            old.Tone(ji.r(4, 3), 1, 1),
        )
        self.assertEqual(simultan_events4, simultan_events4_expected)

        simultan_events0 = self.poly0.find_exact_simultan_events(0, 0)
        self.assertEqual(simultan_events0, (self.poly0[1][0],))
        simultan_events1 = self.poly0.find_exact_simultan_events(0, 0, False)
        self.assertEqual(simultan_events1, (self.poly0[1].convert2absolute()[0],))
        simultan_events2 = self.poly1.find_exact_simultan_events(1, 0)
        simultan_events2_expected = (self.poly1[2][0], self.poly1[2][0])
        self.assertEqual(simultan_events2, simultan_events2_expected)
        simultan_events3 = self.poly1.find_exact_simultan_events(1, 1)
        simultan_events3_expected = (self.t8, self.t7, self.t7, self.t7, self.t2)
        self.assertEqual(simultan_events3, simultan_events3_expected)
Example #3
0
 def detect_intervals_and_duration_pairs_per_tone_per_voice(
         voices: tuple) -> tuple:
     voices = tuple(old.Melody(v) for v in voices)
     interval_and_time_pairs_per_tone_per_voice = []
     for v_idx, voice in enumerate(voices):
         poly = old.Polyphon(v for v_idx1, v in enumerate(voices)
                             if v_idx1 != v_idx)
         melody = voice.copy()
         interval_and_time_pairs_per_tone = []
         for tone in melody.convert2absolute():
             start, stop = tone.delay, tone.duration
             simultan_events = functools.reduce(
                 operator.add,
                 tuple(m[:] for m in poly.cut_up_by_time(start, stop)))
             interval_and_time_pairs = []
             for simultan_event in simultan_events:
                 if not simultan_event.pitch.is_empty:
                     interval = simultan_event.pitch - tone.pitch
                     interval_and_time_pairs.append(
                         (interval, simultan_event.duration))
             interval_and_time_pairs_per_tone.append(
                 tuple(interval_and_time_pairs))
         interval_and_time_pairs_per_tone_per_voice.append(
             tuple(interval_and_time_pairs_per_tone))
     return tuple(interval_and_time_pairs_per_tone_per_voice)
Example #4
0
 def test_cut_up_by_idx(self):
     poly0 = old.Polyphon(
         (
             old.Melody([old.Tone(ji.r(1, 1), 2), old.Tone(ji.r(1, 1), 3)]),
             old.Melody([old.Tone(ji.r(3, 2), 3), old.Tone(ji.r(3, 2), 2)]),
             old.Melody([old.Tone(ji.r(4, 3), 1), old.Tone(ji.r(4, 3), 2)]),
         )
     )
     poly0_cut = poly0.cut_up_by_idx(2, 1)
     poly0_cut_expected = old.Polyphon(
         (
             old.Melody([old.Tone(ji.r(1, 1), 1), old.Tone(ji.r(1, 1), 1)]),
             old.Melody([old.Tone(ji.r(3, 2), 2)]),
             old.Melody([old.Tone(ji.r(4, 3), 2)]),
         )
     )
     self.assertEqual(poly0_cut, poly0_cut_expected)
Example #5
0
    def test_cut_up_by_time(self):
        poly0 = old.Polyphon(
            (
                old.Melody([old.Tone(ji.r(1, 1), 2), old.Tone(ji.r(1, 1), 3)]),
                old.Melody([old.Tone(ji.r(3, 2), 3), old.Tone(ji.r(3, 2), 2)]),
                old.Melody([old.Tone(ji.r(4, 3), 1), old.Tone(ji.r(4, 3), 2)]),
            )
        )
        poly0_cut = poly0.cut_up_by_time(1, 3)
        poly0_cut_expected = old.Polyphon(
            (
                old.Melody([old.Tone(ji.r(1, 1), 1), old.Tone(ji.r(1, 1), 1)]),
                old.Melody([old.Tone(ji.r(3, 2), 2)]),
                old.Melody([old.Tone(ji.r(4, 3), 2)]),
            )
        )
        self.assertEqual(poly0_cut, poly0_cut_expected)

        poly1_cut = poly0.cut_up_by_time(1, 3, add_earlier=False)
        poly1_cut_expected = old.Polyphon(
            (
                old.Melody([old.Rest(1), old.Tone(ji.r(1, 1), 1)]),
                old.Melody([old.Rest(2)]),
                old.Melody([old.Tone(ji.r(4, 3), 2)]),
            )
        )
        self.assertEqual(poly1_cut, poly1_cut_expected)

        poly2_cut = poly0.cut_up_by_time(1, 3, hard_cut=False)
        poly2_cut_expected = old.Polyphon(
            (
                old.Melody([old.Tone(ji.r(1, 1), 2), old.Tone(ji.r(1, 1), 3)]),
                old.Melody([old.Tone(ji.r(3, 2), 3)]),
                old.Melody([old.Rest(1), old.Tone(ji.r(4, 3), 2)]),
            )
        )
        self.assertEqual(poly2_cut[2], poly2_cut_expected[2])
Example #6
0
class PolyTest(unittest.TestCase):
    p0 = ji.r(5, 4)
    p1 = ji.r(3, 2)
    p2 = ji.r(1, 1)
    p3 = ji.r(6, 5)
    p4 = ji.r(7, 4)
    p5 = ji.r(9, 8)
    t0 = old.Tone(p0, rhy.Unit(1))
    t1 = old.Tone(p1, rhy.Unit(1))
    t2 = old.Tone(p2, rhy.Unit(1))
    t3 = old.Tone(p3, rhy.Unit(1))
    t3 = old.Tone(p3, rhy.Unit(1))
    t4 = old.Tone(p4, rhy.Unit(1))
    t5 = old.Tone(p5, rhy.Unit(1))
    t6 = old.Tone(p0, rhy.Unit(2))
    t7 = old.Tone(p0, rhy.Unit(0.5))
    t8 = old.Tone(p0, rhy.Unit(1.5))
    t9 = old.Tone(p1, rhy.Unit(1.5))
    t10 = old.Tone(p5, rhy.Unit(0.5))
    t11 = old.Tone(p2, rhy.Unit(1))
    melody0 = old.Melody((t0, t1))
    melody1 = old.Melody((t2, t3))
    melody2 = old.Melody((t6, t6, t0, t7))  # duration 5.5
    melody3 = old.Melody((t7, t6, t2, t2))  # duration 4.5
    melody4 = old.Melody((t7, t7, t7, t2, t2))  # duration 3.5
    melody5 = old.Melody((t10, t9, t3, t8, t0))  # duration 5.5
    melody6 = old.Melody((t6, t6, t2, t7))  # duration 5.5

    poly0 = old.Polyphon([melody0, melody1])
    poly1 = old.Polyphon([melody2, melody3, melody4])
    poly2 = old.Polyphon([melody6, melody5])

    def test_chordify(self):
        chord0 = old.Chord(ji.JIHarmony([self.t0.pitch, self.t2.pitch]), rhy.Unit(1))
        chord1 = old.Chord(ji.JIHarmony([self.t1.pitch, self.t3.pitch]), rhy.Unit(1))
        cadence0 = old.Cadence([chord0, chord1])
        self.assertEqual(cadence0, self.poly0.chordify())

        chord0 = old.Chord(ji.JIHarmony([self.p0, self.p5]), rhy.Unit(0.5))
        chord1 = old.Chord(ji.JIHarmony([self.p0, self.p1]), rhy.Unit(1.5))
        chord2 = old.Chord(ji.JIHarmony([self.p0, self.p3]), rhy.Unit(1))
        chord3 = old.Chord(ji.JIHarmony([self.p0]), rhy.Unit(1))
        chord4 = old.Chord(ji.JIHarmony([self.p0, self.p2]), rhy.Unit(0.5))
        chord5 = old.Chord(ji.JIHarmony([self.p0]), rhy.Unit(0.5))
        expected = old.Cadence([chord0, chord1, chord2, chord3, chord4, chord4, chord5])

        result = self.poly2.chordify(
            harmony_class=ji.JIHarmony, cadence_class=old.Cadence, add_longer=True
        )

        for ex, re in zip(expected, result):
            print(ex, re)

        self.assertEqual(expected, result)

    def test_find_simultan_events(self):
        simultan_events0 = self.poly0.find_simultan_events(0, 0)
        self.assertEqual(simultan_events0, (self.poly0[1].convert2absolute()[0],))
        simultan_events1 = self.poly0.find_simultan_events(1, 1)
        self.assertEqual(simultan_events1, (self.poly0[0].convert2absolute()[1],))
        simultan_events2 = self.poly1.find_simultan_events(0, 1)
        simultan_events2_comp = (
            self.poly1[1].convert2absolute()[1],
            self.poly1[1].convert2absolute()[2],
            self.poly1[1].convert2absolute()[3],
            self.poly1[2].convert2absolute()[-2],
            self.poly1[2].convert2absolute()[-1],
        )
        self.assertEqual(simultan_events2, simultan_events2_comp)
        simultan_events3 = self.poly1.find_simultan_events(1, 1)
        simultan_events3_comp = (
            self.poly1[0].convert2absolute()[0],
            self.poly1[0].convert2absolute()[1],
            self.poly1[2].convert2absolute()[1],
            self.poly1[2].convert2absolute()[2],
            self.poly1[2].convert2absolute()[3],
        )
        self.assertEqual(simultan_events3, simultan_events3_comp)

    def test_find_exact_simultan_events(self):
        poly2 = old.Polyphon(
            (
                old.Melody([old.Tone(ji.r(1, 1), 2), old.Tone(ji.r(1, 1), 3)]),
                old.Melody([old.Tone(ji.r(3, 2), 3), old.Tone(ji.r(3, 2), 2)]),
                old.Melody([old.Tone(ji.r(4, 3), 1), old.Tone(ji.r(4, 3), 2)]),
            )
        )
        simultan_events4 = poly2.find_exact_simultan_events(0, 1)
        simultan_events4_expected = (
            old.Tone(ji.r(3, 2), 1, 1),
            old.Tone(ji.r(3, 2), 2, 2),
            old.Tone(ji.r(4, 3), 1, 1),
        )
        self.assertEqual(simultan_events4, simultan_events4_expected)

        simultan_events0 = self.poly0.find_exact_simultan_events(0, 0)
        self.assertEqual(simultan_events0, (self.poly0[1][0],))
        simultan_events1 = self.poly0.find_exact_simultan_events(0, 0, False)
        self.assertEqual(simultan_events1, (self.poly0[1].convert2absolute()[0],))
        simultan_events2 = self.poly1.find_exact_simultan_events(1, 0)
        simultan_events2_expected = (self.poly1[2][0], self.poly1[2][0])
        self.assertEqual(simultan_events2, simultan_events2_expected)
        simultan_events3 = self.poly1.find_exact_simultan_events(1, 1)
        simultan_events3_expected = (self.t8, self.t7, self.t7, self.t7, self.t2)
        self.assertEqual(simultan_events3, simultan_events3_expected)

    def test_cut_up_by_time(self):
        poly0 = old.Polyphon(
            (
                old.Melody([old.Tone(ji.r(1, 1), 2), old.Tone(ji.r(1, 1), 3)]),
                old.Melody([old.Tone(ji.r(3, 2), 3), old.Tone(ji.r(3, 2), 2)]),
                old.Melody([old.Tone(ji.r(4, 3), 1), old.Tone(ji.r(4, 3), 2)]),
            )
        )
        poly0_cut = poly0.cut_up_by_time(1, 3)
        poly0_cut_expected = old.Polyphon(
            (
                old.Melody([old.Tone(ji.r(1, 1), 1), old.Tone(ji.r(1, 1), 1)]),
                old.Melody([old.Tone(ji.r(3, 2), 2)]),
                old.Melody([old.Tone(ji.r(4, 3), 2)]),
            )
        )
        self.assertEqual(poly0_cut, poly0_cut_expected)

        poly1_cut = poly0.cut_up_by_time(1, 3, add_earlier=False)
        poly1_cut_expected = old.Polyphon(
            (
                old.Melody([old.Rest(1), old.Tone(ji.r(1, 1), 1)]),
                old.Melody([old.Rest(2)]),
                old.Melody([old.Tone(ji.r(4, 3), 2)]),
            )
        )
        self.assertEqual(poly1_cut, poly1_cut_expected)

        poly2_cut = poly0.cut_up_by_time(1, 3, hard_cut=False)
        poly2_cut_expected = old.Polyphon(
            (
                old.Melody([old.Tone(ji.r(1, 1), 2), old.Tone(ji.r(1, 1), 3)]),
                old.Melody([old.Tone(ji.r(3, 2), 3)]),
                old.Melody([old.Rest(1), old.Tone(ji.r(4, 3), 2)]),
            )
        )
        self.assertEqual(poly2_cut[2], poly2_cut_expected[2])

    def test_cut_up_by_idx(self):
        poly0 = old.Polyphon(
            (
                old.Melody([old.Tone(ji.r(1, 1), 2), old.Tone(ji.r(1, 1), 3)]),
                old.Melody([old.Tone(ji.r(3, 2), 3), old.Tone(ji.r(3, 2), 2)]),
                old.Melody([old.Tone(ji.r(4, 3), 1), old.Tone(ji.r(4, 3), 2)]),
            )
        )
        poly0_cut = poly0.cut_up_by_idx(2, 1)
        poly0_cut_expected = old.Polyphon(
            (
                old.Melody([old.Tone(ji.r(1, 1), 1), old.Tone(ji.r(1, 1), 1)]),
                old.Melody([old.Tone(ji.r(3, 2), 2)]),
                old.Melody([old.Tone(ji.r(4, 3), 2)]),
            )
        )
        self.assertEqual(poly0_cut, poly0_cut_expected)
Example #7
0
 def convert2cadence(self, gender=True):
     return old.Polyphon(self.convert2voices()).chordify()
Example #8
0
    def __init__(
        self,
        action_per_voice: tuple,
        sound_per_voice: tuple,
        allowed_pitches_per_voice: tuple,
        allowed_attacks_per_voice: tuple,
        weights_per_beat: tuple,
        predefined_voices: tuple = tuple([]),
        allow_unisono: bool = True,
        allow_melodic_octaves: bool = False,
        harmonic_weight: float = 2,
        melodic_weight: float = 1,
        random_seed: int = 1000,
        harmonic_range: tuple = (0, 1),
        melodic_range: tuple = (0, 1),
        distance_range: tuple = (0, 1),
        metrical_range: tuple = (0, 1),
    ) -> None:
        self.test_arguments_for_equal_size(
            "voice specific arguments",
            (
                action_per_voice,
                sound_per_voice,
                allowed_attacks_per_voice,
                allowed_pitches_per_voice,
            ),
            lambda data: len(data),
        )
        self.test_arguments_for_equal_size(
            "allowed_attacks_per_voice",
            allowed_attacks_per_voice + tuple(vox.delay for vox in predefined_voices),
            lambda rhythm: sum(rhythm),
        )

        # set attributes
        available_pitches = functools.reduce(operator.add, allowed_pitches_per_voice)
        for vox in predefined_voices:
            available_pitches += tuple(p for p in vox.pitch if not p.is_empty)

        import random

        random.seed(random_seed)

        self._average_distance_per_voice = self._detect_average_distance_per_voice(
            action_per_voice, allowed_attacks_per_voice
        )
        self._linspace_for_distance_likelihood = interpolations.Linear()(
            0, 1, self._GRIDSIZE
        )
        self._duration = len(weights_per_beat)
        self._melodic_weight = melodic_weight
        self._harmonic_weight = harmonic_weight
        self._predefined_voices = predefined_voices
        self._predefined_polyphon = old.Polyphon(predefined_voices)
        self._weights_per_beat = tools.scale(weights_per_beat, *metrical_range)
        self._sound_per_voice = sound_per_voice
        self._allowed_pitches_per_voice = allowed_pitches_per_voice
        self._absolute_allowed_attacks_per_voice = tuple(
            tuple(r.convert2absolute()) for r in allowed_attacks_per_voice
        )
        self._random_module = random
        self._n_voices = len(sound_per_voice)
        self._melodicity_dict_per_voice = self._detect_melodicity_dict_per_voice(
            allowed_pitches_per_voice
        )
        self._harmonicity_dict = self._make_harmonicity_dict(available_pitches)
        self._allow_melodic_octaves = allow_melodic_octaves
        self._allow_unisono = allow_unisono

        self._position_and_voices_pairs = self._detect_position_and_voices_pairs(
            allowed_attacks_per_voice
        )

        super().__init__(self._make_voices())