def ch1_basic_II_C_4(show=True, *arguments, **keywords): data = [[clef.TrebleClef(), 'b#4', 'e4', 'd#5'], [clef.AltoClef(), 'c-4'], [clef.BassClef(), 'f#3', 'c3']] ex = ch1_basic_II_C(data, '-h') if show: ex.show()
class Instrument: # TODO ''' represents an instrument; associated with midi channel etc (see music21 docs) # TODO detector for whether instrument is capable of specific technique, # double-stop, etc. # TODO instruments like cello may use multiple clefs ''' name_to_instrument21 = { 'violin': instrument21.Violin(), 'viola': instrument21.Viola(), 'cello': instrument21.Violoncello() } name_to_clef21 = { 'violin': clef21.TrebleClef(), 'viola': clef21.AltoClef(), 'cello': clef21.BassClef() } def __init__(self, name): self.instrument = Instrument.name_to_instrument21[name] self.clef = Instrument.name_to_clef21[name] # there isn't a precise to_music21 analogue def check_pitch(self, pitch): # true if pitch within instrument's range low = self.instrument.lowestNote # assume these are always music21 Pitch objects high = self.instrument.highestNote pitch_21 = pitch.to_music21() if low is not None and low > pitch_21: return False if high is not None and high < pitch_21: return False return True
def ch1_basic_II_C_3(show=True, *arguments, **keywords): data = [[clef.BassClef(), 'f#2', 'c-3'], [clef.TrebleClef(), 'e4', 'b-5', 'a#4'], [clef.AltoClef(), 'f-3']] ex = ch1_basic_II_C(data, 'h') if show: ex.show()
def toBasicGABC(self, useClef=None): ''' returns the character representing inNote in the given clef (default = AltoClef) see http://home.gna.org/gregorio/gabc/ for more details. 'd' = lowest line >>> n = alpha.chant.GregorianNote("C4") >>> c = clef.AltoClef() >>> n.toBasicGABC(c) 'h' >>> c2 = clef.SopranoClef() >>> n.toBasicGABC(c2) 'd' ''' inNote = self usedDefaultClef = False if useClef is None: useClef = clef.AltoClef() usedDefaultClef = True asciiD = 100 asciiA = 97 asciiM = 109 if not hasattr(useClef, 'lowestLine'): raise ChantException( "useClef has to define the diatonicNoteNum representing the lowest line" ) stepsAboveLowestLine = inNote.pitch.diatonicNoteNum - useClef.lowestLine asciiNote = stepsAboveLowestLine + asciiD if asciiNote < asciiA: if usedDefaultClef is True: raise ChantException( "note is too low for the default clef (AltoClef), choose a lower one" ) else: raise ChantException( "note is too low for the clef (%s), choose a lower one" % str(useClef)) elif asciiNote > asciiM: if usedDefaultClef is True: raise ChantException( "note is too high for the default clef (AltoClef), choose a higher one" ) else: raise ChantException( "note is too high for the clef (%s), choose a higher one" % str(useClef)) else: return six.unichr(asciiNote) # unichr on python2; chr python3
def ch1_writing_I_B_1(show=True, *arguments, **keywords): ''' p.6 Transcribe these melodies into the clef specified without changing octaves. ''' # camptown races ex = converter.parse("tinynotation: 2/4 g8 g e g", makeNotation=False) ex.insert(0, clef.AltoClef()) # maintain clef if show: ex.show()
def ch1_writing_I_B_1(show=True, *arguments, **keywords): ''' p.6 Transcribe these melodies into the clef specified without changing octaves. ''' from music21 import tinyNotation # camptown races ex = tinyNotation.TinyNotationStream("g8 g e g", "2/4") ex.insert(0, clef.AltoClef()) # maintain clef if show: ex.show()
def ch1_basic_II_B_1(show=True, *arguments, **keywords): ''' p4. For each of the five trebleclef pitches on the left, write the alto-clef equivalent on the right. Then label each pitch with the correct name and octave designation. ''' humdata = ''' **kern 1B- 1f# 1a- 1c 1G# *- ''' exercise = converter.parseData(humdata) for n in exercise.flat.notes: # have to use flat here n.lyric = n.nameWithOctave exercise.insert(0, clef.AltoClef()) if show: exercise.show()
def testSimpleFile(self): s = GregorianStream() s.append(clef.AltoClef()) n = GregorianNote("C4") l = note.Lyric("Po") l.syllabic = "start" n.lyrics.append(l) n.oriscus = True s.append(n) n2 = GregorianNote("D4") s.append(n2) n3 = GregorianNote("C4") n3.stropha = True s.append(n3) n4 = GregorianNote("B3") n4.stropha = True s.append(n4) gabcText = s.toGABCText() bsc = BaseScoreConverter() bsc.score = gabcText bsc.incipit = "Populus" bsc.mode = 'VII' fn = bsc.writeFile("style: modern;\n\n%%\n" + gabcText) texfn = bsc.launchGregorio(fn) texfh = open(texfn) texcontents = texfh.read() texfh.close() bsc.score = texcontents dtw = DefaultTeXWrapper() newgabcText = dtw.substituteInfo(bsc) texfh2 = open(texfn, 'w') texfh2.write(newgabcText) texfh2.close() pdffn = bsc.launchLaTeX(texfn) os.system('open %s' % pdffn)
def matrix_to_score(self, matrix, verbose=False): ''' Takes a matrix of (P, T, 2) and turn it into a music21.stream.Score object, where P is the number of parts, T is the number of time slices, and dim is the note vector. ''' # (4 parts, # ticks, 2) assert len(matrix.shape) == 3, \ "Input matrix needs to have 3-dimensions." num_parts, num_ticks, num_dim = matrix.shape assert num_parts == 4, "Input matrix needs to have 4 parts." assert num_ticks > 0, "No time slices in this matrix." assert num_dim == 2, "Note vector size mismatch." # need to make sure all pieces start with an articulated note, even if # it's a rest. matrix[:, 0, 1] = [1, 1, 1, 1] score = Score() parts = list(map(self._matrix_to_part, matrix)) parts[0].insert(0, instrument.Violin()) parts[0].partName = "Violin I" parts[0].clef = clef.TrebleClef() parts[1].insert(0, instrument.Violin()) parts[1].partName = "Violin II" parts[1].clef = clef.TrebleClef() parts[2].insert(0, instrument.Viola()) parts[2].clef = clef.AltoClef() parts[3].insert(0, instrument.Violoncello()) parts[3].clef = clef.BassClef() _ = list(map(lambda part: score.append(part), parts)) return score
def testStreams01(self): ''' Basic stream issues ''' #from music21 import note, stream, clef, metadata, spanner #==== "fig-df02" # Storing, Ordering, and Timing Elements n1 = note.Note('g3', type='half') n2 = note.Note('d4', type='half') cf1 = clef.AltoClef() m1 = stream.Measure(number=1) m1.append([n1, n2]) m1.insert(0, cf1) # the measure has three elements assert len(m1) == 3 # the offset returned is the most-recently set assert n2.offset == 2.0 # automatic sorting positions Clef first assert m1[0] == cf1 # list-like indices follow sort order assert m1.index(n2) == 2 # can find an element based on a given offset assert m1.getElementAtOrBefore(3) == n2 n3 = note.Note('g#3', quarterLength=0.5) n4 = note.Note('d-4', quarterLength=3.5) m2 = stream.Measure(number=2) m2.append([n3, n4]) # appended position is after n3 assert n4.offset == .5 assert m2.highestOffset == .5 # can access objects on elements assert m2[1].duration.quarterLength == 3.5 # the Stream duration is the highest offset + duration assert m2.duration.quarterLength == 4 p1 = stream.Part() p1.append([m1, m2]) # the part has 2 components assert len(p1) == 2 # the Stream duration is the highest offset + durations assert p1.duration.quarterLength == 8 # can access Notes from Part using multiple indices assert p1[1][0].pitch.nameWithOctave == 'G#3' s1 = stream.Score() s1.append(p1) md1 = metadata.Metadata(title='The music21 Stream') s1.insert(0, md1) # calling show by default renders musicxml output #s1.show() #==== "fig-df02" end #==== "fig-df03" # Positioning the Same Element in Multiple Containers # show positioning the same element in multiple containers # do not yet use a flat representation s2 = stream.Stream() s3 = stream.Stream() s2.insert(10, n2) s3.insert(40, n2) # the offset attribute returns the last assigned assert n2.offset == 40 # we can provide a site to finde a location-specific offset assert n2.getOffsetBySite(m1) == 2.0 assert n2.getOffsetBySite(s2) == 10 # the None site provides a default offset assert set(n2.sites.get()) == set([None, m1, s2, s3]) # the same instance is found in all Streams assert m1.hasElement(n2) == True assert s2.hasElement(n2) == True assert s3.hasElement(n2) == True # only offset is independent to each location n2.pitch.transpose('-M2', inPlace=True) assert s2[s2.index(n2)].nameWithOctave == 'C4' assert s3[s3.index(n2)].nameWithOctave == 'C4' assert m1[m1.index(n2)].nameWithOctave == 'C4' # the transposition is maintained in the original context #s1.show() #==== "fig-df03" end #==== "fig-df04" # Simultaneous Access to Hierarchical and Flat Representations #s1.flat.show('t') # lengths show the number of elements; indices are sequential s1Flat = s1.flat assert len(s1) == 2 assert len(s1Flat) == 6 assert s1Flat[4] == n3 assert s1Flat[5] == n4 # adding another Part to the Score results in a different flat representation n5 = note.Note('a#1', quarterLength=2.5) n6 = note.Note('b2', quarterLength=1.5) m4 = stream.Measure(number=2) m4.append([n5, n6]) r1 = note.Rest(type='whole') cf2 = clef.bestClef(m4) # = BassClef m3 = stream.Measure(number=1) m3.append([cf2, r1]) p2 = stream.Part() p2.append([m3, m4]) s1.insert(0, p2) assert 'BassClef' in cf2.classes # objects are sorted by offset s1Flat = s1.flat assert len(s1) == 3 assert len(s1.flat) == 10 assert s1Flat[6] == n3 assert s1Flat[7] == n5 assert s1Flat[8] == n4 assert s1Flat[9] == n6 # the F-sharp in m. 2 now as offsets for both flat non-flat sites assert n3.getOffsetBySite(m2) == 0 assert n3.getOffsetBySite(s1Flat) == 4 # the B in m. 2 now as offsets for both flat non-flat sites assert n6.getOffsetBySite(m4) == 2.5 assert n6.getOffsetBySite(s1Flat) == 6.5 #s1.show() #==== "fig-df04" end #==== "fig-df05" # Iterating and Filtering Elements by Class # get the Clef object, and report its sign, from Measure 1 assert m1.getElementsByClass('Clef').stream()[0].sign == 'C' # collect into a list the sign of all clefs in the flat Score assert [cf.sign for cf in s1.flat.getElementsByClass('Clef')] == ['C', 'F'] # collect the offsets Measures in the first part assert [e.offset for e in p1.elements] == [0.0, 4.0] # collect the offsets of Note in the first part flattened assert [e.offset for e in p1.flat.notesAndRests] == [0.0, 2.0, 4.0, 4.5] # collect the offsets of Notes in all parts flattened assert [e.offset for e in s1.flat.notesAndRests ] == [0.0, 0.0, 2.0, 4.0, 4.0, 4.5, 6.5] # get all pitch names match = [] for e in s1.flat.getElementsByClass('Note').stream(): match.append(e.pitch.nameWithOctave) assert match == ['G3', 'C4', 'G#3', 'A#1', 'D-4', 'B2'] # collect all Notes and transpose up a perfect fifth for n in s1.flat.getElementsByClass('Note').stream(): n.transpose('P5', inPlace=True) # check that all pitches are correctly transposed match = [] for e in s1.flat.getElementsByClass('Note').stream(): match.append(e.pitch.nameWithOctave) assert match == ['D4', 'G4', 'D#4', 'E#2', 'A-4', 'F#3'] #s1.show() #==== "fig-df05" end #==== "fig-df06" # Searching by Locations and Contexts # a Note can always find a Clef self.assertIs(n4.getContextByClass('Clef'), cf1) # must search oldest sites first assert n6.getContextByClass('Clef', sortByCreationTime='reverse') == cf2 # # a Note can find their Measure number from a flat Part # match = [] # for e in p1.flat.getElementsByClass('Note'): # match.append(e.getContextByClass('Measure').number) # assert match == [1, 1, 2, 2] # all Notes can find their Measure number from a flat Score match = [] for e in s1.flat.notesAndRests: match.append([e.name, e.getContextByClass('Measure').number]) assert match == [['D', 1], ['rest', 1], ['G', 1], ['D#', 2], ['E#', 2], ['A-', 2], ['F#', 2]] #==== "fig-df06" end #==== "fig-df06" # Non-Hierarchical Object Associations #oldIds = [] #for idKey in n1.sites.siteDict: # print (idKey, n1.sites.siteDict[idKey].isDead) # oldIds.append(idKey) #print("-------") # Spanners can be positioned in Parts or Measures sp1 = spanner.Slur([n1, n4]) p1.append(sp1) sp2 = spanner.Slur([n5, n6]) m4.insert(0, sp2) #print(id(sp1), id(sp1.spannerStorage), n1.sites.siteDict[id(sp1.spannerStorage)].isDead) #if id(sp1.spannerStorage) in oldIds: # print ("******!!!!!!!!!*******") # Elements can report on what Spanner they belong to ss1 = n1.getSpannerSites() self.assertTrue(sp1 in ss1, (ss1, sp1)) ss6 = n6.getSpannerSites() assert sp2 in ss6 # p1Flat = p1.flat # assert sp1.getDurationSpanBySite(p1Flat) == [0.0, 8.0] # # p2Flat = p2.flat # assert sp2.getDurationSpanBySite(p2Flat) == [4.0, 8.0] #s1.show() #==== "fig-df06" end # additional tests self.assertEqual(m1.clef, cf1)
def createClef(self, attributes): r''' Add a new clef to the current measure and return the currentClef. Clef lines should look like: \|Clef\|Type:ClefType or \|Clef\|Type:ClefType\|OctaveShift:Octave Down (or Up) >>> nwt = noteworthy.translate.NoteworthyTranslator() >>> nwt.currentMeasure = stream.Measure() >>> nwt.createClef({"Type": "Treble"}) >>> nwt.currentMeasure.show('text') {0.0} <music21.clef.TrebleClef> >>> nwt.currentClef 'TREBLE' >>> nwt.createClef({"Type" : "Bass", "OctaveShift" : "Octave Down"}) >>> nwt.currentMeasure.show('text') {0.0} <music21.clef.TrebleClef> {0.0} <music21.clef.Bass8vbClef> If no clef can be found then it raises a NoteworthyTranslate exception >>> nwt.createClef({"Type" : "OBonobo"}) Traceback (most recent call last): NoteworthyTranslateException: Did not find a proper clef in type, OBonobo ''' currentClef = None if 'OctaveShift' in attributes: if attributes['OctaveShift'] == 'Octave Down': octaveShift = -1 elif attributes['OctaveShift'] == 'Octave Up': octaveShift = 1 else: raise NoteworthyTranslateException( 'Did not get a proper octave shift from %s' % attributes[3]) else: octaveShift = 0 cl = attributes['Type'] if cl == "Treble": if octaveShift == 0: self.currentMeasure.append(clef.TrebleClef()) currentClef = "TREBLE" elif octaveShift == -1: self.currentMeasure.append(clef.Treble8vbClef()) currentClef = "TREBLE8dw" elif octaveShift == 1: self.currentMeasure.append(clef.Treble8vaClef()) currentClef = "TREBLE8up" elif cl == "Bass": if octaveShift == 0: self.currentMeasure.append(clef.BassClef()) currentClef = "BASS" elif octaveShift == -1: self.currentMeasure.append(clef.Bass8vbClef()) currentClef = "BASS8dw" elif octaveShift == 1: self.currentMeasure.append(clef.Bass8vaClef()) currentClef = "BASS8up" elif cl == "Alto": if octaveShift != 0: raise NoteworthyTranslateException('cannot shift octaves on an alto clef') self.currentMeasure.append(clef.AltoClef()) currentClef = "ALTO" elif cl == "Tenor": if octaveShift != 0: raise NoteworthyTranslateException('cannot shift octaves on a tenor clef') self.currentMeasure.append(clef.TenorClef()) currentClef = "TENOR" if currentClef is None: raise NoteworthyTranslateException('Did not find a proper clef in type, %s' % cl) self.currentClef = currentClef
def test_clef_to_lily_8(self): bee_ell = clef.AltoClef() expected = u"\\clef alto\n" self.assertEqual(functions.clef_to_lily(bee_ell), expected)
def createClef(self, attributes): r''' Add a new clef to the current measure and return the currentClef. Clef lines should look like: \|Clef\|Type:ClefType or \|Clef\|Type:ClefType\|OctaveShift:Octave Down (or Up) >>> nwt = noteworthy.translate.NoteworthyTranslator() >>> nwt.currentMeasure = stream.Measure() >>> nwt.createClef({'Type': 'Treble'}) >>> nwt.currentMeasure.show('text') {0.0} <music21.clef.TrebleClef> >>> nwt.currentClef 'TREBLE' >>> nwt.createClef({'Type' : 'Bass', 'OctaveShift' : 'Octave Down'}) >>> nwt.currentMeasure.show('text') {0.0} <music21.clef.TrebleClef> {0.0} <music21.clef.Bass8vbClef> If no clef can be found then it raises a NoteworthyTranslate exception >>> nwt.createClef({'Type' : 'OrangeClef'}) Traceback (most recent call last): music21.noteworthy.translate.NoteworthyTranslateException: Did not find a proper clef in type, OrangeClef ''' currentClef = None if 'OctaveShift' in attributes: if attributes['OctaveShift'] == 'Octave Down': octaveShift = -1 elif attributes['OctaveShift'] == 'Octave Up': octaveShift = 1 else: raise NoteworthyTranslateException( f'Did not get a proper octave shift from {attributes[3]}') else: octaveShift = 0 cl = attributes['Type'] if cl == 'Treble': if octaveShift == 0: self.currentMeasure.append(clef.TrebleClef()) currentClef = 'TREBLE' elif octaveShift == -1: self.currentMeasure.append(clef.Treble8vbClef()) currentClef = 'TREBLE8dw' elif octaveShift == 1: self.currentMeasure.append(clef.Treble8vaClef()) currentClef = 'TREBLE8up' elif cl == 'Bass': if octaveShift == 0: self.currentMeasure.append(clef.BassClef()) currentClef = 'BASS' elif octaveShift == -1: self.currentMeasure.append(clef.Bass8vbClef()) currentClef = 'BASS8dw' elif octaveShift == 1: self.currentMeasure.append(clef.Bass8vaClef()) currentClef = 'BASS8up' elif cl == 'Alto': if octaveShift != 0: raise NoteworthyTranslateException( 'cannot shift octaves on an alto clef') self.currentMeasure.append(clef.AltoClef()) currentClef = 'ALTO' elif cl == 'Tenor': if octaveShift != 0: raise NoteworthyTranslateException( 'cannot shift octaves on a tenor clef') self.currentMeasure.append(clef.TenorClef()) currentClef = 'TENOR' if currentClef is None: raise NoteworthyTranslateException( f'Did not find a proper clef in type, {cl}') self.currentClef = currentClef