Example #1
0
    def _reset_pitches(self, as_copy):
        line = self.source_line.clone() if as_copy else self.source_line
        for note in line.get_all_notes():
            if self.temporal_extent.contains(
                    note.get_absolute_position().position):
                hc = self.source_hct.get_hc_by_position(
                    note.get_absolute_position())
                if hc not in self.hc_flip_map.keys():
                    if isinstance(hc.chord, SecondaryChord):
                        f = self._build_secondary_flip_function(hc)
                    else:
                        low, high = TDiatonicReflection._adjust_flip_cue_to_tonality(
                            self.cue_pitch, hc.tonality)
                        if high is None:
                            f = DiatonicPitchReflectionFunction(
                                hc.tonality, self.cue_pitch,
                                self.domain_pitch_range, self.flip_type)
                        else:
                            f = DiatonicPitchReflectionFunction(
                                hc.tonality, low, self.domain_pitch_range,
                                FlipType.LowerNeighborOfPair)
                    self.hc_flip_map[hc] = f
                else:
                    f = self.hc_flip_map[hc]

                note.diatonic_pitch = f[note.diatonic_pitch]
        return line
    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_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_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'])
Example #6
0
    def _build_secondary_flip_function(self, hc):
        # Strategy - for secondary chords, we simply build a reflection for the secondary scale.
        #  The cue pitch is used if the cue pitch exists in the secondary scale.
        #  otherwise we build a reflection_tests around the neighboring pitches to the cue.
        #  This is about the simplest stragegy to use in this situation, and has credibility by virtue of using
        #  the same cue pitch.  However, it may result in irregular resolutions in chord
        #  sequences, like V/ii, ii
        secondary_tonality = hc.chord.secondary_tonality

        lo_cue_tone, hi_cue_tone = TDiatonicReflection._compute_cue_tone(
            self.cue_pitch.diatonic_tone, secondary_tonality)
        octave = self.cue_pitch.octave
        if hi_cue_tone is None:  # case where lo_cue_tone should be enharmonic to cue_pitch.diatonic_tone
            if self.cue_pitch.chromatic_distance < DiatonicPitch(
                    octave, lo_cue_tone).chromatic_distance:
                octave = octave - 1
            elif self.cue_pitch.chromatic_distance > DiatonicPitch(
                    octave, lo_cue_tone).chromatic_distance:
                octave = octave + 1

            lo_cue_pitch = DiatonicPitch(octave, lo_cue_tone)
            f = DiatonicPitchReflectionFunction(secondary_tonality,
                                                lo_cue_pitch,
                                                self.domain_pitch_range)
        else:
            if DiatonicPitch(
                    octave, lo_cue_tone
            ).chromatic_distance > self.cue_pitch.chromatic_distance:
                octave = octave - 1
            lo_cue_pitch = DiatonicPitch(octave, lo_cue_tone)
            f = DiatonicPitchReflectionFunction(secondary_tonality,
                                                lo_cue_pitch,
                                                self.domain_pitch_range,
                                                FlipType.LowerNeighborOfPair)

        #
        # Note: the above produces the same tonal function as TonalFunction.create_adapted_function
        #       The former uses a reversal based on the same cue scale index, while the latter
        #       would do that anyway by pickup up on the original note permutation derived from reflection_tests.
        #
        return f
Example #7
0
    def remap_chord(self, hc):

        chord = hc.chord
        chord_tonality = hc.tonality

        if not isinstance(chord, SecondaryChord):
            f = self.hc_flip_map[hc] if hc in self.hc_flip_map.keys() else \
                DiatonicPitchReflectionFunction(hc.tonality, self.cue_pitch, self.domain_pitch_range)
            new_chord_tones = [f.tonal_function[t[0]] for t in chord.tones]
            chords = ChordClassifier.classify_all_roots(
                new_chord_tones, chord_tonality)
            if chords is not None and len(chords) > 0:
                return chords[0]
            else:
                raise Exception(
                    'Cannot remap/classify chord {0} based on chord.'.format(
                        ', '.join(str(t) for t in new_chord_tones)))
        else:
            secondary_tonality = chord.secondary_tonality
            if hc in self.hc_flip_map.keys():
                secondary_function = self.hc_flip_map[hc].tonal_function
            else:
                secondary_function = self._build_secondary_flip_function(
                    hc).tonal_function

            # Alternatively, in the else part, we could have done:
            #   secondary_function = f.tonal_function.create_adapted_function(secondary_tonality, secondary_tonality)
            # but to be consistent within the logic, we go for the reflection_tests constructiobn
            # of the secondary function
            # as embodied in tFlip._build_secondary_flip_function()

            new_chord_tones = [secondary_function[t[0]] for t in chord.tones]
            chords = ChordClassifier.classify_all_roots(
                new_chord_tones, secondary_tonality)

            if chords is not None and len(chords) > 0:
                new_chord = chords[0]
            else:
                raise Exception(
                    'Cannot remap/classify chord {0} based on chord.'.format(
                        ', '.join(str(t) for t in new_chord_tones)))

            secondary_chord_template = SecondaryChordTemplate(
                new_chord.chord_template,
                chord.chord_template.secondary_scale_degree,
                secondary_tonality.modality.modality_type)
            secondary_chord = SecondaryChord(secondary_chord_template,
                                             chord_tonality)
            return secondary_chord
    def test_check_chromatics_on_pentatonic(self):
        t_domain = Tonality.create(ModalityType.MajorPentatonic,
                                   DiatonicTone('E'))
        # E F# G# B C# E
        r = PitchRange.create('E:1', 'E:7')

        f = DiatonicPitchReflectionFunction(
            t_domain, DiatonicPitch(4, DiatonicToneCache.get_tone('G#')), r,
            FlipType.CenterTone)
        TestFlipOnTonality.print_map('test_check_chromatics_on_pentatonic', f)

        t = f.tonal_function
        assert 'G#' == t['G#'].diatonic_symbol
        assert 'F#' == t['B'].diatonic_symbol
        assert 'E' == t['C#'].diatonic_symbol
        assert 'B' == t['F#'].diatonic_symbol
        assert 'C#' == t['E'].diatonic_symbol

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

        assert 'E#:5' == str(f['C:4'])
        assert 'D#:5' == str(f['D:4'])
        assert 'B#:4' == str(f['F:4'])
        assert 'G##:4' == str(
            f['G:4'])  # Note this and next are not symmetrical!
        assert 'G:4' == str(f['A#:4'])
        assert 'F##:4' == str(f['A:4'])

        assert 'E##:5' == str(f['Cb:4'])
        assert 'D##:5' == str(f['Db:4'])
        assert 'C##:5' == str(f['Eb:4'])
        assert 'B##:4' == str(f['Fb:4'])
        assert 'G###:4' == str(f['Gb:4'])
        assert 'F###:4' == str(
            f['Ab:4']
        )  # Very interesting case!!! closest is G#, but need F# to get to G#
        assert 'F##:4' == str(f['Bb:4'])

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

        t_domain = Tonality.create(ModalityType.WholeTone, DiatonicTone('C'))
        r = PitchRange.create('E:1', 'E:7')

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

        TestFlipOnTonality.print_map('test_find_pitch', f)

        for t in t_domain.annotation:
            p = DiatonicPitch(1, t)
            closest_pitch, closest_distance = f._find_closest_pitch(p)
            print('pitch {0}  closest = ({1}, {2})'.format(
                p, closest_pitch, closest_distance))

        p = DiatonicPitch.parse("A:3")
        closest_pitch, closest_distance = f._find_closest_pitch(p)
        print('pitch {0}  closest = ({1}, {2})'.format(p, closest_pitch,
                                                       closest_distance))

        p = DiatonicPitch.parse("Ab:3")
        closest_pitch, closest_distance = f._find_closest_pitch(p)
        print('pitch {0}  closest = ({1}, {2})'.format(p, closest_pitch,
                                                       closest_distance))

        p = DiatonicPitch.parse("B:3")
        closest_pitch, closest_distance = f._find_closest_pitch(p)
        print('pitch {0}  closest = ({1}, {2})'.format(p, closest_pitch,
                                                       closest_distance))

        p = DiatonicPitch.parse("Cb:3")
        closest_distance = f._find_closest_pitch(p)
        print('pitch {0}  closest = ({1}, {2})'.format(p, closest_pitch,
                                                       closest_distance))

        p = DiatonicPitch.parse("C#:3")
        closest_pitch, closest_distance = f._find_closest_pitch(p)
        print('pitch {0}  closest = ({1}, {2})'.format(p, closest_pitch,
                                                       closest_distance))
    def test_check_chromatics_on_c(self):
        t_domain = Tonality.create(ModalityType.Major, DiatonicTone('C'))
        r = PitchRange.create('E:1', 'E:7')

        f = DiatonicPitchReflectionFunction(
            t_domain, DiatonicPitch(4, DiatonicToneCache.get_tone('G')), r,
            FlipType.CenterTone)
        TestFlipOnTonality.print_map('test_check_chromatics_on_c', f)

        pitch = f['C#:4']
        print('Map {0} --> {1}'.format('C#:4', pitch))
        # assert 'Db:5' == f['C#:4']
        pitch = f['D#:4']
        print('Map {0} --> {1}'.format('D#:4', pitch))
        pitch = f['E#:4']
        print('Map {0} --> {1}'.format('E#:4', pitch))
        pitch = f['F#:4']
        print('Map {0} --> {1}'.format('F#:4', pitch))
        pitch = f['G#:4']
        print('Map {0} --> {1}'.format('G#:4', pitch))
        pitch = f['A#:4']
        print('Map {0} --> {1}'.format('A#:4', pitch))
        pitch = f['B#:4']
        print('Map {0} --> {1}'.format('B#:4', pitch))

        pitch = f['Cb:4']
        print('Map {0} --> {1}'.format('Cb:4', pitch))
        pitch = f['Db:4']
        print('Map {0} --> {1}'.format('Db:4', pitch))
        pitch = f['Eb:4']
        print('Map {0} --> {1}'.format('Eb:4', pitch))
        pitch = f['Fb:4']
        print('Map {0} --> {1}'.format('Fb:4', pitch))
        pitch = f['Gb:4']
        print('Map {0} --> {1}'.format('Gb:4', pitch))
        pitch = f['Ab:4']
        print('Map {0} --> {1}'.format('Ab:4', pitch))
        pitch = f['Bb:4']
        print('Map {0} --> {1}'.format('Bb:4', pitch))