Ejemplo n.º 1
0
 def mk_siter_cadence(
     self,
     siter_panerus_pitch,
     gender,
     previous_signified: int,
     previous_side_prime: int,
     current_signified: int,
     current_side_prime: int,
     following_signified: int,
     following_side_prime: int,
     stresses,
 ) -> old.JICadence:
     siter_pitches = self.siter_style.convert2interpolation(
         gender,
         previous_signified,
         previous_side_prime,
         current_signified,
         current_side_prime,
         following_signified,
         following_side_prime,
         stresses,
     )
     siter_pitches = tuple(ji.JIHarmony([p]) for p in siter_pitches)
     siter_pitches = (ji.JIHarmony(siter_panerus_pitch), ) + siter_pitches
     return old.JICadence([old.Chord(h, 1) for h in siter_pitches])
Ejemplo n.º 2
0
def mk_simple_conversion(
    mode: modes.Mode, funcs: tuple, subfunctions_per_interpol: tuple
) -> old.JICadence:
    """Expect real functions (with applied modulation), not symbolic functions"""

    def get_from_func_pitch(func) -> ji.JIPitch:
        p = func(mode)
        if p.set_val_border(2).primes == (3,):  # 3 * 9 doesn't exist in current tuning
            return p.normalize(2) - ji.r(2, 1)
        else:
            return mel.TheEmptyPitch

    def filter_subfunc_pitch(pitch) -> ji.JIPitch:
        if pitch == ji.r(1, 1):
            pitch += ji.r(2, 1)
        if pitch in SITER_BARUNG.pitches:
            return pitch
        else:
            return mel.TheEmptyPitch

    res = []
    for func0, func1, subfuncline in zip(funcs, funcs[1:], subfunctions_per_interpol):
        fp = get_from_func_pitch(func0)
        subfunc_pitches = list(
            (filter_subfunc_pitch(p),)
            for p in subfuncline.convert_signifiers2pitches(mode, func0, func1)[:-1]
        )
        if fp:
            subfunc_pitches[0] = subfunc_pitches[0] + (fp,)
        for h in subfunc_pitches:
            h = tuple(p for p in h if p)
            res.append(h)

    return old.JICadence([old.Chord(ji.JIHarmony(h), 1) for h in res])
def mk_simple_conversion(mode: modes.Mode, compounds_per_function: tuple,
                         funcs: tuple) -> old.JICadence:
    def define_gong(mode) -> ji.JIPitch:
        gong_pitch = ji.r(
            functools.reduce(operator.mul, (mode.x, mode.y, mode.z)), 1)
        if not mode.gender:
            gong_pitch = gong_pitch.inverse()
        return gong_pitch.normalize(2) - ji.r(4, 1)

    def get_pitch(f) -> ji.JIPitch:
        p = f(mode)
        if p.set_val_border(2).primes == (
                3, ):  # 3 * 9 doesn't exist in current tuning
            return mel.TheEmptyPitch
        else:
            return f(mode).normalize() - ji.r(2, 1)

    gong = define_gong(mode)
    pitches = tuple(get_pitch(f) for f in funcs)
    pitches = ((gong, p) if f.gong else (p, ) for f, p in zip(funcs, pitches))

    return old.JICadence([
        old.Chord(ji.JIHarmony(tuple(pi for pi in p if pi)), delay)
        for p, delay in zip(pitches, compounds_per_function)
    ])
Ejemplo n.º 4
0
 def divide_recursively(cadence, size=1):
     duration = float(cadence.duration)
     beats = duration / size
     try:
         assert float(beats) == int(beats)
     except AssertionError:
         msg = "{0} beats for size {1} in cadence {2}.".format(
             beats, size, cadence)
         msg += " Attribute 'beats' has to be an integer number."
         raise ValueError(msg)
     beats = int(beats)
     group = tuple(size for i in range(beats))
     divided = MDC.divide_cadence_by_groups(cadence, group,
                                            is_pitch_sustained)
     result = []
     for div in divided:
         if len(div) == 1:
             p = ji.JIHarmony(div[0].pitch)
             if len(p) == 0:
                 p = mel.TheEmptyPitch
             result.append(p)
         else:
             result.append(divide_recursively(div, size / 2))
     if size < 1:
         assert len(result) == 2
         if result[1] == mel.TheEmptyPitch and type(result[0]) != tuple:
             return result[0]
     return tuple(result)
Ejemplo n.º 5
0
    def create_cadence(
        self,
        stresses: tuple,
        does_siter_play: tuple,
        gender: bool,
        previous_signified: int,
        current_signified: int,
        following_signified: int,
        previous_side_prime: int,
        current_side_prime: int,
        following_side_prime: int,
    ) -> old.JICadence:
        chord0 = old.Chord(ji.JIHarmony([]), 1)

        pattern = self.detect_pattern(
            stresses,
            does_siter_play,
            gender,
            previous_signified,
            current_signified,
            following_signified,
            previous_side_prime,
            current_side_prime,
            following_side_prime,
        )

        final_cadence = [chord0]
        for idx, pat in enumerate(pattern):
            pat = list(pat)
            final_cadence += pat

        return old.JICadence(final_cadence)
Ejemplo n.º 6
0
def mk_loop_cadence_with_tuk(loopsize: int,
                             meter: metre.Metre) -> old.JICadence:
    size = meter.size
    loop_amount = size // loopsize
    rest = size % loopsize
    harmony0 = ji.JIHarmony([ji.r(3, 2)])
    harmony1 = ji.JIHarmony([ji.r(1, 1)])
    basic_cadence = [old.Chord(harmony0, 0.5)
                     ] + [old.Chord(harmony1, 1) for i in range(loopsize - 1)]
    basic_cadence.append(old.Chord(harmony1, 0.5))
    print(old.JICadence(basic_cadence).duration)
    cadence = [basic_cadence for i in range(loop_amount)]
    cadence = functools.reduce(operator.add, cadence)
    if rest:
        cadence.append(old.Chord(harmony0, rest))
    return old.JICadence(cadence)
Ejemplo n.º 7
0
 def mk_mdc_gong_and_tong(cadence, timeflow) -> tuple:
     cadence_gong, cadence_tong = [], []
     for chord in cadence:
         hg, ht = [], []
         for p in chord.pitch:
             if p < ji.r(1, 2):
                 hg.append(p)
             else:
                 ht.append(p)
         cadence_gong.append(old.Chord(ji.JIHarmony(hg), chord.delay))
         cadence_tong.append(old.Chord(ji.JIHarmony(ht), chord.delay))
     cadences = tuple(
         old.JICadence(c).discard_rests()
         for c in (cadence_gong, cadence_tong))
     return tuple(
         MDC.mk_mdc_by_cadence(c, timeflow,
                               Score.TIME_LV_PER_INSTRUMENT[0], False)
         for c in cadences)
Ejemplo n.º 8
0
def mk_loop_cadence(loopsize: int, meter: metre.Metre) -> old.JICadence:
    size = meter.size
    loop_amount = size // loopsize
    rest = size % loopsize
    harmony = ji.JIHarmony([ji.r(3, 2)])
    cadence = [old.Chord(harmony, loopsize) for i in range(loop_amount)]
    if rest:
        cadence.append(old.Chord(harmony, rest))
    return old.JICadence(cadence)
Ejemplo n.º 9
0
 def distribute_harmony(harmony) -> tuple:
     harmonies_per_mdc = [[] for i in range(amount_mdc)]
     for pitch in harmony:
         if pitch != mel.TheEmptyPitch:
             for instridx in decomposition[pitch]:
                 harmonies_per_mdc[instridx].append(pitch)
     container = []
     for idx, harmony in enumerate(harmonies_per_mdc):
         if harmony:
             container.append(ji.JIHarmony(harmony))
         else:
             container.append(mel.TheEmptyPitch)
     return tuple(container)
Ejemplo n.º 10
0
 def find_normalize_dependent_combinations(
     self,
     primes,
     maxlevel,
     gender,
     compound,
     compound_asymmetrical,
     three_compound,
     allow_stacking,
     normalize,
     additional_intervals,
 ):
     # find all intervals:
     intervals = ji.JIHarmony(
         Tree.find_intervals(
             primes,
             maxlevel,
             gender,
             compound,
             compound_asymmetrical,
             three_compound,
         ))
     for additional in additional_intervals:
         intervals.add(additional)
     intervals = [
         i.set_val_border(1).normalize(normalize) for i in intervals
     ]
     self.intervals = intervals
     comb_intervals = [
         inter for inter in intervals if inter != ji.r(1, 1, val_border=2)
     ]
     if allow_stacking is True:
         combinations = tuple(
             itertools.combinations_with_replacement(comb_intervals, 2))
     else:
         combinations = tuple(itertools.combinations(comb_intervals, 2))
     valid_combinations = []
     for interval in intervals:
         valid = []
         for comb in combinations:
             if (comb[0] + comb[1]).normalize(normalize) == interval:
                 valid.append(comb)
         valid_combinations.append(valid)
     return valid_combinations
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
0
 def divide_recursively(remaining_cadence,
                        remaining_groups,
                        divided_cadences: list = []) -> list:
     if remaining_cadence:
         new_cadence = type(remaining_cadence)([])
         surplus_element = None
         group_size = remaining_groups[0]
         acc = 0
         for idx, item in enumerate(remaining_cadence):
             size = float(item.delay)
             acc += size
             if acc == group_size:
                 new_cadence.append(item)
                 break
             elif acc < group_size:
                 new_cadence.append(item)
             elif acc > group_size:
                 diff = acc - group_size
                 item0 = item.copy()
                 item0.delay -= diff
                 item0.duration -= diff
                 item1 = item.copy()
                 item1.delay = diff
                 item1.duration = diff
                 if is_pitch_sustained is False:
                     item1.pitch = ji.JIHarmony([])
                 new_cadence.append(item0)
                 surplus_element = item1
                 break
         divided_cadences.append(new_cadence)
         remaining_cadence = remaining_cadence[idx + 1:]
         if surplus_element is not None:
             remaining_cadence.insert(0, surplus_element)
         return divide_recursively(remaining_cadence,
                                   remaining_groups[1:],
                                   divided_cadences)
     else:
         return divided_cadences
Ejemplo n.º 13
0
    def create_cadence(
        self,
        stresses: tuple,
        does_siter_play: tuple,
        gender: bool,
        previous_signified: int,
        current_signified: int,
        following_signified: int,
        previous_side_prime: int,
        current_side_prime: int,
        following_side_prime: int,
    ) -> old.JICadence:

        if self.apply_with_header_if_header_exist:
            cadence = old.JICadence([])
        else:
            cadence = old.JICadence([old.Chord(ji.JIHarmony([]), 0.5)])

        divided_stresses = self.divide_stresses(stresses)
        amount_divisions = len(divided_stresses)
        is_with_modulation = current_signified != following_signified
        for idx, division in enumerate(divided_stresses):
            if idx == 0 and self.apply_with_header_if_header_exist:
                add_header = True
            else:
                add_header = False

            amount_stresses = len(division)
            is_with_resolution = not all(tuple(not s for s in division))
            conditions_for_modulation = (
                is_with_modulation,
                not is_with_resolution,
                idx + 1 == amount_divisions,
            )
            if all(conditions_for_modulation):
                pattern = self.pattern[1][amount_stresses]
                cadence += self.convert_modulation_pattern(
                    gender,
                    current_signified,
                    current_side_prime,
                    following_signified,
                    following_side_prime,
                    pattern,
                    add_header,
                )
            else:
                pattern_idx = int(amount_stresses)
                if is_with_resolution:
                    add_tail = True
                else:
                    pattern_idx += 1
                    add_tail = False

                pattern = self.pattern[0][pattern_idx]
                cadence += self.convert_resolution_pattern(
                    gender,
                    current_signified,
                    current_side_prime,
                    pattern,
                    add_header,
                    add_tail,
                )

        return old.JICadence(cadence)
Ejemplo n.º 14
0
    def find_intervals(
        primes,
        maxlevel,
        gender: int,
        compound=True,
        compound_asymmetrical=True,
        three_compound=True,
    ):
        val_border = 2
        intervals = ji.JIHarmony([])
        for p in primes:
            for lv in range(maxlevel):
                scale = lv + 1
                intervals.add(ji.r(p, 1, val_border=val_border).scalar(scale))
                intervals.add(ji.r(1, p, val_border=val_border).scalar(scale))
        if compound is True:
            for p0, p1 in itertools.combinations(primes, 2):
                for lv in range(maxlevel):
                    scale = lv + 1
                    intervals.add(
                        ji.r(p0, p1, val_border=val_border).scalar(scale))
                    intervals.add(
                        ji.r(1, p1 * p0, val_border=val_border).scalar(scale))
                    intervals.add(
                        ji.r(p0 * p1, 1, val_border=val_border).scalar(scale))
                    intervals.add(
                        ji.r(p1, p0, val_border=val_border).scalar(scale))
                if compound_asymmetrical is True:
                    for lv in range(maxlevel):
                        scale0 = lv
                        scale1 = lv + 1
                        p00A = ji.r(p0, 1,
                                    val_border=val_border).scalar(scale0)
                        p10A = ji.r(1, p1,
                                    val_border=val_border).scalar(scale1)
                        p01A = ji.r(p0, 1,
                                    val_border=val_border).scalar(scale1)
                        p11A = ji.r(1, p1,
                                    val_border=val_border).scalar(scale0)
                        pres0 = p00A + p10A
                        pres1 = p01A + p11A
                        intervals.add(pres0)
                        intervals.add(pres1)
                        intervals.add(pres0.inverse())
                        intervals.add(pres1.inverse())
        if three_compound is True:
            for p0, p1, p2 in itertools.combinations(primes, 3):
                for lv in range(maxlevel):
                    scale = lv + 2
                    intervals.add(
                        ji.r(p0 + p2, p1, val_border=val_border).scalar(scale))
                    intervals.add(
                        ji.r(p1 + p2, p0, val_border=val_border).scalar(scale))
                    intervals.add(
                        ji.r(p0 + p1, p2, val_border=val_border).scalar(scale))
                if compound_asymmetrical is True:
                    for lv in range(maxlevel):

                        def make_zero_inverse(p0, p1, p2):
                            return p0 + p1 + p2

                        def make_one_inverse(p0, p1, p2):
                            return p0 + p1 + p2.inverse()

                        def make_two_inverse(p0, p1, p2):
                            return p0 + p1.inverse() + p2.inverse()

                        def make_all_inverse(p0, p1, p2):
                            return p0.inverse() + p1.inverse() + p2.inverse()

                        scale0 = lv
                        scale1 = lv + 1
                        scale2 = lv + 2
                        p00A = ji.r(p0, 1,
                                    val_border=val_border).scalar(scale0)
                        p10A = ji.r(p1, 1,
                                    val_border=val_border).scalar(scale0)
                        p20A = ji.r(p2, 1,
                                    val_border=val_border).scalar(scale0)
                        p01A = ji.r(p0, 1,
                                    val_border=val_border).scalar(scale1)
                        p11A = ji.r(p1, 1,
                                    val_border=val_border).scalar(scale1)
                        p21A = ji.r(p2, 1,
                                    val_border=val_border).scalar(scale1)
                        p02A = ji.r(p0, 1,
                                    val_border=val_border).scalar(scale2)
                        p12A = ji.r(p1, 1,
                                    val_border=val_border).scalar(scale2)
                        p22A = ji.r(p2, 1,
                                    val_border=val_border).scalar(scale2)
                        data = [
                            p00A, p10A, p20A, p01A, p11A, p21A, p02A, p12A,
                            p22A
                        ]
                        comb = itertools.combinations(data, 3)
                        for c in comb:
                            for p in itertools.permutations(c):
                                intervals.add(make_one_inverse(*p))
                                intervals.add(make_two_inverse(*p))
                                intervals.add(make_all_inverse(*p))

        if gender != 0:
            if gender == 1:
                intervals = (p for p in intervals if p.gender is True)
            elif gender == -1:
                intervals = (p for p in intervals if p.gender is False)
            else:
                raise ValueError("Invalid arg for gender")
        return list(intervals)
Ejemplo n.º 15
0
 def find_octave_independent_combinations(
     self,
     primes,
     maxlevel,
     gender,
     compound,
     compound_asymmetrical,
     three_compound,
     allow_stacking,
     octaves,
     additional_intervals,
 ):
     # find all intervals:
     intervals = ji.JIHarmony(
         Tree.find_intervals(
             primes,
             maxlevel,
             gender,
             compound,
             compound_asymmetrical,
             three_compound=three_compound,
         ))
     for additional in additional_intervals:
         intervals.add(additional)
     comb_intervals = [
         inter for inter in intervals if inter != ji.r(1, 1, val_border=2)
     ]
     if allow_stacking is True:
         combinations = tuple(
             itertools.combinations_with_replacement(comb_intervals, 2))
     else:
         combinations = tuple(itertools.combinations(comb_intervals, 2))
     valid_combinations = []
     for interval in intervals:
         valid = []
         for comb in combinations:
             if comb[0] + comb[1] == interval:
                 valid.append(
                     [c.set_val_border(1).normalize(2) for c in comb])
         valid_combinations.append(valid)
     resulting_intervals = [
         i.set_val_border(1).normalize(2) for i in intervals
     ]
     if octaves is not None:
         add = []
         for octave in octaves:
             for inter in resulting_intervals:
                 add.append(inter + octave)
         resulting_intervals.extend(add)
     resulting_valid_combinations = []
     for interval, valid_combination in zip(
             resulting_intervals, itertools.cycle(valid_combinations)):
         really_valid = []
         for combination in valid_combination:
             for oct_comb in itertools.combinations_with_replacement(
                     octaves, 2):
                 combination0 = [
                     combination[0] + oct_comb[0],
                     combination[1] + oct_comb[1],
                 ]
                 combination1 = [
                     combination[0] + oct_comb[1],
                     combination[1] + oct_comb[0],
                 ]
                 for c in (combination0, combination1):
                     if c[0] + c[1] == interval:
                         really_valid.append(c)
         resulting_valid_combinations.append(really_valid)
     self.intervals = resulting_intervals
     return resulting_valid_combinations