def generateFirstSpecies(self, stream1, minorScale): '''Given a stream (the cantus firmus) and the stream's key in the form of a MinorScale object, generates a stream of first species counterpoint that follows the rules of 21M.301.''' # DOES NOT YET CHECK FOR TOO MANY THIRDS/SIXTHS IN A ROW, # DOES NOT YET RAISE LEADING TONES, AND DOES NOT CHECK FOR NOODLING. stream2 = Stream([]) firstNote = stream1.notes[0] choices = [interval.transposeNote(firstNote, "P1"),\ interval.transposeNote(firstNote, "P5"),\ interval.transposeNote(firstNote, "P8")] note1 = random.choice(choices) note1.duration = firstNote.duration stream2.append(note1) afterLeap = False for i in range(1, len(stream1.notes)): prevFirmus = stream1.notes[i-1] currFirmus = stream1.notes[i] prevNote = stream2.notes[i-1] choices = self.generateValidNotes(prevFirmus, currFirmus, prevNote, afterLeap, minorScale) if len(choices) == 0: raise ModalCounterpointException("Sorry, please try again") newNote = random.choice(choices) newNote.duration = currFirmus.duration stream2.append(newNote) int = interval.notesToInterval(prevNote, newNote) if int.generic.undirected > 3: afterLeap = True else: afterLeap = False return stream2
def raiseLeadingTone(self, stream1, minorScale): '''Given a stream of notes and a minor scale object, returns a new stream that raises all the leading tones of the original stream. Also raises the sixth if applicable to avoid augmented intervals.''' notes2 = stream1.notes[:] stream2 = Stream(notes2) sixth = minorScale.pitchFromScaleDegree(6).name seventh = minorScale.pitchFromScaleDegree(7).name tonic = minorScale.getTonic().name for i in range(len(stream1.notes)-2): note1 = stream1.notes[i] note2 = stream1.notes[i+1] note3 = stream1.notes[i+2] if note1 is not None and note2 is not None and note3 is not None: if note1.name == sixth and note2.name == seventh and note3.name == tonic: newNote1 = interval.transposeNote(note1, "A1") newNote2 = interval.transposeNote(note2, "A1") stream2.notes[i] = newNote1 stream2.notes[i+1] = newNote2 for i in range(len(stream1.notes)-1): note1 = stream1.notes[i] note2 = stream1.notes[i+1] if note1 is not None and note2 is not None: if note1.name == seventh and note2.name == tonic: newNote = interval.transposeNote(note1, "A1") stream2.notes[i] = newNote return stream2
def parseData(self, sounding, qL=2, splitNote="C4"): theSound = sounding.IntervallStruktur bassnotes = list(sounding.Bassnoten) bassschritte = sounding.Bassschritte followingSoundings = [] for bs in bassschritte: for syz in bassschritte[bs]: followingSoundings.append((bs, syz)) #print(followingSoundings) bass = note.Note(bassnotes[0]) bass.quarterLength = qL for each in followingSoundings: self._distributeNotes2VocalScore(theSound, bass, splitNote) secondBass = interval.transposeNote(bass, each[0]) self._distributeNotes2VocalScore(each[1], secondBass, splitNote)
def _distributeNotes2VocalScore(self, listOfIntervals, bassNote, splitNote="C4"): cpBass = deepcopy(bassNote) if bassNote.pitch >= pitch.Pitch(splitNote): self.part1.append(cpBass) else: self.part2.append(cpBass) #offset setzen offset = cpBass.offset #Akkorde hinzusetzen for intv in listOfIntervals: #print(intv) nNew = interval.transposeNote(bassNote, intv) if nNew.pitch >= pitch.Pitch(splitNote): self.part1.insert(offset, nNew) else: self.part2.insert(offset, nNew)
def generateValidNotes(self, prevFirmus, currFirmus, prevNote, afterLeap, minorScale): '''Helper function for generateFirstSpecies; gets a list of possible next notes based on valid melodic intervals, then checks each one so that parallel/hidden fifths/octaves, voice crossing, and invalid harmonies are prevented. Adds extra weight to notes that would create contrary motion.''' print currFirmus.name valid = [] bottomInt = interval.notesToInterval(prevFirmus, currFirmus) if bottomInt.direction < 0: ascending = True else: ascending = False n1 = interval.transposeNote(prevNote, "m2") n2 = interval.transposeNote(prevNote, "M2") n3 = interval.transposeNote(prevNote, "m3") n4 = interval.transposeNote(prevNote, "M3") n5 = interval.transposeNote(prevNote, "P4") n6 = interval.transposeNote(prevNote, "P5") if afterLeap: possible = [n1, n2, n3, n4] else: possible = [n1, n2, n3, n4, n5, n6] possible.extend(possible) n7 = interval.transposeNote(prevNote, "m-2") n8 = interval.transposeNote(prevNote, "M-2") n9 = interval.transposeNote(prevNote, "m-3") n10 = interval.transposeNote(prevNote, "M-3") n11 = interval.transposeNote(prevNote, "P-4") n12 = interval.transposeNote(prevNote, "P-5") if afterLeap: possible.extend([n7, n8, n9, n10]) else: possible.extend([n7, n8, n9, n10, n11, n12]) print "possible: ", [note1.name for note1 in possible] for note1 in possible: try: validHarmony = self.isValidHarmony(note1, currFirmus) except: validHarmony = False # vlq = VoiceLeadingQuartet(prevNote, prevFirmus, note1, currFirmus) # par5 = vlq.parallelFifth() # par8 = vlq.parallelOctave() # hid5 = vlq.hiddenFifth() # hid8 = vlq.hiddenOctave() # par1 = vlq.parallelUnison() try: par5 = self.isParallelFifth(prevNote, note1, prevFirmus, currFirmus) except: par5 = True try: par8 = self.isParallelOctave(prevNote, note1, prevFirmus, currFirmus) except: par8 = True try: hid5 = self.isHiddenFifth(prevNote, note1, prevFirmus, currFirmus) except: hid5 = True try: hid8 = self.isHiddenOctave(prevNote, note1, prevFirmus, currFirmus) except: hid8 = True try: par1 = self.isParallelUnison(prevNote, note1, prevFirmus, currFirmus) except: par1 = True try: distance = interval.notesToInterval(currFirmus, note1) if distance.direction < 0: crossing = True else: crossing = False except: crossing = True goodNotes = minorScale.getConcreteMelodicMinorScale() goodNames = [note2.name for note2 in goodNotes] if validHarmony and (not par5) and (not par8) and (not hid5) and\ (not hid8) and (not par1) and (not crossing): if note1.name in goodNames: print "adding: ", note1.name, note1.octave valid.append(note1) print return valid