Example #1
0
    def test_note_match_chordal_precision(self):

        print('----- test_note_match_chordal_precision -----')
        lge = LineGrammarExecutor()

        # note_match_chordal=True, and pattern has a chordal note that is not chordal in the pattern.
        #  E in pattern is chordal @ 3rd but C in target is choral @ 5th is
        pattern = '{<C-Major: I> [iD:4 G   E C:5]}'
        target = '{<F-Minor: v> [iAb:3 G:4 C C:5]}'
        target_line, target_hct = lge.parse(target)

        search = MelodicSearch.create(pattern)

        answers = search.search(
            target_line, target_hct,
            GlobalSearchOptions(note_match_chordal=True,
                                note_match_chordal_precision=True))
        assert answers is not None
        assert 0 == len(answers)

        # C --> Ab: both 3rds
        target = '{<F-Minor: v> [iAb:3 G:4 E C:5]}'
        target_line, target_hct = lge.parse(target)

        search = MelodicSearch.create(pattern)

        answers = search.search(
            target_line, target_hct,
            GlobalSearchOptions(note_match_chordal=True,
                                note_match_chordal_precision=True))
        assert answers is not None
        assert 1 == len(answers)
Example #2
0
    def test_hct_match_tonality_modality(self):
        print('----- test_hct_match_tonality_modality -----')
        lge = LineGrammarExecutor()

        # hct_match_tonality_modality=True, and pattern/target are different modalities.
        pattern = '{<C-Major: I> [iC:4 G F A] <G-Major: I> qB:4 (I, 2)[iE:5 G C]}'
        target = '{<F-Minor: v> qF:4 C:5 <F-Major: I> [iF:4 C:5 Bb:4 D:5] <C-Minor: I> qE:5 (I, 2)[iA:6 C:7 F:6]}'
        target_line, target_hct = lge.parse(target)

        search = MelodicSearch.create(pattern)

        answers = search.search(
            target_line, target_hct,
            GlobalSearchOptions(hct_match_tonality_modality=True))
        assert answers is not None
        assert 0 == len(answers)

        # hct_match_tonality_key_tone=True, and pattern/target are same modalities.
        target = '{<F-Minor: v> qF:4 C:5 <C-Major: I> [iF:4 C:5 B:4 D:5] <A-Major: I> qC#:6 (I, 2)[iF#:6 A D]}'
        target_line, target_hct = lge.parse(target)

        search = MelodicSearch.create(pattern)

        answers = search.search(
            target_line, target_hct,
            GlobalSearchOptions(hct_match_tonality_modality=True))
        assert answers is not None
        assert 1 == len(answers)
Example #3
0
    def test_note_match_chordal(self):

        print('----- test_note_match_chordal -----')
        lge = LineGrammarExecutor()

        # note_match_chordal=True, and pattern has a chordal note that is not chordal in the pattern.
        #  G in pattern is chordal but A in pattern is not
        pattern = '{<C-Major: I> [iD:4 A G F]}'
        target = '{<F-Minor: v> [iE:4 G A F]}'
        target_line, target_hct = lge.parse(target)

        search = MelodicSearch.create(pattern)

        answers = search.search(target_line, target_hct,
                                GlobalSearchOptions(note_match_chordal=True))
        assert answers is not None
        assert 0 == len(answers)

        target = '{<F-Minor: v> [iE:4 G E D]}'
        target_line, target_hct = lge.parse(target)

        answers = search.search(target_line, target_hct,
                                GlobalSearchOptions(note_match_chordal=True))
        assert answers is not None
        assert 1 == len(answers)
Example #4
0
    def test_note_match_non_scalar_precision(self):

        print('----- test_note_match_non_scalar_precision -----')
        lge = LineGrammarExecutor()

        pattern = '{<C-Major: I> [iD:4 G  F Ab]}'
        target = '{<G-Major: v> [iA:3 D:4 C F]}'
        target_line, target_hct = lge.parse(target)

        search = MelodicSearch.create(pattern)

        answers = search.search(
            target_line, target_hct,
            GlobalSearchOptions(note_match_non_scalar_precision=True))
        assert answers is not None
        assert 0 == len(answers)

        target = '{<G-Major: v> [iA:3 D:4 C Eb]}'
        target_line, target_hct = lge.parse(target)

        search = MelodicSearch.create(pattern)

        answers = search.search(
            target_line, target_hct,
            GlobalSearchOptions(note_match_non_scalar_precision=True))
        assert answers is not None
        assert 1 == len(answers)
def structural_match():
    lge = LineGrammarExecutor()

    # test for non-structural match
    pattern = '{<C-Major: I> [iC:4 G F A] <:V> hB:4}'
    target = '{<F-Minor: v> qF:4 C:5 <C-Major: I> iC:4 G F A <:V> hB:4 }'
    target_line, target_hct = lge.parse(target)

    search = MelodicSearch.create(pattern)

    answers = search.search(target_line, target_hct, GlobalSearchOptions(structural_match=False))
    assert answers is not None
    assert 1 == len(answers)
    assert Position(1, 2) == answers[0]

    # test for illegal non-structural match
    answers = search.search(target_line, target_hct, GlobalSearchOptions(structural_match=True))
    assert answers is not None
    assert 0 == len(answers)

    pattern = '{<C-Major: I> [iC:4 G F A] <:V> qB:4 (I, 2)[E:5 G C]}'
    target = '{<F-Minor: v> qF:4 C:5 <C-Major: I> [iC:4 G F A] <:V> qB:4 (I, 2)[E:5 G C]}'
    target_line, target_hct = lge.parse(target)
    search = MelodicSearch.create(pattern)
    answers = search.search(target_line, target_hct, GlobalSearchOptions(structural_match=True))

    assert answers is not None
    assert 1 == len(answers)
def basic_search_example():
    print('----- test simple hct setup -----')

    lge = LineGrammarExecutor()

    pattern = '{<C-Major: I> qC:4 D iE F}'
    target = '{qC:4 D iE F <E-Major: v> qF# hG# <Ab-Minor: ii> qAb:3 Cb:4 iDb F <D-Major: I> qD E F#}'
    target_line, target_hct = lge.parse(target)

    search = MelodicSearch.create(pattern)

    answers = search.search(target_line, target_hct)

    assert answers is not None
    assert 2 == len(answers)
    assert Position(0) == answers[0]
    assert Position(3, 2) == answers[1]

    answers = search.search(target_line, target_hct, GlobalSearchOptions(note_match_chordal=True))

    assert answers is not None
    assert 1 == len(answers)
    assert Position(0) == answers[0]

    target = '{qC:4 D iE F <E-Major: v> qF# hG# <Ab-Minor: ii> qBb:3 Cb:4 iDb Eb <D-Major: I> qD E F#}'
    target_line, target_hct = lge.parse(target)

    answers = search.search(target_line, target_hct, GlobalSearchOptions(note_match_chordal=True))

    assert answers is not None
    assert 2 == len(answers)
    assert Position(0) == answers[0]
    assert Position(3, 2) == answers[1]
Example #7
0
    def test_note_match_scalar_precision(self):

        print('----- test_note_match_scalar_precision -----')
        lge = LineGrammarExecutor()

        # note_match_scalar_precision=True, and pattern/target are different scale degrees on one note.
        pattern = '{<C-Major: I> [iC:4 G F A] <G-Major: I> qB:4 (I, 2)[iE:5 G C]}'
        target = '{<F-Minor: v> qF:4 C:5 <F-Major: I> [iF:4 C:5 Bb:4 D:5] <C-Minor: ii> qEb:5 (I, 2)[iA:6 C:7 G:6]}'
        target_line, target_hct = lge.parse(target)

        search = MelodicSearch.create(pattern)

        answers = search.search(
            target_line, target_hct,
            GlobalSearchOptions(note_match_scalar_precision=True))
        assert answers is not None
        assert 0 == len(answers)

        # note_match_scalar_precision=True, and pattern/target note corrected.
        target = '{<F-Minor: v> qF:4 C:5 <F-Major: I> [iF:4 C:5 Bb:4 D:5] <C-Minor: ii> qEb:5 (I, 2)[iA:6 C:7 F:6]}'
        target_line, target_hct = lge.parse(target)

        search = MelodicSearch.create(pattern)

        answers = search.search(
            target_line, target_hct,
            GlobalSearchOptions(note_match_scalar_precision=True))
        assert answers is not None
        assert 1 == len(answers)
Example #8
0
    def test_hct_match_relative_chord(self):

        print('----- test_hct_match_relative_chord -----')
        lge = LineGrammarExecutor()

        # hct_match_relative_chord=True, and pattern/target are different chords.
        pattern = '{<C-Major: I> [iC:4 G F A] <G-Major: I> qB:4 (I, 2)[iE:5 G C]}'
        target = '{<F-Minor: v> qF:4 C:5 <F-Major: I> [iF:4 C:5 Bb:4 D:5] <C-Minor: ii> qE:5 (I, 2)[iA:6 C:7 F:6]}'
        target_line, target_hct = lge.parse(target)

        search = MelodicSearch.create(pattern)

        answers = search.search(
            target_line, target_hct,
            GlobalSearchOptions(hct_match_relative_chord=True))
        assert answers is not None
        assert 0 == len(answers)

        # hct_match_relative_chord=True, and pattern/target are same chords.
        pattern = '{<C-Major: I> [iC:4 G F A] <G-Major: I> qB:4 (I, 2)[iE:5 G C]}'
        target = '{<F-Minor: v> qF:4 C:5 <F-Major: I> [iF:4 C:5 Bb:4 D:5] <C-Minor: i> qEb:5 (I, 2)[iA:6 C:7 F:6]}'
        target_line, target_hct = lge.parse(target)

        search = MelodicSearch.create(pattern)

        answers = search.search(
            target_line, target_hct,
            GlobalSearchOptions(hct_match_relative_chord=True))
        assert answers is not None
        assert 1 == len(answers)
Example #9
0
    def test_for_book_example_2(self):
        print('----- test for book example 2 -----')

        source_instance_expression = '{<A-Major:i> [sA:4 A A A] qA:4 [iA:4 A] <:iv> qA:4 [sA:4 A A A] qA:4}'
        target_instance_expression = '{<G-Major:i> wA:4 <:iv> wA:4}'
        lge = LineGrammarExecutor()

        source_instance_line, source_instance_hct = lge.parse(
            source_instance_expression)

        actors = source_instance_line.get_all_notes()
        for a in actors:
            print("{0}".format(a))

        target_instance_line, target_instance_hct = lge.parse(
            target_instance_expression)
        target_hcs = target_instance_hct.hc_list()
        for hc in target_hcs:
            print("{0}".format(hc))

        pitch_range = PitchRange(
            DiatonicPitch.parse('C:4').chromatic_distance,
            DiatonicPitch.parse('C:6').chromatic_distance)

        p_map = PMap.create(source_instance_expression, pitch_range,
                            [('G-Major:I', Duration(3, 4)),
                             ('G-Major:IV', Duration(3, 4))])

        actors = p_map.actors

        policies = OrderedSet()
        policies.add(
            StepSequenceConstraint(
                [actors[0], actors[1], actors[2], actors[3]], [1, 1, 1]))
        policies.add(ChordalPitchConstraint(actors[0]))
        policies.add(ChordalPitchConstraint(actors[4]))
        policies.add(ChordalPitchConstraint(actors[8]))
        policies.add(
            StepSequenceConstraint(
                [actors[8], actors[9], actors[10], actors[11]], [1, -1, -1]))
        policies.add(EqualPitchConstraint([actors[0], actors[12]]))
        policies.add(EqualPitchConstraint([actors[4], actors[7]]))
        policies.add(
            RelativeDiatonicConstraint(actors[4], actors[5],
                                       Interval(3, IntervalType.Major),
                                       Interval(1, IntervalType.Perfect)))
        policies.add(StepSequenceConstraint([actors[5], actors[6]], [-1]))

        # policies.add(ChordalPitchConstraint(actors[7]))

        solver = PitchConstraintSolver(policies)

        full_results, partial_results = solver.solve(p_map)
        print('Results has {0} results.'.format(len(full_results)))

        for pm in full_results:
            if str(pm[actors[7]].note.diatonic_pitch) == 'D:4' and str(
                    pm[actors[0]].note.diatonic_pitch) == 'G:4':
                print("{0}".format(pm))
Example #10
0
    def test_multi_hc_pattern_hct(self):
        print('----- test multi hc pattern hct setup -----')

        lge = LineGrammarExecutor()

        pattern = '{<C-Major: I> qC:4 D <F-Minor: iv> iBb:5 Db F}'

        # Test one hit
        target = '{qC:4 D <F-Minor: v> C G <Ab-Minor: ii> Bb C Db <D-Major: I> D E F#}'
        target_line, target_hct = lge.parse(target)

        search = MelodicSearch.create(pattern)

        answers = search.search_hct(
            target_hct, GlobalSearchOptions(hct_match_tonality_key_tone=True))

        assert answers is not None
        assert 1 == len(answers)
        assert 'C-Major' == str(answers[0][0].tonality)

        # Test two hits
        target = '{qC:4 D <F-Minor: v> C G <Ab-Minor: ii> Bb C Db <D-Major: I> D E F# ' \
                 '<C-Major: I> qC:4 D <F-Minor: v> C G <Ab-Minor: ii> Bb C Db}'
        target_line, target_hct = lge.parse(target)

        answers = search.search_hct(
            target_hct, GlobalSearchOptions(hct_match_tonality_key_tone=True))

        assert answers is not None
        assert 2 == len(answers)
        assert 'C-Major' == str(answers[0][0].tonality)
        assert 'C-Major' == str(answers[1][0].tonality)

        # Test 3-hc pattern
        pattern = '{<C-Major: I> qC:4 D <F-Minor: iv> iBb:5 Db F <A-Minor: iii> qA:5 C}'
        search = MelodicSearch.create(pattern)

        target = '{qC:4 D <F-Minor: v> C G <Ab-Minor: ii> Bb C Db <C-Major: I> D E F# ' \
                 '<F-Major: I> iC:4 D E <A-Minor: v> qC G A <Ab-Minor: ii> Bb C Db}'
        target_line, target_hct = lge.parse(target)

        answers = search.search_hct(
            target_hct, GlobalSearchOptions(hct_match_tonality_key_tone=True))

        assert answers is not None
        assert 1 == len(answers)
        assert 'C-Major' == str(answers[0][0].tonality)
        assert Position(7, 4) == answers[0][0].position
Example #11
0
    def test_tuplet(self):
        print('----- test_tuplet -----')
        music_text_line = LineGrammarExecutor()

        s = '{qC:4 D:4 ((1:8), 2)[E:3 F G]}'
        line, _ = music_text_line.parse(s)
        print(line)
        print('-----')

        notes = line.sub_notes
        assert len(notes) == 3
        assert 'C:4' == str(notes[0].diatonic_pitch)
        assert 'D:4' == str(notes[1].diatonic_pitch)
        assert isinstance(notes[2], Tuplet)
        tuplet = notes[2]
        t_notes = tuplet.sub_notes
        assert len(t_notes) == 3
        assert 'E:3' == str(t_notes[0].diatonic_pitch)
        assert 'F:3' == str(t_notes[1].diatonic_pitch)
        assert 'G:3' == str(t_notes[2].diatonic_pitch)
        assert Duration(1, 4) == tuplet.duration
        assert Duration(1, 12) == t_notes[0].duration

        s = '{C:4 (q, 3)[E:3 F (i, 2)[G:5 A B] B]}'
        line, _ = music_text_line.parse(s)
        print(line)
        print('-----')

        notes = line.sub_notes
        assert len(notes) == 2
        assert 'C:4' == str(notes[0].diatonic_pitch)
        assert isinstance(notes[1], Tuplet)
        tuplet = notes[1]
        t_notes = tuplet.sub_notes
        assert len(t_notes) == 4
        assert 'E:3' == str(t_notes[0].diatonic_pitch)
        assert 'F:3' == str(t_notes[1].diatonic_pitch)
        assert isinstance(t_notes[2], Tuplet)
        assert 'B:3' == str(t_notes[3].diatonic_pitch)
        assert Duration(3, 4) == tuplet.duration

        assert isinstance(t_notes[2], Tuplet)
        tt_notes = t_notes[2].sub_notes
        assert len(tt_notes) == 3
        assert 'G:5' == str(tt_notes[0].diatonic_pitch)
        assert 'A:5' == str(tt_notes[1].diatonic_pitch)
        assert 'B:5' == str(tt_notes[2].diatonic_pitch)
        assert Duration(3, 16) == t_notes[2].duration
Example #12
0
    def test_simple_hct_setup(self):
        print('----- test simple hct setup -----')

        lge = LineGrammarExecutor()

        pattern = '{<C-Major: I> qC:4 D}'
        target = '{qC:4 D <E-Major: v> F# <Ab-Minor: ii> Bb C Db <D-Major: I> D E F#}'
        target_line, target_hct = lge.parse(target)

        search = MelodicSearch.create(pattern)

        answers = search.search_hct(target_hct, GlobalSearchOptions())

        assert answers is not None
        assert 3 == len(answers)
        assert 'C-Major' == str(answers[0][0].tonality)
        assert 'Ab-MelodicMinor' == str(answers[1][0].tonality)
        assert 'D-Major' == str(answers[2][0].tonality)

        for hc in answers:
            print('({0}, {1})'.format(hc[0], hc[1]))
        print('-----')

        answers = search.search_hct(
            target_hct, GlobalSearchOptions(hct_match_tonality_modality=True))

        assert answers is not None
        assert 2 == len(answers)

        for hc in answers:
            print('({0}, {1})'.format(hc[0], hc[1]))
        print('-----')

        assert 'C-Major' == str(answers[0][0].tonality)
        assert 'D-Major' == str(answers[1][0].tonality)
Example #13
0
    def test_hct_simple_shift(self):
        print('----- test_hct_simple_shift -----')

        line_str = '{<C-Major: I> C:4 E F D <:IV> F A <:V> G D <:VI> a c b a}'
        lge = LineGrammarExecutor()
        target_line, target_hct = lge.parse(line_str)

        root_shift_interval = TonalInterval.create_interval('C:4', 'G:4')

        tshift = TShift(target_line, target_hct, root_shift_interval)

        temporal_extent = Interval(Fraction(1, 1), Fraction(2, 1))
        tshift.apply(temporal_extent, as_copy=False)
        TestTShift.print_notes(target_line)
        TestTShift.print_hct(target_hct)

        notes = target_line.get_all_notes()
        assert 12 == len(notes)
        assert 'C:5' == str(notes[4].diatonic_pitch)
        assert 'E:5' == str(notes[5].diatonic_pitch)
        assert 'D:5' == str(notes[6].diatonic_pitch)
        assert 'A:4' == str(notes[7].diatonic_pitch)

        hc_list = target_hct.hc_list()
        assert len(hc_list) == 4
        assert hc_list[1].chord.chord_template.scale_degree == 4
        assert {t[0].diatonic_symbol
                for t in hc_list[1].chord.tones} == {'C', 'E', 'G'}
        assert hc_list[1].chord.chord_template.inversion == 1
        assert hc_list[1].tonality.modal_index == 0
        assert hc_list[1].tonality.basis_tone.diatonic_symbol == 'G'
        assert hc_list[1].tonality.root_tone.diatonic_symbol == 'G'
        assert hc_list[1].tonality.modality_type == ModalityType.Major
        assert hc_list[1].chord.chord_type.value == TertianChordType.Maj
Example #14
0
 def create(source_expression,
            default_root_shift_interval=None,
            default_range_modality_type=None):
     lge = LineGrammarExecutor()
     source_line, source_hct = lge.parse(source_expression)
     return TShift(source_line, source_hct, default_root_shift_interval,
                   default_range_modality_type)
Example #15
0
    def create(line_str, pitch_range, target_hct_list=None):
        """
        Create a PMap from
        :param line_str: a melodic string
        :param pitch_range: PitchRange
        :param target_hct_list: list of pairs ('tonality:chord', duration)
        :return: pmap
        Note if target_hct_list is not specified, we use the hct from the line_str.
        """
        lge = LineGrammarExecutor()
        line, hct = lge.parse(line_str)
        if target_hct_list is not None:
            hct = PMap.build_hct(target_hct_list)
        actors = line.get_all_notes()

        d = OrderedDict()
        for note in actors:
            hc = hct[note.get_absolute_position().position]
            if hc is None:
                raise Exception(
                    'Cannot locate harmonic context for note \'{0}\''.format(
                        note))
            contextual_note = ContextualNote(PolicyContext(hc, pitch_range))
            d[note] = contextual_note

        return PMap(d)
Example #16
0
    def test_sub_line(self):
        print('----- test_sub_line -----')

        source_instance_expression = '{<C-Major:I> qC:4 D E F <:v> [iD:5 B:4 A G] qC:5 D <:I> G:4 iF E hC}'
        lge = LineGrammarExecutor()

        source_instance_line, source_instance_hct = lge.parse(
            source_instance_expression)

        sub_line, start, duration = source_instance_line.sub_line(
            Interval(Fraction(1, 2), Fraction(2)))

        print(str(source_instance_line))
        print(str(sub_line))

        notes = sub_line.get_all_notes()
        assert notes is not None
        assert len(notes) == 8
        assert 'E:4' == str(notes[0].diatonic_pitch)
        assert 'F:4' == str(notes[1].diatonic_pitch)

        with self.assertRaises(Exception) as context:
            source_instance_line.sub_line(Interval(Fraction(1), Fraction(5,
                                                                         4)))
            self.assertTrue('This is broken' in str(context.exception))

        sub_line, start, duration = source_instance_line.sub_line()

        print(str(source_instance_line))
        print(str(sub_line))

        assert sub_line.duration.duration == Fraction(3)
    def test_hct_rebuild_perfect_overlap(self):
        print('----- test_hct_rebuild_perfect_overlap -----')

        line_str = '{<C-Major: I> hA:5 <:IV> B  qC G <:VI> hD}'
        lge = LineGrammarExecutor()
        target_line, target_hct = lge.parse(line_str)

        print('--- before transformation ---')
        TestTChromaticFlip.print_notes(target_line)
        TestTChromaticFlip.print_hct(target_hct)

        cue = DiatonicPitch(5, 'c')

        f = TChromaticReflection(target_line, target_hct, cue)

        temporal_extent = Interval(Fraction(1, 2), Fraction(3, 2))
        score_line, score_hct = f.apply(temporal_extent, cue)
        print('--- after transformation ---')
        TestTChromaticFlip.print_notes(score_line)
        TestTChromaticFlip.print_hct(score_hct)

        print('--- transformation ---')
        TestTChromaticFlip.print_function(f, target_hct)

        notes = score_line.get_all_notes()
        assert 'Db:4' == str(notes[1].diatonic_pitch)
        assert 'C:5' == str(notes[2].diatonic_pitch)
        assert 'F:4' == str(notes[3].diatonic_pitch)

        hc_list = score_hct.hc_list()
        assert len(hc_list) == 3
        assert hc_list[1].chord.chord_template.scale_degree == 1
        assert {t[0].diatonic_symbol
                for t in hc_list[1].chord.tones} == {'G', 'C', 'Eb'}
        assert hc_list[1].chord.chord_template.inversion == 3
Example #18
0
    def test_line_structures(self):
        print('----- test line structures -----')
        source_instance_expression = '{<C-Major:I> iC:4 D E F G A B C:5 D E F G} }'
        lge = LineGrammarExecutor()
        source_instance_line, source_instance_hct = lge.parse(source_instance_expression)
        notes = source_instance_line.get_all_notes()

        line = Line()
        line.pin(notes[0], Offset(Fraction(1, 2)))
        line.pin(notes[1], Offset(Fraction(3, 4)))

        line1 = Line()
        line1.pin(notes[3], Offset(Fraction(1, 4)))
        line1.pin(notes[4], Offset(Fraction(1, 2)))
        line.pin(line1, Offset(Fraction(2)))

        lite_score = TestTDilation.create_score_1(line, source_instance_hct, 'piano', (4, 4, 'swww'))

        trans = TDilation(lite_score)
        new_score = trans.apply(Fraction(2), False, True)
        all_notes = new_score.line.get_all_notes()
        assert all_notes[2].get_absolute_position().position == Fraction(9, 2)

        print(line)
        print(new_score.line)
Example #19
0
    def test_beam(self):
        print('----- test_beam -----')
        music_text_line = LineGrammarExecutor()

        s = '{qC:4 D:4 [E:3 F G A B:4]}'
        line, _ = music_text_line.parse(s)
        print(line)
        print('-----')

        notes = line.sub_notes
        assert len(notes) == 3
        assert 'C:4' == str(notes[0].diatonic_pitch)
        assert 'D:4' == str(notes[1].diatonic_pitch)
        assert isinstance(notes[2], Beam)
        beam = notes[2]
        b_notes = beam.sub_notes
        assert len(b_notes) == 5
        assert 'E:3' == str(b_notes[0].diatonic_pitch)
        assert 'F:3' == str(b_notes[1].diatonic_pitch)
        assert 'G:3' == str(b_notes[2].diatonic_pitch)
        assert 'A:3' == str(b_notes[3].diatonic_pitch)
        assert 'B:4' == str(b_notes[4].diatonic_pitch)

        s = '{C:4 [E:3 F [G:5 A B C] B]}'
        line, _ = music_text_line.parse(s)
        print(line)
        print('-----')

        notes = line.sub_notes
        assert len(notes) == 2
        assert 'C:4' == str(notes[0].diatonic_pitch)
        assert isinstance(notes[1], Beam)
        beam = notes[1]
        b_notes = beam.sub_notes
        assert len(b_notes) == 4
        assert 'E:3' == str(b_notes[0].diatonic_pitch)
        assert 'F:3' == str(b_notes[1].diatonic_pitch)
        assert isinstance(b_notes[2], Beam)
        assert 'B:3' == str(b_notes[3].diatonic_pitch)
        bb_notes = b_notes[2].sub_notes
        assert len(bb_notes) == 4
        assert 'G:5' == str(bb_notes[0].diatonic_pitch)
        assert 'A:5' == str(bb_notes[1].diatonic_pitch)
        assert 'B:5' == str(bb_notes[2].diatonic_pitch)
        assert 'C:5' == str(bb_notes[3].diatonic_pitch)
Example #20
0
    def test_embedded_harmonic_tag(self):
        print('----- embedded_harmonic_tag -----')

        music_text_line = LineGrammarExecutor()

        s = '{qC:4 D:4 [<E-Major: IV> F G A]}'
        line, hct = music_text_line.parse(s)
        print(line)
        print('-----')

        hclist = hct.hc_list()
        assert hclist is not None
        assert len(hclist) == 2
        first = hclist[0]
        second = hclist[1]
        assert 'C-Major' == str(first.tonality)
        assert ['C', 'E',
                'G'] == [t[0].diatonic_symbol for t in first.chord.tones]
        assert 'E-Major' == str(second.tonality)
        assert ['A', 'C#',
                'E'] == [t[0].diatonic_symbol for t in second.chord.tones]

        assert Duration(1, 2) == first.duration
        assert Duration(3, 8) == second.duration

        s = '{qC:4 D:4 <E-Major: IV> [F G A]}'
        line, hct = music_text_line.parse(s)
        print(line)
        print('-----')

        hclist = hct.hc_list()
        assert hclist is not None
        assert len(hclist) == 2
        first = hclist[0]
        second = hclist[1]
        assert 'C-Major' == str(first.tonality)
        assert ['C', 'E',
                'G'] == [t[0].diatonic_symbol for t in first.chord.tones]
        assert 'E-Major' == str(second.tonality)
        assert ['A', 'C#',
                'E'] == [t[0].diatonic_symbol for t in second.chord.tones]

        assert Duration(1, 2) == first.duration
        assert Duration(3, 8) == second.duration
Example #21
0
    def test_entangled_harmonic_tag(self):
        music_text_line = LineGrammarExecutor()

        s = '{qC:4 D:4 [E:3 <F-Major: IV> F A C]}'
        line, hct = music_text_line.parse(s)
        print(line)
        print('-----')

        hclist = hct.hc_list()
        assert hclist is not None
        assert len(hclist) == 2
        first = hclist[0]
        second = hclist[1]
        assert 'C-Major' == str(first.tonality)
        assert ['C', 'E',
                'G'] == [t[0].diatonic_symbol for t in first.chord.tones]
        assert 'F-Major' == str(second.tonality)
        assert ['Bb', 'D',
                'F'] == [t[0].diatonic_symbol for t in second.chord.tones]

        assert Duration(5, 8) == first.duration
        assert Duration(3, 8) == second.duration

        s = '{qC:4 D:4 (q, 3)[E:3 <F-Major: IV> F A C]}'
        line, hct = music_text_line.parse(s)
        print(line)
        print('-----')

        hclist = hct.hc_list()
        assert hclist is not None
        assert len(hclist) == 2
        first = hclist[0]
        second = hclist[1]
        assert 'C-Major' == str(first.tonality)
        assert ['C', 'E',
                'G'] == [t[0].diatonic_symbol for t in first.chord.tones]
        assert 'F-Major' == str(second.tonality)
        assert ['Bb', 'D',
                'F'] == [t[0].diatonic_symbol for t in second.chord.tones]

        assert Duration(11, 16) == first.duration
        assert Duration(9, 16) == second.duration
Example #22
0
    def test_secondary_chord(self):
        print('----- test_secondary_chord -----')
        music_text_line = LineGrammarExecutor()

        s = '{<C-Major: V/V> F#:4 A D}'
        line, hct = music_text_line.parse(s)
        print(line)
        print('-----')

        hclist = hct.hc_list()
        assert hclist is not None
        assert len(hclist) == 1
        first = hclist[0]

        assert 'C-Major' == str(first.tonality)
        assert isinstance(first.chord.chord_template, SecondaryChordTemplate)
        assert 5 == first.chord.chord_template.secondary_scale_degree
        assert 5 == first.chord.chord_template.principal_chord_template.scale_degree

        s = '{<F-Major: IIIDom7/V-Natural> F#:4 A D}'
        line, hct = music_text_line.parse(s)
        print(line)
        print('-----')

        hclist = hct.hc_list()
        assert hclist is not None
        assert len(hclist) == 1
        first = hclist[0]

        assert 'F-Major' == str(first.tonality)
        assert isinstance(first.chord.chord_template, SecondaryChordTemplate)
        assert 5 == first.chord.chord_template.secondary_scale_degree
        assert 3 == first.chord.chord_template.principal_chord_template.scale_degree
        assert isinstance(first.chord.chord_template.principal_chord_template,
                          TertianChordTemplate)
        assert TertianChordType(
            TertianChordType.Dom7
        ) == first.chord.chord_template.principal_chord_template.chord_type
        assert 'C-NaturalMinor' == str(first.chord.secondary_tonality)
        assert {'Eb', 'G', 'Bb',
                'Db'} == {t[0].diatonic_symbol
                          for t in first.chord.tones}
Example #23
0
    def test_durations(self):
        print('----- test_durations -----')
        music_text_line = LineGrammarExecutor()

        s = '{wC:4 hD:4 qE:4 iF:4 sG:4 tA:4 xB:4}'
        line, _ = music_text_line.parse(s)
        print(line)
        print('-----')

        notes = line.get_all_notes()
        assert Duration(1) == notes[0].duration
        assert Duration(1, 2) == notes[1].duration
        assert Duration(1, 4) == notes[2].duration
        assert Duration(1, 8) == notes[3].duration
        assert Duration(1, 16) == notes[4].duration
        assert Duration(1, 32) == notes[5].duration
        assert Duration(1, 64) == notes[6].duration

        s = '{WC:4 HD:4 QE:4 IF:4 SG:4 TA:4 XB:4}'
        line, _ = music_text_line.parse(s)
        print(line)
        print('-----')

        notes = line.get_all_notes()
        assert Duration(1) == notes[0].duration
        assert Duration(1, 2) == notes[1].duration
        assert Duration(1, 4) == notes[2].duration
        assert Duration(1, 8) == notes[3].duration
        assert Duration(1, 16) == notes[4].duration
        assert Duration(1, 32) == notes[5].duration
        assert Duration(1, 64) == notes[6].duration

        s = '{(2:1)C:4 (3:2)D:4 (4:3)E:4}'
        line, _ = music_text_line.parse(s)
        print(line)
        print('-----')

        notes = line.get_all_notes()
        assert Duration(2, 1) == notes[0].duration
        assert Duration(3, 2) == notes[1].duration
        assert Duration(4, 3) == notes[2].duration
Example #24
0
    def create_score(line_expression, instrument, ts):
        lge = LineGrammarExecutor()
        source_instance_line, source_instance_hct = lge.parse(line_expression)

        tempo_seq = TempoEventSequence()
        ts_seq = EventSequence()
        tempo_seq.add(TempoEvent(Tempo(60, Duration(1, 4)), Position(0)))
        ts_seq.add(TimeSignatureEvent(TimeSignature(ts[0], Duration(1, ts[1]), ts[2]), Position(0)))

        c = InstrumentCatalog.instance()
        instrument = c.get_instrument(instrument)

        return LiteScore(source_instance_line, source_instance_hct, instrument, tempo_seq, ts_seq)
Example #25
0
    def test_structural_match(self):
        print('----- test_structural_match -----')
        lge = LineGrammarExecutor()

        # Used in book
        pattern = '{<C-Major: I> [iC:4 G F A] <G-Major: I> qB:4 (I, 2)[iE:5 F# C]}'
        target = '{<F-Minor: v> qF:4 C:5 <F-Major: I> [iF:4 C:5 Bb:4 D:5] <C-Major: I> qE:5 (I, 2)[iA:5 C:6 F:5]}'
        target_line, target_hct = lge.parse(target)

        search = MelodicSearch.create(pattern)

        answers = search.search(target_line, target_hct, GlobalSearchOptions())
        assert answers is not None

        print('test_multi_hc_pattern_search - test 2')
        for i, a in zip(range(1, len(answers) + 1), answers):
            print('[{0}] {1}'.format(i, a))

        assert 1 == len(answers)
        assert Position(1, 2) == answers[0]

        # test for non-structural match
        pattern = '{<C-Major: I> iC:4 G F A <G-Major: I> qB:4 (1:12)E:5 G C}'
        target = '{<F-Minor: v> qF:4 C:5 <C-Major: I> [iC:4 G F A] <G-Major: I> qB:4 (I, 2)[E:5 G C]}'
        target_line, target_hct = lge.parse(target)

        search = MelodicSearch.create(pattern)

        answers = search.search(target_line, target_hct,
                                GlobalSearchOptions(structural_match=False))
        assert answers is not None
        assert 1 == len(answers)
        assert Position(1, 2) == answers[0]

        # test for illegal non-structural match
        answers = search.search(target_line, target_hct,
                                GlobalSearchOptions(structural_match=True))
        assert answers is not None
        assert 0 == len(answers)
Example #26
0
    def test_beam_structures(self):
        print('----- test beam structures -----')
        source_instance_expression = '{<C-Major:I> [[iC:4 D]]} }'
        lge = LineGrammarExecutor()
        source_instance_line, source_instance_hct = lge.parse(source_instance_expression)

        lite_score = TestTDilation.create_score_1(source_instance_line, source_instance_hct, 'piano', (4, 4, 'swww'))

        trans = TDilation(lite_score)
        new_score = trans.apply(Fraction(2), True, True)
        line = new_score.line
        notes = line.get_all_notes()
        for note in notes:
            print(note)
Example #27
0
    def create(source_pattern_expr, target_pattern_expr, target_hc_exprs):
        """
        Constructor.
        :param source_pattern_expr: 'find' pattern expression - for line and hct.
        :param target_pattern_expr: 'replacement' pattern expression - for replacement line and hct.
        :param target_hc_exprs: HCExpression to build target instance from 'find' instances.
        :return:
        """
        lge = LineGrammarExecutor()
        source_line, source_hct = lge.parse(source_pattern_expr)
        target_line, target_hct = lge.parse(target_pattern_expr)

        return SubstitutionPattern(source_line, source_hct, target_line,
                                   target_hct, target_hc_exprs)
Example #28
0
    def build_hct(hc_expressed_list):
        parse_str = '{'
        for t in hc_expressed_list:
            parse_str += '<' + t[0] + '> qC:4 '
        parse_str += '}'

        lge = LineGrammarExecutor()

        _, hct = lge.parse(parse_str)
        new_hct = HarmonicContextTrack()
        for hc, t in zip(hct.hc_list(), hc_expressed_list):
            new_hc = HarmonicContext(hc.tonality, hc.chord, t[1])
            new_hct.append(new_hc)
        return new_hct
    def test_hct_rebuild_perfect_overlap(self):
        print('----- test_hct_rebuild_perfect_overlap -----')

        line_str = '{<C-Major: I> hA:5 <:IV> B  qC G <:VI> hD}'
        lge = LineGrammarExecutor()
        target_line, target_hct = lge.parse(line_str)
        TestTFlip.print_hct(target_hct)

        cue = DiatonicPitch(5, 'd')

        tflip = TDiatonicReflection(target_line, target_hct, cue)

        temporal_extent = Interval(Fraction(1, 2), Fraction(3, 2))
        score_line, score_hct = tflip.apply(temporal_extent, cue)
        TestTFlip.print_notes(score_line)
        TestTFlip.print_hct(score_hct)

        hc_list = score_hct.hc_list()
        assert hc_list[0].position == Position(0)
        assert hc_list[0].duration == Duration(1, 2)
        assert hc_list[0].chord.chord_type == TertianChordType(
            TertianChordType.Maj)
        assert hc_list[0].chord.chord_template.scale_degree == 1
        assert {t[0].diatonic_symbol
                for t in hc_list[0].chord.tones} == {'C', 'E', 'G'}
        assert hc_list[0].chord.chord_template.inversion == 1

        assert hc_list[1].position == Position(1, 2)
        assert hc_list[1].duration == Duration(1)
        assert hc_list[1].chord.chord_type == TertianChordType(
            TertianChordType.Min)
        assert hc_list[1].chord.chord_template.scale_degree == 3
        assert {t[0].diatonic_symbol
                for t in hc_list[1].chord.tones} == {'G', 'B', 'E'}
        assert hc_list[1].chord.chord_template.inversion == 3

        assert hc_list[2].position == Position(3, 2)
        assert hc_list[2].duration == Duration(1, 2)
        assert hc_list[2].chord.chord_type == TertianChordType(
            TertianChordType.Min)
        assert hc_list[2].chord.chord_template.scale_degree == 6
        assert {t[0].diatonic_symbol
                for t in hc_list[2].chord.tones} == {'A', 'C', 'E'}
        assert hc_list[2].chord.chord_template.inversion == 1

        notes = score_line.get_all_notes()
        assert str(notes[1].diatonic_pitch) == "F:4"
        assert str(notes[2].diatonic_pitch) == "E:5"
        assert str(notes[3].diatonic_pitch) == "A:4"
def create_score(grammar_str, instrument, ts):
    lge = LineGrammarExecutor()
    target_line, target_hct = lge.parse(grammar_str)

    tempo_seq = TempoEventSequence()
    ts_seq = EventSequence()
    tempo_seq.add(TempoEvent(Tempo(60, Duration(1, 4)), Position(0)))
    ts_seq.add(
        TimeSignatureEvent(TimeSignature(ts[0], Duration(1, ts[1]), ts[2]),
                           Position(0)))

    c = InstrumentCatalog.instance()
    violin = c.get_instrument(instrument)

    return LiteScore(target_line, target_hct, violin, tempo_seq, ts_seq)