def testDecode(self): encoder = music_encoders.MidiPerformanceEncoder(steps_per_second=100, num_velocity_bins=32, min_pitch=21, max_pitch=108, ngrams=[(277, 129)]) ids = [ 302, # VELOCITY(25) 41, # NOTE-ON(60) 310 # TIME-SHIFT(100), NOTE-OFF(60) ] # Decode method returns MIDI filename, read and convert to NoteSequence. filename = encoder.decode(ids) ns = note_seq.midi_file_to_sequence_proto(filename) # Remove default tempo & time signature. del ns.tempos[:] del ns.time_signatures[:] expected_ns = note_seq.NoteSequence(ticks_per_quarter=220) testing_lib.add_track_to_sequence(expected_ns, 0, [(60, 97, 0.0, 1.0)]) # Add source info fields. expected_ns.source_info.encoding_type = ( note_seq.NoteSequence.SourceInfo.MIDI) expected_ns.source_info.parser = ( note_seq.NoteSequence.SourceInfo.PRETTY_MIDI) self.assertEqual(expected_ns, ns)
def encode(self, s): """Transforms melody from a midi_file into a list of melody event indices. Args: s: Path to a MIDI file. Returns: ids: List of encoded melody event indices. """ ns = note_seq.midi_file_to_sequence_proto(s) return self.encode_note_sequence(ns)
def encode(self, s): """Transform a MIDI filename into a list of performance event indices. Args: s: Path to the MIDI file. Returns: ids: List of performance event indices. """ if s: ns = note_seq.midi_file_to_sequence_proto(s) else: ns = note_seq.NoteSequence() return self.encode_note_sequence(ns)
def load_midi(midi_path, min_pitch=36, max_pitch=84): """Load midi as a notesequence.""" midi_path = util.expand_path(midi_path) ns = note_seq.midi_file_to_sequence_proto(midi_path) pitches = np.array([n.pitch for n in ns.notes]) velocities = np.array([n.velocity for n in ns.notes]) start_times = np.array([n.start_time for n in ns.notes]) end_times = np.array([n.end_time for n in ns.notes]) valid = np.logical_and(pitches >= min_pitch, pitches <= max_pitch) notes = { 'pitches': pitches[valid], 'velocities': velocities[valid], 'start_times': start_times[valid], 'end_times': end_times[valid] } return ns, notes
def midi_quantizer(self, input_midi, output_midi): """ Transform a MIDI filename into a list of performance event indices. Args: s: Path to the MIDI file. Returns: ids: List of performance event indices. """ if input_midi: ns = note_seq.midi_file_to_sequence_proto(input_midi) ns = note_seq.sequences_lib.apply_sustain_control_changes(ns) del ns.control_changes[:] else: ns = note_seq.protobuf.music_pb2.NoteSequence() note_seq.sequence_proto_to_midi_file(ns, output_midi) return output_midi
def encode(self, input_midi): """ Transform a MIDI filename into a list of performance event indices. Args: input_midi: Path to the MIDI file. Returns: ids: List of performance event indices. """ if input_midi: ns = note_seq.midi_file_to_sequence_proto(input_midi) ns = note_seq.sequences_lib.apply_sustain_control_changes(ns) del ns.control_changes[:] else: ns = note_seq.protobuf.music_pb2.NoteSequence() self.filter_pitches(ns) return self.encode_note_sequence(ns)
def encode_transposition(self, input_midi): """ Augment and transform a MIDI file into a list of performance event indices. Args: input_midi: Path to input MIDI file Returns: ids: List of performance event indices. """ if input_midi: ns = note_seq.midi_file_to_sequence_proto(input_midi) ns = note_seq.sequences_lib.apply_sustain_control_changes(ns) del ns.control_changes[:] else: ns = note_seq.protobuf.music_pb2.NoteSequence() for augment_fn in self.augment_fns: # Augment and encode the performance. try: # print(augment_fn) augmented_performance_sequence = augment_fn(ns) except DataAugmentationError: # print(DataAugmentationError) continue yield self.encode_note_sequence(augmented_performance_sequence)
def run_with_flags(generator): """Generates melodies and saves them as MIDI files. Uses the options specified by the flags defined in this module. Args: generator: The MelodyRnnSequenceGenerator to use for generation. """ if not FLAGS.output_dir: tf.logging.fatal('--output_dir required') return FLAGS.output_dir = os.path.expanduser(FLAGS.output_dir) primer_midi = None if FLAGS.primer_midi: primer_midi = os.path.expanduser(FLAGS.primer_midi) if not tf.gfile.Exists(FLAGS.output_dir): tf.gfile.MakeDirs(FLAGS.output_dir) primer_sequence = None qpm = FLAGS.qpm if FLAGS.qpm else note_seq.DEFAULT_QUARTERS_PER_MINUTE if FLAGS.primer_melody: primer_melody = note_seq.Melody(ast.literal_eval(FLAGS.primer_melody)) primer_sequence = primer_melody.to_sequence(qpm=qpm) elif primer_midi: primer_sequence = note_seq.midi_file_to_sequence_proto(primer_midi) if primer_sequence.tempos and primer_sequence.tempos[0].qpm: qpm = primer_sequence.tempos[0].qpm else: tf.logging.warning( 'No priming sequence specified. Defaulting to a single middle C.') primer_melody = note_seq.Melody([60]) primer_sequence = primer_melody.to_sequence(qpm=qpm) # Derive the total number of seconds to generate based on the QPM of the # priming sequence and the num_steps flag. seconds_per_step = 60.0 / qpm / generator.steps_per_quarter total_seconds = FLAGS.num_steps * seconds_per_step # Specify start/stop time for generation based on starting generation at the # end of the priming sequence and continuing until the sequence is num_steps # long. generator_options = generator_pb2.GeneratorOptions() if primer_sequence: input_sequence = primer_sequence # Set the start time to begin on the next step after the last note ends. if primer_sequence.notes: last_end_time = max(n.end_time for n in primer_sequence.notes) else: last_end_time = 0 generate_section = generator_options.generate_sections.add( start_time=last_end_time + seconds_per_step, end_time=total_seconds) if generate_section.start_time >= generate_section.end_time: tf.logging.fatal( 'Priming sequence is longer than the total number of steps ' 'requested: Priming sequence length: %s, Generation length ' 'requested: %s', generate_section.start_time, total_seconds) return else: input_sequence = music_pb2.NoteSequence() input_sequence.tempos.add().qpm = qpm generate_section = generator_options.generate_sections.add( start_time=0, end_time=total_seconds) generator_options.args['temperature'].float_value = FLAGS.temperature generator_options.args['beam_size'].int_value = FLAGS.beam_size generator_options.args['branch_factor'].int_value = FLAGS.branch_factor generator_options.args[ 'steps_per_iteration'].int_value = FLAGS.steps_per_iteration tf.logging.debug('input_sequence: %s', input_sequence) tf.logging.debug('generator_options: %s', generator_options) # Make the generate request num_outputs times and save the output as midi # files. date_and_time = time.strftime('%Y-%m-%d_%H%M%S') digits = len(str(FLAGS.num_outputs)) for i in range(FLAGS.num_outputs): generated_sequence = generator.generate(input_sequence, generator_options) midi_filename = '%s_%s.mid' % (date_and_time, str(i + 1).zfill(digits)) midi_path = os.path.join(FLAGS.output_dir, midi_filename) note_seq.sequence_proto_to_midi_file(generated_sequence, midi_path) tf.logging.info('Wrote %d MIDI files to %s', FLAGS.num_outputs, FLAGS.output_dir)
def run_with_flags(generator): """Generates polyphonic tracks and saves them as MIDI files. Uses the options specified by the flags defined in this module. Args: generator: The PolyphonyRnnSequenceGenerator to use for generation. """ if not FLAGS.output_dir: tf.logging.fatal('--output_dir required') return output_dir = os.path.expanduser(FLAGS.output_dir) primer_midi = None if FLAGS.primer_midi: primer_midi = os.path.expanduser(FLAGS.primer_midi) if not tf.gfile.Exists(output_dir): tf.gfile.MakeDirs(output_dir) primer_sequence = None qpm = FLAGS.qpm if FLAGS.qpm else note_seq.DEFAULT_QUARTERS_PER_MINUTE if FLAGS.primer_pitches: primer_sequence = music_pb2.NoteSequence() primer_sequence.tempos.add().qpm = qpm primer_sequence.ticks_per_quarter = note_seq.STANDARD_PPQ for pitch in ast.literal_eval(FLAGS.primer_pitches): note = primer_sequence.notes.add() note.start_time = 0 note.end_time = 60.0 / qpm note.pitch = pitch note.velocity = 100 primer_sequence.total_time = primer_sequence.notes[-1].end_time elif FLAGS.primer_melody: primer_melody = note_seq.Melody(ast.literal_eval(FLAGS.primer_melody)) primer_sequence = primer_melody.to_sequence(qpm=qpm) elif primer_midi: primer_sequence = note_seq.midi_file_to_sequence_proto(primer_midi) if primer_sequence.tempos and primer_sequence.tempos[0].qpm: qpm = primer_sequence.tempos[0].qpm else: tf.logging.warning( 'No priming sequence specified. Defaulting to empty sequence.') primer_sequence = music_pb2.NoteSequence() primer_sequence.tempos.add().qpm = qpm primer_sequence.ticks_per_quarter = note_seq.STANDARD_PPQ # Derive the total number of seconds to generate. seconds_per_step = 60.0 / qpm / generator.steps_per_quarter generate_end_time = FLAGS.num_steps * seconds_per_step # Specify start/stop time for generation based on starting generation at the # end of the priming sequence and continuing until the sequence is num_steps # long. generator_options = generator_pb2.GeneratorOptions() # Set the start time to begin when the last note ends. generate_section = generator_options.generate_sections.add( start_time=primer_sequence.total_time, end_time=generate_end_time) if generate_section.start_time >= generate_section.end_time: tf.logging.fatal( 'Priming sequence is longer than the total number of steps ' 'requested: Priming sequence length: %s, Total length ' 'requested: %s', generate_section.start_time, generate_end_time) return generator_options.args['temperature'].float_value = FLAGS.temperature generator_options.args['beam_size'].int_value = FLAGS.beam_size generator_options.args['branch_factor'].int_value = FLAGS.branch_factor generator_options.args[ 'steps_per_iteration'].int_value = FLAGS.steps_per_iteration generator_options.args['condition_on_primer'].bool_value = ( FLAGS.condition_on_primer) generator_options.args['no_inject_primer_during_generation'].bool_value = ( not FLAGS.inject_primer_during_generation) tf.logging.debug('primer_sequence: %s', primer_sequence) tf.logging.debug('generator_options: %s', generator_options) # Make the generate request num_outputs times and save the output as midi # files. date_and_time = time.strftime('%Y-%m-%d_%H%M%S') digits = len(str(FLAGS.num_outputs)) for i in range(FLAGS.num_outputs): generated_sequence = generator.generate(primer_sequence, generator_options) midi_filename = '%s_%s.mid' % (date_and_time, str(i + 1).zfill(digits)) midi_path = os.path.join(output_dir, midi_filename) note_seq.sequence_proto_to_midi_file(generated_sequence, midi_path) tf.logging.info('Wrote %d MIDI files to %s', FLAGS.num_outputs, output_dir)
def run_with_flags(generator): """Generates performance tracks and saves them as MIDI files. Uses the options specified by the flags defined in this module. Args: generator: The PerformanceRnnSequenceGenerator to use for generation. """ if not FLAGS.output_dir: tf.logging.fatal('--output_dir required') return output_dir = os.path.expanduser(FLAGS.output_dir) primer_midi = None if FLAGS.primer_midi: primer_midi = os.path.expanduser(FLAGS.primer_midi) if not tf.gfile.Exists(output_dir): tf.gfile.MakeDirs(output_dir) primer_sequence = None if FLAGS.primer_pitches: primer_sequence = music_pb2.NoteSequence() primer_sequence.ticks_per_quarter = note_seq.STANDARD_PPQ for pitch in ast.literal_eval(FLAGS.primer_pitches): note = primer_sequence.notes.add() note.start_time = 0 note.end_time = 60.0 / note_seq.DEFAULT_QUARTERS_PER_MINUTE note.pitch = pitch note.velocity = 100 primer_sequence.total_time = note.end_time elif FLAGS.primer_melody: primer_melody = note_seq.Melody(ast.literal_eval(FLAGS.primer_melody)) primer_sequence = primer_melody.to_sequence() elif primer_midi: primer_sequence = note_seq.midi_file_to_sequence_proto(primer_midi) else: tf.logging.warning( 'No priming sequence specified. Defaulting to empty sequence.') primer_sequence = music_pb2.NoteSequence() primer_sequence.ticks_per_quarter = note_seq.STANDARD_PPQ # Derive the total number of seconds to generate. seconds_per_step = 1.0 / generator.steps_per_second generate_end_time = FLAGS.num_steps * seconds_per_step # Specify start/stop time for generation based on starting generation at the # end of the priming sequence and continuing until the sequence is num_steps # long. generator_options = generator_pb2.GeneratorOptions() # Set the start time to begin when the last note ends. generate_section = generator_options.generate_sections.add( start_time=primer_sequence.total_time, end_time=generate_end_time) if generate_section.start_time >= generate_section.end_time: tf.logging.fatal( 'Priming sequence is longer than the total number of steps ' 'requested: Priming sequence length: %s, Total length ' 'requested: %s', generate_section.start_time, generate_end_time) return for control_cls in note_seq.all_performance_control_signals: if FLAGS[control_cls.name].value is not None and ( generator.control_signals is None or not any(control.name == control_cls.name for control in generator.control_signals)): tf.logging.warning( 'Control signal requested via flag, but generator is not set up to ' 'condition on this control signal. Request will be ignored: %s = %s', control_cls.name, FLAGS[control_cls.name].value) if (FLAGS.disable_conditioning is not None and not generator.optional_conditioning): tf.logging.warning( 'Disable conditioning flag set, but generator is not set up for ' 'optional conditioning. Requested disable conditioning flag will be ' 'ignored: %s', FLAGS.disable_conditioning) if generator.control_signals: for control in generator.control_signals: if FLAGS[control.name].value is not None: generator_options.args[control.name].string_value = ( FLAGS[control.name].value) if FLAGS.disable_conditioning is not None: generator_options.args['disable_conditioning'].string_value = ( FLAGS.disable_conditioning) generator_options.args['temperature'].float_value = FLAGS.temperature generator_options.args['beam_size'].int_value = FLAGS.beam_size generator_options.args['branch_factor'].int_value = FLAGS.branch_factor generator_options.args[ 'steps_per_iteration'].int_value = FLAGS.steps_per_iteration tf.logging.debug('primer_sequence: %s', primer_sequence) tf.logging.debug('generator_options: %s', generator_options) # Make the generate request num_outputs times and save the output as midi # files. date_and_time = time.strftime('%Y-%m-%d_%H%M%S') digits = len(str(FLAGS.num_outputs)) for i in range(FLAGS.num_outputs): generated_sequence = generator.generate(primer_sequence, generator_options) midi_filename = '%s_%s.mid' % (date_and_time, str(i + 1).zfill(digits)) midi_path = os.path.join(output_dir, midi_filename) note_seq.sequence_proto_to_midi_file(generated_sequence, midi_path) tf.logging.info('Wrote %d MIDI files to %s', FLAGS.num_outputs, output_dir)