def __init__(self, tonic=None, mode=None): if tonic is not None: if hasattr(tonic, 'classes') and ('Music21Object' in tonic.classes or 'Pitch' in tonic.classes): if hasattr(tonic, 'name'): tonic = tonic.name elif hasattr( tonic, 'pitches') and tonic.pitches: # chord w/ >= 1 pitch if mode is None: if tonic.isMinorTriad() is True: mode = 'minor' else: mode = 'major' tonic = tonic.root().name if mode is None: if 'm' in tonic: mode = 'minor' tonic = re.sub('m', '', tonic) elif 'M' in tonic: mode = 'major' tonic = re.sub('M', '', tonic) elif tonic.lower() == tonic: mode = 'minor' else: mode = 'major' else: mode = mode.lower() sharps = pitchToSharps(tonic, mode) KeySignature.__init__(self, sharps) scale.DiatonicScale.__init__(self, tonic=tonic) if hasattr(tonic, 'classes') and 'Pitch' in tonic.classes: self.tonic = tonic else: self.tonic = pitch.Pitch(tonic) self.type = mode self.mode = mode # build the network for the appropriate scale self._abstract._buildNetwork(self.type) # optionally filled attributes # store a floating point value between 0 and 1 regarding # correlation coefficent between the detected key and the algorithm for detecting the key self.correlationCoefficient = None # store an ordered list of alternative Key objects self.alternateInterpretations = []
def testGetAugDimScore(self): pList = [pitch.Pitch('C'), pitch.Pitch('D'), pitch.Pitch('E')] es = EnharmonicSimplifier(pList) poss = [pitch.Pitch('C'), pitch.Pitch('D'), pitch.Pitch('E')] testAugDimScore = es.getAugDimScore(poss) self.assertEqual(len(pList), 3) self.assertIsInstance(testAugDimScore, int)
def retrieveSegments(self, fbRules=None, numParts=4, maxPitch=None): ''' generates the segmentList from an fbList, including any overlaid Segments if fbRules is None, creates a new rules.Rules() object if maxPitch is None, uses pitch.Pitch('B5') ''' if fbRules is None: fbRules = rules.Rules() if maxPitch is None: maxPitch = pitch.Pitch('B5') segmentList = [] bassLine = self.generateBassLine() if len(self._overlaidParts) >= 1: self._overlaidParts.append(bassLine) currentMapping = checker.extractHarmonies(self._overlaidParts) else: currentMapping = checker.createOffsetMapping(bassLine) allKeys = sorted(currentMapping.keys()) bassLine = bassLine.flat.notes bassNoteIndex = 0 previousBassNote = bassLine[bassNoteIndex] bassNote = currentMapping[allKeys[0]][-1] previousSegment = segment.OverlaidSegment(bassNote, bassNote.notationString, self._fbScale, fbRules, numParts, maxPitch) previousSegment.quarterLength = previousBassNote.quarterLength segmentList.append(previousSegment) for k in allKeys[1:]: (startTime, unused_endTime) = k bassNote = currentMapping[k][-1] currentSegment = segment.OverlaidSegment(bassNote, bassNote.notationString, self._fbScale, fbRules, numParts, maxPitch) for partNumber in range(1, len(currentMapping[k])): upperPitch = currentMapping[k][partNumber - 1] currentSegment.fbRules._partPitchLimits.append((partNumber, upperPitch)) if startTime == previousBassNote.offset + previousBassNote.quarterLength: bassNoteIndex += 1 previousBassNote = bassLine[bassNoteIndex] currentSegment.quarterLength = previousBassNote.quarterLength else: for partNumber in range(len(currentMapping[k]), numParts + 1): previousSegment.fbRules._partsToCheck.append(partNumber) # Fictitious, representative only for harmonies preserved # with addition of melody or melodies currentSegment.quarterLength = 0.0 segmentList.append(currentSegment) previousSegment = currentSegment return segmentList
def generate_tonic_triad(root_scale, tonic, string_set, voicing): # generate the starting chord for this particular string set triad_root = pitch.Pitch(tonic) triad_root.octave = string_set[0].lowest_pitch.octave triad_root.transposeAboveTarget(string_set[0].lowest_pitch, inPlace=True) if voicing == Voicing.Closed: tonic_triad = chord.Chord(root_scale.pitchesFromScaleDegrees([1, 3, 5], triad_root, triad_root.transpose(11))) elif voicing == Voicing.Drop2_A_form or voicing == Voicing.Drop2_B_form: tonic_triad = chord.Chord([triad_root, triad_root.transpose(7), triad_root.transpose(16)]) else: raise Exception("invalid voicing passed") return tonic_triad
def testSetTonic(self): from music21 import chord k = Key() # Set tonic attribute from single pitch b = pitch.Pitch('B') k.tonic = b self.assertIs(k.tonic, b) # Initialize with tonic from chord - no longer allowed. # Call root explicitly b_flat_maj = chord.Chord('Bb4 D5 F5').root() k = Key(tonic=b_flat_maj) self.assertEqual(k.tonic.name, 'B-')
def init_UI(self): self.master.title("Logitech G-Suite Macro API Lua Script Generator for Shawzin - App GUI") self.master.geometry(f"{self.width}x{self.height}+{0}+{0}") self.master.resizable(True, False) self.config(width=self.width, height=self.height) self.grid(row=0) self.update_idletasks() # Pitch Buttons self.pitch_buttons = [] for gui_column in range(3): # for each octave of pitch buttons for octave_offset in range(12): # for each pitch in that octave # create a button on the GUI to add that pitch to the current chord self.pitch_buttons.append(PitchAdderButton(self, pitch.Pitch(60 + 12*gui_column + octave_offset))) # and configure the button's positioning self.pitch_buttons[-1].grid(row=11-octave_offset, column=gui_column, columnspan=1, sticky="NW") # disable the buttons of pitches that are not actually playable on shawzin for button in self.pitch_buttons: if button.pitch.midi == 83 or button.pitch.midi >= 88: button.config(state="disabled") # WaitTime Buttons self.wait_buttons = [] # for each rest length /2 for i, inv_notelen in enumerate((1, 2, 4, 8, 16, 32)): # create a button on the GUI to add a rest of that length onto the piece self.wait_buttons.append(WaitAdderButton(self, inv_notelen)) # and configure the button's positioning self.wait_buttons[-1].grid(row=i, column=3, columnspan=1, sticky="NE") # for each rest length /3 for i, inv_notelen in enumerate((3, 6, 12, 24, 48)): # create a button self.wait_buttons.append(WaitAdderButton(self, inv_notelen)) # configure its positioning self.wait_buttons[-1].grid(row=i+1, column=4, columnspan=1, sticky="NE") # Quarter Note Length Entry (WIP) # TODO self.quarter_length_entry = QuarterLengthEntry(self) self.quarter_length_entry.grid(row=1, column=5, columnspan=2, sticky="NE") self.quarter_length_entry_label = tk.Label(self) self.quarter_length_entry_label.config(text="Quarter Note Length", anchor="s") self.quarter_length_entry_label.grid(row=0, column=5, columnspan=2, sticky="SW") # Backspace Button self.backspace_button = BackspaceButton(self) # deletes most recent chord + rest self.backspace_button.grid(row=3, column=5, columnspan=2, sticky="SW") # Generate Button self.generate_button = GeneratorButton(self) # stores the piece to output file self.generate_button.grid(row=4, column=5, columnspan=2, sticky="SW")
def __init__(self, tonic: t.Union[str, pitch.Pitch, note.Note] = 'C', mode=None): if isinstance(tonic, (note.Note, pitch.Pitch)): tonicStr = tonic.name else: tonicStr = tonic if mode is None: if 'm' in tonicStr: mode = 'minor' tonicStr = re.sub('m', '', tonicStr) elif 'M' in tonicStr: mode = 'major' tonicStr = re.sub('M', '', tonicStr) elif tonicStr.lower() == tonicStr: mode = 'minor' else: mode = 'major' else: mode = mode.lower() sharps = pitchToSharps(tonicStr, mode) tonicPitch: pitch.Pitch if isinstance(tonic, pitch.Pitch): tonicPitch = tonic elif isinstance(tonic, note.Note): tonicPitch = tonic.pitch else: tonicPitch = pitch.Pitch(tonicStr) KeySignature.__init__(self, sharps) scale.DiatonicScale.__init__(self, tonic=tonicPitch) self.tonic = tonicPitch self.type: str = mode self.mode: str = mode # build the network for the appropriate scale if self._abstract is not None: self._abstract.buildNetwork(self.type) # optionally filled attributes # store a floating point value between 0 and 1 regarding # correlation coefficient between the detected key and the algorithm for detecting the key self.correlationCoefficient = None # store an ordered list of alternative Key objects self.alternateInterpretations: t.List[Key] = []
def getPitches(pitchNames=('C', 'E', 'G'), bassPitch: Union[str, pitch.Pitch] = 'C3', maxPitch: Union[str, pitch.Pitch] = 'C8'): ''' Given a list of pitchNames, a bassPitch, and a maxPitch, returns a sorted list of pitches between the two limits (inclusive) which correspond to items in pitchNames. >>> from music21.figuredBass import segment >>> from music21 import pitch >>> pitches = segment.getPitches() >>> print(', '.join([p.nameWithOctave for p in pitches])) C3, E3, G3, C4, E4, G4, C5, E5, G5, C6, E6, G6, C7, E7, G7, C8 >>> pitches = segment.getPitches(['G', 'B', 'D', 'F'], bassPitch=pitch.Pitch('B2')) >>> print(', '.join([p.nameWithOctave for p in pitches])) B2, D3, F3, G3, B3, D4, F4, G4, B4, D5, F5, G5, B5, D6, F6, G6, B6, D7, F7, G7, B7 >>> pitches = segment.getPitches(['F##', 'A#', 'C#'], bassPitch=pitch.Pitch('A#3')) >>> print(', '.join([p.nameWithOctave for p in pitches])) A#3, C#4, F##4, A#4, C#5, F##5, A#5, C#6, F##6, A#6, C#7, F##7, A#7 ''' if isinstance(bassPitch, str): bassPitch = pitch.Pitch(bassPitch) if isinstance(maxPitch, str): maxPitch = pitch.Pitch(maxPitch) iter1 = itertools.product(pitchNames, range(maxPitch.octave + 1)) iter2 = map(lambda x: pitch.Pitch(x[0] + str(x[1])), iter1) iter3 = itertools.filterfalse(lambda samplePitch: bassPitch > samplePitch, iter2) iter4 = itertools.filterfalse(lambda samplePitch: samplePitch > maxPitch, iter3) allPitches = list(iter4) allPitches.sort() return allPitches
def toPitch(pitchString, languageString): ''' Converts a string to a :class:`music21.pitch.Pitch` object given a language. Supported languages are French, German, Italian, and Spanish Defaults to C natural >>> languageExcerpts.naturalLanguageObjects.toPitch("Es", "de") <music21.pitch.Pitch E-> >>> languageExcerpts.naturalLanguageObjects.toPitch("H", "de") <music21.pitch.Pitch B> >>> for i in ['As', 'A', 'Ais']: ... print(languageExcerpts.naturalLanguageObjects.toPitch(i, "de")) A- A A# ''' langDict = generateLanguageDictionary(languageString) if pitchString not in langDict: return pitch.Pitch("C") return pitch.Pitch(langDict[pitchString])
def convertToPitch(pitchString): ''' Converts a pitch string to a music21 pitch, only if necessary. >>> from music21 import * >>> pitchString = 'C5' >>> convertToPitch(pitchString) C5 >>> convertToPitch(pitch.Pitch('E4')) #does nothing E4 ''' pitchValue = pitchString if type(pitchString) == str: pitchValue = pitch.Pitch(pitchString) return pitchValue
def testCleanFlat(self): from music21 import pitch cs = harmony.ChordSymbol(root='eb', bass='bb', kind='dominant') self.assertEqual(cs.bass(), pitch.Pitch('B-2')) self.assertIs(cs.pitches[0], cs.bass()) cs = harmony.ChordSymbol('e-7/b-') self.assertEqual(cs.root(), pitch.Pitch('E-3')) self.assertEqual(cs.bass(), pitch.Pitch('B-2')) self.assertEqual(cs.pitches[0], pitch.Pitch('B-2')) # common.cleanedFlatNotation() shouldn't be called by # the following calls, which what is being tested here: cs = harmony.ChordSymbol('b-3') self.assertEqual(cs.root(), pitch.Pitch('b-3')) self.assertEqual(cs.pitches[0], pitch.Pitch('B-3')) self.assertEqual(cs.pitches[1], pitch.Pitch('D4')) cs = harmony.ChordSymbol('bb3') self.assertEqual(cs.root(), pitch.Pitch('b3')) self.assertEqual(cs.pitches[0], pitch.Pitch('B3')) self.assertEqual(cs.pitches[1], pitch.Pitch('D#4'))
def midi_pitch(self): mat = re.match(PigNote.PITCH_RE, self.name) base_name = mat.group(1) accidental = mat.group(2) octave = mat.group(3) m21_accidental = '' for acc in accidental: if acc == 'b': m21_accidental += '-' else: m21_accidental += '#' m21_name = base_name + m21_accidental + octave pit = pitch.Pitch(m21_name) # print("{} ==> {} and {}".format(self.name, m21_name, pit.midi)) return pit.midi
def transpose(midi_dir, key): kk = 0 save_dir = create_midi_dir(midi_dir) for fn in glob.glob(midi_dir + '/*.mid'): s = converter.parse(fn) k = s.analyze('key') i = interval.Interval(k.tonic, pitch.Pitch(key)) sNew = s.transpose(i) head, tail = os.path.split(fn) filename = tail.split('.')[0] newFileName = save_dir + "/" + key + "_" + str(filename) + ".mid" sNew.write('midi', newFileName) print("Saved midi file to {}".format(newFileName)) kk += 1 return midi_dir
def testMicrotoneA(self): p = pitch.Pitch('a4') p.microtone = 25 self.assertEqual(str(p), 'A4(+25c)') self.assertEqual(p.ps, 69.25) p.microtone = '-10' self.assertEqual(str(p), 'A4(-10c)') self.assertEqual(p.ps, 68.90) self.assertEqual(p.pitchClass, 9) p = p.transpose(12) self.assertEqual(str(p), 'A5(-10c)') self.assertEqual(p.ps, 80.90)
def getPitches(self): ''' Returns a list of all the pitches (or None for each) given the FretNote information. This requires a tuning to be set. >>> firstNote = tablature.FretNote(string=4, fret=3, fingering=3) >>> secondNote = tablature.FretNote(string=2, fret=1, fingering=1) >>> gfb = tablature.GuitarFretBoard(fretNotes=[firstNote, secondNote]) >>> gfb.getPitches() [None, None, <music21.pitch.Pitch F3>, None, <music21.pitch.Pitch C4>, None] What if the User provides an empty FretBoard? >>> gfb2 = tablature.GuitarFretBoard(fretNotes=[]) >>> gfb2.getPitches() [None, None, None, None, None, None] Works for other stringed instruments, as long as the tuning is included (see below). >>> tablature.UkeleleFretBoard().numStrings 4 >>> uke = tablature.UkeleleFretBoard(fretNotes=[firstNote, secondNote]) >>> uke.getPitches() [<music21.pitch.Pitch B-4>, None, <music21.pitch.Pitch F4>, None] ''' if len(self.tuning) != self.numStrings: raise TablatureException( 'Tuning must be set first, tuned for {0} notes, on a {1} string instrument'.format( len(self.tuning), self.numStrings )) pitchList: List[Optional['music21.pitch.Pitch']] = [None] * self.numStrings if not self.fretNotes: return pitchList for thisFretNote in self.fretNotes: pitchListPosition = (thisFretNote.string * -1) tuningPitch = self.tuning[pitchListPosition] tuningPitchAsPs = tuningPitch.ps actualPitch = tuningPitchAsPs + thisFretNote.fret displayPitch = pitch.Pitch(actualPitch) pitchList[pitchListPosition] = displayPitch return pitchList
def save_mat2_mid(mat, fname='output/test.mid'): music_stream = stream.Stream() for dense_line in np.array(mat): (notes,) = np.where(dense_line[:-1]>0.5) pitches = [] for n in notes: pitches.append(pitch.Pitch(midi=n)) crd = chord.Chord(notes= pitches, quarterLength=np.round(dense_line[-1]*2048)/2048) music_stream.append(crd) md = midi.translate.streamToMidiFile(music_stream) md.open(fname, 'wb') md.write() md.close()
def __init__(self, fretNotes=None, displayFrets=4): numStrings = 6 super().__init__(numStrings, fretNotes, displayFrets) self.tuning = [ pitch.Pitch('E2'), pitch.Pitch('A2'), pitch.Pitch('D3'), pitch.Pitch('G3'), pitch.Pitch('B3'), pitch.Pitch('E4') ]
def get_mus21_pitch(note): """Convert pygliss.note to music21.pitch.""" if note.accidental == '+': return pitch.Pitch(name=note.note + "~" + str(note.octave)) elif note.accidental == '#': return pitch.Pitch(name=note.note + "#" + str(note.octave)) elif note.accidental == '++': return pitch.Pitch(name=note.note + "#~" + str(note.octave)) elif note.accidental == '-': return pitch.Pitch(name=note.note + "`" + str(note.octave)) elif note.accidental == 'b': return pitch.Pitch(name=note.note + "-" + str(note.octave)) elif note.accidental == '--': return pitch.Pitch(name=note.note + "-`" + str(note.octave)) else: return pitch.Pitch(note.note + str(note.octave))
def getNoteFromFileName(filename): #print("getNoteFromFileName", filename) result = notefilenamepattern.search(filename) if result == None: return None #print("result", result.group(0)) fullnote = result.group(0) try: p = pitch.Pitch(fullnote) return p.midi except(pitch.AccidentalException, pitch.PitchException) as err: print("Cannot make note from " + fullnote) return None return None
def pitchClassSet(self): r''' Gets the pitch-class set of all elements in a verticality. >>> score = corpus.parse('bwv66.6') >>> tree = timespans.streamToTimespanTree(score, flatten=True, classList=(note.Note, chord.Chord)) >>> verticality = tree.getVerticalityAt(1.0) >>> for pitchClass in sorted(verticality.pitchClassSet): ... pitchClass ... <music21.pitch.Pitch C#> <music21.pitch.Pitch F#> <music21.pitch.Pitch A> ''' pitchClassSet = set() for currentPitch in self.pitchSet: pitchClass = pitch.Pitch(currentPitch.name) pitchClassSet.add(pitchClass) return pitchClassSet
def modifyPitchName(self, pitchNameToAlter): ''' Given a pitch name, modify its accidental given the Modifier's :attr:`~music21.figuredBass.notation.Modifier.accidental`. >>> from music21.figuredBass import notation >>> m1 = notation.Modifier('#') >>> m2 = notation.Modifier('-') >>> m3 = notation.Modifier('n') >>> m1.modifyPitchName('D') # Sharp 'D#' >>> m2.modifyPitchName('F') # Flat 'F-' >>> m3.modifyPitchName('C#') # Natural 'C' ''' pitchToAlter = pitch.Pitch(pitchNameToAlter) self.modifyPitch(pitchToAlter, True) return pitchToAlter.name
def sample_by_symbol(interval_size, direction, prev_note, matrix): i = interval.Interval() intervals = [] if interval_size == 'S': if direction == 'UP': r = range(0, 6) else: r = range(0, -6, -1) else: if direction == 'UP': r = range(6, 11) else: r = range(-6, -11, -1) for i in r: i = interval.Interval(i) inter = get_normal_pitch_name(i.transposePitch(pitch.Pitch(prev_note))) intervals.append(inter) return sample_random_pitch(matrix, intervals, prev_note)
def getOnePitchFromPosition(self, pos): ''' get one pitch from a position... >>> nwt = noteworthy.translate.NoteworthyTranslator() >>> nwt.currentClef = 'BASS' >>> p = nwt.getOnePitchFromPosition('b3') >>> p <music21.pitch.Pitch G-3> >>> p.ps 54.0 ''' accidental = "" if pos[0] in ['n', 'b', '#', 'x', 'v']: accidental = pos[0] pos = pos[1:] if accidental == 'b': accidental = '-' elif accidental == 'x': accidental = '##' elif accidental == 'v': accidental = "--" positionNote = int(pos) (noteStep, octave) = self.getStepAndOctaveFromPosition(positionNote) p = pitch.Pitch() p.step = noteStep p.octave = octave pname = p.nameWithOctave if accidental != "": p.accidental = pitch.Accidental(accidental) self.activeAccidentals[pname] = accidental ## previous accidental in same bar that is still active elif pname in self.activeAccidentals: p.accidental = pitch.Accidental(self.activeAccidentals[pname]) else: stepAccidental = self.currentKey.accidentalByStep(noteStep) if stepAccidental is not None: p.accidental = stepAccidental return p
def get_or_create_sample(inputfilepath=None, tone=None, bpm=None, midi=None, notename=None, octave=None): if (notename and octave): p = pitch.Pitch(notename) p.octave = octave midi = p.midi if Sample.exists(tone=tone, midi=midi): return Sample.get(tone=tone, midi=midi) return Sample(inputfilepath=inputfilepath, tone=tone, bpm=bpm, midi=midi, notename=notename, octave=octave)
def getNoteList(part, transpose=True): notes = [] if transpose == True: part = part.transpose( interval.Interval(part.analyze('key').tonic, pitch.Pitch('C'))) for x in part.recurse().notes: if (x.isNote): #print(x.pitch, x.duration.type, x.duration.quarterLength, x.tie, x.octave, x.quarterLength,x.pitch.midi) # x.seconds not always there notes.append(x) if (x.isChord): print("chord") raise NotImplementedError for a in x._notes: pass #print(a.pitch, a.duration.type, a.duration.quarterLength, a.tie, a.octave, a.quarterLength) print("endchord") return notes
def reMIDIfy(minisong, output): # empty stream s1 = stream.Stream() # assign the tempo based on what was read t = tempo.MetronomeMark('fast', song_tempo, note.Note(type='quarter')) s1.append(t) channels = minisong.shape[2] # fill in the stream with notes according to the minisong values # by channel for curr_channel in range(channels): inst = instrument.fromString(instrument_list[curr_channel]) new_part = stream.Part() new_part.insert(0, inst) # by beat for beat in range(BEATS_PER_MINISONG): notes = [] # by pitch in a beat for curr_pitch in range(NOTE_RANGE): #if this pitch is produced with at least 10% likelihood then count it if minisong[beat][curr_pitch][curr_channel] > VOLUME_CUTOFF: p = pitch.Pitch() p.midi = curr_pitch + LOWEST_PITCH n = note.Note(pitch=p) n.pitch = p n.volume.velocity = minisong[beat][curr_pitch][ curr_channel] * MAX_VOL n.quarterLength = LENGTH_PER_BEAT notes.append(n) if notes: my_chord = chord.Chord(notes) else: my_chord = note.Rest() my_chord.quarterLength = LENGTH_PER_BEAT new_part.append(my_chord) s1.insert(curr_channel, new_part) mf = midi.translate.streamToMidiFile(s1) mf.open(output + ".mid", 'wb') mf.write() mf.close()
def convertToPitch(pitchString): ''' Converts a pitchString to a :class:`~music21.pitch.Pitch`, only if necessary. >>> from music21.figuredBass import realizerScale >>> pitchString = 'C5' >>> realizerScale.convertToPitch(pitchString) <music21.pitch.Pitch C5> >>> realizerScale.convertToPitch(pitch.Pitch('E4')) # does nothing <music21.pitch.Pitch E4> ''' if isinstance(pitchString, pitch.Pitch): return pitchString if isinstance(pitchString, str): try: return pitch.Pitch(pitchString) except: raise ValueError("Cannot convert string " + pitchString + " to a music21 Pitch.") raise TypeError("Cannot convert " + pitchString + " to a music21 Pitch.")
def convertToPitch(pitchString): ''' Converts a pitchString to a :class:`~music21.pitch.Pitch`, only if necessary. >>> from music21.figuredBass import notation >>> pitchString = 'C5' >>> notation.convertToPitch(pitchString) <music21.pitch.Pitch C5> >>> notation.convertToPitch(pitch.Pitch('E4')) # does nothing <music21.pitch.Pitch E4> ''' if isinstance(pitchString, pitch.Pitch): return pitchString if isinstance(pitchString, str): try: return pitch.Pitch(pitchString) except: raise ValueError('Cannot convert string ' + pitchString + ' to a music21 Pitch.') raise TypeError('Cannot convert ' + pitchString + ' to a music21 Pitch.')
def allSinglePossibilities(self): ''' Returns an iterator through a set of naive possibilities for a Segment, using :attr:`~music21.figuredBass.segment.Segment.numParts`, the pitch of :attr:`~music21.figuredBass.segment.Segment.bassNote`, and :attr:`~music21.figuredBass.segment.Segment.allPitchesAboveBass`. >>> from music21.figuredBass import segment >>> segmentA = segment.Segment() >>> allPossib = segmentA.allSinglePossibilities() >>> allPossib.__class__ <... 'itertools.product'> The number of naive possibilities is always the length of :attr:`~music21.figuredBass.segment.Segment.allPitchesAboveBass` raised to the (:attr:`~music21.figuredBass.segment.Segment.numParts` - 1) power. The power is 1 less than the number of parts because the bass pitch is constant. >>> allPossibList = list(allPossib) >>> len(segmentA.allPitchesAboveBass) 9 >>> segmentA.numParts 4 >>> len(segmentA.allPitchesAboveBass) ** (segmentA.numParts-1) 729 >>> len(allPossibList) 729 >>> for i in (81, 275, 426): ... [str(p) for p in allPossibList[i]] ['E3', 'C3', 'C3', 'C3'] ['C4', 'C4', 'G4', 'C3'] ['G4', 'G3', 'C4', 'C3'] ''' iterables = [self.allPitchesAboveBass] * (self.numParts - 1) iterables.append([pitch.Pitch(self.bassNote.pitch.nameWithOctave)]) return itertools.product(*iterables)
def collapseArpeggios(self, scoreTree): r''' Collapses arpeggios in `tree`. ''' for verticalities in scoreTree.iterateVerticalitiesNwise(n=2): one, two = verticalities onePitches = sorted(one.pitchSet) twoPitches = sorted(two.pitchSet) if onePitches[0].nameWithOctave != twoPitches[0].nameWithOctave: continue elif one.measureNumber != two.measureNumber: continue bothPitches = set() bothPitches.update([x.nameWithOctave for x in onePitches]) bothPitches.update([x.nameWithOctave for x in twoPitches]) bothPitches = sorted([pitch.Pitch(x) for x in bothPitches]) # if not timespanStream.Verticality.pitchesAreConsonant(bothPitches): # intervalClasses = self._getIntervalClassSet(bothPitches) # if intervalClasses not in ( # frozenset([1, 3, 4]), # frozenset([1, 4, 5]), # frozenset([2, 3, 5]), # frozenset([2, 4, 6]), # ): # continue horizontalities = scoreTree.unwrapVerticalities(verticalities) for unused_part, timespanList in horizontalities.items(): if len(timespanList) < 2: continue elif timespanList[0].pitches == timespanList[1].pitches: continue bothPitches = timespanList[0].pitches + timespanList[1].pitches sumChord = chord.Chord(bothPitches) scoreTree.removeTimespanList(timespanList) merged = timespanList[0].new( element=sumChord, endTime=timespanList[1].endTime, ) scoreTree.insert(merged)