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')
Ejemplo n.º 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)
Ejemplo n.º 3
0
    def __init__(self, tonality, increment, aux_tonality=None):
        self.__tonality = tonality
        self.__increment = increment
        self.__aux_tonality = aux_tonality

        if tonality.cardinality != 7:
            raise Exception('Expect tonalities with cardinality 7 only.')

        self.__tone_map = dict()
        if aux_tonality is None:
            annotation = self.tonality.annotation
            for index in range(0, self.tonality.cardinality):
                dt = annotation[index]
                mapped_tone = self.tonality.annotation[(index + self.increment) % self.tonality.cardinality]
                if dt.augmentation_offset != 0:
                    mapped_tone = DiatonicTone.alter_tone_by_augmentation(mapped_tone, -dt.augmentation_offset)
                self.tone_map[dt.diatonic_letter] = mapped_tone
        else:
            annotation = self.tonality.annotation           # target scale
            aux_annotation = self.aux_tonality.annotation   # source scale
            for index in range(0, self.aux_tonality.cardinality):
                dt = aux_annotation[index]
                mapped_tone = annotation[index]
                if dt.augmentation_offset != 0:
                    mapped_tone = DiatonicTone.alter_tone_by_augmentation(mapped_tone, -dt.augmentation_offset)
                self.tone_map[dt.diatonic_letter] = mapped_tone
    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.')
Ejemplo n.º 5
0
    def get_end_pitch(self, pitch):
        """
        Given a pitch and this interval, Assuming pitch is the starting pitch of the interval,
        compute the end pitch.
        
        Args:
          pitch: DiatonicPitch
          
        Returns:
          DiatonicPitch of end tone
        """
        diatonic_dist = pitch.diatonic_distance() + self.diatonic_distance
        tone_index = diatonic_dist % 7
        end_pitch_string = DiatonicTone.get_diatonic_letter(tone_index)
        end_pitch_octave = diatonic_dist // 7

        chromatic_dist = pitch.chromatic_distance + self.chromatic_distance

        normal_pitch = DiatonicPitch(
            end_pitch_octave, DiatonicFoundation.get_tone(end_pitch_string))

        alteration = chromatic_dist - normal_pitch.chromatic_distance

        end_pitch_string += DiatonicTone.augmentation(alteration)

        return DiatonicPitch.parse(end_pitch_string + ':' +
                                   str(end_pitch_octave))
Ejemplo n.º 6
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']
    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'])
Ejemplo n.º 8
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
Ejemplo n.º 9
0
    def print_book_map(tag, f):
        print(tag)
        domain_tonality = f.domain_tonality
        range_tonality = f.range_tonality

        print('CrossTonalityShiftPitchFunction {0}--> {1}'.format(
            domain_tonality, range_tonality))

        domain_annotation = domain_tonality.annotation[:-1]
        presentation_reg = 4
        domain_presentation_pitches = list()
        last_pitch = None
        for t in domain_annotation:
            domain_pitch = DiatonicPitch(presentation_reg, t)
            # augment register if crossing past C, e.g. B:4 > C:4
            if last_pitch is not None and last_pitch.chromatic_distance > domain_pitch.chromatic_distance:
                presentation_reg = presentation_reg + 1
                domain_pitch = DiatonicPitch(presentation_reg, t)

            for a in [-1, 0, 1]:
                a_tone = DiatonicTone.alter_tone_by_augmentation(t, a)
                domain_pitch_mod = DiatonicPitch(presentation_reg, a_tone)
                domain_presentation_pitches.append(domain_pitch_mod)
            last_pitch = domain_pitch

        for domain_pitch in domain_presentation_pitches:
            range_pitch = f[domain_pitch]
            print('{0} --> {1}'.format(domain_pitch, range_pitch))
    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)
Ejemplo n.º 11
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)
Ejemplo n.º 12
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)
Ejemplo n.º 13
0
    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')
    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'])
Ejemplo n.º 15
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'])
Ejemplo n.º 18
0
    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)
Ejemplo n.º 19
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'])
Ejemplo n.º 20
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')
Ejemplo n.º 21
0
    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')
Ejemplo n.º 22
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')
Ejemplo n.º 23
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'])
    def _map_non_tonality_tone(self, ttone, pure_tonal_map):
        # Get the closest tone in terms of chromatic distance.
        closest_tone, closest_distance = self._find_closest_tone(ttone)

        dd = closest_tone.diatonic_index - ttone.diatonic_index
        # Look for octave crossing.  if dd in {-5, -6] closest pitch is one octave up.
        if dd in [-5, -6]:  # [1, 2] are alright.  pitch < closest_pitch
            dd = (7 + dd) % 7
        elif dd in [5, 6]:  # [-1, -2] are alright.  pitch > closest_pitch
            dd = dd - 7

        closest_tone_target = pure_tonal_map[closest_tone]
        index = (closest_tone_target.diatonic_index + dd) % 7
        tone = DiatonicToneCache.get_tone('CDEFGAB'[index])

        # Octave 4 is chosen arbitrarily, and using dd we determine if ttone and closest need different
        # octave assignments.  We do this in order to get accurate chromatic distances below.
        if dd < 0:
            octave = 3 if DiatonicPitch.crosses_c(tone, closest_tone_target, True) else 4
        elif dd > 0:
            octave = 5 if DiatonicPitch.crosses_c(tone, closest_tone_target, False) else 4
        else:
            octave = 4

        target_pitch = DiatonicPitch(octave, tone)
        actual_distance = target_pitch.chromatic_distance - DiatonicPitch(4, closest_tone_target).chromatic_distance
        # recall: closest_distance is chrom. dist to get from closest pitch to pitch: we are on 'other side', so
        #         we use the negative of it.
        correction = closest_distance - actual_distance

        if correction == 0:
            return tone
        result_tone = DiatonicTone.alter_tone_by_augmentation(tone, correction)

        return result_tone
Ejemplo n.º 25
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'])
Ejemplo n.º 26
0
    def __create_chord_on_diatonic_tonality(self, diatonic_tone,
                                            diatonic_tonality):
        if not diatonic_tonality:
            raise Exception(
                "Cannot base secundal chord on tone {0} without tonality.".
                format(diatonic_tone.diatonic_symbol))
        # The tonality must include this tone.
        tone_scale = diatonic_tonality.annotation
        found_index = -1
        for i in range(0, len(tone_scale)):
            if diatonic_tone == tone_scale[i]:
                found_index = i
                break
        if found_index == -1:
            raise Exception(
                "For secundal chord based on tone {0}, tone must be in given tonality {1}"
                .format(diatonic_tone.diatonic_symbol, diatonic_tonality))
        self.chord_basis = []
        basis_tone = tone_scale[found_index]
        for i in range(0, 3):
            tone = tone_scale[(found_index + i) % (len(tone_scale) - 1)]
            pitch_a = DiatonicPitch(1, basis_tone.diatonic_symbol)
            b_octave = 2 if basis_tone.diatonic_index > tone.diatonic_index else 1
            pitch_b = DiatonicPitch(b_octave, tone.diatonic_symbol)
            interval = Interval.create_interval(pitch_a, pitch_b)
            # If for any reason, the interval is not perfect or augmented (we know it is a 4th), just adjust tone upward
            #    It is unknown if this can happen in a diatonic scale in practice.
            if interval.interval_type.value == IntervalType.Diminished:
                tone = DiatonicTone.alter_tone_by_augmentation(tone, 1)
                pitch_b = DiatonicPitch(b_octave, tone.diatonic_symbol)
                interval = Interval.create_interval(pitch_a, pitch_b)
            self.chord_basis.append(interval)

            self.__tones.append((tone, interval))
            basis_tone = tone
Ejemplo n.º 27
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'])
Ejemplo n.º 28
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)
Ejemplo n.º 29
0
    def end_tone_from_pure_distance(tone, dd, cc, up_down=True):
        """
        Given a tone and diatonic/chromatic distances compute the end tone above or below it.
        :param tone:
        :param dd:
        :param cc:
        :param up_down:
        :return:
        """
        new_dd = (tone.diatonic_index +
                  dd) % 7 if up_down else (tone.diatonic_index - dd) % 7
        end_tone = DiatonicToneCache.get_tone(
            DiatonicTone.get_diatonic_letter(new_dd))
        aug = (cc - (end_tone.placement - tone.placement) % 12) if up_down else \
            (cc - (tone.placement - end_tone.placement) % 12)

        return DiatonicTone.alter_tone_by_augmentation(end_tone, aug)
Ejemplo n.º 30
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