def _pretty_export_import_pretty_test(self, part1): # pretty print the part pstring1 = part1.pretty() with TemporaryFile() as f: # save part to musicxml save_musicxml(part1, f) f.flush() f.seek(0) _tmp = f.read().decode('utf8') f.seek(0) # load part from musicxml part2 = load_musicxml(f) # pretty print saved/loaded part: pstring2 = part2.pretty() # test pretty printed strings for equality equal = pstring1 == pstring2 if not equal: print(pstring1) print(pstring2) print(_tmp) show_diff(pstring1, pstring2) msg = 'Exported and imported score does not yield identical pretty printed representations' self.assertTrue(equal, msg)
def test_unfold_timeline(self): for fn, fn_target_1, fn_target_2 in MUSICXML_UNFOLD_TESTPAIRS: part = load_musicxml(fn, validate=False) part = score.unfold_part_maximal(part) result = save_musicxml(part).decode("UTF-8") with open(fn_target_1) as f: target = f.read() equal = target == result if not equal: show_diff(result, target) msg = "Unfolding part of MusicXML file {} does not yield expected result".format( fn) self.assertTrue(equal, msg) # check unfold with update_id part = score.unfold_part_maximal(part, update_ids=True) result = save_musicxml(part).decode("UTF-8") with open(fn_target_2) as f: target = f.read() equal = target == result if not equal: show_diff(result, target) msg = "Unfolding part of MusicXML file {} does not yield expected result".format( fn) self.assertTrue(equal, msg)
class TestVoSA(unittest.TestCase): """ Test VoSA """ score = load_musicxml(VOSA_TESTFILES[0]) def test_vosa_chew(self): # Example from Chew and Wu. # notearray = musicxml_to_notearray(VOSA_TESTFILES[0], beat_times=False) voices = estimate_voices(self.score, monophonic_voices=True) # ground_truth_voices = np.array([3, 2, 1, 3, 3, 2, 3, 3, 2, 3, # 3, 1, 1, 2, 1, 1, 3, 2, 1, 1]) ground_truth_voices = np.array( [1, 2, 3, 1, 1, 2, 1, 1, 2, 1, 1, 3, 3, 2, 3, 3, 1, 2, 3, 3] ) self.assertTrue( np.all(voices == ground_truth_voices), "Incorrect voice assignment." ) def test_vosa_chew_chordnotes(self): # Example from Chew and Wu. # notearray = musicxml_to_notearray(VOSA_TESTFILES[0], beat_times=False) voices = estimate_voices(self.score, monophonic_voices=False) ground_truth_voices = np.array( [1, 2, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 3, 2, 2, 1, 1, 2, 2] ) self.assertTrue( np.all(voices == ground_truth_voices), "Incorrect voice assignment." )
def get_performance_info(piece, performer): assert data.DATASET_DIR musicxml_fn = os.path.join(data.DATASET_DIR, 'musicxml', '{}.musicxml'.format(piece)) match_fn = os.path.join(data.DATASET_DIR, 'match', '{}_{}.match'.format(piece, performer)) part = partitura.load_musicxml(musicxml_fn) ppart, alignment = partitura.load_match(match_fn, first_note_at_zero=True) return part, ppart, alignment
def test_import_export(self): for fn in MUSICXML_IMPORT_EXPORT_TESTFILES: with open(fn) as f: parts = load_musicxml(f, validate=False) result = save_musicxml(parts).decode('UTF-8') f.seek(0) target = f.read() equal = target == result if not equal: show_diff(result, target) msg = "Import and export of MusicXML of file {} does not yield identical result".format(fn) self.assertTrue(equal, msg)
class TestKeyEstimation(unittest.TestCase): """ Test key estimation """ score = load_musicxml(EXAMPLE_MUSICXML) def test_part(self): key = estimate_key(self.score) self.assertTrue(key == "Am", "Incorrect key") def test_note_array(self): key = estimate_key(self.score.note_array) self.assertTrue(key == "Am", "Incorrect key")
class TestKeyEstimation(unittest.TestCase): """ Test key estimation """ score = load_musicxml(EXAMPLE_MUSICXML) def test_part(self): spelling = estimate_spelling(self.score) comparisons = compare_spelling(spelling, self.score.notes) self.assertTrue(np.all(comparisons), "Incorrect spelling") def test_note_array(self): spelling = estimate_spelling(self.score.note_array) comparisons = compare_spelling(spelling, self.score.notes) self.assertTrue(np.all(comparisons), "Incorrect spelling")
class TestTonalTension(unittest.TestCase): score = load_musicxml(EXAMPLE_MUSICXML) performance = load_performance_midi(EXAMPLE_MIDI) def test_prepare_notearray(self): target_note_array = np.array( [ (0.0, 2.0, 69, 64, "n0", "A", 0, 4, 0, -1), (1.0, 1.0, 72, 64, "n1", "C", 0, 5, 0, -1), (1.0, 1.0, 76, 64, "n2", "E", 0, 5, 0, -1), ], dtype=[ ("onset_sec", "<f4"), ("duration_sec", "<f4"), ("pitch", "<i4"), ("velocity", "<i4"), ("id", "<U256"), ("step", "<U1"), ("alter", "<i8"), ("octave", "<i8"), ("ks_fifths", "<i4"), ("ks_mode", "<i4"), ], ) note_array = prepare_note_array(self.performance) for name in target_note_array.dtype.names: self.assertTrue( np.all(note_array[name] == target_note_array[name]), f"Note arrays are not equal for field {name}", ) def test_estimate_tonaltension(self): tonal_tension = estimate_tonaltension(self.score) target_tension = np.array( [(0, 0, 0, 0.19651566), (2.0, 0.33333334, 0.07754743, 0.13506594)], dtype=[ ("onset_beat", "<f4"), ("cloud_diameter", "<f4"), ("cloud_momentum", "<f4"), ("tensile_strain", "<f4"), ], ) self.assertTrue(np.all(tonal_tension == target_tension), "estimated tension is incorrect!")
def test_export_import_pprint(self): # create a part part1 = score.Part('My Part') # create contents divs = 10 ts = score.TimeSignature(3, 4) page1 = score.Page(1) system1 = score.System(1) measure1 = score.Measure(number=1) note1 = score.Note(step='A', octave=4, voice=1, staff=1) rest1 = score.Rest(voice=1, staff=1) note2 = score.Note(step='C', octave=5, alter=-1, voice=2, staff=1) # and add the contents to the part: part1.set_quarter_duration(0, divs) part1.add(ts, 0) part1.add(measure1, 0, 30) part1.add(page1, 0) part1.add(system1, 0) part1.add(note1, 0, 15) part1.add(rest1, 15, 30) part1.add(note2, 0, 30) score.set_end_times(part1) # pretty print the part pstring1 = part1.pretty() with TemporaryFile() as f: # save part to musicxml save_musicxml(part1, f) f.flush() f.seek(0) # load part from musicxml part2 = load_musicxml(f) # pretty print saved/loaded part: pstring2 = part2.pretty() # test pretty printed strings for equality equal = pstring1 == pstring2 if not equal: show_diff(pstring1, pstring2) msg = 'Exported and imported score does not yield identical pretty printed representations' self.assertTrue(equal, msg)
def compute_basis_from_xml(xml_fn, input_names): # Load MusicXML file part = load_musicxml(xml_fn, force_note_ids=True) expand_grace_notes(part) part = unfold_part_maximal(part) # Compute basis functions _basis, bf_names = make_basis(part, list(set([bf.split('.')[0] for bf in input_names]))) basis = np.zeros((len(_basis), len(input_names))) for i, n in enumerate(input_names): try: ix = bf_names.index(n) except ValueError: continue basis[:, i] = _basis[:, ix] return basis, part
def load_score(score_fn): """ Load a score format supported by partitura. Currently the accepted formats are MusicXML and MIDI (native Python support), plus all formats for which MuseScore has support import-support (requires MuseScore 3) Parameters ---------- score_fn : str Filename of the score to load. Returns ------- :class:`partitura.score.Part` A score part. """ part = None # Load MusicXML try: return load_musicxml(score_fn, force_note_ids='keep') except: pass # Load MIDI try: return load_score_midi(score_fn, assign_note_ids=True) except: pass # Load MuseScore try: return load_via_musescore(score_fn, force_note_ids='keep') except: pass # Load a part in compressed pickle format try: part = load_pyc_bz(score_fn) if isinstance(part, Part): return part else: part = None except: pass if part is None: raise ValueError('The score is not in one of the supported formats')
import argparse import partitura import copy parser = argparse.ArgumentParser() parser.add_argument('in', help="Input musicxml file") parser.add_argument('out', help="Destination file") parser.add_argument('--note', help='Change the note to replicate') args = parser.parse_args() score = partitura.load_musicxml(getattr(args, "in")) to_purge = [] added_notes = [] for note in score.timeline.iter_all(partitura.score.Note, include_subclasses=True): if note.step == "D" and note not in added_notes and note.duration > 1: containing_timepoint = next( iter([ point for point in score.timeline.points if note in point.starting_objects[partitura.score.Note] ])) for i in range(0, note.duration): new_d = copy.copy(note) new_d._sym_dur = None new_d.start = score.timeline.get_or_add_point(note.start.t + i) new_d.end = score.timeline.get_or_add_point(new_d.start.t + 1) score.timeline.add(new_d, containing_timepoint.t + i, containing_timepoint.t + i + 1) to_purge.append(note)