def extract_drums(msd_id: str) -> Optional[PrettyMIDI]: """ Extracts a PrettyMIDI instance of all the merged drum tracks from the given MSD id. :param msd_id: the MSD id :return: the PrettyMIDI instance of the merged drum tracks """ os.makedirs(args.path_output_dir, exist_ok=True) midi_md5 = get_matched_midi_md5(msd_id, MSD_SCORE_MATCHES) midi_path = get_midi_path(msd_id, midi_md5, args.path_dataset_dir) pm = PrettyMIDI(midi_path) pm_drums = copy.deepcopy(pm) pm_drums.instruments = [instrument for instrument in pm_drums.instruments if instrument.is_drum] if len(pm_drums.instruments) > 1: # Some drum tracks are split, we can merge them drums = Instrument(program=0, is_drum=True) for instrument in pm_drums.instruments: for note in instrument.notes: drums.notes.append(note) pm_drums.instruments = [drums] if len(pm_drums.instruments) != 1: raise Exception(f"Invalid number of drums {msd_id}: " f"{len(pm_drums.instruments)}") return pm_drums
def extract_pianos(msd_id: str) -> List[PrettyMIDI]: """ Extracts a list of PrettyMIDI instance of all the separate piano tracks from the given MSD id. :param msd_id: the MSD id :return: the list of PrettyMIDI instances of the separate piano tracks """ os.makedirs(args.path_output_dir, exist_ok=True) midi_md5 = get_matched_midi_md5(msd_id, MSD_SCORE_MATCHES) midi_path = get_midi_path(msd_id, midi_md5, args.path_dataset_dir) pm = PrettyMIDI(midi_path) pm.instruments = [ instrument for instrument in pm.instruments if instrument.program in PIANO_PROGRAMS and not instrument.is_drum ] pm_pianos = [] if len(pm.instruments) > 1: for piano_instrument in pm.instruments: pm_piano = copy.deepcopy(pm) pm_piano_instrument = Instrument(program=piano_instrument.program) pm_piano.instruments = [pm_piano_instrument] for note in piano_instrument.notes: pm_piano_instrument.notes.append(note) pm_pianos.append(pm_piano) else: pm_pianos.append(pm) for index, pm_piano in enumerate(pm_pianos): if len(pm_piano.instruments) != 1: raise Exception(f"Invalid number of piano {msd_id}: " f"{len(pm_piano.instruments)}") if pm_piano.get_end_time() > 1000: raise Exception(f"Piano track too long {msd_id}: " f"{pm_piano.get_end_time()}") return pm_pianos
def get_instrument_classes(msd_id) -> Optional[list]: """ Returns the list of instruments classes given by PrettyMIDI for the MSD id. :param msd_id: the MSD id :return: the list of instruments classes """ midi_md5 = get_matched_midi_md5(msd_id, MSD_SCORE_MATCHES) midi_path = get_midi_path(msd_id, midi_md5, args.path_dataset_dir) pm = PrettyMIDI(midi_path) classes = [ program_to_instrument_class(instrument.program) for instrument in pm.instruments if not instrument.is_drum ] drums = ["Drums" for instrument in pm.instruments if instrument.is_drum] classes = classes + drums if not classes: raise Exception(f"No program classes for {msd_id}: " f"{len(classes)}") return classes