def CheckReadWriteMidi(self, filename): """Test writing to a MIDI file and comparing it to the original Sequence.""" source_midi = pretty_midi.PrettyMIDI(filename) sequence_proto = midi_io.midi_to_sequence_proto(source_midi) translated_midi = midi_io.sequence_proto_to_pretty_midi(sequence_proto) # Write the translated midi to a file. with tempfile.NamedTemporaryFile(prefix='MidiIoTest') as temp_file: translated_midi.write(temp_file.name) # Read it back in and compare to source. created_midi = pretty_midi.PrettyMIDI(temp_file.name) created_sequence = midi_io.midi_to_sequence_proto(created_midi) self.CheckPrettyMidiAndSequence(translated_midi, created_sequence)
def convert_directory(root_dir, sub_dir, sequence_writer, recursive=False): """Converts MIDIs to NoteSequences and writes to `sequence_writer`. MIDI files found in the specified directory specified by the combination of `root_dir` and `sub_dir` and converted to NoteSequence protos with the basename of `root_dir` as the collection_name, and the relative path to the MIDI file from `root_dir` as the filename. If `recursive` is true, recursively converts any subdirectories of the specified directory. Args: root_dir: A string specifying a root directory. sub_dir: A string specifying a path to a directory under `root_dir` in which to convert MIDI contents. sequence_writer: A NoteSequenceRecordWriter to write the resulting NoteSequence protos to. recursive: A boolean specifying whether or not recursively convert MIDIs contained in subdirectories of the specified directory. Returns: The number of NoteSequence protos written as an integer. """ dir_to_convert = os.path.join(root_dir, sub_dir) tf.logging.info("Converting MIDI files in '%s'.", dir_to_convert) files_in_dir = tf.gfile.ListDirectory(os.path.join(dir_to_convert)) recurse_sub_dirs = [] sequences_written = 0 sequences_skipped = 0 for file_in_dir in files_in_dir: full_file_path = os.path.join(dir_to_convert, file_in_dir) if tf.gfile.IsDirectory(full_file_path): if recursive: recurse_sub_dirs.append(os.path.join(sub_dir, file_in_dir)) continue try: sequence = midi_io.midi_to_sequence_proto( tf.gfile.FastGFile(full_file_path).read()) except midi_io.MIDIConversionError as e: tf.logging.warning( 'Could not parse MIDI file %s. It will be skipped. Error was: %s', full_file_path, e) sequences_skipped += 1 continue sequence.collection_name = os.path.basename(root_dir) sequence.filename = os.path.join(sub_dir, file_in_dir) sequence.id = note_sequence_io.generate_id(sequence.filename, sequence.collection_name, 'midi') sequence_writer.write(sequence) sequences_written += 1 tf.logging.info("Converted %d MIDI files in '%s'.", sequences_written, dir_to_convert) tf.logging.info('Could not parse %d MIDI files.', sequences_skipped) for recurse_sub_dir in recurse_sub_dirs: sequences_written += convert_directory(root_dir, recurse_sub_dir, sequence_writer, recursive) return sequences_written
def convert_directory(root_dir, sub_dir, sequence_writer, recursive=False): """Converts MIDIs to NoteSequences and writes to `sequence_writer`. MIDI files found in the specified directory specified by the combination of `root_dir` and `sub_dir` and converted to NoteSequence protos with the basename of `root_dir` as the collection_name, and the relative path to the MIDI file from `root_dir` as the filename. If `recursive` is true, recursively converts any subdirectories of the specified directory. Args: root_dir: A string specifying a root directory. sub_dir: A string specifying a path to a directory under `root_dir` in which to convert MIDI contents. sequence_writer: A NoteSequenceRecordWriter to write the resulting NoteSequence protos to. recursive: A boolean specifying whether or not recursively convert MIDIs contained in subdirectories of the specified directory. Returns: The number of NoteSequence protos written as an integer. """ dir_to_convert = os.path.join(root_dir, sub_dir) tf.logging.info("Converting MIDI files in '%s'.", dir_to_convert) files_in_dir = tf.gfile.ListDirectory(os.path.join(dir_to_convert)) recurse_sub_dirs = [] sequences_written = 0 sequences_skipped = 0 for file_in_dir in files_in_dir: full_file_path = os.path.join(dir_to_convert, file_in_dir) if tf.gfile.IsDirectory(full_file_path): if recursive: recurse_sub_dirs.append(os.path.join(sub_dir, file_in_dir)) continue try: sequence = midi_io.midi_to_sequence_proto( tf.gfile.FastGFile(full_file_path).read()) except midi_io.MIDIConversionError as e: tf.logging.warning( 'Could not parse MIDI file %s. It will be skipped. Error was: %s', full_file_path, e) sequences_skipped += 1 continue sequence.collection_name = os.path.basename(root_dir) sequence.filename = os.path.join(sub_dir, file_in_dir) sequence.id = note_sequence_io.generate_id(sequence.filename, sequence.collection_name, 'midi') sequence_writer.write(sequence) sequences_written += 1 tf.logging.info("Converted %d MIDI files in '%s'.", sequences_written, dir_to_convert) tf.logging.info('Could not parse %d MIDI files.', sequences_skipped) for recurse_sub_dir in recurse_sub_dirs: sequences_written += convert_directory( root_dir, recurse_sub_dir, sequence_writer, recursive) return sequences_written
def CheckReadWriteMidi(self, filename): """Test writing to a MIDI file and comparing it to the original Sequence.""" # TODO(deck): The input MIDI file is opened in pretty-midi and # re-written to a temp file, sanitizing the MIDI data (reordering # note ons, etc). Issue 85 in the pretty-midi GitHub # (http://github.com/craffel/pretty-midi/issues/85) requests that # this sanitization be available outside of the context of a file # write. If that is implemented, this rewrite code should be # modified or deleted. with tempfile.NamedTemporaryFile(prefix='MidiIoTest') as rewrite_file: original_midi = pretty_midi.PrettyMIDI(filename) original_midi.write(rewrite_file.name) source_midi = pretty_midi.PrettyMIDI(rewrite_file.name) sequence_proto = midi_io.midi_to_sequence_proto(source_midi) # Translate the NoteSequence to MIDI and write to a file. with tempfile.NamedTemporaryFile(prefix='MidiIoTest') as temp_file: midi_io.sequence_proto_to_midi_file(sequence_proto, temp_file.name) # Read it back in and compare to source. created_midi = pretty_midi.PrettyMIDI(temp_file.name) self.CheckPrettyMidiAndSequence(created_midi, sequence_proto)
def CheckSequenceToPrettyMidi(self, filename): """Test the translation from Sequence proto to PrettyMIDI.""" source_midi = pretty_midi.PrettyMIDI(filename) sequence_proto = midi_io.midi_to_sequence_proto(source_midi) translated_midi = midi_io.sequence_proto_to_pretty_midi(sequence_proto) self.CheckPrettyMidiAndSequence(translated_midi, sequence_proto)
def CheckMidiToSequence(self, filename): """Test the translation from PrettyMIDI to Sequence proto.""" source_midi = pretty_midi.PrettyMIDI(filename) sequence_proto = midi_io.midi_to_sequence_proto(source_midi) self.CheckPrettyMidiAndSequence(source_midi, sequence_proto)