def ruleFrequency(startNumber=2, endNumber=459): ''' ''' ballataObj = cadencebook.BallataSheet() num1 = 0 num2 = 0 num3 = 0 num4a = 0 num4b = 0 for i in range(startNumber, endNumber): # all ballate # if (i == 15): # pass pieceObj = ballataObj.makeWork( i) ## N.B. -- we now use Excel column numbers for thisPolyphonicSnippet in pieceObj.snippets: if thisPolyphonicSnippet is None: continue for thisPart in thisPolyphonicSnippet.parts: thisStream = thisPart.flat.notes num1 += capuaRuleOne(thisStream) num2 += capuaRuleTwo(thisStream) num3 += capuaRuleThree(thisStream) num4a += capuaRuleFourA(thisStream) num4b += capuaRuleFourB(thisStream) return (num1, num2, num3, num4a, num4b)
def testCompare1(self): ballataObj = cadencebook.BallataSheet() totalDict = { 'totalNotes': 0, 'pmfcAlt': 0, 'capuaAlt': 0, 'pmfcNotCapua': 0, 'capuaNotPmfc': 0, 'pmfcAndCapua': 0, } for i in range(232, 349): # 232-349 is most of Landini PMFC pieceObj = ballataObj.makeWork( i) ## N.B. -- we now use Excel column numbers if pieceObj.incipit is None: continue environLocal.printDebug(pieceObj.title) cadenceA = pieceObj.cadenceA if cadenceA is not None and len(cadenceA.parts) >= 2: srcStream1 = cadenceA.parts[0] #.flat.notesAndRests #srcStream2 = cadenceA.parts[1].flat.notesAndRests ## ignore 3rd voice for now... #twoStreams1 = twoStreams.TwoStreamComparer(srcStream1, srcStream2) #twoStreams1.intervalToOtherStreamWhenAttacked() #srcStream1.attachIntervalsBetweenStreams(srcStream2) #srcStream2.attachIntervalsBetweenStreams(srcStream1) applyCapuaToStream(srcStream1) thisDict = compareSrcStreamCapuaToEditor(srcStream1) for thisKey in thisDict: totalDict[thisKey] += thisDict[thisKey] self.assertEqual(totalDict['capuaAlt'], 18) self.assertEqual(totalDict['totalNotes'], 200) environLocal.printDebug(totalDict)
def find(startRow=2, endRow=469, searchInterval=7): opus = stream.Opus() ballatas = cadencebook.BallataSheet() for row in range(startRow, endRow): ballata = ballatas.makeWork(row) if findInWork(ballata, searchInterval): print(ballata.title + ' has a generic interval of %d somewhere' % searchInterval) opus.insert(0, ballata.asScore()) if len(opus) > 0: opus.show('lily.pdf')
def find(): ballatas = cadencebook.BallataSheet() opus = stream.Opus() i = 0 for ballata in ballatas: if i > 10: break if (ballata.timeSigBegin == "6/8" or ballata.timeSigBegin == "9/8"): incipit = ballata.incipit if incipit != None: i += 1 opus.insert(0, incipit) opus.show('lily.pdf')
def searchForIntervals(notesStr): ''' notesStr is the same as above. Now however we check to see if the generic intervals are the same, rather than the note names. Useful if the clef is missing. ''' notesArr = notesStr.split() noteObjArr = [] for tN in notesArr: tNObj = note.Note() tNObj.name = tN[0] tNObj.octave = int(tN[1]) noteObjArr.append(tNObj) interObjArr = [] for i in range(len(noteObjArr) - 1): int1 = interval.notesToInterval(noteObjArr[i], noteObjArr[i + 1]) interObjArr.append(int1) #print interObjArr searcher1 = IntervalSearcher(interObjArr) ballataObj = cadencebook.BallataSheet() streamOpus = stream.Opus() for thisWork in ballataObj: print(thisWork.title) for thisCadence in thisWork.snippets: if thisCadence is None: continue for i in range(len(thisCadence.parts)): if searcher1.compareToStream( thisCadence.parts[i].flat) is True: notesStr = "" for thisNote in thisCadence.parts[i].flat.notesAndRests: #thisNote.editorial.color = "blue" if thisNote.isRest is False: notesStr += thisNote.nameWithOctave + " " else: notesStr += "r " streamOpus.insert(0, thisCadence) # streamLily += "\\score {" + \ # "<< \\time " + str(thisCadence.timeSig) + \ # "\n \\new Staff {" + str(thisCadence.parts[i].lily) + "} >>" + \ # thisCadence.header() + "\n}\n" print(u"In piece %r found in stream %d: %s" % (thisWork.title, i, notesStr)) if len(streamOpus) > 0: streamOpus.show('lily.png')
def runPiece(pieceNum = 331, snipNum = 0): # random default piece... ballataObj = cadencebook.BallataSheet() pieceObj = ballataObj.makeWork(pieceNum) # pieceObj.snippets[0].lily.showPNG() applyCapuaToScore(pieceObj) # pieceObj.snippets[snipNum].show('lily.png') srcStream = pieceObj.snippets[snipNum].parts[0].flat.notesAndRests cmpStream = pieceObj.snippets[snipNum].parts[1].flat.notesAndRests ## ignore 3rd voice for now... srcStream.attachIntervalsBetweenStreams(cmpStream) for note in srcStream.notes: if note.editorial.harmonicInterval is not None: environLocal.printDebug(note.name) environLocal.printDebug(note.editorial.harmonicInterval.semiSimpleName) if "capua-ficta" in note.editorial.misc: environLocal.printDebug(note.editorial.misc['capua-ficta'])
def landiniTonality(show = True): ''' generates information about the tonality of Landini's ballate using the tenor (streamName = "T") and the A cadence (which we would believe would end the piece) ''' ballataObj = cadencebook.BallataSheet() worksList = [] for thisWork in ballataObj: if thisWork.composer == "Landini": worksList.append(thisWork) tCounter = TonalityCounter(worksList, streamName = "T", cadenceName = "A") tCounter.run() if show is True: print(tCounter.output)
def searchForNotes(notesStr): '''the notesStr is a string of notes in the following form: "C4 D4 E4 B3 C4" that's it: name, octave. With no accidentals. If octave is 0 then it means do not bother checking for octaves. Currently octave is ignored anyhow. ''' notesArr = notesStr.split() noteObjArr = [] for tN in notesArr: tNName = tN[0] if tNName.lower() != "r": tNObj = note.Note() tNObj.name = tN[0] tNObj.octave = int(tN[1]) else: tNObj = note.Rest() noteObjArr.append(tNObj) ballataObj = cadencebook.BallataSheet() searcher1 = NoteSearcher(noteObjArr) streamOpus = stream.Opus() for thisWork in ballataObj: for thisCadence in thisWork.snippets: if thisCadence is None: continue for i in range(len(thisCadence.parts)): if searcher1.compareToStream( thisCadence.parts[i].flat) is True: notesStr = "" for thisNote in thisCadence.parts[i].flat.notesAndRests: #thisNote.editorial.color = "blue" if thisNote.isRest is False: notesStr += thisNote.nameWithOctave + " " else: notesStr += "r " streamOpus.insert(0, thisCadence) # streamLily += "\\score {" + \ # "<< \\time " + str(thisCadence.timeSig) + \ # "\n \\new Staff {" + str(thisCadence.parts[i].lily) + "} >>" + \ # thisCadence.header() + "\n}\n" print(u"In piece %r found in stream %d: %s" % (thisWork.title, i, notesStr)) if len(streamOpus) > 0: streamOpus.show('lily.png')
def pitchToNoteLength(): ''' get a quick 3D image of the relationship between pitch and notelength in trecento ballata cadences ''' allStream = stream.Stream() b = cadencebook.BallataSheet() for work in b: for snippet in work.snippets: if snippet is None: continue for thisStream in snippet.streams: allStream.append(thisStream) #c = music21.analysis.correlate.NoteAnalysis(allStream.flat) #c.noteAttributeCount() g = graph.Plot3DBarsPitchSpaceQuarterLength(allStream.flat) g.process()
def testShowFourA(self): ballataObj = cadencebook.BallataSheet() showStream = stream.Opus() for i in range(2, 45): #459): # all ballate pieceObj = ballataObj.makeWork(i) ## N.B. -- we now use Excel column numbers theseSnippets = pieceObj.snippets for thisSnippet in theseSnippets: if thisSnippet is None: continue appendSnippet = False theseStreams = thisSnippet.parts for thisStream in theseStreams: if capuaRuleFourA(thisStream) > 0: appendSnippet = True if appendSnippet is True: showStream.insert(0, thisSnippet) showStream.show('lily.pdf')
def countCadencePercentages(): ballatas = cadencebook.BallataSheet() totalPieces = 0.0 firstNoteTotal = defaultdict(lambda: 0) lastNoteTotal = defaultdict(lambda: 0) for thisWork in ballatas: incipit = thisWork.incipit cadenceB = thisWork.cadenceA #BClos or thisWork.cadenceBOuvert # if thisWork.composer != 'A. Zacara' and thisWork.composer != 'Zacharias': # continue if incipit is None or cadenceB is None: continue incipitTenor = incipit.tenor cadenceBTenor = cadenceB.tenor if incipitTenor is None or cadenceBTenor is None: continue firstNotes = incipitTenor.getElementsByClass(note.Note) lastNotes = cadenceBTenor.getElementsByClass(note.Note) if len(firstNotes) == 0 or len(lastNotes) == 0: continue firstNote = firstNotes[0] lastNote = lastNotes[-1] print(thisWork.title, firstNote.name, lastNote.name) totalPieces += 1.0 # for float division later firstNoteTotal[firstNote.name] += 1 lastNoteTotal[lastNote.name] += 1 print("First note distribution:") for thisName in firstNoteTotal: print(thisName, firstNoteTotal[thisName] / totalPieces) print("Last note distribution:") for thisName in lastNoteTotal: print(thisName, lastNoteTotal[thisName] / totalPieces)
def testRun1(self): ballataSht = cadencebook.BallataSheet() pieceObj = ballataSht.makeWork(20) ## N.B. -- we now use Excel column numbers if pieceObj.incipit is None: return None cadenceA = pieceObj.cadenceA if len(cadenceA.parts) >= 2: srcStream1 = cadenceA.parts[0].flat.notes srcStream2 = cadenceA.parts[1].flat.notes ## ignore 3rd voice for now... clearFicta(srcStream1) compareThreeFictas(srcStream1, srcStream2) cons, imperfCons, diss = compareOnesrcStream(srcStream1, srcStream2) # for note in srcStream1: # print note.name # print note.editorial.ficta # print note.editorial.harmonicInterval.diatonic.name restoreFicta(srcStream1) self.assertEqual([cons, imperfCons, diss], [4, 3, 3])
def searchForVat1969(): '''There is a particular piece in Vatican MS 1969 that I have been searching for forever, its first ending concludes DED and second ending CDC, OR SOME TRANSPOSITION of these notes. Find it!''' ballataObj = cadencebook.BallataSheet() for thisWork in ballataObj: cadB1 = thisWork.cadenceB1Class() cadB2 = thisWork.cadenceB2Class() if (cadB2 is None or len(cadB2.parts) == 0): continue if (cadB1 is None or len(cadB1.parts) == 0): continue for i in range(0, len(cadB2.parts)): strB1 = cadB1.parts[i].flat strB2 = cadB2.parts[i].flat if len(strB1.notesAndRests) < 3 or len(strB2.notesAndRests) < 3: break if findUpDown(strB1.notesAndRests[-3], strB1.notesAndRests[-2], strB1.notesAndRests[-1]): if findUpDown(strB2.notesAndRests[-3], strB2.notesAndRests[-2], strB2.notesAndRests[-1]): print(thisWork.title.encode('utf-8') + " ",) b1b2int = interval.Interval(note1 = strB1.notesAndRests[-1], note2 = strB2.notesAndRests[-1]) print(b1b2int.diatonic.generic.niceName)
def anonBallataTonality(show = True): ''' Gives a list of all anonymous ballate with their incipit tenor note and cadence tenor notes keeps track of how often they are the same and how often they are different. And then generates a PNG of the incipit and first cadence of all the ones that are the same. ''' ballataObj = cadencebook.BallataSheet() worksList = [] for thisWork in ballataObj: if thisWork.composer == ".": worksList.append(thisWork) tCounter = TonalityCounter(worksList, streamName = "T", cadenceName = "A") tCounter.run() if show is True: print(tCounter.output) print("Generating Lilypond PNG of all pieces where the first note of the tenor is the same pitchclass as the last note of Cadence A") print("It might take a while, esp. on the first Lilypond run...") tCounter.displayStream.show('lily.png')
def testRunNonCrederDonna(self): pieceNum = 331 # Francesco, PMFC 4 6-7: Non creder, donna ballataObj = cadencebook.BallataSheet() pieceObj = ballataObj.makeWork(pieceNum) applyCapuaToCadencebookWork(pieceObj) srcStream = pieceObj.snippets[0].parts[0].flat.notesAndRests cmpStream = pieceObj.snippets[0].parts[1].flat.notesAndRests ## ignore 3rd voice for now... srcStream.attachIntervalsBetweenStreams(cmpStream) cmpStream.attachIntervalsBetweenStreams(srcStream) #colorCapuaFicta(srcStream, cmpStream, 'both') outList = [] for note in srcStream: if note.editorial.harmonicInterval is not None: outSublist = [] outSublist.append(note.name) outSublist.append(note.editorial.harmonicInterval.simpleName) if "capua-ficta" in note.editorial.misc: outSublist.append(repr(note.editorial.misc['capua-ficta'])) else: outSublist.append(None) outList.append(outSublist) self.assertEqual(outList, [[u'A', 'P5', None], [u'A', 'M6', None], [u'G', 'P5', None], [u'G', 'm6', None], [u'A', 'm7', None], [u'F', 'd5', '<accidental sharp>'], [u'G', 'm6', None], [u'A', 'P1', None], [u'B', 'M6', None], [u'A', 'P5', None], [u'G', 'm7', None], [u'G', 'm6', None], [u'F', 'd5', None], [u'E', 'M3', None], [u'D', 'P1', None] ]) #pieceObj.asOpus().show('lily.pdf') return pieceObj
def sortMelodicFifths(): ''' Finds instances of melodic Perfect fifths or Fourths (a harmonic version should also be made) to see if the B-F# fifth/fourth is actually less used than other common fifths when adjusting for the % of notes that are B or F#. ''' ballataObj = cadencebook.BallataSheet() for pieceObj in ballataObj: if pieceObj.incipit is None: continue print(pieceObj.title) for polyphonicSnippet in pieceObj.snippets: if polyphonicSnippet is None: continue for thisStream in polyphonicSnippet.streams: thisStream.generateIntervalLists() for thisNote in thisStream: if thisNote.editorial is None: continue elif thisNote.editorial.melodicIntervalOverRests is None: continue elif thisNote.editorial.melodicIntervalOverRests.simpleName == "P4" or \ thisNote.editorial.melodicIntervalOverRests.simpleName == "P5": print(thisNote.name)
def improvedHarmony(startPiece=2, endPiece=459): ''' Find how often an augmented or diminished interval was corrected to a perfect interval and vice-versa by capua. Returns a dict showing the results >>> #_DOCS_SHOW trecento.capua.improvedHarmony() >>> print("{'imperfCapua': 22, 'imperfIgnored': 155, 'perfCapua': 194, 'perfIgnored': 4057}") #_DOCS_HIDE {'imperfCapua': 22, 'imperfIgnored': 155, 'perfCapua': 194, 'perfIgnored': 4057} ''' ballataObj = cadencebook.BallataSheet() checkDict = { "perfIgnored": 0, "perfCapua": 0, "imperfIgnored": 0, "imperfCapua": 0 } for i in range(startPiece, endPiece): # all ballate # for i in range(2, 29): # small number of ballate # for i in range(232, 373): # all of Landini ballate # environLocal.printDebug("Working on piece number %d " % i) pieceObj = ballataObj.makeWork( i) ## N.B. -- we now use Excel column numbers if pieceObj.incipit is None: continue for thisSnippet in pieceObj.snippets: #thisSnippetAppended = False if thisSnippet is None: continue if "Incipit" in thisSnippet.classes: continue thisSnippetParts = thisSnippet.parts if len(thisSnippetParts) < 2: continue srcStream1 = thisSnippetParts['C'].flat.notesAndRests srcStream2 = thisSnippetParts[ 'T'].flat.notesAndRests ## ignore 3rd voice for now... srcStream1.attachIntervalsBetweenStreams(srcStream2) #srcStream2.attachIntervalsBetweenStreams(srcStream1) applyCapuaToStream(srcStream1) for ss in [srcStream1, srcStream2]: srcStreamNotes = ss.notes # get rid of rests #srcStreamLen = len(srcStreamNotes) for (i, note1) in enumerate(srcStreamNotes): hI = note1.editorial.harmonicInterval if hI is None or \ hI.generic.perfectable is False or \ hI.generic.simpleUndirected == 4: continue #### KEEP PROGRAMMING FROM HERE if hI.diatonic.specificName == "Perfect": if "capua-ficta" in note1.editorial.misc: checkDict[ "perfCapua"] += 1 ## ugh Capua changed a P1, P5, or P8 else: checkDict[ "perfIgnored"] += 1 ## yay Capua left it alone else: if "capua-ficta" in note1.editorial.misc: checkDict[ "imperfCapua"] += 1 ## yay Capua changed a A1 or d1, A5 or d5, or A8 or d8 else: checkDict[ "imperfIgnored"] += 1 ## hrumph, Capua left it alone return checkDict
def findCorrections(correctionType="Maj3", startPiece=2, endPiece=459): ''' Find all cases where a Major 3rd moves inward to unison (within the next two or three notes, excluding rests) and see how often the PMFC editors correct it to minor 3rd and how often Capua gets it. or if correctionType == "min6" find all instances of a minor 6th moving outward to octave and see how often the PMFC editors correct it to a Major 6th and how often Capua gets it. # # >>> (totalDict, foundPieceOpus) = findCorrections(correctionType="Maj3", 2, 50) # >>> print(totalDict) # {'potentialChange': 82, 'capuaAlt': 30, 'pmfcAndCapua': 3, 'capuaNotPmfc': 27, 'pmfcAlt': 4, 'pmfcNotCapua': 1, 'totalNotes': 82} # >>> foundPieceOpus.show('lily.pdf') # >>> (totalDict, foundPieceOpus) = findCorrections(correctionType="min6") # >>> print(totalDict) # {'potentialChange': 82, 'capuaAlt': 30, 'pmfcAndCapua': 3, 'capuaNotPmfc': 27, 'pmfcAlt': 4, 'pmfcNotCapua': 1, 'totalNotes': 82} # >>> foundPieceOpus.show('lily.pdf') # >>> #_DOCS_SHOW (totalDict, foundPieceOpus) = trecento.capua.correctedMin6() # >>> totalDict = {'potentialChange': 82, 'capuaAlt': 30, 'pmfcAndCapua': 3, 'capuaNotPmfc': 27, 'pmfcAlt': 4, 'pmfcNotCapua': 1, 'totalNotes': 82} #_DOCS_HIDE # >>> print(totalDict) # {'alterAll': 82, 'capuaAlt': 30, 'pmfcAndCapua': 3, 'capuaNotPmfc': 27, 'pmfcAlt': 4, 'pmfcNotCapua': 1, 'totalNotes': 82} # >>> #_DOCS_SHOW foundPieceOpus.show('lily.pdf') ''' ballataObj = cadencebook.BallataSheet() totalDict = { 'totalNotes': 0, 'pmfcAlt': 0, 'capuaAlt': 0, 'pmfcNotCapua': 0, 'capuaNotPmfc': 0, 'pmfcAndCapua': 0, 'potentialChange': 0 } if correctionType == 'Maj3': notesToCheck = 1 simpleNameToCheck = 'm3' elif correctionType == "min6": notesToCheck = 2 # allows Landini cadences, but not much more simpleNameToCheck = 'M6' else: raise CapuaException( "Invalid correctionType to check; I can check 'Maj3' or 'min6'") foundPieceOpus = stream.Opus() for i in range(startPiece, endPiece): # all ballate # for i in range(2, 29): # small number of ballate # for i in range(232, 373): # all of Landini ballate pieceObj = ballataObj.makeWork( i) ## N.B. -- we now use Excel column numbers if pieceObj.incipit is None: continue environLocal.warn("Working on piece number %d, %s " % (i, pieceObj.title)) for thisSnippet in pieceObj.snippets: thisSnippetAppended = False if thisSnippet is None: continue if "Incipit" in thisSnippet.classes: continue thisSnippetParts = thisSnippet.parts if len(thisSnippetParts) < 2: continue srcStream1 = thisSnippetParts['C'].flat.notesAndRests srcStream2 = thisSnippetParts[ 'T'].flat.notesAndRests ## ignore 3rd voice for now... srcStream1.attachIntervalsBetweenStreams(srcStream2) srcStream2.attachIntervalsBetweenStreams(srcStream1) if thisSnippetAppended is False: foundPieceOpus.insert(0, thisSnippet) thisSnippetAppended = True applyCapuaToStream(srcStream1) applyCapuaToStream(srcStream2) for ss in [srcStream1, srcStream2]: srcStreamNotes = ss.notes # get rid of rests srcStreamLen = len(srcStreamNotes) for (i, note1) in enumerate(srcStreamNotes): if note1.editorial.harmonicInterval is None or \ note1.editorial.harmonicInterval.simpleName != simpleNameToCheck: continue if i >= srcStreamLen - notesToCheck: if i == srcStreamLen - 1: continue else: nextFewNotes = srcStreamNotes[i + 1:] else: nextFewNotes = srcStreamNotes[i + 1:i + 1 + notesToCheck] #nextFewNotes = srcStream1.notesFollowingNote(note1, notesToCheck, allowRests = False) foundP8 = False for thisNote in nextFewNotes: if thisNote is None: raise CapuaException( "This was only supposed to return non-None, what is up???" ) if thisNote.editorial.harmonicInterval is None: continue ## probably a rest; should not happen if correctionType == 'Maj3': if thisNote.editorial.harmonicInterval.simpleName == "P1": foundP8 = True elif correctionType == 'min6': if thisNote.editorial.harmonicInterval.semiSimpleName == "P8": foundP8 = True if foundP8 is False: continue newResults = compareNoteCapuaToEditor(note1) newResults['potentialChange'] = 1 for thisKey in newResults: if thisKey == 'alterAll': continue if thisKey == 'capuaNotPmfc' and newResults[ thisKey] == 1: if thisSnippetAppended is False: foundPieceOpus.insert(0, thisSnippet) thisSnippetAppended = True totalDict[thisKey] += newResults[thisKey] return (totalDict, foundPieceOpus)
def nonLandiniTonality(show = True): ''' generates information about the tonality of not anonymous ballate that are not by Francesco (Landini) using the tenor (streamName = "T") and the A cadence (which we would believe would end the piece) >>> #_DOCS_SHOW trecento.tonality.nonLandiniTonality(show = True) Prints something like this:: Deduto sey a quel C F A pianger l'ochi C D Con dogliosi martire E D De[h], vogliateme oldire C G Madonna, io me ramento C D Or tolta pur F A I' senti' matutino G C Ad ogne vento C C ... etc... ... Donna, perche mi veggi G D Lasso! grav' è 'l partire F F La vaga luce G F Lena virtù et sperança F D Ma' ria avere C F Non c'è rimasa fe' G D Or sie che può G D Perchè vendetta F D Perch'i' non sep(p)i G D Poc' [h]anno di mirar F D S'amor in cor gentile F C Se per virtù amor, C G Sofrir m'estuet A C Una cosa di veder G D Vago et benigno amor G D L'adorno viso C G Già molte volte G C O me! al cor dolente D D Benchè lontan mi trovi A D Dicovi per certança G G Ferito già d'un amoroso A D Movit' a pietade D D Non voler donna A D Sol mi trafig(g)e 'l cor C C Se le lagrime antique F F **** A A 1 A C 3 A D 15 A diff 18 B F 1 B diff 1 C A 1 **** C C 10 C D 4 C F 2 C G 4 C diff 11 D A 1 D C 6 **** D D 16 D F 4 D G 10 D diff 21 E C 2 E D 1 E F 1 E diff 4 F A 2 F B 1 F C 3 F D 8 **** F F 11 F G 4 F diff 18 G A 1 G B 1 G C 12 G D 15 G E 1 G F 1 **** G G 11 G diff 31 Total Same 49 32.0% Total Diff 104 68.0% ''' ballataObj = cadencebook.BallataSheet() worksList = [] for thisWork in ballataObj: if show == True: print(thisWork.title) if thisWork.composer != "Landini" and thisWork.composer != ".": worksList.append(thisWork) tCounter = TonalityCounter(worksList, streamName = "T", cadenceName = "A") tCounter.run() if show is True: print(tCounter.output)