Theory Analyzer methods provide easy analysis tools for common music theory type queries regarding a Score (must have parts), such as finding the parallel fifths, locating the passing tones, finding dissonant harmonic intervals, etc. These analysis methods typically operate in the following way:
get voiceLeading objects from a score these methods break the score up into voiceLeading atoms, and return objects of that type. These objects are then useful because they provide easy access to the components within them, and those components (notes, chords, etc.) contain a direct pointer to the original object in the score.
You can then iterate through these objects and access the attributes directly. Here is an example of this that will analyze the root motion in a score:
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import theoryAnalyzer
>>> p = corpus.parse('leadsheet').flat.getElementsByClass('Harmony')
>>> p = harmony.realizeChordSymbolDurations(p)
>>> averageMotion = 0
>>> l = theoryAnalyzer.getLinearSegments(p,0,2, ['Harmony']) #gets a list of tuples, adjacent chord symbol objects in the score
>>> for x in l:
... averageMotion+= abs(x.rootInterval().intervalClass) #rootInterval() returns the interval between the roots of the first chordSymbol and second
>>> averageMotion=averageMotion/len(l)
>>> averageMotion #average intervalClass in this piece is about 4
4
get only interesting music theory voiceLeading objects from a score These methods return voiceLeading objects identified by certain methods. For example, they may return all the parallel fifths in the score as voiceLeadingQuartetObjects.
identify music theory objects in score These identify methods were the original purpose of theoryAnalyzer, to identify interesting music theory anomalies in a score, color them, and write specific text regarding them. However, if you find these methods more useful as ‘get’ methods (such as those above), merely run the identify method and access the score’s self.analysisData['dictKey']
special use case: remove passing tones/neighbor tones These methods provide a preliminary implementation for removing passing tones & neighbor tones from a score. As an example, the steps involved in these methods calls include:
break the score into verticalSlices
formsverticalSliceTriplets out of these vertical slices
break each verticalSliceTriplet into threeNoteLinearSegments
check to see if the threeNoteLinearSegment couldBePassingTone() or couldBeNeighborTone() (horizontal analysis)
check to see if the verticalSlice identified as a possible passingTone or neighborTone is dissonant
check to see if previous verticalSlice and next verticalSlice isdissonant
if all checks are true, the passingTone or neighborTone is removed from the score (because the whole point of parsing the score into voiceLeadingObjects was to maintain a direct pointer to the original object in the score.
the gap created by the deletion is filled in by extending the duration of the previous note
>>> from music21 import * >>> from music21.demos.theoryAnalysis import theoryAnalyzer >>> p = corpus.parse('bwv6.6').measures(0,20) >>> p.show()
>>> theoryAnalyzer.removePassingTones(p) >>> theoryAnalyzer.removeNeighborTones(p) >>> p.show()![]()
returns a list of VerticalSlice objects in by parsing the score. Note that it uses the combined rhythm of the parts to determine what vertical slices to take. Default is to return only objects of type Note, Chord, Harmony, and Rest.
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> n1 = note.Note('c5')
>>> n1.quarterLength = 4
>>> n2 = note.Note('f4')
>>> n2.quarterLength = 2
>>> n3 = note.Note('g4')
>>> n3.quarterLength = 2
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(n1)
>>> part1 = stream.Part()
>>> part1.append(n2)
>>> part1.append(n3)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.getVerticalSlices(sc)
[<music21.voiceLeading.VerticalSlice contentDict=defaultdict(<type 'list'>, {0: [<music21.note.Note C>], 1: [<music21.note.Note F>]}) , <music21.voiceLeading.VerticalSlice contentDict=defaultdict(<type 'list'>, {0: [<music21.note.Note C>], 1: [<music21.note.Note G>]}) ]
>>> len(theoryAnalyzer.getVerticalSlices(sc))
2
>>> sc4 = stream.Score()
>>> part4 = stream.Part()
>>> part4.append(chord.Chord(['A','B','C']))
>>> part4.append(chord.Chord(['A','B','C']))
>>> part4.append(chord.Chord(['A','B','C']))
>>> sc4.insert(part4)
>>> theoryAnalyzer.getVerticalSlices(sc4)
[<music21.voiceLeading.VerticalSlice contentDict=defaultdict(<type 'list'>, {0: [<music21.chord.Chord A B C>]}) , <music21.voiceLeading.VerticalSlice contentDict=defaultdict(<type 'list'>, {0: [<music21.chord.Chord A B C>]}) , <music21.voiceLeading.VerticalSlice contentDict=defaultdict(<type 'list'>, {0: [<music21.chord.Chord A B C>]}) ]
>>> sc3 = stream.Score()
>>> p1 = stream.Part()
>>> p1.append(harmony.ChordSymbol('C', quarterLength = 1))
>>> p1.append(harmony.ChordSymbol('D', quarterLength = 3))
>>> p1.append(harmony.ChordSymbol('E7', quarterLength = 4))
>>> sc3.append(p1)
>>> getVerticalSlices(sc3)
[<music21.voiceLeading.VerticalSlice contentDict=defaultdict(<type 'list'>, {0: [<music21.harmony.ChordSymbol C>]}) , <music21.voiceLeading.VerticalSlice contentDict=defaultdict(<type 'list'>, {0: [<music21.harmony.ChordSymbol D>]}) , <music21.voiceLeading.VerticalSlice contentDict=defaultdict(<type 'list'>, {0: [<music21.harmony.ChordSymbol E7>]}) ]
extracts and returns a list of the VoiceLeadingQuartet objects present between partNum1 and partNum2 in the score
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(note.Note('c4'))
>>> part0.append(note.Note('g4'))
>>> part0.append(note.Note('c5'))
>>> sc.insert(part0)
>>> part1 = stream.Part()
>>> part1.append(note.Note('d4'))
>>> part1.append(note.Note('e4'))
>>> part1.append(note.Note('f5'))
>>> sc.insert(part1)
>>> theoryAnalyzer.getVLQs(sc, 0, 1)
[<music21.voiceLeading.VoiceLeadingQuartet v1n1=<music21.note.Note C> , v1n2=<music21.note.Note G>, v2n1=<music21.note.Note D>, v2n2=<music21.note.Note E> , <music21.voiceLeading.VoiceLeadingQuartet v1n1=<music21.note.Note G> , v1n2=<music21.note.Note C>, v2n1=<music21.note.Note E>, v2n2=<music21.note.Note F> ]
>>> len(theoryAnalyzer.getVLQs(sc, 0, 1))
2
extracts and returns a list of the ThreeNoteLinearSegment objects present in partNum in the score (three note linear segments are made up of ONLY three notes)
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(note.Note('c4'))
>>> part0.append(note.Note('g4'))
>>> part0.append(note.Note('c5'))
>>> part0.append(note.Note('c6'))
>>> sc.insert(part0)
>>> theoryAnalyzer.getThreeNoteLinearSegments(sc, 0)
[<music21.voiceLeading.ThreeNoteLinearSegment n1=<music21.note.Note C> n2=<music21.note.Note G> n3=<music21.note.Note C> , <music21.voiceLeading.ThreeNoteLinearSegment n1=<music21.note.Note G> n2=<music21.note.Note C> n3=<music21.note.Note C> ]
>>> len(theoryAnalyzer.getThreeNoteLinearSegments(sc, 0))
2
>>> theoryAnalyzer.getThreeNoteLinearSegments(sc, 0)[1]
<music21.voiceLeading.ThreeNoteLinearSegment n1=<music21.note.Note G> n2=<music21.note.Note C> n3=<music21.note.Note C>
extracts and returns a list of all the linear segments in the piece at the partNum specified, the length of which specified by lengthLinearSegment: Currently Supported: ThreeNoteLinearSegment
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(note.Note('c4'))
>>> part0.append(note.Note('g4'))
>>> part0.append(note.Note('c5'))
>>> part0.append(note.Note('c6'))
>>> sc.insert(part0)
>>> len(theoryAnalyzer.getLinearSegments(sc, 0,3, ['Note']))
2
>>> theoryAnalyzer.getLinearSegments(sc, 0,3, ['Note'])
[<music21.voiceLeading.ThreeNoteLinearSegment n1=<music21.note.Note C> n2=<music21.note.Note G> n3=<music21.note.Note C> , <music21.voiceLeading.ThreeNoteLinearSegment n1=<music21.note.Note G> n2=<music21.note.Note C> n3=<music21.note.Note C> ]
>>> sc2 = stream.Score()
>>> part1 = stream.Part()
>>> part1.append(chord.Chord(['C','E','G']))
>>> part1.append(chord.Chord(['G','B','D']))
>>> part1.append(chord.Chord(['E','G','C']))
>>> part1.append(chord.Chord(['F','A','C']))
>>> sc2.insert(part1)
>>> theoryAnalyzer.getLinearSegments(sc2, 0,2, ['Chord'])
[<music21.voiceLeading.TwoChordLinearSegment objectList=[<music21.chord.Chord C E G>, <music21.chord.Chord G B D>] , <music21.voiceLeading.TwoChordLinearSegment objectList=[<music21.chord.Chord G B D>, <music21.chord.Chord E G C>] , <music21.voiceLeading.TwoChordLinearSegment objectList=[<music21.chord.Chord E G C>, <music21.chord.Chord F A C>] ]
>>> len(theoryAnalyzer.getLinearSegments(sc2, 0,2, ['Chord']))
3
>>> for x in theoryAnalyzer.getLinearSegments(sc2, 0,2, ['Chord']):
... print x.rootInterval(), x.bassInterval()
<music21.interval.ChromaticInterval 7> <music21.interval.ChromaticInterval 2>
<music21.interval.ChromaticInterval -7> <music21.interval.ChromaticInterval -2>
<music21.interval.ChromaticInterval 5> <music21.interval.ChromaticInterval 0>
>>> sc3 = stream.Score()
>>> part2 = stream.Part()
>>> part2.append(harmony.ChordSymbol('D-', quarterLength = 1))
>>> part2.append(harmony.ChordSymbol('C11', quarterLength = 1))
>>> part2.append(harmony.ChordSymbol('C7', quarterLength = 1))
>>> sc3.insert(part2)
>>> len(theoryAnalyzer.getLinearSegments(sc3, 0,2, ['Harmony']))
2
>>> theoryAnalyzer.getLinearSegments(sc3,0,2, ['Harmony'])
[<music21.voiceLeading.TwoChordLinearSegment objectList=[<music21.harmony.ChordSymbol D->, <music21.harmony.ChordSymbol C11>] , <music21.voiceLeading.TwoChordLinearSegment objectList=[<music21.harmony.ChordSymbol C11>, <music21.harmony.ChordSymbol C7>] ]
extracts and returns a list of the VerticalSliceNTuplet or the corresponding subclass (currently only supports triplets)
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part1 = stream.Part()
>>> part0.append(note.Note('c4'))
>>> part0.append(note.Note('g4'))
>>> part0.append(note.Note('c5'))
>>> part0.append(note.Note('e6'))
>>> part1.append(note.Note('e4'))
>>> part1.append(note.Note('f4'))
>>> part1.append(note.Note('a5'))
>>> part1.append(note.Note('d6'))
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> len(theoryAnalyzer.getVerticalSliceNTuplets(sc, 3))
2
>>> theoryAnalyzer.getVerticalSliceNTuplets(sc, 3)[1]
<music21.voiceLeading.VerticalSliceTriplet listofVerticalSlices=[<music21.voiceLeading.VerticalSlice contentDict=defaultdict(<type 'list'>, {0: [<music21.note.Note G>], 1: [<music21.note.Note F>]}) , <music21.voiceLeading.VerticalSlice contentDict=defaultdict(<type 'list'>, {0: [<music21.note.Note C>], 1: [<music21.note.Note A>]}) , <music21.voiceLeading.VerticalSlice contentDict=defaultdict(<type 'list'>, {0: [<music21.note.Note E>], 1: [<music21.note.Note D>]}) ]
returns a list of all the harmonic intervals (Interval ) occurring between the two specified parts.
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(note.Note('e4'))
>>> part0.append(note.Note('d4'))
>>> part1 = stream.Part()
>>> part1.append(note.Note('a3'))
>>> part1.append(note.Note('b3'))
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> len(theoryAnalyzer.getHarmonicIntervals(sc, 0,1))
2
>>> theoryAnalyzer.getHarmonicIntervals(sc, 0,1)[0].name
'P5'
>>> theoryAnalyzer.getHarmonicIntervals(sc, 0,1)[1].name
'm3'
returns a list of all the melodic intervals (Interval) in the specified part.
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(note.Note('c4'))
>>> part0.append(note.Note('g4'))
>>> part0.append(note.Note('c5'))
>>> sc.insert(part0)
>>> theoryAnalyzer.getMelodicIntervals(sc,0)
[<music21.interval.Interval P5>, <music21.interval.Interval P4>]
>>> theoryAnalyzer.getMelodicIntervals(sc, 0)[0].name
'P5'
>>> theoryAnalyzer.getMelodicIntervals(sc, 0)[1].name
'P4'
Identifies all parallel fifths in score, or only the parallel fifths found between partNum1 and partNum2, and returns these as instances of VoiceLeadingQuartet
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('c5'))
>>> p0measure1.append(note.Note('d5'))
>>> p0measure1.append(note.Note('e5'))
>>> p0measure1.append(note.Note('g5'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c4'))
>>> p1measure1.append(note.Note('g4'))
>>> p1measure1.append(note.Note('a4'))
>>> p1measure1.append(note.Note('c4'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.getParallelFifths(sc)
[<music21.voiceLeading.VoiceLeadingQuartet v1n1=<music21.note.Note D> , v1n2=<music21.note.Note E>, v2n1=<music21.note.Note G>, v2n2=<music21.note.Note A> , <music21.voiceLeading.VoiceLeadingQuartet v1n1=<music21.note.Note E> , v1n2=<music21.note.Note G>, v2n1=<music21.note.Note A>, v2n2=<music21.note.Note C> ]
>>> len(sc.analysisData['ResultDict']['parallelFifths'])
2
returns a list of all passing tones present in the score, as identified by hasPassingTone()
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> sc.insert(0, meter.TimeSignature('2/4'))
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('A4', quarterLength = 0.5))
>>> p0measure1.append(note.Note('G4', quarterLength = 0.5))
>>> p0measure1.append(note.Note('F#4', quarterLength = 1.0))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('A2', quarterLength = 1.0))
>>> p1measure1.append(note.Note('D3', quarterLength = 1.0))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.getPassingTones(sc)
[<music21.note.Note G>]
returns a list of all passing tones present in the score, as identified by hasNeighborTone()
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> sc.insert(0, meter.TimeSignature('2/4'))
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('E-3', quarterLength = 1.0))
>>> p0measure1.append(note.Note('C3', quarterLength = 1.0))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('C2', quarterLength = 0.5))
>>> p1measure1.append(note.Note('B1', quarterLength = 0.5))
>>> p1measure1.append(note.Note('C2', quarterLength = 1.0))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.getNeighborTones(sc)
[<music21.note.Note B>]
Identifies all parallel octaves in score (if no part numbers specified), or only the parallel octaves found between partNum1 and partNum2, and returns these as instances of VoiceLeadingQuartet
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('c5'))
>>> p0measure1.append(note.Note('g5'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c4'))
>>> p1measure1.append(note.Note('g4'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.getParallelOctaves(sc)
[<music21.voiceLeading.VoiceLeadingQuartet v1n1=<music21.note.Note C> , v1n2=<music21.note.Note G>, v2n1=<music21.note.Note C>, v2n2=<music21.note.Note G> ]
Identifies parallel fifths (calls parallelFifth()) between two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of VLQTheoryResult objects in score.analysisData['ResultDict']['parallelFifths']. Optionally, a color attribute may be specified to color all corresponding notes in the score.
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('c5'))
>>> p0measure1.append(note.Note('d5'))
>>> p0measure1.append(note.Note('e5'))
>>> p0measure1.append(note.Note('g5'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c4'))
>>> p1measure1.append(note.Note('g4'))
>>> p1measure1.append(note.Note('a4'))
>>> p1measure1.append(note.Note('c4'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyParallelFifths(sc)
>>> len(sc.analysisData['ResultDict']['parallelFifths'])
2
>>> sc.analysisData['ResultDict']['parallelFifths'][0].text
'Parallel fifth in measure 1: Part 1 moves from D to E while part 2 moves from G to A'
Identifies parallel octaves (calls parallelOctave()) between two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of VLQTheoryResult objects in score.analysisData['ResultDict']['parallelOctaves']. Optionally, a color attribute may be specified to color all corresponding notes in the score.
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('c5'))
>>> p0measure1.append(note.Note('g5'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c4'))
>>> p1measure1.append(note.Note('g4'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyParallelOctaves(sc)
>>> len(sc.analysisData['ResultDict']['parallelOctaves'])
1
>>> sc.analysisData['ResultDict']['parallelOctaves'][0].text
'Parallel octave in measure 1: Part 1 moves from C to G while part 2 moves from C to G'
Identifies parallel unisons (calls parallelUnison()) between two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of VLQTheoryResult objects in score.analysisData['ResultDict']['parallelUnisons']. Optionally, a color attribute may be specified to color all corresponding notes in the score.
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('c5'))
>>> p0measure1.append(note.Note('d5'))
>>> p0measure1.append(note.Note('e5'))
>>> p0measure1.append(note.Note('f5'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c5'))
>>> p1measure1.append(note.Note('d5'))
>>> p1measure1.append(note.Note('e5'))
>>> p1measure1.append(note.Note('f5'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyParallelUnisons(sc)
>>> len(sc.analysisData['ResultDict']['parallelUnisons'])
3
>>> sc.analysisData['ResultDict']['parallelUnisons'][2].text
'Parallel unison in measure 1: Part 1 moves from E to F while part 2 moves from E to F'
Identifies hidden fifths (calls hiddenFifth()) between two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of VLQTheoryResult objects in self.resultDict['hiddenFifths']. Optionally, a color attribute may be specified to color all corresponding notes in the score.
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('e5'))
>>> p0measure1.append(note.Note('d5'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c5'))
>>> p1measure1.append(note.Note('g4'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyHiddenFifths(sc)
>>> len(sc.analysisData['ResultDict']['hiddenFifths'])
1
>>> sc.analysisData['ResultDict']['hiddenFifths'][0].text
'Hidden fifth in measure 1: Part 1 moves from E to D while part 2 moves from C to G'
Identifies hidden octaves (calls hiddenOctave()) between two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of VLQTheoryResult objects in score.analysisData['ResultDict']['hiddenOctaves']. Optionally, a color attribute may be specified to color all corresponding notes in the score.
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('e4'))
>>> p0measure1.append(note.Note('f4'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('d3'))
>>> p1measure1.append(note.Note('f3'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyHiddenOctaves(sc)
>>> len(sc.analysisData['ResultDict']['hiddenOctaves'])
1
>>> sc.analysisData['ResultDict']['hiddenOctaves'][0].text
'Hidden octave in measure 1: Part 1 moves from E to F while part 2 moves from D to F'
Identifies improper resolutions of dissonant intervals (calls improperResolution()) between two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of VLQTheoryResult objects in self.resultDict['improperResolution']. Optionally, a color attribute may be specified to color all corresponding notes in the score.
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('f#4'))
>>> p0measure1.append(note.Note('a4'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('C3'))
>>> p1measure1.append(note.Note('B2'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyImproperResolutions(sc)
>>> len(sc.analysisData['ResultDict']['improperResolution'])
1
>>> sc.analysisData['ResultDict']['improperResolution'][0].text
'Improper resolution of Augmented Fourth in measure 1: Part 1 moves from F# to A while part 2 moves from C to B'
Identifies a leap/skip in one voice not set with a step in the other voice (calls leapNotSetWithStep()) between two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of VLQTheoryResult objects in self.resultDict['leapNotSetWithStep']. Optionally, a color attribute may be specified to color all corresponding notes in the score.
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('C4'))
>>> p0measure1.append(note.Note('G3'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('A2'))
>>> p1measure1.append(note.Note('D2'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyLeapNotSetWithStep(sc)
>>> len(sc.analysisData['ResultDict']['LeapNotSetWithStep'])
1
>>> sc.analysisData['ResultDict']['LeapNotSetWithStep'][0].text
'Leap not set with step in measure 1: Part 1 moves from C to G while part 2 moves from A to D'
Identifies if the piece opens correctly; calls opensIncorrectly()
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('C#4'))
>>> p0measure1.append(note.Note('G3'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('A2'))
>>> p1measure1.append(note.Note('D2'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyOpensIncorrectly(sc)
>>> len(sc.analysisData['ResultDict']['opensIncorrectly'])
1
>>> sc.analysisData['ResultDict']['opensIncorrectly'][0].text
'Opening harmony is not in style'
Identifies if the piece closes correctly; calls closesIncorrectly()
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('B4'))
>>> p0measure1.append(note.Note('A4'))
>>> p0measure1.append(note.Note('A4'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('G2'))
>>> p1measure1.append(note.Note('F2'))
>>> p1measure1.append(note.Note('G2'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.setKeyMeasureMap(sc,{1:'G'})
>>> theoryAnalyzer.identifyClosesIncorrectly(sc)
>>> len(sc.analysisData['ResultDict']['closesIncorrectly'])
1
>>> sc.analysisData['ResultDict']['closesIncorrectly'][0].text
'Closing harmony is not in style'
Identifies the passing tones in the piece by looking at the vertical and horizontal cross-sections. Optionally specify unaccentedOnly to identify only unaccented passing tones (passing tones on weak beats). unaccentedOnly by default set to True
Optionally label each identified passing tone with an editorial NoteEditorial value of editorialValue at note.editorial.misc[editorialDictKey]
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> sc.insert(0, meter.TimeSignature('2/4'))
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('A4', quarterLength = 0.5))
>>> p0measure1.append(note.Note('G4', quarterLength = 0.5))
>>> p0measure1.append(note.Note('F#4', quarterLength = 1.0))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('A2', quarterLength = 1.0))
>>> p1measure1.append(note.Note('D3', quarterLength = 1.0))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyPassingTones(sc)
>>> len(sc.analysisData['ResultDict']['unaccentedPassingTones'])
1
>>> sc.analysisData['ResultDict']['unaccentedPassingTones'][0].text
'G identified as a passing tone in part 1'
primitively removes the passing tones found in a piece and fills the gap by extending note duraitons (method under development)
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> sc.insert(0, meter.TimeSignature('2/4'))
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('A4', quarterLength = 0.5))
>>> p0measure1.append(note.Note('G4', quarterLength = 0.5))
>>> p0measure1.append(note.Note('F#4', quarterLength = 1.0))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('A2', quarterLength = 1.0))
>>> p1measure1.append(note.Note('D3', quarterLength = 1.0))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.removePassingTones(sc)
>>> for x in sc.flat.notes:
... print x
<music21.note.Note A>
<music21.note.Note A>
<music21.note.Note F#>
<music21.note.Note D>
Identifies the neighbor tones in the piece by looking at the vertical and horizontal cross-sections. Optionally specify unaccentedOnly to identify only unaccented neighbor tones (neighbor tones on weak beats). unaccentedOnly by default set to True
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> sc.insert(0, meter.TimeSignature('2/4'))
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('E-3', quarterLength = 1.0))
>>> p0measure1.append(note.Note('C3', quarterLength = 1.0))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('C2', quarterLength = 0.5))
>>> p1measure1.append(note.Note('B1', quarterLength = 0.5))
>>> p1measure1.append(note.Note('C2', quarterLength = 1.0))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyNeighborTones(sc)
>>> len(sc.analysisData['ResultDict']['unaccentedNeighborTones'])
1
>>> sc.analysisData['ResultDict']['unaccentedNeighborTones'][0].text
'B identified as a neighbor tone in part 2'
primitively removes the neighbor tones found in a piece and fills the gap by extending note duraitons (method under development)
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> sc.insert(0, meter.TimeSignature('2/4'))
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('E-3', quarterLength = 1.0))
>>> p0measure1.append(note.Note('C3', quarterLength = 1.0))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('C2', quarterLength = 0.5))
>>> p1measure1.append(note.Note('B1', quarterLength = 0.5))
>>> p1measure1.append(note.Note('C2', quarterLength = 1.0))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.removeNeighborTones(sc)
>>> for x in sc.flat.notes:
... print x
<music21.note.Note E->
<music21.note.Note C>
<music21.note.Note C>
<music21.note.Note C>
Identifies dissonant harmonic intervals (calls isConsonant()) between the two parts (if specified) or between all possible pairs of parts (if not specified) and stores the resulting list of IntervalTheoryResultObject objects in self.resultDict['dissonantHarmonicIntervals']. Optionally, a color attribute may be specified to color all corresponding notes in the score.
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('c'))
>>> p0measure1.append(note.Note('f'))
>>> p0measure1.append(note.Note('b'))
>>> p0measure1.append(note.Note('c'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('b-'))
>>> p1measure1.append(note.Note('c'))
>>> p1measure1.append(note.Note('f'))
>>> p1measure1.append(note.Note('c'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyDissonantHarmonicIntervals(sc)
>>> len(sc.analysisData['ResultDict']['dissonantHarmonicIntervals'])
3
>>> sc.analysisData['ResultDict']['dissonantHarmonicIntervals'][2].text
'Dissonant harmonic interval in measure 1: Augmented Fourth from F to B between part 1 and part 2'
Identifies dissonant harmonic intervals that are not passing tones or neighbor tones or don’t resolve correctly
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('a3'))
>>> p0measure1.append(note.Note('f3'))
>>> p0measure1.append(note.Note('e3'))
>>> p0measure1.append(note.Note('c4'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyImproperDissonantIntervals(sc)
>>> len(sc.analysisData['ResultDict']['improperDissonantIntervals'])
2
>>> sc.analysisData['ResultDict']['improperDissonantIntervals'][1].text
'Improper dissonant harmonic interval in measure 1: Perfect Fourth from C to F between part 1 and part 2'
Identifies dissonant melodic intervals (A2, A4, d5, m7, M7) in the part (if specified) or for all parts (if not specified) and stores the resulting list of IntervalTheoryResultObject objects in self.resultDict['dissonantMelodicIntervals']. Optionally, a color attribute may be specified to color all corresponding notes in the score.
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('f3'))
>>> p0measure1.append(note.Note('g#3'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('d2'))
>>> p1measure1.append(note.Note('a-2'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyDissonantMelodicIntervals(sc)
>>> len(sc.analysisData['ResultDict']['dissonantMelodicIntervals'])
2
>>> sc.analysisData['ResultDict']['dissonantMelodicIntervals'][0].text
'Dissonant melodic interval in part 1 measure 1: Augmented Second from F to G#'
>>> sc.analysisData['ResultDict']['dissonantMelodicIntervals'][1].text
'Dissonant melodic interval in part 2 measure 1: Diminished Fifth from D to A-'
Identifies the roman numerals in the piece by iterating throgh the vertical slices and figuring out which roman numeral best corresponds to that vertical slice. Optionally specify the responseOffsetMap which limits the resultObjects returned to only those with verticalSlice's.offset(leftAlign=True) included in the list. For example, if only roman numerals were to be written for the vertical slice at offset 0, 6, and 7 in the piece, pass responseOffsetMap = [0,6,7]
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('a3'))
>>> p0measure1.append(note.Note('B-3'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c2'))
>>> p1measure1.append(note.Note('g2'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.setKeyMeasureMap(sc, {0:'Bb'} )
>>> theoryAnalyzer.identifyTonicAndDominantRomanNumerals(sc)
>>> len(sc.analysisData['ResultDict']['romanNumeralsVandI'])
2
>>> sc.analysisData['ResultDict']['romanNumeralsVandI'][0].text
'Roman Numeral of A,C is V64'
>>> sc.analysisData['ResultDict']['romanNumeralsVandI'][1].text
'Roman Numeral of B-,G is I'
identify all the harmonic intervals in the score between partNum1 or partNum2, or if not specified ALL possible combinations
IntervalTheoryResult created with .value set to the the string most commonly used to identify the interval (0 through 9, with A4 and d5)
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('a3'))
>>> p0measure1.append(note.Note('f#3'))
>>> p0measure1.append(note.Note('e3'))
>>> p0measure1.append(note.Note('c4'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyHarmonicIntervals(sc)
>>> len(sc.analysisData['ResultDict']['harmonicIntervals'])
4
>>> sc.analysisData['ResultDict']['harmonicIntervals'][1].value
'A4'
>>> sc.analysisData['ResultDict']['harmonicIntervals'][0].text
'harmonic interval between B and A between parts 1 and 2 is a Minor Seventh'
identify all the scale degrees in the score in partNum, or if not specified ALL partNums
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('a3'))
>>> p0measure1.append(note.Note('f#3'))
>>> p0measure1.append(note.Note('e3'))
>>> p0measure1.append(note.Note('c4'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.setKeyMeasureMap(sc, {0:'G'})
>>> theoryAnalyzer.identifyScaleDegrees(sc)
>>> len(sc.analysisData['ResultDict']['scaleDegrees'])
8
>>> sc.analysisData['ResultDict']['scaleDegrees'][1].value
'7'
>>> sc.analysisData['ResultDict']['scaleDegrees'][1].text
'scale degree of F# in part 1 is 7'
Identifies the motion types in the score by analyzing each voice leading quartet between partNum1 and partNum2, or all possible voiceLeadingQuartets if not specified
VLQTheoryResult by calling motionType() Possible values for VLQTheoryResult are ‘Oblique’, ‘Parallel’, ‘Similar’, ‘Contrary’, ‘Anti-Parallel’, ‘No Motion’
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('a3'))
>>> p0measure1.append(note.Note('f#3'))
>>> p0measure1.append(note.Note('e3'))
>>> p0measure1.append(note.Note('c4'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> p1measure1.append(note.Note('b2'))
>>> p1measure1.append(note.Note('c3'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyMotionType(sc)
>>> len(sc.analysisData['ResultDict']['motionType'])
3
>>> sc.analysisData['ResultDict']['motionType'][1].value
'Similar'
>>> sc.analysisData['ResultDict']['motionType'][1].text
'Similar Motion in measure 1: Part 1 moves from F# to E while part 2 moves from C to B'
wrapper method that calls all identify methods for common-practice counterpoint errors, assigning a color identifier to each
ParallelFifths = red, ParallelOctaves = yellow, HiddenFifths = orange, HiddenOctaves = green, ParallelUnisons = blue, ImproperResolutions = purple, improperDissonances = white, DissonantMelodicIntervals = cyan, incorrectOpening = brown, incorrectClosing = gray
adds an attribute “analysisData” to a Stream object if it does not exist.
also adds to any embedded Streams...
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import theoryAnalyzer
>>> p = stream.Part()
>>> s = stream.Score()
>>> s.insert(0, p)
>>> hasattr(p, 'analysisData')
False
>>> hasattr(s, 'analysisData')
False
>>> theoryAnalyzer.addAnalysisData(s)
>>> hasattr(p, 'analysisData')
True
>>> hasattr(s, 'analysisData')
True
>>> 'ResultDict' in p.analysisData
True
remove a a result entry or entries from the resultDict by specifying which key or keys in the dictionary you’d like remove. Pass in a list of dictKeys or just a single dictionary key.
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import theoryAnalyzer
>>> sc = stream.Score()
>>> theoryAnalyzer.addAnalysisData(sc)
>>> sc.analysisData['ResultDict'] = {'sampleDictKey': 'sample response', 'h1':'another sample response', 5:'third sample response'}
>>> theoryAnalyzer.removeFromAnalysisData(sc, 'sampleDictKey')
>>> sc.analysisData['ResultDict']
{'h1': 'another sample response', 5: 'third sample response'}
>>> theoryAnalyzer.removeFromAnalysisData(sc, ['h1',5])
>>> sc.analysisData['ResultDict']
{}
easily specify the key of the score by measure in a dictionary correlating measure number to key, such as {1:’C’, 2:’D’, 3:’B-‘,5:’g’}. optionally pass in the music21 key object or the key string. This is used for analysis purposes only - no key object is actually added to the score. Check the music xml to verify measure numbers; pickup measures are usually 0.
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> n1 = note.Note('c5')
>>> n1.quarterLength = 4
>>> n2 = note.Note('f4')
>>> n2.quarterLength = 2
>>> n3 = note.Note('g4')
>>> n3.quarterLength = 2
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(n1)
>>> part1 = stream.Part()
>>> part1.append(n2)
>>> part1.append(n3)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.setKeyMeasureMap(sc, {1:'C',2:'a'})
>>> theoryAnalyzer.getKeyMeasureMap(sc)
{1: 'C', 2: 'a'}
returns the keymeasuremap in the score, if present. returns None otherwise
uses keyMeasureMap to return music21 key object. If keyMeasureMap not specified, returns key analysis of theory score as a whole.
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> s = stream.Score()
>>> theoryAnalyzer.setKeyMeasureMap(s, {1:'C', 2:'G', 4:'a', 7:'C'})
>>> theoryAnalyzer.getKeyAtMeasure(s, 3)
<music21.key.Key of G major>
>>> theoryAnalyzer.getKeyAtMeasure(s, 5)
<music21.key.Key of a minor>
>>> sc = corpus.parse('bach/bwv66.6')
>>> theoryAnalyzer.getKeyAtMeasure(sc, 5)
<music21.key.Key of f# minor>
returns string of all results found by calling all identify methods on the TheoryAnalyzer score
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> p0measure1 = stream.Measure(number=1)
>>> p0measure1.append(note.Note('c5'))
>>> p0measure1.append(note.Note('d5'))
>>> p0measure1.append(note.Note('e5'))
>>> p0measure1.append(note.Note('g5'))
>>> part0.append(p0measure1)
>>> part1 = stream.Part()
>>> p1measure1 = stream.Measure(number=1)
>>> p1measure1.append(note.Note('c4'))
>>> p1measure1.append(note.Note('g4'))
>>> p1measure1.append(note.Note('a4'))
>>> p1measure1.append(note.Note('c4'))
>>> part1.append(p1measure1)
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> theoryAnalyzer.identifyCommonPracticeErrors(sc)
>>> print theoryAnalyzer.getResultsString(sc)
commonPracticeErrors:
Parallel fifth in measure 1: Part 1 moves from D to E while part 2 moves from G to A
Parallel fifth in measure 1: Part 1 moves from E to G while part 2 moves from A to C
Hidden fifth in measure 1: Part 1 moves from C to D while part 2 moves from C to G
Closing harmony is not in style
colors the notes of all results found in typeList by calling all identify methods on Theory Analyzer.
returns string of all results found by calling all identify methods on the TheoryAnalyzer score
Gets a list of all possible pairs of partNumbers: tuples (partNum1, partNum2) where 0 <= partNum1 < partnum2 < numParts
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> part0 = stream.Part()
>>> part0.append(note.Note('c5'))
>>> part1 = stream.Part()
>>> part1.append(note.Note('g4'))
>>> part2 = stream.Part()
>>> part2.append(note.Note('c4'))
>>> sc.insert(part0)
>>> sc.insert(part1)
>>> sc.insert(part2)
>>> theoryAnalyzer.getAllPartNumPairs(sc)
[(0, 1), (0, 2), (1, 2)]
>>> theoryAnalyzer.getAllPartNumPairs(sc)[0]
(0, 1)
>>> theoryAnalyzer.getAllPartNumPairs(sc)[1]
(0, 2)
>>> theoryAnalyzer.getAllPartNumPairs(sc)[2]
(1, 2)
returns a list of notes present in the score. If Rests are present, appends None to the list
>>> from music21 import *
>>> from music21.demos.theoryAnalysis import *
>>> sc = stream.Score()
>>> p = stream.Part()
>>> p.repeatAppend(note.Note('C'), 3)
>>> p.append(note.Rest(1.0))
>>> sc.append(p)
>>> theoryAnalyzer.getNotes(sc, 0)
[<music21.note.Note C>, <music21.note.Note C>, <music21.note.Note C>, None]