def convert2cadence(self, tempo_factors_per_unit: tuple,
                        delays: tuple) -> old.JICadence:
        """
        """
        def return_item_and_sizes(element, lv=0) -> tuple:
            if type(element) == ji.JIHarmony or element == mel.TheEmptyPitch:
                return ((element, lv), )
            else:
                ret = tuple([])
                for tup in (return_item_and_sizes(it, lv + 1)
                            for it in element):
                    ret += tup
                return ret

        divisions_per_elements = int(tempo.TempoLine.divisions_per_element)
        cadence = []
        unit_count = 0
        for meter in self.__structure:
            for compound in meter:
                for unit in compound:

                    delay = delays[unit_count]
                    if delay:
                        if cadence:
                            cadence[-1].delay += delay.duration
                            cadence[-1].duration += delay.duration
                        else:
                            cadence.append(old.Rest(delay.duration))

                    factors = tempo_factors_per_unit[unit_count]

                    abstract_delays = []
                    harmonies = []

                    for element in unit:
                        item_and_size_pairs = return_item_and_sizes(element)
                        for pair in item_and_size_pairs:
                            harmonies.append(pair[0])
                            de = int(divisions_per_elements * (1 /
                                                               (2**pair[1])))
                            abstract_delays.append(de)

                    real_delays = tuple(
                        itertools.accumulate([0] + abstract_delays))
                    real_delays = tuple(
                        sum(factors[idx0:idx1])
                        for idx0, idx1 in zip(real_delays, real_delays[1:]))

                    for h, de in zip(harmonies, real_delays):
                        if h:
                            cadence.append(old.Chord(h, de))
                        else:
                            cadence.append(old.Rest(de))

                    unit_count += 1

        cadence = old.JICadence(cadence).discard_rests()
        return cadence
    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)
Exemple #3
0
 def test_split(self):
     tone0 = old.Tone(ji.r(1, 1, 2), rhy.Unit(2), rhy.Unit(1))
     tone0B = old.Tone(ji.r(1, 1, 2), rhy.Unit(1), rhy.Unit(1))
     tone1 = old.Tone(ji.r(1, 1, 2), rhy.Unit(3), rhy.Unit(1))
     tone1B = old.Tone(ji.r(1, 1, 2), rhy.Unit(1), rhy.Unit(1))
     pause0 = old.Rest(rhy.Unit(1))
     pause1 = old.Rest(rhy.Unit(2))
     melody0 = old.Melody([tone0, tone1])
     melody1 = old.Melody([tone0B, pause0, tone1B, pause1])
     self.assertEqual(melody0.split(), melody1)
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)
    def render(self, name: str, cadence: old.Cadence) -> subprocess.Popen:
        seq = []
        for chord in cadence:
            dur = float(chord.delay)
            if chord.pitch != mel.TheEmptyPitch and bool(chord.pitch):
                size = len(chord.pitch)
                for idx, pi in enumerate(chord.pitch):
                    if idx + 1 == size:
                        de = float(dur)
                    else:
                        de = 0
                    if pi != mel.TheEmptyPitch:
                        if chord.volume:
                            volume = chord.volume
                        else:
                            volume = self.volume

                        tone = midiplug.PyteqTone(
                            ji.JIPitch(pi, multiply=self.CONCERT_PITCH),
                            de,
                            dur,
                            volume=volume,
                        )
                    else:
                        tone = midiplug.PyteqTone(
                            mel.TheEmptyPitch, de, dur, volume=self.volume
                        )
                    seq.append(tone)
            else:
                seq.append(old.Rest(dur))

        pt = midiplug.Pianoteq(tuple(seq), self.available_midi_notes)
        return pt.export2wav(name, 1, self.preset, self.fxp)
        def return_cadence_and_instrument_for_complex(idx, tf, time_lv,
                                                      is_sutained, cadences,
                                                      instruments,
                                                      is_full_or_not_per_sec):
            def detect_correct_instrument_for_empty_section(
                    idx, is_full_or_not_per_sec):
                for is_full_or_not in is_full_or_not_per_sec[idx + 1:]:
                    if is_full_or_not[0]:
                        return instruments[1]
                    elif is_full_or_not[1]:
                        return instruments[2]
                for is_full_or_not in reversed(is_full_or_not_per_sec[:idx]):
                    if is_full_or_not[0]:
                        return instruments[1]
                    elif is_full_or_not[1]:
                        return instruments[2]
                return instruments[0]

            if all(is_full_or_not_per_sec[idx]):
                return cadences[0], instruments[0]
            elif all(tuple(not b for b in is_full_or_not_per_sec[idx])):
                i = detect_correct_instrument_for_empty_section(
                    idx, is_full_or_not_per_sec)
                return old.JICadence([old.Rest(tf.size)]), i
            else:
                if cadences[0]:
                    return cadences[0], instruments[1]
                else:
                    return cadences[1], instruments[2]
Exemple #7
0
class ToneSetTest(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))
    t0_set = old.Tone(p0, rhy.Unit(0), rhy.Unit(1))
    t1_set = old.Tone(p1, rhy.Unit(1), rhy.Unit(1))
    t2_set = old.Tone(p2, rhy.Unit(2), rhy.Unit(1))
    t3_set = old.Tone(p3, rhy.Unit(3), rhy.Unit(1))
    t4_set = old.Tone(p4, rhy.Unit(4), rhy.Unit(1))
    t5_set = old.Tone(p5, rhy.Unit(5), rhy.Unit(1))
    t6_set = old.Tone(p5, rhy.Unit(1), rhy.Unit(5))
    mel0 = old.Melody([t0, t1, t2, t3, t4, t5])
    mel1 = old.Melody([old.Rest(rhy.Unit(1)), t1, t2, t3, t4, t5])
    mel2 = old.Melody([t0, t1])
    set0 = old.ToneSet([t0_set, t1_set, t2_set, t3_set, t4_set, t5_set])
    set1 = old.ToneSet([t1_set, t2_set, t3_set, t4_set, t5_set])
    set2 = old.ToneSet([t1_set, t6_set, t2_set])

    def test_constructor(self):
        self.assertEqual(old.ToneSet.from_melody(ToneSetTest.mel0), ToneSetTest.set0)

    def test_converter(self):
        self.assertEqual(ToneSetTest.mel0, ToneSetTest.set0.convert2melody())
        self.assertEqual(ToneSetTest.mel1, ToneSetTest.set1.convert2melody())

    def test_pop_by(self):
        popped = ToneSetTest.set0.copy().pop_by_pitch(ToneSetTest.p0, ToneSetTest.p1)
        self.assertEqual(ToneSetTest.mel2, popped.convert2melody())
        popped = ToneSetTest.set0.copy().pop_by_start(rhy.Unit(0), rhy.Unit(1))
        self.assertEqual(ToneSetTest.mel2, popped.convert2melody())

    def test_pop_by_time(self):
        for t in self.set0.pop_by_time(1):
            self.assertEqual(t, self.t1_set)
        for t in self.set0.pop_by_time(1.5):
            self.assertEqual(t, self.t1_set)
        test_set0 = self.set2.pop_by_time(1.5)
        test_set_compare0 = old.ToneSet([self.t1_set, self.t6_set])
        test_set1 = self.set2.pop_by_time(2.7)
        test_set_compare1 = old.ToneSet([self.t2_set, self.t6_set])
        self.assertEqual(test_set0, test_set_compare0)
        self.assertEqual(test_set1, test_set_compare1)

    def test_pop_by_correct_dur_and_delay(self):
        poped_by = self.set0.pop_by_pitch(self.p0, self.p5)
        melody = poped_by.convert2melody()
        self.assertEqual(melody[0].delay, rhy.Unit(5))
        self.assertEqual(melody[0].duration, rhy.Unit(1))
 def solve(self, a: int, b: int, x: int, mode: modes.Mode,
           rhythm: tuple) -> tuple:
     primes0, primes1 = self.detect_start_and_stop_primes(a, b, x, mode)
     pitch0, pitch1 = tuple(
         AbstractExpansion.transform_primes2pitches(p, mode)
         for p in (primes0, primes1))
     high_pitches = self.detect_high_pitches(primes0, primes1, mode)
     complete_duration = rhythm[0] * rhythm[1]
     low_line = old.Rest(complete_duration)
     middle_line = tuple(
         old.Tone(p, rhythm[1]) for p in ShiftedEx.detect_middle_pitches(
             pitch0, pitch1, rhythm[0]))
     high_line = ShiftedEx.make_high_line(high_pitches, rhythm)
     return (low_line, middle_line, high_line)
Exemple #9
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])
Exemple #10
0
    def test_cut_up_by_time(self):
        t0 = old.Tone(ji.r(1, 1), rhy.Unit(2))
        t1 = old.Tone(ji.r(2, 1), rhy.Unit(2))
        t2 = old.Tone(ji.r(1, 1), rhy.Unit(1))
        r0 = old.Rest(1)

        melody0 = old.Melody([t0, t1, t1, t0, t1])
        melody1 = old.Melody([t1, t1, t0])
        melody2 = old.Melody([r0, t1, t1, t0])
        melody3 = old.Melody([t2, t1, t1, t0])
        melody4 = old.Melody([t1, t1, t2])

        self.assertEqual(melody0.cut_up_by_time(2, 8), melody1)
        self.assertEqual(melody0.cut_up_by_time(1, 8), melody2)
        self.assertEqual(melody0.cut_up_by_time(1, 8, add_earlier=True), melody3)
        self.assertEqual(melody0.cut_up_by_time(2, 7, hard_cut=True), melody4)
        self.assertEqual(melody0.cut_up_by_time(2, 7, hard_cut=False), melody1)
    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]
Exemple #12
0
    def __call__(self, name: str, cadence: old.JICadence) -> None:
        seq = []
        for chord in cadence:
            dur = float(chord.delay)
            if chord.pitch != mel.TheEmptyPitch and bool(chord.pitch):
                size = len(chord.pitch)
                for idx, pi in enumerate(chord.pitch):
                    if idx + 1 == size:
                        de = float(dur)
                    else:
                        de = 0
                    tone = pyteq.PyteqTone(
                        ji.JIPitch(pi, multiply=self.CONCERT_PITCH),
                        de,
                        dur,
                        volume=self.volume,
                    )
                    seq.append(tone)
            else:
                seq.append(old.Rest(dur))

        pt = pyteq.Pianoteq(tuple(seq), self.available_midi_notes)
        pt.export2wav(name, 1, self.preset, self.fxp)
Exemple #13
0
    def make_diva_sequence(self, voice: tuple, tempo_factor: float) -> tuple:
        diva_sequence = []

        for tone in voice:
            delay = tone.delay * tempo_factor

            if tone.pitch.is_empty:
                dt = old.Rest(delay)

            else:
                div_synth_args = {
                    arg: next(self.init_arguments[arg])
                    for arg in self.init_arguments
                }
                dt = midiplug.DivaTone(ji.JIPitch(
                    tone.pitch, multiply=globals.CONCERT_PITCH),
                                       delay,
                                       delay,
                                       volume=tone.volume,
                                       **div_synth_args)

            diva_sequence.append(dt)

        return tuple(diva_sequence)
Exemple #14
0
 def test_duration(self):
     self.assertEqual(self.melody0.duration, sum(self.rhy0))
     melody1 = old.Melody([old.Rest(3)])
     self.assertEqual(melody1.duration, 3)
    def make_high_line(pitches: tuple, rhythm: tuple) -> tuple:
        def convert_pattern2pitches(pattern: tuple) -> tuple:
            return tuple(pitches[idx] if idx else mel.TheEmptyPitch
                         for idx in pattern)

        if rhythm[1] == 1:
            return (old.Rest(rhythm[0] * rhythm[1]), )
        elif rhythm[1] == 2:
            pattern0 = (0, 1, 0, None)
            pattern1 = (0, None, 0, 2)
            amount_pattern = (rhythm[0] - 1) // 2
            pattern_cycle = itertools.cycle(
                tuple(
                    convert_pattern2pitches(p) for p in (pattern0, pattern1)))
            pitch_line = functools.reduce(
                operator.add,
                tuple(next(pattern_cycle) for n in range(amount_pattern)))
            if rhythm[0] % 2 == 0:
                pitch_line = (pitches[0], mel.TheEmptyPitch) + pitch_line
            pitch_line = (mel.TheEmptyPitch, ) + pitch_line + (pitches[-1], )

            try:
                assert len(pitch_line) == rhythm[0] * rhythm[1]
            except AssertionError:
                raise AssertionError("exp: {0} but {1}".format(
                    len(pitch_line), rhythm[0] * rhythm[1]))

            return tuple(
                old.Melody(old.Tone(p, 1)
                           for p in pitch_line).tie_pauses().discard_rests())
        elif rhythm[1] == 3:
            patternA = (mel.TheEmptyPitch, pitches[1], pitches[0])
            patternB = (mel.TheEmptyPitch, pitches[2], pitches[0])
            dead_pattern = (mel.TheEmptyPitch, mel.TheEmptyPitch, pitches[0])

            pattern_type_cycle = itertools.cycle((1, 0, 0))
            choice_cycle = itertools.cycle((0, 1))
            choices = tuple(
                next(choice_cycle) for n in range(((rhythm[0] - 1) // 2) * 2))
            if rhythm[0] % 2 == 0:
                choices = (0, ) + choices
            choices = (1, ) + choices

            pattern_types = (next(pattern_type_cycle) for n in choices)

            pitch_line = functools.reduce(
                operator.add,
                tuple((patternA,
                       patternB)[choice] if ptype == 0 else dead_pattern
                      for choice, ptype in zip(choices, pattern_types)),
            )

            try:
                assert len(pitch_line) == rhythm[0] * rhythm[1]
            except AssertionError:
                raise AssertionError("exp: {0} but {1}".format(
                    len(pitch_line), rhythm[0] * rhythm[1]))

            return tuple(
                old.Melody(old.Tone(p, 1)
                           for p in pitch_line).tie_pauses().discard_rests())
        else:
            msg = "No solution for rhythmic structure {0} available".format(
                rhythm)
            raise ValueError(msg)