def annotate_fingers_xml(sf, hand, args, is_right=True): p0 = sf.parts[args.rbeam if is_right else args.lbeam] idx = 0 for el in p0.flat.getElementsByClass("GeneralNote"): if el.isNote: n = hand.noteseq[idx] if hand.lyrics: el.addLyric(n.fingering) else: el.articulations.append(Fingering(n.fingering)) idx += 1 elif el.isChord: for j, cn in enumerate(el.pitches): n = hand.noteseq[idx] if hand.lyrics: nl = len(cn.chord21.pitches) - cn.chordnr el.addLyric(cn.fingering, nl) else: el.articulations.append(Fingering(n.fingering)) idx += 1 return sf
def PIG2Stream(fname, beam=0, time_unit=.5, fixtempo=0): """ Convert a PIG text file to a music21 Stream object. time_unit must be multiple of 2. beam = 0, right hand beam = 1, left hand. """ from music21 import stream, note, chord from music21.articulations import Fingering import numpy as np f = open(fname, "r") lines = f.readlines() f.close() #work out note type from distribution of durations # triplets are squashed to the closest figure durations = [] firstonset = 0 blines=[] for l in lines: if l.startswith('//'): continue _, onset, offset, name, _, _, channel, _ = l.split() onset, offset = float(onset), float(offset) if beam != int(channel): continue if not firstonset: firstonset = onset if offset-onset<0.0001: continue durations.append(offset-onset) blines.append(l) durations = np.array(durations) logdurs = -np.log2(durations) mindur = np.min(logdurs) expos = (logdurs-mindur).astype(int) if np.max(expos) > 3: mindur = mindur + 1 #print(durations, '\nexpos=',expos, '\nmindur=', mindur) sf = stream.Part() sf.id = beam # first rest if not fixtempo and firstonset: r = note.Rest() logdur = -np.log2(firstonset) r.duration.quarterLength = 1.0/time_unit/pow(2, int(logdur-mindur)) sf.append(r) n = len(blines) for i in range(n): if blines[i].startswith('//'): continue _, onset, offset, name, _, _, _, finger = blines[i].split() onset, offset = float(onset), float(offset) name = name.replace('b', '-') chordnotes = [name] for j in range(1, 5): if i+j<n: noteid1, onset1, offset1, name1, _, _, _, finger1 = blines[i+j].split() onset1 = float(onset1) if onset1 == onset: name1 = name1.replace('b', '-') chordnotes.append(name1) if len(chordnotes)>1: an = chord.Chord(chordnotes) else: an = note.Note(name) if '_' not in finger: x = Fingering(abs(int(finger))) x.style.absoluteY = 20 an.articulations.append(x) if fixtempo: an.duration.quarterLength = fixtempo else: logdur = -np.log2(offset - onset) an.duration.quarterLength = 1.0/time_unit/pow(2, int(logdur-mindur)) #print('note/chord:', an, an.duration.quarterLength, an.duration.type, 't=',onset) sf.append(an) # rest up to the next if i+1<n: _, onset1, _, _, _, _, _, _ = blines[i+1].split() onset1 = float(onset1) if onset1 - offset > 0: r = note.Rest() if fixtempo: r.duration.quarterLength = fixtempo logdur = -np.log2(onset1 - offset) d = int(logdur-mindur) if d<4: r.duration.quarterLength = 1.0/time_unit/pow(2, d) sf.append(r) return sf
def generate(self, start_measure=0, nmeasures=1000): if start_measure == 1: start_measure = 0 # avoid confusion with python numbering if self.LR == "left": for anote in self.noteseq: anote.x = -anote.x # play left as a right on a mirrored keyboard start_finger, out, vel = 0, [0] * 9, 0 N = len(self.noteseq) if self.depth < 2: self.depth = 2 if self.depth > 9: self.depth = 9 for i in range(N): ############## an = self.noteseq[i] if an.measure: if an.measure < start_measure: continue if an.measure > start_measure + nmeasures: break if i > N - 11: self.autodepth = False self.depth = 9 best_finger = 0 if i > N - 10: if len(out) > 1: best_finger = out.pop(1) else: ninenotes = self.noteseq[i:i + 9] out, vel = self.optimize_seq(ninenotes, start_finger) best_finger = out[0] start_finger = out[1] an.fingering = best_finger self.set_fingers_positions(out, ninenotes, 0) self.fingerseq.append(list(self.cfps)) if best_finger > 0 and i < N - 3: fng = Fingering(best_finger) if an.isChord: if self.lyrics: if len(an.chord21.pitches) <= 3: # dont show fingering in the lyrics line for >3 note-chords nl = len(an.chord21.pitches) - an.chordnr an.chord21.addLyric(best_finger, nl) else: an.chord21.articulations.append(fng) else: if self.lyrics: an.note21.addLyric(best_finger) else: an.note21.articulations.append(fng) #---------------------------------------------------------------------------- print if self.verbose: print("meas." + str(an.measure), end=' ') print(" finger:" + str(best_finger) + " on " + an.name + str(an.octave), end=' ') if i < N - 10: print("\tv=" + str(round(vel, 1)), end='') if self.autodepth: print("\t" + " " + str(out[0:self.depth]) + " d:" + str(self.depth)) else: print("\t" + (" " * (i % self.depth)) + str(out[0:self.depth])) else: print() else: if i and not i % 100 and an.measure: print('scanned', i, 'notes in', an.measure + 1, 'measures for', self.LR, 'hand..')
def generateFingering(self, nmeasures=1000): if self.LR == "left": #play left hand on a mirrored keyboard for anote in self.noteseq: anote.x = -anote.x start_finger, out, costf = 0, [0] * 9, 0 # Remove existing fingerings for an in self.noteseq: if an.isChord: an.chord21.articulations = [ a for a in an.chord21.articulations if type(a) is not Fingering ] else: an.note21.articulations = [ a for a in an.note21.articulations if type(a) is not Fingering ] for inote in range(len(self.noteseq)): an = self.noteseq[inote] i = inote % self.fstep # position inside the group of step notes if an.measure > nmeasures: break if i == 0: if inote <= len(self.noteseq) - 9: ninenotes = self.noteseq[inote:inote + 9] out, costf = self.optimize_seq(ninenotes, start_finger) best_finger = out[i] else: #close to the end of score best_finger = out[9 - len(self.noteseq) + inote] else: best_finger = out[i] start_finger = out[i + 1] bestfpos = self.set_fingers_positions(out, ninenotes, i) self.fingerseq.append(bestfpos) an.fingering = best_finger if best_finger > 0: if an.isChord: an.chord21.articulations.append(Fingering(best_finger)) else: an.note21.articulations.append(Fingering(best_finger)) #----------------------------- print("meas." + str(an.measure), end='') print(" finger:" + str(best_finger) + " on " + an.name + str(an.octave), end='') if i == 0: print("\tv=" + str(int(costf * 10.) / 10.), end='') if self.autodepth: print("\t" + " " + str(out[0:self.depth]) + " d =", self.depth) else: print("\t" + (" " * (inote % self.depth)) + str(out[0:self.depth])) else: print()