def __init__(self, principal_chord_template, secondary_scale_degree, secondary_modality): """ Constructor. Args: principal_chord_template: ChordTemplate for the numerator. secondary_scale_degree: (int) which scale degree 1 --> 6. secondary_modality: Modality for the denominator if specified (None if not specified). """ ChordTemplate.__init__(self) self.__principal_chord_template = principal_chord_template self.__secondary_scale_degree = secondary_scale_degree self.__secondary_modality = secondary_modality
def create_track(chords, tonality): hc_track = HarmonicContextTrack() for c in chords: chord_t = ChordTemplate.generic_chord_template_parse(c[0]) chord = chord_t.create_chord(tonality) duration = Duration(c[1]) if isinstance(c[1], int) else Duration(c[1][0], c[1][1]) hc_track.append(HarmonicContext(tonality, chord, duration)) return hc_track
def __init__(self, diatonic_basis, scale_degree, chord_type, tension_intervals, inversion, inversion_interval=None): """ Constructor Args: diatonic_basis: DiatonicTone used as root of chord, e.g. C major chord, the C part scale_degree: int version of roman numeral chord_type: The chord type ala TertianChordType tension_intervals: list of Interval's comprising the tensions inversion: int for which of the chord tones (ordinal) serves as root [origin 1] inversion_interval: if specified, indicates which interval should be the base. (both this in interval cannot be non-null.) """ ChordTemplate.__init__(self) self.__diatonic_basis = diatonic_basis # DiatonicTone self.__scale_degree = scale_degree self.__chord_type = chord_type self.__tension_intervals = tension_intervals # list of [number, augmentation] representing intervals self.__inversion = inversion # which tone of n is the bass self.__inversion_interval = inversion_interval self.__base_intervals = [] if chord_type: self.__base_intervals.extend(TertianChordTemplate.TERTIAN_CHORD_TYPE_MAP[self.chord_type.value]) # Remove duplicate tensions seen = set() seen_add = seen.add deduped_tension_intervals = [tension for tension in self.tension_intervals if not (tension.semitones() in seen or seen_add(tension.semitones()))] self.__tension_intervals = deduped_tension_intervals # Inversion check - only if chord type was given, not for cases like II if self.chord_type and (self.inversion is not None) and \ self.inversion > len(self.base_intervals) + len(self.tension_intervals): raise Exception('Illegal inversion {0} for {1}'.format(self.inversion, self.__str__())) if self.inversion_interval is not None and \ self.inversion_interval not in self.base_intervals and \ self.inversion_interval not in self.tension_intervals: raise Exception('Illegal inversion_interval {0}'.format(self.inversion_interval))
def __init__(self, diatonic_basis, scale_degree, chord_type, specified_seconds, inversion): """ Constructor Args: diatonic_basis: DiatonicTone used as root of chord, e.g. C major chord, the C part scale_degree: int version of roman numeral chord_type: The chord type ala SecundalChordType specified_seconds: list of Interval's secondary notes inversion: int for which of the chord tones (ordinal) serves as root [origin 1] """ ChordTemplate.__init__(self) self.__diatonic_basis = diatonic_basis # DiatonicTone self.__scale_degree = scale_degree self.__chord_type = chord_type self.__inversion = inversion # which tone of n is the bass self.__base_intervals = list() if chord_type: self.__base_intervals.extend( SecundalChordTemplate.SECUNDAL_CHORD_TYPE_MAP[ chord_type.value]) self.__specified_seconds = specified_seconds if specified_seconds: intervals = list() intervals.append(Interval(1, IntervalType.Perfect)) for ltr in specified_seconds: intervals.append( Interval( 2, IntervalType.Major if ltr == 'M' else IntervalType.Minor)) self.__base_intervals.extend(intervals) # Inversion check - only if chord type was given, not for cases like II if self.chord_type and self.inversion > len(self.base_intervals): raise Exception('Illegal inversion {0} for {1}'.format( self.inversion, self.__str__()))
def __init__(self, diatonic_basis, scale_degree, chord_type, specified_fourths, inversion): """ Constructor Args: diatonic_basis: DiatonicTone used as root of chord, e.g. C major chord, the C part scale_degree: int version of roman numeral chord_type: The chord type ala SecundalChordType specified_fourths: list of incremental fourth Interval's comprising the chord, e.g. [p, P, P] usually used in lieu of, or addition to chord_type chord_type inversion: int for which of the chord tones (ordinal) serves as root [origin 1] """ ChordTemplate.__init__(self) self.__diatonic_basis = diatonic_basis # DiatonicTone self.__scale_degree = scale_degree self.__chord_type = chord_type self.__inversion = inversion # which tone of n is the bass self.__base_intervals = [] if chord_type: self.__base_intervals.extend( QuartalChordTemplate.QUARTAL_CHORD_TYPE_MAP[chord_type.value]) self.__specified_fourths = specified_fourths if specified_fourths: intervals = list() intervals.append(Interval(1, IntervalType.Perfect)) for ltr in specified_fourths: intervals.append( Interval( 4, IntervalType.Perfect if ltr == 'P' or ltr == 'p' else IntervalType.Augmented)) self.__base_intervals.extend(intervals) # Inversion check - only if chord type was given, not for cases like II if self.chord_type and self.inversion > len(self.base_intervals): raise Exception('Illegal inversion {0} for {1}'.format( self.inversion, self.__str__()))
def __init__(self): """ Constructor. """ self.tie_list = list() self.__line = Line() self.current_level = Level(self.__line, LineConstructor.DEFAULT_LINE_DURATION) self.level_stack = list() self.current_tonality = LineConstructor.DEFAULT_TONALITY self.harmonic_tag_list = list() self.current_harmonic_tag = None # Set up a default harmonic tag. In cases where a tag is immediately specified, this is discarded self.construct_harmonic_tag(LineConstructor.DEFAULT_TONALITY, ChordTemplate.generic_chord_template_parse('ti'))
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 Exception( 'Unable to parse chord string to completion: {0}'.format( chord_string)) m = SecondaryChordTemplate.SECONDARY_CHORD_PATTERN.match(chord_string) if not m: raise SecondaryChordException( 'Unable to parse chord string to completion: {0}'.format( chord_string)) principal_chord_text = m.group( SecondaryChordTemplate.INITIAL_CHORD_TEXT_NAME) secondary_scale_degree_text = m.group( SecondaryChordTemplate.SCALE_DEGREE_NAME) secondary_scale_degree = ChordTemplate.SCALE_DEGREE_MAP[ secondary_scale_degree_text] secondary_modality_text = m.group( SecondaryChordTemplate.DIATONIC_MODALITIES_NAME) secondary_modality = ModalityType( secondary_modality_text) if secondary_modality_text else None principal_chord_template = ChordTemplate.generic_chord_template_parse( principal_chord_text) if not principal_chord_template: raise SecondaryChordException( 'Unable to parse principle chord in secondary template: {0}'. format(principal_chord_text)) logging.info('{0}, {1}, {2}, {3}'.format( principal_chord_text, str(principal_chord_template), secondary_scale_degree, str(secondary_modality) if secondary_modality else '')) return SecondaryChordTemplate(principal_chord_template, secondary_scale_degree, secondary_modality)
def construct_chord_template(self, tone, chord_type_str, chord_modality): if tone: chord_template_str = 't' + tone.diatonic_symbol + (chord_modality if chord_modality else '') else: chord_template_str = 't' + chord_type_str + (chord_modality if chord_modality else '') return ChordTemplate.generic_chord_template_parse(chord_template_str)
def interpret(self, hc_list, duration=Duration(1, 4)): """ Give a list of HarmonicContext's, interpret the HCExpression into a HarmonicContext. :param hc_list: :param duration: :return: HarmonicContext """ if isinstance(self.key, str): key_tone = DiatonicToneCache.get_tone(self.key) else: if self.key not in range(0, len(hc_list)): raise Exception('@{0} not in range.'.format(self.key)) key_tone = hc_list[self.key].tonality.diatonic_tone if self.key_modifier is not None: key_tone = self.key_modifier.get_end_tone(key_tone) if self.modality_index: if isinstance(self.modality_index, str): modal_index = int(self.modality_index) else: if self.modality_index not in range(0, len(hc_list)): raise Exception('@{0} not in range.'.format( self.modality_index)) modal_index = hc_list[self.modality_index].tonality.modal_index else: modal_index = 0 if isinstance(self.key_modality, str): modality_type = ModalityType(self.key_modality) else: if self.key_modality not in range(0, len(hc_list)): raise Exception('@{0} not in range.'.format(self.key_modality)) modality_type = hc_list[self.key_modality].tonality.modality_type # Note: chord_numeral is origin 1 if isinstance(self.chord_numeral, str): chord_numeral = ChordTemplate.SCALE_DEGREE_MAP[self.chord_numeral] else: if self.chord_numeral not in range(0, len(hc_list)): raise Exception('@{0} not in range.'.format( self.chord_numeral)) chord_numeral = hc_list[ self.chord_numeral].chord.chord_template.scale_degree if self.chord_type: if isinstance(self.chord_type, str): chord_type = TertianChordType.to_type(self.chord_type) else: if self.chord_type not in range(0, len(hc_list)): raise Exception('@{0} not in range.'.format( self.chord_type)) chord_type = hc_list[self.chord_type].chord.chord_type else: chord_type = None tonality = Tonality.create(modality_type, key_tone, modal_index) chord_template = ChordTemplate.generic_chord_template_parse( ChordTemplate.SCALE_DEGREE_REVERSE_MAP[chord_numeral] + (str(chord_type) if chord_type else '')) chord = chord_template.create_chord(tonality) hc = HarmonicContext(tonality, chord, duration) return hc