def test_midi_import_mode_1(self): parts = load_score_midi(self.tmpfile.name, part_voice_assign_mode=1) by_track = partition(itemgetter(0), self.notes_per_tr_ch.keys()) msg = ( 'Number of partgroups {} does not equal number of tracks {} while ' 'testing part_voice_assign_mode=0 in load_score_midi').format( len(parts), len(by_track)) self.assertEqual(len(parts), len(by_track), msg) for part_group, tr in zip(parts, by_track): msg = '{} should be a PartGroup instance but it is not' self.assertTrue(isinstance(part_group, score.PartGroup), msg) n_parts = len(part_group.children) n_channels = len(by_track[tr]) msg = ( 'PartGroup should have as many parts as there are ' 'channels in the corresponding track {}, but it has {}'.format( n_channels, n_parts)) self.assertEqual(n_parts, n_channels, msg) for part, tr_ch in zip(part_group.children, by_track[tr]): notes_in_track = self.notes_per_tr_ch[tr_ch] notes_in_part = len(part.notes) msg = 'Part should have {} notes but it has {}'.format( notes_in_track, notes_in_part) self.assertEqual(notes_in_part, notes_in_track)
def test_midi_import_mode_0(self): parts = load_score_midi(self.tmpfile.name, part_voice_assign_mode=0) by_track = partition(itemgetter(0), self.notes_per_tr_ch.keys()) msg = ('Number of parts {} does not equal number of tracks {} while ' 'testing part_voice_assign_mode=0 in load_score_midi').format( len(parts), len(by_track)) self.assertEqual(len(parts), len(by_track), msg) for part, tr in zip(parts, by_track): msg = '{} should be a Part instance but it is not'.format(part) self.assertTrue(isinstance(part, score.Part), msg) n_track_notes = sum(self.notes_per_tr_ch[tr_ch] for tr_ch in by_track[tr]) part_notes = part.notes n_part_notes = len(part_notes) msg = 'Part should have {} notes but it has'.format( n_track_notes, n_part_notes) self.assertEqual(n_track_notes, n_part_notes, msg) n_ch_notes = [ self.notes_per_tr_ch[tr_ch] for tr_ch in by_track[tr] ] n_voice_notes = [ len(vn) for v, vn in partition( lambda x: x, [n.voice for n in part_notes]).items() ] msg = ( 'Part voices should have {} notes respectively, but they have {}' .format(n_ch_notes, n_voice_notes)) self.assertEqual(n_ch_notes, n_voice_notes, msg)
def test_midi_import_mode_4(self): part = load_score_midi(self.tmpfile.name, part_voice_assign_mode=4) msg = '{} should be a Part instance but it is not'.format(part) self.assertTrue(isinstance(part, score.Part), msg) midi_notes = sum(self.notes_per_tr_ch.values()) part_notes = len(part.notes) msg = 'Part should have {} notes but it has'.format( midi_notes, part_notes) self.assertEqual(midi_notes, part_notes, msg)
def test_midi_import_mode_5(self): parts = load_score_midi(self.tmpfile.name, part_voice_assign_mode=5) msg = ('Number of parts should be {} but it is {}'.format( len(self.notes_per_tr_ch), len(parts))) self.assertEqual(len(parts), len(self.notes_per_tr_ch), msg) for part, trch_notes in zip(parts, self.notes_per_tr_ch.values()): part_notes = len(part.notes) msg = ('Part should have {} notes but it has'.format( trch_notes, part_notes)) self.assertEqual(part_notes, trch_notes, msg)
def test_midi_import_mode_2(self): part = load_score_midi(self.tmpfile.name, part_voice_assign_mode=2) msg = '{} should be a Part instance but it is not'.format(part) self.assertTrue(isinstance(part, score.Part), msg) by_track = partition(itemgetter(0), self.notes_per_tr_ch.keys()) by_voice = partition(lambda x: x.voice, part.notes) n_track_notes = [ sum(self.notes_per_tr_ch[tr_ch] for tr_ch in tr_chs) for tr_chs in by_track.values() ] n_voice_notes = ([len(notes) for notes in by_voice.values()]) msg = ('Number of notes per voice {} does not match number of ' 'notes per track {}'.format(n_voice_notes, n_track_notes)) self.assertEqual(n_voice_notes, n_track_notes, msg)
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')
def test_midi_import_mode_3(self): parts = load_score_midi(self.tmpfile.name, part_voice_assign_mode=3) by_track = partition(itemgetter(0), self.notes_per_tr_ch.keys()) msg = ('Number of parts {} does not equal number of tracks {}'.format( len(parts), len(by_track))) self.assertEqual(len(parts), len(by_track), msg) for part, tr in zip(parts, by_track): msg = '{} should be a Part instance but it is not'.format(part) self.assertTrue(isinstance(part, score.Part), msg) n_track_notes = sum(self.notes_per_tr_ch[tr_ch] for tr_ch in by_track[tr]) part_notes = part.notes n_part_notes = len(part_notes) msg = 'Part should have {} notes but it has'.format( n_track_notes, n_part_notes) self.assertEqual(n_track_notes, n_part_notes, msg)
def test_tuplets(self): for example_gen_func in self.example_gen_funcs: mid, actual, normal = example_gen_func() with NamedTemporaryFile(suffix=".mid") as fh: mid.save(fh.name) part = load_score_midi(fh.name, part_voice_assign_mode=0) notes = part.notes if len(actual) != len(normal): LOGGER.warning("Error in example case, skipping test") return msg = "Example Part has an unexpected number of notes (expected {}, got {})".format( len(actual), len(notes)) self.assertEqual(len(notes), len(actual), msg) sym_durs = [n.symbolic_duration for n in notes] msg = "Incorrectly detected tuplets" self.assertEqual(actual, [sd.get("actual_notes") for sd in sym_durs], msg) self.assertEqual(normal, [sd.get("normal_notes") for sd in sym_durs], msg)
import numpy as np import os import glob import partitura from scipy.interpolate import interp1d from utils import BeatMap score = partitura.load_score_midi('../score/Bruckner_7_Adagio.mid', estimate_voice_info=False) midi_score = partitura.load_performance_midi('../score/Bruckner_7_Adagio.mid', merge_tracks=True) if not isinstance(score, (partitura.score.PartGroup, partitura.score.Part)): pg = partitura.score.PartGroup() pg.children = score score = pg score_note_array = score.note_array midi_note_array = midi_score.note_array unique_s_onsets = np.unique(score_note_array['onset']) unique_m_onsets = np.unique(midi_note_array['p_onset']) midi_beat_map = BeatMap(input_times=unique_m_onsets, output_times=unique_s_onsets, i_min_time=unique_m_onsets.min(), i_max_time=np.max(midi_note_array['p_onset'] + midi_note_array['p_duration']), o_min_time=unique_s_onsets.min(), o_max_time=np.max(score_note_array['onset'] +