def append_guitar_data(self, tuning, capo): ''' Append meta data about the guitar the transcriber is using ''' mei_path = self.get_abs_path() mei_doc = XmlImport.documentFromFile(mei_path) staff_def = mei_doc.getElementsByName('staffDef')[0] g = Guitar(tuning=str(tuning), capo=capo) sounding_pitches = g.strings # From the MEI guidelines: # "this is given using the written pitch, not the sounding pitch. # For example, the Western 6-string guitar, in standard tuning, sounds an octave below written pitch." written_pitches = [s.pname + str(s.oct+1) for s in sounding_pitches] staff_def.addAttribute('lines', str(len(sounding_pitches))) staff_def.addAttribute('tab.strings', " ".join(written_pitches)) # Capo could be implicitly encoded by setting the pitches of the open strings # but I really don't like this solution. Instructions are lost about how to tune # and perform the piece on the guitar. # TODO: this attribute doesn't exist in MEI, make a custom build if capo > 0: staff_def.addAttribute('tab.capo', str(capo)) XmlExport.meiDocumentToFile(mei_doc, mei_path)
def output_mei(self, output_path): ''' Write the generated mei to disk ''' # output mei file XmlExport.meiDocumentToFile(self.meidoc, output_path)
def append_guitar_data(self, tuning, capo): ''' Append meta data about the guitar the transcriber is using ''' mei_path = self.get_abs_path() mei_doc = XmlImport.documentFromFile(mei_path) staff_def = mei_doc.getElementsByName('staffDef')[0] g = Guitar(tuning=str(tuning), capo=capo) sounding_pitches = g.strings # From the MEI guidelines: # "this is given using the written pitch, not the sounding pitch. # For example, the Western 6-string guitar, in standard tuning, sounds an octave below written pitch." written_pitches = [s.pname + str(s.oct + 1) for s in sounding_pitches] staff_def.addAttribute('lines', str(len(sounding_pitches))) staff_def.addAttribute('tab.strings', " ".join(written_pitches)) # Capo could be implicitly encoded by setting the pitches of the open strings # but I really don't like this solution. Instructions are lost about how to tune # and perform the piece on the guitar. # TODO: this attribute doesn't exist in MEI, make a custom build if capo > 0: staff_def.addAttribute('tab.capo', str(capo)) XmlExport.meiDocumentToFile(mei_doc, mei_path)
def sanitize_mei_str(self, mei_str, output_mei_path=None, prune=True): self.mei_doc = XmlImport.documentFromText(mei_str) self._sanitize_mei(prune) if output_mei_path: XmlExport.meiDocumentToFile(self.mei_doc, str(output_mei_path)) else: return XmlExport.meiDocumentToText(self.mei_doc)
def output_mei(self, output_path): ''' Write the generated mei to disk ''' # output mei file if self.meidoc == None: raise Warning('The MEI document has not yet been created'); return XmlExport.meiDocumentToFile(self.meidoc, output_path)
def massage_mei(in_file, out_file): try: analysis = make_analysis(in_file) MEI_instructions = TransformData( arranger_to_editor=True, obliterate_incipit=analysis.first_measure_empty, replace_longa=True, editorial_resp=analysis.has_arranger_element, alternates_list=analysis.alternates_list) old_MEI_doc = XmlImport.documentFromFile(in_file) new_MEI_doc = transform_mei(old_MEI_doc, MEI_instructions) XmlExport.meiDocumentToFile(new_MEI_doc, out_file) except Exception as ex: logging.critical(ex) logging.critical("Error during massaging " + in_file)
def mei_append_metamusic(self): ''' Append meta data for the musical work to the mei document ''' mei_path = self.get_abs_path() mei_doc = XmlImport.documentFromFile(mei_path) mei = mei_doc.getRootElement() mei_head = MeiElement('meiHead') music = mei.getChildrenByName('music')[0] file_desc = MeiElement('fileDesc') # title title_stmt = MeiElement('titleStmt') title = MeiElement('title') title.setValue(str(self.fk_mid.title)) # contributers resp_stmt = MeiElement('respStmt') pers_name_artist = MeiElement('persName') pers_name_artist.addAttribute('role', 'artist') pers_name_artist.setValue(str(self.fk_mid.artist)) pers_name_tabber = MeiElement('persName') pers_name_tabber.addAttribute('role', 'tabber') pers_name_tabber.setValue(str(self.fk_mid.copyright)) # encoding information encoding_desc = MeiElement('encodingDesc') app_info = MeiElement('appInfo') application = MeiElement('application') application.setValue('Robotaba') mei_head.addChild(file_desc) file_desc.addChild(title_stmt) title_stmt.addChild(title) title_stmt.addChild(resp_stmt) resp_stmt.addChild(pers_name_artist) resp_stmt.addChild(pers_name_tabber) title_stmt.addChild(encoding_desc) encoding_desc.addChild(app_info) app_info.addChild(application) # attach mei metadata to the document mei.addChildBefore(music, mei_head) XmlExport.meiDocumentToFile(mei_doc, mei_path)
def test_documentwritefailure(self): doc = MeiDocument() root = MeiElement("mei") root.id = "myid" doc.root = root with self.assertRaises(FileWriteFailureException) as cm: ret = XmlExport.meiDocumentToFile(doc, "C:/StupidPath") self.assertTrue(isinstance(cm.exception, FileWriteFailureException))
def save_elite(self, score, output_path=None): ''' Save the elite tablature to the specified output path, or return a string representation of the MeiDocument. The output file should be a copy on the HDD of the original input file, to preserve meta-data and other contents of the file not maintained in the internal representation of the musical document. PARAMETERS ---------- output_path {String}: the output path of the mei file ''' # get list of tablature data to append to note elements # plucks is a list of tuples (MeiElement.id, Pluck) plucks = [] for chromo in self.elites: for g in chromo.genes: if isinstance(g.guitar_event, Pluck): plucks.append((g.score_event.id, g.guitar_event)) elif isinstance(g.guitar_event, Strum): for p, n in zip(g.guitar_event.plucks, g.score_event.notes): plucks.append((n.id, p)) # add the tablature data to the original mei document for p in plucks: note = score.meidoc.getElementById(p[0]) note.addAttribute('tab.string', str(p[1].string+1)) note.addAttribute('tab.fret', str(p[1].fret)) if output_path is not None: # write the modified document to disk XmlExport.meiDocumentToFile(score.meidoc, output_path) else: # return a string of the MeiDocument return XmlExport.meiDocumentToText(score.meidoc)
def Run(self): old_filename = self.mei_file if (len(old_filename) < EXT_LENGTH or old_filename[-EXT_LENGTH:] not in EXT): logging.info("No file extension provided; " + EXT[0] + " used.") old_filename += EXT[0] old_MEI_doc = XmlImport.documentFromFile(old_filename) logging.info('running test case ' + self.name + ' Input: ' + old_filename) new_MEI_doc = transform(old_MEI_doc, self.transform_data) new_filename = (old_filename[:-EXT_LENGTH] + self.outsuffix + '_' + old_filename[-EXT_LENGTH:]) status = XmlExport.meiDocumentToFile(new_MEI_doc, new_filename) if status: logging.info("Done. Transformed file saved as " + new_filename) pass else: logging.error("Transformation failed") return new_MEI_doc
def write_transformation(file_path, data=TransformData()): old_MEI_doc = XmlImport.documentFromFile(file_path) new_MEI_doc = transform_mei(old_MEI_doc, data) XmlExport.meiDocumentToFile(new_MEI_doc, file_path)
def write_mei(self, notes, output_path=None): # begin constructing mei document meidoc = MeiDocument() mei = MeiElement('mei') meidoc.setRootElement(mei) mei_head = MeiElement('meiHead') mei.addChild(mei_head) music = MeiElement('music') body = MeiElement('body') mdiv = MeiElement('mdiv') score = MeiElement('score') score_def = MeiElement('scoreDef') # assume 4/4 time signature meter_count = 4 meter_unit = 4 score_def.addAttribute('meter.count', str(meter_count)) score_def.addAttribute('meter.unit', str(meter_unit)) staff_def = MeiElement('staffDef') staff_def.addAttribute('n', '1') staff_def.addAttribute('label.full', 'Electric Guitar') staff_def.addAttribute('clef.shape', 'TAB') instr_def = MeiElement('instrDef') instr_def.addAttribute('n', 'Electric_Guitar') instr_def.addAttribute('midi.channel', '1') instr_def.addAttribute('midi.instrnum', '28') mei.addChild(music) music.addChild(body) body.addChild(mdiv) mdiv.addChild(score) score.addChild(score_def) score_def.addChild(staff_def) staff_def.addChild(instr_def) section = MeiElement('section') score.addChild(section) # another score def score_def = MeiElement('scoreDef') score_def.addAttribute('meter.count', str(meter_count)) score_def.addAttribute('meter.unit', str(meter_unit)) section.addChild(score_def) # start writing pitches to file note_container = None for i, frame_n in enumerate(notes): if i % meter_count == 0: measure = MeiElement('measure') measure.addAttribute('n', str(int(i/meter_count + 1))) staff = MeiElement('staff') staff.addAttribute('n', '1') layer = MeiElement('layer') layer.addAttribute('n', '1') section.addChild(measure) measure.addChild(staff) staff.addChild(layer) note_container = layer if len(frame_n) > 1: chord = MeiElement('chord') for n in frame_n: note = MeiElement('note') pname = n['pname'][0].upper() note.addAttribute('pname', pname) note.addAttribute('oct', str(n['oct'])) if len(n['pname']) > 1 and n['pname'][1] == '#': # there is an accidental note.addAttribute('accid.ges', 's') note.addAttribute('dur', str(meter_unit)) chord.addChild(note) note_container.addChild(chord) else: n = frame_n[0] note = MeiElement('note') pname = n['pname'][0].upper() note.addAttribute('pname', pname) note.addAttribute('oct', str(n['oct'])) if len(n['pname']) > 1 and n['pname'][1] == '#': # there is an accidental note.addAttribute('accid.ges', 's') note.addAttribute('dur', str(meter_unit)) note_container.addChild(note) if output_path is not None: XmlExport.meiDocumentToFile(meidoc, output_path) else: return XmlExport.meiDocumentToText(meidoc)
def write_mei(self): if self._meidoc: XmlExport.meiDocumentToFile(self._meidoc, self._output_mei_path)
def test_basicexport(self): docf = XmlImport.documentFromFile(os.path.join("test", "testdocs", "beethoven.mei")) status = XmlExport.meiDocumentToFile(docf, os.path.join(self.tempdir,"filename.mei")) self.assertTrue(status)
def write_mei(self, notes, audio_path, output_path=None): from pymei import MeiDocument, MeiElement, XmlExport # combine features with the same timestamps note_events = [] for n in notes: ts = n.timestamp.toSeconds() note_num = int(n.values[0]) + 1 # it looks like everything is transposed a semitone down ... transposing up # if the last timestamp is equal to this timestamp, combine into a chord if len(note_events) > 0 and note_events[-1][0] == ts: note_events[-1][1].append(note_num) else: note_events.append([ts, [note_num]]) # sort by timestamp in ascending order note_events = sorted(note_events, key=lambda n: n[0]) # begin constructing mei document meidoc = MeiDocument() mei = MeiElement('mei') meidoc.setRootElement(mei) music = MeiElement('music') timeline = MeiElement('timeline') timeline.addAttribute('avref', str(audio_path)) body = MeiElement('body') mdiv = MeiElement('mdiv') score = MeiElement('score') score_def = MeiElement('scoreDef') # assume 4/4 time signature meter_count = 4 meter_unit = 4 score_def.addAttribute('meter.count', str(meter_count)) score_def.addAttribute('meter.unit', str(meter_unit)) staff_def = MeiElement('staffDef') staff_def.addAttribute('n', '1') staff_def.addAttribute('label.full', 'Electric Guitar') staff_def.addAttribute('clef.shape', 'TAB') instr_def = MeiElement('instrDef') instr_def.addAttribute('n', 'Electric_Guitar') instr_def.addAttribute('midi.channel', '1') instr_def.addAttribute('midi.instrnum', '28') mei.addChild(music) music.addChild(timeline) music.addChild(body) body.addChild(mdiv) mdiv.addChild(score) score.addChild(score_def) score_def.addChild(staff_def) staff_def.addChild(instr_def) section = MeiElement('section') score.addChild(section) # another score def score_def = MeiElement('scoreDef') score_def.addAttribute('meter.count', str(meter_count)) score_def.addAttribute('meter.unit', str(meter_unit)) section.addChild(score_def) # start writing pitches to file note_container = None for i, note_event in enumerate(note_events): if i % meter_count == 0: measure = MeiElement('measure') measure.addAttribute('n', str(int(i/meter_count + 1))) staff = MeiElement('staff') staff.addAttribute('n', '1') layer = MeiElement('layer') layer.addAttribute('n', '1') section.addChild(measure) measure.addChild(staff) staff.addChild(layer) note_container = layer ts = note_event[0] when = MeiElement('when') if i == 0: timeline.addAttribute('origin', when.getId()) when.addAttribute('absolute', str(ts)) timeline.addChild(when) notes = note_event[1] if len(notes) > 1: chord = MeiElement('chord') chord.addAttribute('when', when.getId()) for n in notes: note = MeiElement('note') note_info = PolyTrans.midi_map[n] pname = note_info[0] oct = note_info[1] note.addAttribute('pname', pname[0]) note.addAttribute('oct', str(oct)) if len(pname) > 1 and pname[-1] == '#': # there is an accidental note.addAttribute('accid.ges', 's') note.addAttribute('dur', str(meter_unit)) chord.addChild(note) note_container.addChild(chord) else: n = notes[0] note = MeiElement('note') note.addAttribute('when', when.getId()) note_info = PolyTrans.midi_map[n] pname = note_info[0] oct = note_info[1] note.addAttribute('pname', pname[0]) note.addAttribute('oct', str(oct)) if len(pname) > 1 and pname[-1] == '#': # there is an accidental note.addAttribute('accid.ges', 's') note.addAttribute('dur', str(meter_unit)) note_container.addChild(note) if output_path is not None: XmlExport.meiDocumentToFile(meidoc, output_path) else: return XmlExport.meiDocumentToText(meidoc)
def write_mei(self, notes, output_path=None): # begin constructing mei document meidoc = MeiDocument() mei = MeiElement('mei') meidoc.setRootElement(mei) mei_head = MeiElement('meiHead') mei.addChild(mei_head) music = MeiElement('music') body = MeiElement('body') mdiv = MeiElement('mdiv') score = MeiElement('score') score_def = MeiElement('scoreDef') # assume 4/4 time signature meter_count = 4 meter_unit = 4 score_def.addAttribute('meter.count', str(meter_count)) score_def.addAttribute('meter.unit', str(meter_unit)) staff_def = MeiElement('staffDef') staff_def.addAttribute('n', '1') staff_def.addAttribute('label.full', 'Electric Guitar') staff_def.addAttribute('clef.shape', 'TAB') instr_def = MeiElement('instrDef') instr_def.addAttribute('n', 'Electric_Guitar') instr_def.addAttribute('midi.channel', '1') instr_def.addAttribute('midi.instrnum', '28') mei.addChild(music) music.addChild(body) body.addChild(mdiv) mdiv.addChild(score) score.addChild(score_def) score_def.addChild(staff_def) staff_def.addChild(instr_def) section = MeiElement('section') score.addChild(section) # another score def score_def = MeiElement('scoreDef') score_def.addAttribute('meter.count', str(meter_count)) score_def.addAttribute('meter.unit', str(meter_unit)) section.addChild(score_def) # start writing pitches to file note_container = None for i, frame_n in enumerate(notes): if i % meter_count == 0: measure = MeiElement('measure') measure.addAttribute('n', str(int(i / meter_count + 1))) staff = MeiElement('staff') staff.addAttribute('n', '1') layer = MeiElement('layer') layer.addAttribute('n', '1') section.addChild(measure) measure.addChild(staff) staff.addChild(layer) note_container = layer if len(frame_n) > 1: chord = MeiElement('chord') for n in frame_n: note = MeiElement('note') pname = n['pname'][0].upper() note.addAttribute('pname', pname) note.addAttribute('oct', str(n['oct'])) if len(n['pname']) > 1 and n['pname'][1] == '#': # there is an accidental note.addAttribute('accid.ges', 's') note.addAttribute('dur', str(meter_unit)) chord.addChild(note) note_container.addChild(chord) else: n = frame_n[0] note = MeiElement('note') pname = n['pname'][0].upper() note.addAttribute('pname', pname) note.addAttribute('oct', str(n['oct'])) if len(n['pname']) > 1 and n['pname'][1] == '#': # there is an accidental note.addAttribute('accid.ges', 's') note.addAttribute('dur', str(meter_unit)) note_container.addChild(note) if output_path is not None: XmlExport.meiDocumentToFile(meidoc, output_path) else: return XmlExport.meiDocumentToText(meidoc)
def test_exportwithcomments(self): docf = XmlImport.documentFromFile(os.path.join("test", "testdocs", "campion.mei")) status = XmlExport.meiDocumentToFile(docf, os.path.join(self.tempdir,"filename.mei")) self.assertTrue(status)