def test_across_tonalities(self):
        logging.debug('Start test_across_tonalities.')
        lower_policy_context_1 = TestRelativeDiatonicConstraint.policy_creator(
            ModalityType.Major, DiatonicTone('G'), 'tV', 'C:2', 'C:8')
        lower_policy_context_2 = TestRelativeDiatonicConstraint.policy_creator(
            ModalityType.Major, DiatonicTone('Ab'), 'tI', 'C:2', 'C:8')

        upper_note_1 = Note(DiatonicPitch.parse('C:5'), Duration(1, 8))
        upper_note_2 = Note(DiatonicPitch.parse('D:5'), Duration(1, 8))
        lower_note_1 = ContextualNote(
            lower_policy_context_1,
            Note(DiatonicPitch.parse('F#:5'), Duration(1, 8)))
        lower_note_2 = ContextualNote(lower_policy_context_2)

        p_map = dict([(upper_note_1, lower_note_1),
                      (upper_note_2, lower_note_2)])

        policy = RelativeDiatonicConstraint(upper_note_1, upper_note_2,
                                            Interval(3, IntervalType.Minor),
                                            Interval(3, IntervalType.Major))

        v_result = policy.values(p_map, upper_note_2)

        for note in v_result:
            logging.debug(note)

        pitches = [note.diatonic_pitch for note in v_result]
        assert {str(p) for p in pitches} == {'Eb:5', 'F:5', 'G:5', 'Ab:5'}

        logging.debug('End test_across_tonalities.')
예제 #2
0
    def test_pentatonic_tonal_function(self):
        t_domain = Tonality.create(ModalityType.MajorPentatonic,
                                   DiatonicTone('C'))

        interval = Interval(3, IntervalType.Major)

        f = CrossTonalityShiftTonalFunction.create_shift(t_domain, interval)
        # C, D, E, G. A ==> E, F#, G#, B, C#

        assert 'E' == f['C'].diatonic_symbol
        assert 'F#' == f['D'].diatonic_symbol
        assert 'G#' == f['E'].diatonic_symbol
        assert 'B' == f['G'].diatonic_symbol
        assert 'C#' == f['A'].diatonic_symbol

        assert 'A' == f['F'].diatonic_symbol
        assert 'D#' == f['B'].diatonic_symbol

        assert 'A#' == f['F#'].diatonic_symbol
        assert 'D##' == f['B#'].diatonic_symbol
        assert 'Ab' == f['Fb'].diatonic_symbol
        assert 'D' == f['Bb'].diatonic_symbol

        t_range = Tonality.create(ModalityType.MajorPentatonic,
                                  interval.get_end_tone(DiatonicTone('C')))
        f = CrossTonalityShiftTonalFunction(t_domain, t_range.annotation[2], 2)
        # C, D, E, G. A ==> G#, B, C#, E, F#

        assert 'G#' == f['C'].diatonic_symbol
        assert 'B' == f['D'].diatonic_symbol
        assert 'C#' == f['E'].diatonic_symbol
        assert 'E' == f['G'].diatonic_symbol
        assert 'F#' == f['A'].diatonic_symbol

        TestCrossTonalityShiftTonalFunction.print_function(f)
    def test_is_chordal(self):
        logging.debug('Start test_is_chordal')

        upper_context_note = Note(DiatonicPitch.parse('F:5'), Duration(1, 4))

        lower_policy_context = TestChordalToneConstraint.policy_creator(ModalityType.Major, DiatonicTone('G'), 'tV',
                                                                        'C:2', 'C:8')
        lower_context_note = ContextualNote(lower_policy_context)
        parameter_map = dict([(upper_context_note, lower_context_note)])
        policy = ChordalPitchConstraint(upper_context_note)

        v_result = policy.values(parameter_map, upper_context_note)

        results = {DiatonicTone('D'), DiatonicTone('F#'), DiatonicTone('A')}
        for note in v_result:
            print('test_is_chordal; note = {0}'.format(note))
            tone = note.diatonic_pitch.diatonic_tone
            octave = note.diatonic_pitch.octave
            assert tone in results
            assert octave in range(2, 9)

        assert len(v_result) == 6 * 3

        for note in v_result:
            parameter_map[upper_context_note].note = note
            assert policy.verify(parameter_map) is True
        logging.debug('End test_is_chordal')
예제 #4
0
    def test_setting_values(self):
        t_domain = Tonality.create(ModalityType.Major, DiatonicTone('C'))
        t_range = Tonality.create(ModalityType.MajorPentatonic,
                                  DiatonicTone('A'))
        # A, B, C#, E, F#

        # default map between 2 tonalities of unequal cardinality - empty
        p = {
            'C': 'A',
            'D': 'A',
            'E': 'B',
            'F': 'C#',
            'G': 'C#',
            'A': 'E',
            'B': 'F#'
        }
        f = TonalFunction(t_domain, t_range, p)

        assert DiatonicToneCache.get_tone('A') == f['C']
        assert DiatonicToneCache.get_tone('A') == f['D']
        assert DiatonicToneCache.get_tone('B') == f['E']
        assert DiatonicToneCache.get_tone('C#') == f['F']
        assert DiatonicToneCache.get_tone('C#') == f['G']
        assert DiatonicToneCache.get_tone('E') == f['A']
        assert DiatonicToneCache.get_tone('F#') == f['B']

        assert [0, 0, 1, 2, 2, 3, 4] == f.extract_template().tonal_order

        f['C'] = 'B'
        f['D'] = 'A'
        f['E'] = 'C#'
        f['F'] = 'C#'
        f['G'] = 'F#'
        f['A'] = 'A'
        f['B'] = 'E'

        # del f['D']
        # assert f['D'] is None

        assert [1, 0, 2, 2, 4, 0, 3] == f.extract_template().tonal_order

        f['C#'] = 'B#'
        f['Db'] = 'Ab'
        f['A#'] = 'Eb'

        assert DiatonicToneCache.get_tone('B#') == f['C#']
        assert DiatonicToneCache.get_tone('Ab') == f['Db']
        assert DiatonicToneCache.get_tone('Eb') == f['A#']

        del f['Db']
예제 #5
0
    def test_diatonic_modal_indexed_function(self):
        t_domain = Tonality.create(ModalityType.Major, DiatonicTone('C'))
        i = Interval(2, IntervalType.Major)
        r = PitchRange.create('E:3', 'E:7')

        f = CrossTonalityShiftPitchFunction(t_domain, r, i, modal_index=4)

        print('f={0}'.format(f))

        TestCrossTonalityShiftPitchFunction.print_map('test_diatonic_function',
                                                      f)

        t = f.tonal_function
        print(t)

        # test diatonic maps
        assert 'D:4' == str(f['C:4'])
        assert 'E:4' == str(f['D:4'])
        assert 'F#:4' == str(f['E:4'])
        assert 'G:4' == str(f['F:4'])
        assert 'A:4' == str(f['G:4'])
        assert 'B:4' == str(f['A:4'])
        assert 'C:5' == str(f['B:4'])
        assert 'D:5' == str(f['C:5'])

        assert 'M:2' == str(f.root_shift_interval)
    def test_book_examples(self):
        diatonic_tonality = Tonality.create(ModalityType.Major,
                                            DiatonicTone("A"))

        template = SecondaryChordTemplate.parse('V/V')
        if template:
            print('succeeded')
            chord = template.create_chord(diatonic_tonality)
            print(chord)
        else:
            print("failed")

        template = SecondaryChordTemplate.parse('III/II')
        chord = template.create_chord(diatonic_tonality)
        print(chord)

        template = SecondaryChordTemplate.parse('CMaj7/II')
        chord = template.create_chord(diatonic_tonality)
        print(chord)

        template = SecondaryChordTemplate.parse('V/V[NaturalMinor]')
        chord = template.create_chord(diatonic_tonality)
        print(chord)

        template = SecondaryChordTemplate.parse('V/V[Phrygian]')
        chord = template.create_chord(diatonic_tonality)
        print(chord)

        template = SecondaryChordTemplate.parse('QVIPPAP@2/V')
        chord = template.create_chord(diatonic_tonality)
        print(chord)
예제 #7
0
    def test_basic_policy(self):
        logging.debug('Start test_basic_policy')
        lower_policy_context = TestRelativeScalarStepConstraint.policy_creator(
            ModalityType.Major, DiatonicTone('G'), 'tV', 'C:2', 'C:8')
        note1 = Note(DiatonicPitch.parse('C:5'), Duration(1, 8))
        note2 = Note(DiatonicPitch.parse('D:5'), Duration(1, 8))
        lower_note_1 = ContextualNote(
            lower_policy_context,
            Note(DiatonicPitch.parse('F#:5'), Duration(1, 8)))
        lower_note_2 = ContextualNote(lower_policy_context)

        p_map = dict([(note1, lower_note_1), (note2, lower_note_2)])

        # F#:5 --> G Major two below and 3 above
        policy = RelativeScalarStepConstraint(note1, note2, -2, 3)

        v_result = policy.values(p_map, note2)
        pitches = [n.diatonic_pitch for n in v_result]
        assert len(pitches) == 6
        for s in ['D:5', 'E:5', 'F#:5', 'G:5', 'A:5', 'B:5']:
            assert DiatonicPitch.parse(s) in pitches

        for note in v_result:
            logging.debug(note)

        # Check verify for each answer
        for n in v_result:
            lower_note_2.note = n
            assert policy.verify(p_map)

        logging.debug('End test_basic_policy')
예제 #8
0
    def test_forward_with_extension(self):
        t_domain = Tonality.create(ModalityType.Major, DiatonicTone('E'))
        cycles = [['E', 'G#', 'A', 'C#'], ('F#', 'D#')]

        extension = dict()
        extension['D'] = 'F'
        extension['F'] = 'G'
        permutation_function = TonalityPermutationFunction.create(
            t_domain, cycles, extension)

        r = PitchRange.create('E:3', 'E:7')
        f = TonalityPitchFunction(permutation_function, ('E:4', 'E:5'), r,
                                  False)

        TestTonalityPitchFunction.print_map('test_forward_with_extension', f)

        assert 'G#:5' == str(f['E:4'])
        assert 'G:5' == str(f['F:4'])
        assert 'D#:6' == str(f['F#:4'])
        assert 'A:5' == str(f['G#:4'])
        assert 'C#:6' == str(f['A:4'])
        assert 'B:5' == str(f['B:4'])
        assert 'E:5' == str(f['C#:5'])
        assert 'E:5' == str(f['B##:4'])
        assert 'F:5' == str(f['D:5'])
        assert 'F:5' == str(f['C##:5'])
        assert 'F#:5' == str(f['D#:5'])
예제 #9
0
    def test_simple_tonality_permutation_function(self):
        t_domain = Tonality.create(ModalityType.Major, DiatonicTone('A'))
        cycles = [['C#', 'D'], ['E', 'G#']]
        p = TonalityPermutationFunction.create(t_domain, cycles)

        assert DiatonicToneCache.get_tone('C#') in p.domain
        assert DiatonicToneCache.get_tone('D') in p.domain
        assert DiatonicToneCache.get_tone('E') in p.domain
        assert DiatonicToneCache.get_tone('G#') in p.domain

        assert DiatonicToneCache.get_tone('D') == p['C#']
        assert DiatonicToneCache.get_tone('C#') == p['D']
        assert DiatonicToneCache.get_tone('E') == p['G#']
        assert DiatonicToneCache.get_tone('G#') == p['E']

        f = TonalityPermutationFunction(TonalityPermutation(t_domain, cycles))

        assert DiatonicToneCache.get_tone('C#') in f.domain
        assert DiatonicToneCache.get_tone('D') in f.domain
        assert DiatonicToneCache.get_tone('E') in f.domain
        assert DiatonicToneCache.get_tone('G#') in f.domain

        assert DiatonicToneCache.get_tone('D') == f['C#']
        assert DiatonicToneCache.get_tone('C#') == f['D']
        assert DiatonicToneCache.get_tone('E') == f['G#']
        assert DiatonicToneCache.get_tone('G#') == f['E']
    def test_centered_odd_function(self):
        t_domain = Tonality.create(ModalityType.Major, DiatonicTone('E'))
        r = PitchRange.create('E:3', 'E:7')

        f = DiatonicPitchReflectionFunction(
            t_domain, DiatonicPitch(4, DiatonicToneCache.get_tone('A')), r,
            FlipType.CenterTone)

        print('f={0}'.format(f))

        TestFlipOnTonality.print_map('test_simple_pitch_function', f)

        t = f.tonal_function

        assert 'E' == t['D#'].diatonic_symbol
        assert 'F#' == t['C#'].diatonic_symbol
        assert 'G#' == t['B'].diatonic_symbol
        assert 'A' == t['A'].diatonic_symbol
        assert 'B' == t['G#'].diatonic_symbol
        assert 'C#' == t['F#'].diatonic_symbol
        assert 'D#' == t['E'].diatonic_symbol

        assert 'D#:5' == str(f['E:4'])
        assert 'C#:5' == str(f['F#:4'])
        assert 'A:4' == str(f['A:4'])
        assert 'G#:4' == str(f['B:4'])
        assert 'F#:4' == str(f['C#:5'])
        assert 'E:4' == str(f['D#:5'])
    def test_non_centered_even_function(self):
        t_domain = Tonality.create(ModalityType.WholeTone, DiatonicTone('C'))
        r = PitchRange.create('E:3', 'E:7')

        f = DiatonicPitchReflectionFunction(
            t_domain, DiatonicPitch(4, DiatonicToneCache.get_tone('G#')), r,
            FlipType.UpperNeighborOfPair)

        TestFlipOnTonality.print_map('test_non_centered_even_function', f)

        t = f.tonal_function

        assert 'C' == t['D'].diatonic_symbol
        assert 'D' == t['C'].diatonic_symbol
        assert 'E' == t['A#'].diatonic_symbol
        assert 'F#' == t['G#'].diatonic_symbol
        assert 'G#' == t['F#'].diatonic_symbol
        assert 'A#' == t['E'].diatonic_symbol

        assert 'C:4' == str(f['D:5'])
        assert 'D:4' == str(f['C:5'])
        assert 'E:4' == str(f['A#:4'])
        assert 'F#:4' == str(f['G#:4'])
        assert 'G#:4' == str(f['F#:4'])
        assert 'A#:4' == str(f['E:4'])
        assert 'C:5' == str(f['D:4'])
예제 #12
0
    def test_reversal_on_policy(self):
        logging.debug('Start test_reversal_on_policy')
        lower_policy_context = TestRelativeScalarStepConstraint.policy_creator(
            ModalityType.Major, DiatonicTone('G'), 'tV', 'C:2', 'C:8')
        note1 = Note(DiatonicPitch.parse('C:5'), Duration(1, 8))
        note2 = Note(DiatonicPitch.parse('D:5'), Duration(1, 8))
        lower_note_1 = ContextualNote(lower_policy_context)
        lower_note_2 = ContextualNote(
            lower_policy_context,
            Note(DiatonicPitch.parse('C:5'), Duration(1, 8)))

        p_map = dict([(note1, lower_note_1), (note2, lower_note_2)])

        # F#:5 --> G Major two below and 3 above
        policy = RelativeScalarStepConstraint(note1, note2, -2, 3)

        result = policy.values(p_map, note1)
        pitches = [n.diatonic_pitch for n in result]

        for pitch in pitches:
            logging.debug(pitch)

        # Check that each returned verifies
        for n in result:
            lower_note_1.note = n
            assert policy.verify(p_map)

        logging.debug('End test_reversal_on_policy')
    def test_book_examples(self):
        template = QuartalChordTemplate.parse('GPerAug')
        if template:
            print('succeeded')
            chord = template.create_chord()
            print(chord)
        else:
            print("failed")

        diatonic_tonality = Tonality.create(ModalityType.Major, DiatonicTone("Bb"))
        template = QuartalChordTemplate.parse('IIPerPer@2')
        chord = template.create_chord(diatonic_tonality)
        print(chord)

        template = QuartalChordTemplate.parse('GPPAAPP')
        chord = template.create_chord()
        print(chord)

        template = QuartalChordTemplate.parse('IIIPAPAA@3')
        chord = template.create_chord(diatonic_tonality)
        print(chord)

        template = QuartalChordTemplate.parse('C')
        chord = template.create_chord()
        print(chord)

        template = QuartalChordTemplate.parse('IV')
        chord = template.create_chord(diatonic_tonality)
        print(chord)
예제 #14
0
    def test_simple_fixed_pitch(self):
        logging.debug('Start test_simple_fixed_pitch')

        note = Note(DiatonicPitch.parse("C:5"), Duration(1, 4))

        select_notes = {'A:5', 'C:4', 'Eb:2', 'F#:6'}

        constraint = FixedPitchSelectSetConstraint(
            note, {DiatonicPitch.parse(p)
                   for p in select_notes})

        policy_context = TestFixedPitchSelectSetConstraint.policy_creator(
            ModalityType.Major, DiatonicTone('C'), 'tIV', 'C:2', 'C:8')
        lower_contextual = ContextualNote(policy_context)
        p_map = PMap()
        p_map[note] = lower_contextual

        v_results = constraint.values(p_map, note)
        assert v_results is not None
        assert len(v_results) == len(select_notes)
        for result in v_results:
            print(str(result))

        assert select_notes == {str(n.diatonic_pitch) for n in v_results}

        assert not constraint.verify(p_map)

        lower_contextual.note = Note(DiatonicPitch.parse('Eb:2'),
                                     Duration(1, 4))
        assert constraint.verify(p_map)
예제 #15
0
    def test_is_not_equal(self):
        logging.debug('Start test_is_not_equal')
        note1 = Note(DiatonicPitch.parse('C:5'), Duration(1, 8))
        lower_policy_context = TestNotEqualPitchConstraint.policy_creator(
            ModalityType.Major, DiatonicTone('G'), 'tV', 'C:2', 'C:8')
        lower_context_note_a = ContextualNote(
            lower_policy_context,
            Note(DiatonicPitch.parse('F#:6'), Duration(1, 8)))
        p_map = PMap()
        p_map[note1] = lower_context_note_a

        other_source = []
        for tone in ['B:5', 'D:5', 'E:5']:
            n = Note(DiatonicPitch.parse(tone), Duration(1, 8))
            lower_context_note = ContextualNote(lower_policy_context)
            p_map[n] = lower_context_note
            other_source.append(n)

        params = list([note1])
        params.extend(other_source)
        policy = NotEqualPitchConstraint(params)

        for c_note in p_map.unassigned_actors(policy):
            print(c_note)
            v_result = policy.values(p_map, c_note)
            assert v_result is not None

            assert DiatonicPitch.parse('F#:6') not in {
                n.diatonic_pitch
                for n in v_result
            }

        p_map[other_source[1]].note = Note(DiatonicPitch.parse('E:6'),
                                           Duration(1, 8))
        for c_note in p_map.unassigned_actors(policy):
            print(c_note)
            v_result = policy.values(p_map, c_note)
            assert v_result is not None
            ret_pitches = {n.diatonic_pitch for n in v_result}
            assert len(
                ret_pitches.intersection(
                    {DiatonicPitch.parse('F#:6'),
                     DiatonicPitch.parse('E:6')})) == 0

        assert policy.verify(p_map) is False

        p_map[other_source[2]].note = Note(DiatonicPitch.parse('F#:6'),
                                           Duration(1, 8))
        assert policy.verify(p_map) is False

        p_map[other_source[0]].note = Note(DiatonicPitch.parse('D:6'),
                                           Duration(1, 8))
        assert policy.verify(p_map) is False

        p_map[other_source[2]].note = Note(DiatonicPitch.parse('A:6'),
                                           Duration(1, 8))
        assert policy.verify(p_map) is True

        logging.debug('End test_is_not_equal')
        return
    def test_centered_even_function(self):
        t_domain = Tonality.create(ModalityType.HWOctatonic, DiatonicTone('C'))
        r = PitchRange.create('E:3', 'E:7')

        f = DiatonicPitchReflectionFunction(
            t_domain, DiatonicPitch(4, DiatonicToneCache.get_tone('A')), r,
            FlipType.CenterTone)

        TestFlipOnTonality.print_map('test_centered_even_function', f)

        t = f.tonal_function

        assert 'C' == t['Gb'].diatonic_symbol
        assert 'Db' == t['Fb'].diatonic_symbol
        assert 'Eb' == t['Eb'].diatonic_symbol
        assert 'Fb' == t['Db'].diatonic_symbol
        assert 'Gb' == t['C'].diatonic_symbol
        assert 'G' == t['Bb'].diatonic_symbol
        assert 'A' == t['A'].diatonic_symbol
        assert 'Bb' == t['G'].diatonic_symbol

        assert 'C:4' == str(f['Gb:5'])
        assert 'Db:4' == str(f['Fb:5'])

        assert 'Eb:4' == str(
            f['Eb:5'])  # The other stable tone outside of the centered!

        assert 'Fb:4' == str(f['Db:5'])
        assert 'Gb:4' == str(f['C:5'])
        assert 'G:4' == str(f['Bb:4'])
        assert 'A:4' == str(f['A:4'])
        assert 'Bb:4' == str(f['G:4'])
        assert 'C:5' == str(f['Gb:4'])
        assert 'Db:5' == str(f['Fb:4'])
    def test_non_centered_odd_function(self):
        t_domain = Tonality.create(ModalityType.Major, DiatonicTone('E'))
        r = PitchRange.create('E:3', 'E:7')

        f = DiatonicPitchReflectionFunction(
            t_domain, DiatonicPitch(4, DiatonicToneCache.get_tone('F#')), r,
            FlipType.LowerNeighborOfPair)

        TestFlipOnTonality.print_map('test_non_centered_odd_function', f)

        t = f.tonal_function

        assert 'E' == t['A'].diatonic_symbol
        assert 'F#' == t['G#'].diatonic_symbol
        assert 'G#' == t['F#'].diatonic_symbol
        assert 'A' == t['E'].diatonic_symbol
        assert 'B' == t['D#'].diatonic_symbol
        assert 'C#' == t['C#'].diatonic_symbol
        assert 'D#' == t['B'].diatonic_symbol

        assert 'C#:4' == str(f['C#:5'])
        assert 'D#:4' == str(f['B:4'])
        assert 'E:4' == str(f['A:4'])
        assert 'F#:4' == str(f['G#:4'])
        assert 'G#:4' == str(f['F#:4'])
        assert 'A:4' == str(f['E:4'])
        assert 'B:4' == str(f['D#:4'])
        assert 'C#:5' == str(f['C#:4'])
        assert 'D#:5' == str(f['B:3'])
    def test_non_scale_note(self):
        logging.debug('Start test_non_scale_note')

        note = Note(DiatonicPitch.parse("Bb:4"), Duration(1, 4))
        policy = FixedPitchConstraint(note, DiatonicPitch.parse("Ab:5"))

        policy_context = TestFixedPitchConstraint.policy_creator(
            ModalityType.Major, DiatonicTone('C'), 'tIV', 'C:2', 'C:8')
        contextual_note = ContextualNote(policy_context)
        p_map = PMap()
        p_map[note] = contextual_note

        v_result = policy.values(p_map, note)

        result = next(iter(v_result))
        print('test_non_scale_note note= {0}'.format(result))

        assert result.diatonic_pitch == DiatonicPitch.parse("Ab:5")
        assert result.base_duration == Duration(1, 4)

        contextual_note.note = result

        result = policy.verify(p_map)
        assert result is True

        logging.debug('end test_non_scale_note')
    def test_is_equal(self):
        logging.debug('Start test_is_equal')

        note1 = Note(DiatonicPitch.parse('C:5'), Duration(1, 8))
        note2 = Note(DiatonicPitch.parse('C:5'), Duration(1, 8))

        lower_policy_context = TestEqualPitchConstraint.policy_creator(
            ModalityType.Major, DiatonicTone('G'), 'tV', 'C:2', 'C:8')
        lower_context_note_a = ContextualNote(
            lower_policy_context,
            Note(DiatonicPitch.parse('F#:6'), Duration(1, 8)))
        lower_context_note_b = ContextualNote(lower_policy_context)
        parameter_map = dict([(note1, lower_context_note_a),
                              (note2, lower_context_note_b)])
        parameter_map = PMap(parameter_map)

        policy = EqualPitchConstraint([note1, note2])

        result = policy.values(parameter_map, note2)

        actual_note = next(iter(result))
        print('test_is_equal; note = {0}'.format(actual_note))

        assert actual_note.diatonic_pitch == DiatonicPitch.parse("F#:6")
        assert actual_note.base_duration == Duration(1, 8)

        parameter_map[note2].note = actual_note

        assert policy.verify(parameter_map) is True

        logging.debug('End test_is_equal')
예제 #20
0
    def test_simple_reverse_pitch_function(self):
        t_domain = Tonality.create(ModalityType.Major, DiatonicTone('E'))
        cycles = [['E', 'G#', 'A', 'C#'], ('F#', 'D#')]
        permutation_function = TonalityPermutationFunction.create(
            t_domain, cycles)

        r = PitchRange.create('E:3', 'E:7')
        f = TonalityPitchFunction(permutation_function, ('E:4', 'E:5'), r,
                                  True)

        TestTonalityPitchFunction.print_map(
            'test_simple_reverse_pitch_fnction', f)

        assert 'G#:5' == str(f['E:4'])
        assert 'D#:6' == str(f['F#:4'])
        assert 'A:5' == str(f['G#:4'])
        assert 'C#:6' == str(f['A:4'])
        assert 'B:5' == str(f['B:4'])
        assert 'E:5' == str(f['C#:5'])
        assert 'F#:5' == str(f['D#:5'])

        assert 'G#:4' == str(f['E:5'])
        assert 'D#:5' == str(f['F#:5'])
        assert 'A:4' == str(f['G#:5'])
        assert 'C#:5' == str(f['A:5'])
        assert 'B:4' == str(f['B:5'])
        assert 'E:4' == str(f['C#:6'])
        assert 'F#:4' == str(f['D#:6'])
예제 #21
0
    def test_additional_octaves(self):
        t_domain = Tonality.create(ModalityType.MinorPentatonic,
                                   DiatonicTone('C'))
        i = Interval(12, IntervalType.Perfect)
        r = PitchRange.create('E:3', 'E:7')

        f = CrossTonalityShiftPitchFunction(t_domain, r, i)

        print('f={0}'.format(f))

        assert 'P:12' == str(f.root_shift_interval)

        assert 'G:5' == str(f['C:4'])
        assert 'A:5' == str(f['D:4'])
        assert 'B:5' == str(f['E:4'])
        assert 'C:6' == str(f['F:4'])

        i = Interval(11, IntervalType.Perfect).negation()
        f = CrossTonalityShiftPitchFunction(t_domain, r, i)
        print('f={0}'.format(f))

        assert '-P:11' == str(f.root_shift_interval)

        assert 'G:2' == str(f['C:4'])
        assert 'A:2' == str(f['D:4'])
        assert 'B:2' == str(f['E:4'])
        assert 'C:3' == str(f['F:4'])
예제 #22
0
    def test_pentatonic_tonal_function(self):
        t_domain = Tonality.create(ModalityType.MinorPentatonic,
                                   DiatonicTone('C'))
        i = Interval(5, IntervalType.Perfect)
        r = PitchRange.create('E:3', 'E:7')

        f = CrossTonalityShiftPitchFunction(t_domain, r, i)

        print('f={0}'.format(f))

        TestCrossTonalityShiftPitchFunction.print_map(
            'test_pentatonic_tonal_function', f)

        t = f.tonal_function
        print(t)

        assert 'G' == t['C'].diatonic_symbol
        assert 'Bb' == t['Eb'].diatonic_symbol
        assert 'C' == t['F'].diatonic_symbol
        assert 'D' == t['G'].diatonic_symbol
        assert 'F' == t['Bb'].diatonic_symbol

        assert 'G:5' == str(f['C:5'])
        assert 'F:5' == str(f['Bb:4'])
        assert 'D:5' == str(f['G:4'])
        assert 'C:5' == str(f['F:4'])
        assert 'Bb:4' == str(f['Eb:4'])
        assert 'G:4' == str(f['C:4'])

        # test range
        d = f.domain_pitch_range
        print(d)
        assert d.start_index == DiatonicPitch.parse('E:3').chromatic_distance
        assert d.end_index == DiatonicPitch.parse('E:7').chromatic_distance
        r = f.range_pitch_range
        print(r)
        assert r.start_index == DiatonicPitch.parse('B:3').chromatic_distance
        assert r.end_index == DiatonicPitch.parse('B:7').chromatic_distance

        # test chromatics
        assert 'G#:5' == str(f['C#:5'])
        assert 'F#:5' == str(f['B:4'])
        assert 'E#:5' == str(f['A#:4'])
        assert 'E:5' == str(f['A:4'])
        assert 'D#:5' == str(f['G#:4'])
        assert 'C#:5' == str(f['F#:4'])
        assert 'B:4' == str(f['E:4'])
        assert 'A:4' == str(f['D:4'])
        assert 'A#:4' == str(f['D#:4'])
        assert 'G#:4' == str(f['C#:4'])

        assert 'Gb:5' == str(f['Cb:5'])
        assert 'Fb:5' == str(f['Bbb:4'])
        assert 'Eb:5' == str(f['Ab:4'])
        assert 'Db:5' == str(f['Gb:4'])
        assert 'Cb:5' == str(f['Fb:4'])
        assert 'Bbb:4' == str(f['Ebb:4'])
        assert 'Ab:4' == str(f['Db:4'])
        assert 'Gb:4' == str(f['Cb:4'])
예제 #23
0
 def __build_diatonics(self):
     """
     Builds all diatonic tones for the cache.
     """
     for ltr in DiatonicTone.DIATONIC_LETTERS:
         for aug in DiatonicTone.AUGMENTATIONS:
             self.diatonic_map[(ltr + aug).lower()] = DiatonicTone(ltr +
                                                                   aug)
예제 #24
0
 def test_triad_generation(self):
     diatonic_tonality = Tonality.create(ModalityType.Major, DiatonicTone("C"))
     ret_types = [TertianChordType.Maj, TertianChordType.Min, TertianChordType.Min, TertianChordType.Maj,
                  TertianChordType.Maj,
                  TertianChordType.Min, TertianChordType.Dim]
     for i in range(1, 8):
         chord = TertianChordTemplate.get_triad(diatonic_tonality, i)       
         print(chord)
         assert chord.chord_type.value == ret_types[i - 1]
예제 #25
0
    def test_secondary_chord(self):
        print('----- test_secondary_tonality -----')
        diatonic_tonality = Tonality.create(ModalityType.Major,
                                            DiatonicTone("C"))
        chort_t_i = TertianChordTemplate.parse('tI')
        chord_i = chort_t_i.create_chord(diatonic_tonality)

        chord_v_ii = SecondaryChordTemplate.parse('V/ii').create_chord(
            diatonic_tonality)
        chord_vi_v = SecondaryChordTemplate.parse('vi/V').create_chord(
            diatonic_tonality)

        chord_t_ii = TertianChordTemplate.parse('tii')
        chord_ii = chord_t_ii.create_chord(diatonic_tonality)

        hc_track = HarmonicContextTrack()
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord_i, Duration(1)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord_v_ii, Duration(1)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord_vi_v, Duration(1)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord_ii, Duration(1)))
        TestTFlip.print_hct(hc_track)

        tune = [('C:5', (1, 1)), ('E:5', (1, 1)), ('E:5', (1, 1)),
                ('G:5', (1, 1))]
        line = TestTFlip.build_line(tune)

        cue = DiatonicPitch(5, 'd')

        tflip = TDiatonicReflection(line, hc_track, cue)

        temporal_extent = Interval(Fraction(0), Fraction(4))
        score_line, score_hct = tflip.apply(temporal_extent, cue)
        TestTFlip.print_notes(score_line)
        TestTFlip.print_hct(score_hct)

        notes = score_line.get_all_notes()
        assert len(notes) == 4
        assert str(notes[0].diatonic_pitch) == 'E:5'
        assert str(notes[1].diatonic_pitch) == 'C#:5'
        assert str(notes[2].diatonic_pitch) == 'C:5'
        assert str(notes[3].diatonic_pitch) == 'A:4'

        hc_list = score_hct.hc_list()
        assert len(hc_list) == 4
        assert hc_list[1].chord.primary_chord.chord_template.scale_degree == 7
        assert {t[0].diatonic_symbol
                for t in hc_list[1].chord.tones} == {'C#', 'E', 'G'}
        assert hc_list[1].chord.primary_chord.chord_template.inversion == 3

        assert hc_list[2].chord.primary_chord.chord_template.scale_degree == 7
        assert {t[0].diatonic_symbol
                for t in hc_list[2].chord.tones} == {'C', 'F#', 'A'}
        assert hc_list[2].chord.primary_chord.chord_template.inversion == 3
    def test_standards(self):
        diatonic_tonality = Tonality.create(ModalityType.Major,
                                            DiatonicTone("G"))

        template = SecondaryChordTemplate.parse('V/ii')
        print(template)
        t_chord = template.create_chord(diatonic_tonality)
        print(t_chord)

        s = ', '.join(str(tone[0].diatonic_symbol) for tone in t_chord.tones)
        print(s)
        assert s == 'E, G#, B'

        template = SecondaryChordTemplate.parse('V/IV')
        print(template)
        t_chord = template.create_chord(diatonic_tonality)
        print(t_chord)

        s = ', '.join(str(tone[0].diatonic_symbol) for tone in t_chord.tones)
        print(s)
        assert s == 'G, B, D'

        diatonic_tonality = Tonality.create(ModalityType.Major,
                                            DiatonicTone("G"))
        template = SecondaryChordTemplate.parse('V/ii')
        print(template)
        t_chord = template.create_chord(diatonic_tonality)
        print(t_chord)

        s = ', '.join(str(tone[0].diatonic_symbol) for tone in t_chord.tones)
        print(s)
        assert s == 'E, G#, B'

        diatonic_tonality = Tonality.create(ModalityType.Major,
                                            DiatonicTone("Bb"))
        template = SecondaryChordTemplate.parse('VI/ii')
        print(template)
        t_chord = template.create_chord(diatonic_tonality)
        print(t_chord)

        s = ', '.join(str(tone[0].diatonic_symbol) for tone in t_chord.tones)
        print(s)
        assert s == 'A, C, Eb'
예제 #27
0
    def test_simplified_adapted_function(self):
        t_domain = Tonality.create(ModalityType.Major, DiatonicTone('F'))
        t_range = Tonality.create(ModalityType.MelodicMinor, DiatonicTone('G'))

        f = TonalFunction(t_domain, t_range)

        nt_domain = Tonality.create(ModalityType.Major, DiatonicTone('Ab'))
        nt_range = Tonality.create(ModalityType.MelodicMinor,
                                   DiatonicTone('e'))

        pf = f.create_adapted_function(nt_domain, nt_range)

        assert DiatonicToneCache.get_tone('E') == pf['Ab']
        assert DiatonicToneCache.get_tone('F#') == pf['Bb']
        assert DiatonicToneCache.get_tone('G') == pf['C']
        assert DiatonicToneCache.get_tone('A') == pf['Db']
        assert DiatonicToneCache.get_tone('B') == pf['Eb']
        assert DiatonicToneCache.get_tone('C#') == pf['F']
        assert DiatonicToneCache.get_tone('D#') == pf['G']
예제 #28
0
    def test_simple_tonal_function(self):
        t_domain = Tonality.create(ModalityType.Major, DiatonicTone('C'))
        t_range = Tonality.create(ModalityType.Major, DiatonicTone('A'))

        # default map between 2 tonalities of same cardinality.
        f = TonalFunction(t_domain, t_range)

        assert DiatonicToneCache.get_tone('A') == f['C']
        assert DiatonicToneCache.get_tone('B') == f['D']
        assert DiatonicToneCache.get_tone('C#') == f['E']
        assert DiatonicToneCache.get_tone('D') == f['F']
        assert DiatonicToneCache.get_tone('E') == f['G']
        assert DiatonicToneCache.get_tone('F#') == f['A']
        assert DiatonicToneCache.get_tone('G#') == f['B']

        skeleton = f.extract_template()
        assert [0, 1, 2, 3, 4, 5, 6] == skeleton.tonal_order

        TestTonalFunction.print_function(f)
예제 #29
0
    def test_simple_quartal(self):
        diatonic_tonality = Tonality.create(ModalityType.Major, DiatonicTone("C"))
        chord_list = ChordClassifier.classify(['e', 'a', 'd'], 'e', diatonic_tonality)
        assert 1 == len(chord_list)
        assert "PerPer" == str(chord_list[0].chord_type)

        TestChordClassifier.print_chord_list('test_simple_quartal', chord_list)

        chord_list = ChordClassifier.classify(['e', 'a', 'd', 'Bb'], 'e', diatonic_tonality)
        assert 0 == len(chord_list)
예제 #30
0
    def parse(chord_string):
        """
        Parse an input string into a TertialChordTemplate.
        
        Args:
          chord_string: string input representing chord
        Returns:
          TertianChordTemplate       
        """
        if not chord_string:
            raise TertianChordException('Unable to parse chord string to completion: {0}'.format(chord_string))
        m = TertianChordTemplate.TERTIAN_PATTERN.match(chord_string)
        if not m:
            raise TertianChordException('Unable to parse chord string to completion: {0}'.format(chord_string))

        scale_degree = m.group(TertianChordTemplate.GROUP_SCALE_DEGREE)
        if scale_degree:
            scale_degree = ChordTemplate.SCALE_DEGREE_MAP[scale_degree]
        if m.group(TertianChordTemplate.GROUP_DIATONIC_TONE) is not None:
            diatonic_basis = DiatonicTone(m.group(TertianChordTemplate.GROUP_DIATONIC_TONE))
        else:
            diatonic_basis = None
        chord_name = m.group(TertianChordTemplate.GROUP_CHORD)
        chord_type = None
        if chord_name:
            chord_type = TertianChordType.to_type(chord_name)
        inversion_text = m.group(TertianChordTemplate.GROUP_INVERSION)
        inversion_tension = m.group(TertianChordTemplate.INVERSION_TENSION)
        inversion_interval = None
        inversion = None
        if inversion_tension:
            tensions_parse = TertianChordTemplate.INVERSE_TENSION_PATTERN.findall(inversion_tension)
            for tension in tensions_parse:  # should only be 1
                aug = DiatonicTone.AUGMENTATION_OFFSET_MAPPING[tension[0]]
                interval_type = Interval.available_types(int(tension[1]))[aug]
                inversion_interval = Interval(int(tension[1]), interval_type)
                logging.info('inversion_interval = {0}'.format(str(inversion_interval)))
        elif inversion_text:
            inversion = int(inversion_text)
        else:
            inversion = 1

        tensions = []
        if m.group(TertianChordTemplate.GROUP_TENSIONS):
            tensions_parse = TertianChordTemplate.TENSION_PATTERN.findall(m.group(TertianChordTemplate.GROUP_TENSIONS))
            for tension in tensions_parse:
                aug = DiatonicTone.AUGMENTATION_OFFSET_MAPPING[tension[2]]
                if aug not in Interval.available_types(int(tension[3])):
                    raise TertianChordException('Invalid interval specification for tension \'{0}\''.format(tension[0]))
                interval_type = Interval.available_types(int(tension[3]))[aug]
                interval = Interval(int(tension[3]), interval_type)
                tensions.append(interval)

        return TertianChordTemplate(diatonic_basis, scale_degree, chord_type, tensions, inversion, inversion_interval)