def __init__(self, bassNote = 'C3', notationString = None, fbScale = None, fbRules = rules.Rules(), numParts = 4, maxPitch = 'B5', listOfPitches = None): ''' A Segment corresponds to a 1:1 realization of a bassNote and notationString of a :class:`~music21.figuredBass.realizer.FiguredBassLine`. It is created by passing six arguments: a :class:`~music21.figuredBass.realizerScale.FiguredBassScale`, a bassNote, a notationString, a :class:`~music21.figuredBass.rules.Rules` object, a number of parts and a maximum pitch. Realizations of a Segment are represented as possibility tuples (see :mod:`~music21.figuredBass.possibility` for more details). Methods in Python's `itertools <http://docs.python.org/library/itertools.html>`_ module are used extensively. Methods which generate possibilities or possibility progressions return iterators, which are turned into lists in the examples for display purposes only. if fbScale is None, a realizerScale.FiguredBassScale() is created if fbRules is None, a rules.Rules() instance is created. Each Segment gets its own deepcopy of the one given. Here, a Segment is created using the default values: a FiguredBassScale in C, a bassNote of C3, an empty notationString, and a default Rules object. >>> from music21.figuredBass import segment >>> s1 = segment.Segment() >>> s1.bassNote <music21.note.Note C> >>> s1.numParts 4 >>> s1.pitchNamesInChord ['C', 'E', 'G'] >>> [str(p) for p in s1.allPitchesAboveBass] ['C3', 'E3', 'G3', 'C4', 'E4', 'G4', 'C5', 'E5', 'G5'] >>> s1.segmentChord <music21.chord.Chord C3 E3 G3 C4 E4 G4 C5 E5 G5> ''' if common.isStr(bassNote): bassNote = note.Note(bassNote) if common.isStr(maxPitch): maxPitch = pitch.Pitch(maxPitch) if fbScale is None: global _defaultRealizerScale if _defaultRealizerScale is None: _defaultRealizerScale = realizerScale.FiguredBassScale() fbScale = _defaultRealizerScale # save making it if fbRules is None: self.fbRules = rules.Rules() else: self.fbRules = copy.deepcopy(fbRules) self.bassNote = bassNote self.numParts = numParts self._maxPitch = maxPitch if notationString == None and listOfPitches != None: #must be a chord symbol or roman numeral.... self.pitchNamesInChord = listOfPitches #!---------- Added to accommodate harmony.ChordSymbol and roman.RomanNumeral objects --------! else: self.pitchNamesInChord = fbScale.getPitchNames(self.bassNote.pitch, notationString) self.allPitchesAboveBass = getPitches(self.pitchNamesInChord, self.bassNote.pitch, self._maxPitch) self.segmentChord = chord.Chord(self.allPitchesAboveBass, quarterLength = bassNote.quarterLength) self._environRules = environment.Environment(_MOD)
def __init__(self, inKey=None, inTime=None): if inKey is None: inKey = key.Key('C') if inTime is None: inTime = meter.TimeSignature('4/4') self.inKey = inKey self.inTime = inTime self._paddingLeft = 0.0 self._overlaidParts = stream.Part() self._fbScale = realizerScale.FiguredBassScale(inKey.pitchFromDegree(1), inKey.mode) self._fbList = []
def tonalHarmonyCalculator(): def clearOutput(): return def showPitches(): return def figBass(): return def showRN(): return # Lookup dictionary that maps button to function to call func_dict = { 'lookup': lookupWrapper, 'applyOp': applyOps, 'findOp': generalizedOpsName, 'findRN': showRN, 'pitches': showPitches, 'figBass': figBass, 'CLEAR': clearOutput } # Layout the design of the GUI layout = [ [ sg.Text('Tonal Harmony Calculator', auto_size_text=True, font='Helvetica 24', background_color='#F68E01') ], [ sg.Text( 'Progression lookup / Apply operator / Operators / Roman numerals / Pitches', auto_size_text=True, font='Helvetica 18', background_color='#F68E01'), sg.Button('HELP') ], [ sg.Text('tonal model', size=(12, 1), auto_size_text=True, font='Helvetica 18', background_color='#F68E01'), sg.Input(size=(50, 1)), sg.FileBrowse(), sg.Submit() ], [ sg.Text('operator', auto_size_text=True, font='Helvetica 18', background_color='#F68E01'), sg.InputText(key='ops', size=(16, 1)), sg.Text('initial chord', auto_size_text=True, font='Helvetica 18', background_color='#F68E01'), sg.InputText(key='ch1', size=(16, 1)), sg.Text('final chord', auto_size_text=True, font='Helvetica 18', background_color='#F68E01'), sg.InputText(key='ch2', size=(16, 1)) ], [ sg.Button('lookup'), sg.Button('applyOp'), sg.Button('findOp'), sg.Button('findRN'), sg.Button('pitches'), sg.Button('figBass'), sg.Button('CLEAR'), sg.Quit() ], [sg.Output(size=(76, 20), key='_output_')], [ sg.Text('Marco Buongiorno Nardelli - www.musicntwrk.com (2020)', auto_size_text=True, font='Helvetica 12', background_color='#3364FF') ] ] # Show the Window to the user sg.SetOptions(background_color='#3364FF', element_background_color='#F68E01', text_element_background_color='#F68E01', input_elements_background_color='#F68E01', font='Helvetica 18') window = sg.Window('Unified Theory of Tonal Harmony', layout, keep_on_top=False) # Event loop. Read buttons, make callbacks while True: # Read the Window event, value = window.Read() if event in ('HELP'): print('Usage of the "harmony calculator" app') print('') print( 'tonal model - is the table that stores the operators that connect every chord of a chosen tonal model' ) print('(in roman numeral form).') print( 'The chords that are included in the model can be chosen in tonalHarmonyModels that produces the final' ) print('table. it is read by clicking on "Submit".') print('A minimal model can be downloaded from') print( 'https://github.com/marcobn/musicntwrk/tree/master/musicntwrk-2.0/examples' ) print('') print( 'The next set of enties depend on the action that is requested by the user. They can be filled with:' ) print('') print('operator - voice leading operator as O(i,j,k,...) ') print('') print( 'initial chord - chord in roman numeral or pcs as list of integers' ) print('') print( 'final chord - chord in roman numeral or pcs as list of integers or key as letter (A,a,C#, Bb etc.)' ) print('') print('Actions:') print('') print( 'lookup - given an operator produces the list of all the chords that are connected by it' ) print('') print( 'applyOp - given an operator and a pcs as list of integers, produces the resulting pcs' ) print('') print( 'findOp - given an initial pcs and a final pcs, finds the operator that connects them' ) print('') print( 'findRN - given a pcs in "initial chord" and a key in "final chord" uses music21 to produce the corresponding roman numeral' ) print('') print( 'pitches - given a roman numeral in "initial chord" and a key in "final chord" uses music21 to produce the corresponding pcs ' ) print('') print( 'FigBass - given a pitch and a qualifier (major, minor) in "operator", the bass note (letter) in "initial chord" and the figure in "final chord" produces the pithes of the figured bass' ) if event in ('Submit'): try: f = open(value[0], 'rb') head = pickle.load(f) table = pickle.load(f) f.close() except: print('file not found') if event in ('Quit', None): break # Lookup event in function dictionary try: func_to_call = func_dict[ event] # look for a match in the function dictionary if func_to_call.__name__ == 'lookupWrapper': func_to_call(table, head, ops=value['ops'], cstart=value['ch1'], cend=value['ch2']) elif func_to_call.__name__ == 'applyOps': _ = func_to_call(value['ops'], value['ch1']) elif func_to_call.__name__ == 'generalizedOpsName': a = [] for num in re.findall("[-\d]+", value['ch1']): a.append(int(num)) a = np.asarray(a) b = [] for num in re.findall("[-\d]+", value['ch2']): b.append(int(num)) b = np.asarray(b) _, op = generalizedOpsName(a, b, TET=12, distance='euclidean') print(op) elif func_to_call.__name__ == 'showPitches': chd = m21.roman.RomanNumeral(value['ch1'], value['ch2']) pcs = chd.pitchClasses print(pcs) elif func_to_call.__name__ == 'figBass': a = value['ops'] fbScale = realizerScale.FiguredBassScale( value['ops'].split()[0], value['ops'].split()[1]) pc = [] for p in fbScale.getPitches(value['ch1'], value['ch2']): pc.append(m21.pitch.Pitch(p).pitchClass) print(value['ch1'], value['ch2'], Remove(pc)) elif func_to_call.__name__ == 'showRN': a = [] for num in value['ch1'].replace('[', '').replace(']', '').split(','): if num.isdecimal(): a.append(int(num)) else: a.append(num) n = m21.chord.Chord(a) rn = m21.roman.romanNumeralFromChord( n, m21.key.Key(str(value['ch2']))).figure print(rn) elif func_to_call.__name__ == 'clearOutput': window.FindElement('_output_').Update('') except Exception as e: print(e) pass window.Close() return
def __init__(self, bassNote: t.Union[str, note.Note] = 'C3', notationString: t.Optional[str] = None, fbScale: t.Optional[realizerScale.FiguredBassScale] = None, fbRules: t.Optional[rules.Rules] = None, numParts=4, maxPitch: t.Union[str, pitch.Pitch] = 'B5', listOfPitches=None): ''' A Segment corresponds to a 1:1 realization of a bassNote and notationString of a :class:`~music21.figuredBass.realizer.FiguredBassLine`. It is created by passing six arguments: a :class:`~music21.figuredBass.realizerScale.FiguredBassScale`, a bassNote, a notationString, a :class:`~music21.figuredBass.rules.Rules` object, a number of parts and a maximum pitch. Realizations of a Segment are represented as possibility tuples (see :mod:`~music21.figuredBass.possibility` for more details). Methods in Python's `itertools` module are used extensively. Methods which generate possibilities or possibility progressions return iterators, which are turned into lists in the examples for display purposes only. if fbScale is None, a realizerScale.FiguredBassScale() is created if fbRules is None, a rules.Rules() instance is created. Each Segment gets its own deepcopy of the one given. Here, a Segment is created using the default values: a FiguredBassScale in C, a bassNote of C3, an empty notationString, and a default Rules object. >>> from music21.figuredBass import segment >>> s1 = segment.Segment() >>> s1.bassNote <music21.note.Note C> >>> s1.numParts 4 >>> s1.pitchNamesInChord ['C', 'E', 'G'] >>> [str(p) for p in s1.allPitchesAboveBass] ['C3', 'E3', 'G3', 'C4', 'E4', 'G4', 'C5', 'E5', 'G5'] >>> s1.segmentChord <music21.chord.Chord C3 E3 G3 C4 E4 G4 C5 E5 G5> ''' if isinstance(bassNote, str): bassNote = note.Note(bassNote) if isinstance(maxPitch, str): maxPitch = pitch.Pitch(maxPitch) if fbScale is None: if _defaultRealizerScale['scale'] is None: _defaultRealizerScale[ 'scale'] = realizerScale.FiguredBassScale() fbScale = _defaultRealizerScale[ 'scale'] # save the time of making it assert fbScale is not None # tells mypy that we have it now if fbRules is None: self.fbRules = rules.Rules() else: self.fbRules = copy.deepcopy(fbRules) self._specialResolutionRuleChecking = None self._singlePossibilityRuleChecking = None self._consecutivePossibilityRuleChecking = None self.bassNote = bassNote self.numParts = numParts self._maxPitch = maxPitch if notationString is None and listOfPitches is not None: # must be a chord symbol or roman num. self.pitchNamesInChord = listOfPitches # ------ Added to accommodate harmony.ChordSymbol and roman.RomanNumeral objects ------ else: self.pitchNamesInChord = fbScale.getPitchNames( self.bassNote.pitch, notationString) self.allPitchesAboveBass = getPitches(self.pitchNamesInChord, self.bassNote.pitch, self._maxPitch) self.segmentChord = chord.Chord(self.allPitchesAboveBass, quarterLength=bassNote.quarterLength) self._environRules = environment.Environment(_MOD)