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)
Beispiel #2
0
    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)
Beispiel #3
0
    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)
Beispiel #4
0
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)
Beispiel #8
0
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)