class BluesModality(Modality): """ This class represents major and minor blues modalities - scales with 6 tones over the 12 tone chromatic partition. """ BLUES_MODALITIES = [ ModalityType.MajorBlues, ModalityType.MinorBlues, ] MODALITY_DEFINITION_MAP = { ModalityType.MajorBlues: ModalitySpec( ModalityType.MajorBlues, ['P:1', 'M:2', 'A:1', 'm:2', 'm:3', 'M:2', 'm:3']), # Ascending ModalityType.MinorBlues: ModalitySpec( ModalityType.MinorBlues, ['P:1', 'm:3', 'M:2', 'A:1', 'm:2', 'm:3', 'M:2']), # Ascending } @staticmethod def create(modality_type, modal_index=0): if modality_type not in BluesModality.BLUES_MODALITIES: raise Exception('Type parameter is not blues.') if modality_type not in BluesModality.MODALITY_DEFINITION_MAP: raise Exception( 'Illegal diatonic modality value: {0} - Check Modality_definition_map' .format(str(modality_type))) return Modality(BluesModality.MODALITY_DEFINITION_MAP[modality_type], modal_index) @staticmethod def blues_modality_types_as_string_array(): answer = [str(t) for t in BluesModality.BLUES_MODALITIES] return answer
def test_build_user_defined_tonality(self): modality_type = ModalityType('my_modality') incremental_interval_strs = [ 'P:1', 'm:2', 'M:3', 'm:2', 'm:2', 'M:2', 'A:2' ] modality_spec = ModalitySpec(modality_type, incremental_interval_strs) modality = Modality(modality_spec) tonality = Tonality(modality, 'A') assert 0 == tonality.modal_index assert 'A' == tonality.diatonic_tone.diatonic_symbol assert ['A', 'Bb', 'D', 'Eb', 'Fb', 'Gb', 'A'] == [t.diatonic_symbol for t in tonality.annotation]
class OctatonicModality(Modality): """ Defines the octatonic tonality. The scale is uniform tone-alternating half and whole steps. """ OCTATONIC_MODALITIES = [ ModalityType.HWOctatonic, ModalityType.WHOctatonic, ] MODALITY_DEFINITION_MAP = { ModalityType.HWOctatonic: ModalitySpec( ModalityType.HWOctatonic, ['P:1', 'm:2', 'M:2', 'm:2', 'M:2', 'A:1', 'M:2', 'm:2', 'M:2']), ModalityType.WHOctatonic: ModalitySpec( ModalityType.WHOctatonic, ['P:1', 'M:2', 'm:2', 'M:2', 'A:1', 'M:2', 'm:2', 'M:2', 'm:2']), } @staticmethod def create(modality_type, modal_index=0): if modality_type not in OctatonicModality.OCTATONIC_MODALITIES: raise Exception('Type parameter is not diatonic.') if modality_type not in OctatonicModality.MODALITY_DEFINITION_MAP: raise Exception( 'Illegal diatonic modality value: {0} - Check Modality_definition_map' .format(str(modality_type))) return Modality( OctatonicModality.MODALITY_DEFINITION_MAP[modality_type], modal_index) @staticmethod def octatonic_modality_types_as_string_array(): answer = [str(t) for t in OctatonicModality.OCTATONIC_MODALITIES] return answer
class WholeToneModality(Modality): """ This class represents whole tone modalities - scales with 6 tones over the 12 tone chromatic scale. All tones are 2 semitones apart. """ WHOLE_TONE_SPEC = ModalitySpec( ModalityType.WholeTone, ['P:1', 'M:2', 'M:2', 'M:2', 'M:2', 'M:2', 'd:3']) @staticmethod def create(modality_type, modal_index=0): if modality_type != ModalityType.WholeTone: raise Exception('Type parameter is not WholeTone.') return Modality(WholeToneModality.WHOLE_TONE_SPEC, modal_index)
def test_user_defined_modality(self): print('----- test_user_defined_modality -----') modality_type = ModalityType('MyModality') incremental_interval_strs = [ 'P:1', 'm:2', 'M:3', 'm:2', 'm:2', 'M:2', 'A:2' ] modality_spec = ModalitySpec(modality_type, incremental_interval_strs) ModalityFactory.register_modality(modality_type, modality_spec) music_text_line = LineGrammarExecutor() s = '{<C-!MyModality: I> F#:4 A D}' line, hct = music_text_line.parse(s) print(line) print('-----')
def test_user_defined_modality(self): modality_type = ModalityType('my_modality') incremental_interval_strs = [ 'P:1', 'm:2', 'M:3', 'm:2', 'm:2', 'M:2', 'A:2' ] modality_spec = ModalitySpec(modality_type, incremental_interval_strs) modality = Modality(modality_spec) assert modality.modality_type == modality_type assert modality.get_number_of_tones() == 6 intervals = modality.incremental_intervals assert len(intervals) == 7 assert str(intervals[0]) == 'P:1' assert str(intervals[1]) == 'm:2' assert str(intervals[2]) == 'M:3' assert str(intervals[3]) == 'm:2' assert str(intervals[4]) == 'm:2' assert str(intervals[5]) == 'M:2' assert str(intervals[6]) == 'A:2'
def test_book_examples(self): modality = ModalityFactory.create_modality(ModalityType.Major) assert modality is not None modality = ModalityFactory.create_modality( ModalityType.MajorPentatonic, 1) assert modality is not None my_modality = 'my_modality' modality_type = ModalityType(my_modality) incremental_interval_strs = [ 'P:1', 'm:2', 'M:3', 'm:2', 'm:2', 'M:2', 'A:2' ] modality_spec = ModalitySpec(modality_type, incremental_interval_strs) ModalityFactory.register_modality(modality_type, modality_spec) modality = ModalityFactory.create_modality(ModalityType(my_modality)) assert modality is not None tones = modality.get_tonal_scale(DiatonicFoundation.get_tone('Eb')) print('[{0}]'.format(','.join( str(tone.diatonic_symbol) for tone in tones)))
class DiatonicModality(Modality): """ This class represents diatonic modalities - scales with 7 tones over the 12 tone chromatic scale. These include Major, Minor, and Modal scales. """ DIATONIC_MODALITIES = [ ModalityType.Major, ModalityType.NaturalMinor, ModalityType.MelodicMinor, ModalityType.HarmonicMinor, ModalityType.HarmonicMajor, ModalityType.Ionian, ModalityType.Dorian, ModalityType.Phrygian, ModalityType.Lydian, ModalityType.Mixolydian, ModalityType.Aeolian, ModalityType.Locrian, ] MODALITY_DEFINITION_MAP = { ModalityType.Major: ModalitySpec(ModalityType.Major, ['P:1', 'M:2', 'M:2', 'm:2', 'M:2', 'M:2', 'M:2', 'm:2']), ModalityType.NaturalMinor: ModalitySpec(ModalityType.NaturalMinor, ['P:1', 'M:2', 'm:2', 'M:2', 'M:2', 'm:2', 'M:2', 'M:2']), ModalityType.MelodicMinor: ModalitySpec(ModalityType.MelodicMinor, ['P:1', 'M:2', 'm:2', 'M:2', 'M:2', 'M:2', 'M:2', 'm:2']), ModalityType.HarmonicMinor: ModalitySpec(ModalityType.HarmonicMinor, ['P:1', 'M:2', 'm:2', 'M:2', 'M:2', 'm:2', 'A:2', 'm:2']), ModalityType.HarmonicMajor: ModalitySpec(ModalityType.HarmonicMajor, ['P:1', 'M:2', 'M:2', 'm:2', 'M:2', 'm:2', 'A:2', 'm:2']), ModalityType.Ionian: ModalitySpec(ModalityType.Ionian, ['P:1', 'M:2', 'M:2', 'm:2', 'M:2', 'M:2', 'M:2', 'm:2']), ModalityType.Dorian: ModalitySpec(ModalityType.Dorian, ['P:1', 'M:2', 'm:2', 'M:2', 'M:2', 'M:2', 'm:2', 'M:2']), ModalityType.Phrygian: ModalitySpec(ModalityType.Phrygian, ['P:1', 'm:2', 'M:2', 'M:2', 'M:2', 'm:2', 'M:2', 'M:2']), ModalityType.Lydian: ModalitySpec(ModalityType.Lydian, ['P:1', 'M:2', 'M:2', 'M:2', 'm:2', 'M:2', 'M:2', 'm:2']), ModalityType.Mixolydian: ModalitySpec(ModalityType.Mixolydian, ['P:1', 'M:2', 'M:2', 'm:2', 'M:2', 'M:2', 'm:2', 'M:2']), ModalityType.Aeolian: ModalitySpec(ModalityType.Aeolian, ['P:1', 'M:2', 'm:2', 'M:2', 'M:2', 'm:2', 'M:2', 'M:2']), ModalityType.Locrian: ModalitySpec(ModalityType.Locrian, ['P:1', 'm:2', 'M:2', 'M:2', 'm:2', 'M:2', 'M:2', 'M:2']), } @staticmethod def create(modality_type, modal_index=0): if modality_type not in DiatonicModality.DIATONIC_MODALITIES: raise Exception('Type parameter is not diatonic.') if modality_type not in DiatonicModality.MODALITY_DEFINITION_MAP: raise Exception( 'Illegal diatonic modality value: {0} - Check Modality_definition_map' .format(str(modality_type))) return Modality( DiatonicModality.MODALITY_DEFINITION_MAP[modality_type], modal_index) @staticmethod def diatonic_modality_types_as_string_array(): answer = [t.name for t in DiatonicModality.DIATONIC_MODALITIES] return answer @staticmethod def find_modality(tones): answers = list() if len(tones) == 7: for t in [ ModalityType.Major, ModalityType.NaturalMinor, ModalityType.MelodicMinor, ModalityType.HarmonicMinor, ModalityType.HarmonicMajor ]: modality_spec = DiatonicModality.MODALITY_DEFINITION_MAP[t] p1 = Interval.parse('P:1') for scale_start in range(0, 7): intervals = [p1] + [ Interval.calculate_tone_interval( tones[(scale_start + i) % 7], tones[(scale_start + i + 1) % 7]) for i in range(0, len(tones)) ] if intervals == modality_spec.incremental_intervals: answers.append( DiatonicModality.create(t, (-scale_start) % len(tones))) return answers
class PentatonicModality(Modality): """ This class represents 5 pentatonic modalities - scales with 5 tones over the 12 tone chromatic partition. With circular succession, each is a rotation of the prior. """ PENTATONIC_MODALITIES = [ ModalityType.MajorPentatonic, ModalityType.EgyptianPentatonic, ModalityType.MinorBluesPentatonic, ModalityType.MajorBluesPentatonic, ModalityType.MinorPentatonic, ] MODALITY_DEFINITION_MAP = { ModalityType.MajorPentatonic: ModalitySpec(ModalityType.MajorPentatonic, ['P:1', 'M:2', 'M:2', 'm:3', 'M:2', 'm:3']), ModalityType.EgyptianPentatonic: ModalitySpec(ModalityType.EgyptianPentatonic, ['P:1', 'M:2', 'm:3', 'M:2', 'm:3', 'M:2']), ModalityType.MinorBluesPentatonic: ModalitySpec(ModalityType.MinorBluesPentatonic, ['P:1', 'm:3', 'M:2', 'm:3', 'M:2', 'M:2']), ModalityType.MajorBluesPentatonic: ModalitySpec(ModalityType.MajorBluesPentatonic, ['P:1', 'M:2', 'm:3', 'M:2', 'M:2', 'm:3']), ModalityType.MinorPentatonic: ModalitySpec(ModalityType.MinorPentatonic, ['P:1', 'm:3', 'M:2', 'M:2', 'm:3', 'M:2']), } @staticmethod def create(modality_type, modal_index=0): if modality_type not in PentatonicModality.PENTATONIC_MODALITIES: raise Exception('Type parameter is not diatonic.') if modality_type not in PentatonicModality.MODALITY_DEFINITION_MAP: raise Exception( 'Illegal diatonic modality value: {0} - Check Modality_definition_map' .format(str(modality_type))) return Modality( PentatonicModality.MODALITY_DEFINITION_MAP[modality_type], modal_index) @staticmethod def pentatonic_modality_types_as_string_array(): answer = [str(t) for t in PentatonicModality.PENTATONIC_MODALITIES] return answer @staticmethod def find_modality(tones): answers = list() if len(tones) == 5: for t in [ModalityType.MajorPentatonic]: modality_spec = PentatonicModality.MODALITY_DEFINITION_MAP[t] p1 = Interval.parse('P:1') for scale_start in range(0, 5): intervals = [p1] + [ Interval.calculate_tone_interval( tones[(scale_start + i) % 5], tones[(scale_start + i + 1) % 5]) for i in range(0, len(tones)) ] if intervals == modality_spec.incremental_intervals: answers.append( PentatonicModality.create(t, (-scale_start) % len(tones))) return answers