Example #1
0
    def _generate(self, gen_index, input_sequence, zero_time,
                  response_start_time, response_end_time):
        # pylint: disable-msg=no-member
        response_start_time -= zero_time
        response_end_time -= zero_time

        generator_options = GeneratorOptions()
        generator_options.input_sections.add(start_time=0,
                                             end_time=response_start_time)
        generator_options.generate_sections.add(start_time=response_start_time,
                                                end_time=response_end_time)

        # Set current temperature setting.
        generator_options.args["temperature"].float_value = self._temperature

        # Generate response.
        generator = self._sequence_generators[gen_index]
        logging.warn("Generating sequence using '{}' generator.".format(
            generator.details.id))
        # logging.warn("\tGenerator Details:\t{}".format(generator.details))
        # logging.warn("\tBundle Details:\t{}".format(generator.bundle_details))
        # logging.warn("\tGenerator Options:\t{}".format(generator_options))
        response_sequence = generator.generate(
            adjust_sequence_times(input_sequence, -zero_time),
            generator_options)
        response_sequence = trim_note_sequence(response_sequence,
                                               response_start_time,
                                               response_end_time)
        return adjust_sequence_times(response_sequence, zero_time)
Example #2
0
def generateNewSequence(input_sequence, temperature, write_to_file):

    input_sequence = mm.quantize_note_sequence(input_sequence, 8)
    bundle = sequence_generator_bundle.read_bundle_file(
        '/Library/Application Support/Quin Scacheri/Magenta Beats/drum_kit_rnn.mag'
    )
    generator_map = drums_rnn_sequence_generator.get_generator_map()
    drum_rnn = generator_map['drum_kit'](checkpoint=None, bundle=bundle)
    drum_rnn.initialize()

    qpm = input_sequence.tempos[0].qpm
    last_end_time = (max(
        n.end_time
        for n in input_sequence.notes) if input_sequence.notes else 0)
    #    total_seconds = num_steps * input_sequence.quantization_info.steps_per_quarter;

    generator_options = generator_pb2.GeneratorOptions()
    generator_options.args['temperature'].float_value = temperature
    generate_section = generator_options.generate_sections.add(
        start_time=last_end_time, end_time=8.0)

    new_sequence = drum_rnn.generate(input_sequence, generator_options)
    new_sequence = mm.trim_note_sequence(new_sequence, 2.0, 4.0)
    new_sequence = mm.quantize_note_sequence(new_sequence, 4)
    #
    #    new_sequence.quantization_info.steps_per_quarter = 8

    if (True):
        mm.sequence_proto_to_midi_file(input_sequence, 'primer.mid')
        mm.sequence_proto_to_midi_file(new_sequence, 'new_sequence.mid')

    return new_sequence
 def _generate(self, input_sequence, generator_options):
   if len(generator_options.input_sections) > 1:
       raise mm.SequenceGeneratorException('This model supports at most one input_sections message, but got %s' %len(generator_options.input_sections))
   if len(generator_options.generate_sections) != 1:
       raise mm.SequenceGeneratorException('This model supports only 1 generate_sections message, but got %s' %len(generator_options.generate_sections))
   qpm = (input_sequence.tempos[0].qpm if input_sequence and input_sequence.tempos else mm.DEFAULT_QUARTERS_PER_MINUTE)
   steps_per_second = mm.steps_per_quarter_to_steps_per_second(self.steps_per_quarter, qpm)
   generate_section = generator_options.generate_sections[0]
   if generator_options.input_sections:
       input_section = generator_options.input_sections[0]
       primer_sequence = mm.trim_note_sequence(input_sequence, input_section.start_time, input_section.end_time)
       input_start_step = mm.quantize_to_step(input_section.start_time, steps_per_second, quantize_cutoff=0)
   else:
       primer_sequence = input_sequence
       input_start_step = 0
   last_end_time = (max(n.end_time for n in primer_sequence.notes)
                       if primer_sequence.notes else 0)
   if last_end_time > generate_section.start_time:
       raise mm.SequenceGeneratorException('start time: %s, Final note end time: %s' % (generate_section.start_time, last_end_time))
   quantized_sequence = mm.quantize_note_sequence(primer_sequence, self.steps_per_quarter)
   extracted_melodies, _ = mm.extract_melodies(quantized_sequence, search_start_step=input_start_step, min_bars=0,min_unique_pitches=1, gap_bars=float('inf'),ignore_polyphonic_notes=True)
   assert len(extracted_melodies) <= 1
   start_step = mm.quantize_to_step(
       generate_section.start_time, steps_per_second, quantize_cutoff=0)
   end_step = mm.quantize_to_step(generate_section.end_time, steps_per_second, quantize_cutoff=1.0)
   if extracted_melodies and extracted_melodies[0]:
       melody = extracted_melodies[0]
   else:
       steps_per_bar = int(mm.steps_per_bar_in_quantized_sequence(quantized_sequence))
       melody = mm.Melody([],start_step=max(0, start_step - 1),steps_per_bar=steps_per_bar,steps_per_quarter=self.steps_per_quarter)
   melody.set_length(start_step - melody.start_step)
   arg_types = {
       'temperature': lambda arg: arg.float_value,
       'beam_size': lambda arg: arg.int_value,
       'branch_factor': lambda arg: arg.int_value,
       'steps_per_iteration': lambda arg: arg.int_value
   }
   args = dict((name, value_fn(generator_options.args[name])) for name, value_fn in arg_types.items() if name in generator_options.args)
   generated_melody = self._model.generate_melody(end_step - melody.start_step, melody, **args)
   generated_sequence = generated_melody.to_sequence(qpm=qpm)
   assert (generated_sequence.total_time - generate_section.end_time) <= 1e-5
   return generated_sequence
  def _generate(self, input_sequence, generator_options):
    if len(generator_options.input_sections) > 1:
      raise mm.SequenceGeneratorException(
          'This model supports at most one input_sections message, but got %s' %
          len(generator_options.input_sections))
    if len(generator_options.generate_sections) != 1:
      raise mm.SequenceGeneratorException(
          'This model supports only 1 generate_sections message, but got %s' %
          len(generator_options.generate_sections))

    qpm = (input_sequence.tempos[0].qpm
           if input_sequence and input_sequence.tempos
           else mm.DEFAULT_QUARTERS_PER_MINUTE)
    steps_per_second = mm.steps_per_quarter_to_steps_per_second(
        self.steps_per_quarter, qpm)

    generate_section = generator_options.generate_sections[0]
    if generator_options.input_sections:
      input_section = generator_options.input_sections[0]
      primer_sequence = mm.trim_note_sequence(
          input_sequence, input_section.start_time, input_section.end_time)
      input_start_step = mm.quantize_to_step(
          input_section.start_time, steps_per_second, quantize_cutoff=0)
    else:
      primer_sequence = input_sequence
      input_start_step = 0

    last_end_time = (max(n.end_time for n in primer_sequence.notes)
                     if primer_sequence.notes else 0)
    if last_end_time > generate_section.start_time:
      raise mm.SequenceGeneratorException(
          'Got GenerateSection request for section that is before the end of '
          'the NoteSequence. This model can only extend sequences. Requested '
          'start time: %s, Final note end time: %s' %
          (generate_section.start_time, last_end_time))

    # Quantize the priming sequence.
    quantized_sequence = mm.quantize_note_sequence(
        primer_sequence, self.steps_per_quarter)
    # Setting gap_bars to infinite ensures that the entire input will be used.
    extracted_melodies, _ = mm.extract_melodies(
        quantized_sequence, search_start_step=input_start_step, min_bars=0,
        min_unique_pitches=1, gap_bars=float('inf'),
        ignore_polyphonic_notes=True)
    assert len(extracted_melodies) <= 1

    start_step = mm.quantize_to_step(
        generate_section.start_time, steps_per_second, quantize_cutoff=0)
    # Note that when quantizing end_step, we set quantize_cutoff to 1.0 so it
    # always rounds down. This avoids generating a sequence that ends at 5.0
    # seconds when the requested end time is 4.99.
    end_step = mm.quantize_to_step(
        generate_section.end_time, steps_per_second, quantize_cutoff=1.0)

    if extracted_melodies and extracted_melodies[0]:
      melody = extracted_melodies[0]
    else:
      # If no melody could be extracted, create an empty melody that starts 1
      # step before the request start_step. This will result in 1 step of
      # silence when the melody is extended below.
      steps_per_bar = int(
          mm.steps_per_bar_in_quantized_sequence(quantized_sequence))
      melody = mm.Melody([],
                         start_step=max(0, start_step - 1),
                         steps_per_bar=steps_per_bar,
                         steps_per_quarter=self.steps_per_quarter)

    # Ensure that the melody extends up to the step we want to start generating.
    melody.set_length(start_step - melody.start_step)

    # Extract generation arguments from generator options.
    arg_types = {
        'temperature': lambda arg: arg.float_value,
        'beam_size': lambda arg: arg.int_value,
        'branch_factor': lambda arg: arg.int_value,
        'steps_per_iteration': lambda arg: arg.int_value
    }
    args = dict((name, value_fn(generator_options.args[name]))
                for name, value_fn in arg_types.items()
                if name in generator_options.args)

    generated_melody = self._model.generate_melody(
        end_step - melody.start_step, melody, **args)
    generated_sequence = generated_melody.to_sequence(qpm=qpm)
    assert (generated_sequence.total_time - generate_section.end_time) <= 1e-5
    return generated_sequence
Example #5
0
    def _generate(self, input_sequence, generator_options):
        if len(generator_options.input_sections) > 1:
            raise sequence_generator.SequenceGeneratorError(
                'This model supports at most one input_sections message, but got %s'
                % len(generator_options.input_sections))
        if len(generator_options.generate_sections) != 1:
            raise sequence_generator.SequenceGeneratorError(
                'This model supports only 1 generate_sections message, but got %s'
                % len(generator_options.generate_sections))

        if input_sequence and input_sequence.tempos:
            qpm = input_sequence.tempos[0].qpm
        else:
            qpm = mm.DEFAULT_QUARTERS_PER_MINUTE
        steps_per_second = mm.steps_per_quarter_to_steps_per_second(
            self.steps_per_quarter, qpm)

        generate_section = generator_options.generate_sections[0]
        if generator_options.input_sections:
            input_section = generator_options.input_sections[0]
            primer_sequence = mm.trim_note_sequence(input_sequence,
                                                    input_section.start_time,
                                                    input_section.end_time)
            input_start_step = mm.quantize_to_step(input_section.start_time,
                                                   steps_per_second,
                                                   quantize_cutoff=0.0)
        else:
            primer_sequence = input_sequence
            input_start_step = 0

        if primer_sequence.notes:
            last_end_time = max(n.end_time for n in primer_sequence.notes)
        else:
            last_end_time = 0
        if last_end_time > generate_section.start_time:
            raise sequence_generator.SequenceGeneratorError(
                'Got GenerateSection request for section that is before the end of '
                'the NoteSequence. This model can only extend sequences. Requested '
                'start time: %s, Final note end time: %s' %
                (generate_section.start_time, last_end_time))

        # Quantize the priming sequence.
        quantized_sequence = mm.quantize_note_sequence(primer_sequence,
                                                       self.steps_per_quarter)
        # Setting gap_bars to infinite ensures that the entire input will be used.
        extracted_drum_tracks, _ = drum_pipelines.extract_drum_tracks(
            quantized_sequence,
            search_start_step=input_start_step,
            min_bars=0,
            gap_bars=float('inf'),
            ignore_is_drum=True)
        assert len(extracted_drum_tracks) <= 1

        start_step = mm.quantize_to_step(generate_section.start_time,
                                         steps_per_second,
                                         quantize_cutoff=0.0)
        # Note that when quantizing end_step, we set quantize_cutoff to 1.0 so it
        # always rounds down. This avoids generating a sequence that ends at 5.0
        # seconds when the requested end time is 4.99.
        end_step = mm.quantize_to_step(generate_section.end_time,
                                       steps_per_second,
                                       quantize_cutoff=1.0)

        if extracted_drum_tracks and extracted_drum_tracks[0]:
            drums = extracted_drum_tracks[0]
        else:
            # If no drum track could be extracted, create an empty drum track that
            # starts 1 step before the request start_step. This will result in 1 step
            # of silence when the drum track is extended below.
            steps_per_bar = int(
                mm.steps_per_bar_in_quantized_sequence(quantized_sequence))
            drums = mm.DrumTrack([],
                                 start_step=max(0, start_step - 1),
                                 steps_per_bar=steps_per_bar,
                                 steps_per_quarter=self.steps_per_quarter)

        # Ensure that the drum track extends up to the step we want to start
        # generating.
        drums.set_length(start_step - drums.start_step)

        # Extract generation arguments from generator options.
        arg_types = {
            'temperature': lambda arg: arg.float_value,
            'beam_size': lambda arg: arg.int_value,
            'branch_factor': lambda arg: arg.int_value,
            'steps_per_iteration': lambda arg: arg.int_value
        }
        args = dict((name, value_fn(generator_options.args[name]))
                    for name, value_fn in arg_types.items()
                    if name in generator_options.args)

        generated_drums = self._model.generate_drum_track(
            end_step - drums.start_step, drums, **args)
        generated_sequence = generated_drums.to_sequence(qpm=qpm)
        assert (generated_sequence.total_time -
                generate_section.end_time) <= 1e-5
        return generated_sequence
  def _generate(self, input_sequence, generator_options):
    if len(generator_options.input_sections) > 1:
      raise mm.SequenceGeneratorError(
          'This model supports at most one input_sections message, but got %s' %
          len(generator_options.input_sections))
    if len(generator_options.generate_sections) != 1:
      raise mm.SequenceGeneratorError(
          'This model supports only 1 generate_sections message, but got %s' %
          len(generator_options.generate_sections))

    # This sequence will be quantized later, so it is guaranteed to have only 1
    # tempo.
    qpm = mm.DEFAULT_QUARTERS_PER_MINUTE
    if input_sequence.tempos:
      qpm = input_sequence.tempos[0].qpm

    steps_per_second = mm.steps_per_quarter_to_steps_per_second(
        self.steps_per_quarter, qpm)

    generate_section = generator_options.generate_sections[0]
    if generator_options.input_sections:
      input_section = generator_options.input_sections[0]
      primer_sequence = mm.trim_note_sequence(
          input_sequence, input_section.start_time, input_section.end_time)
      input_start_step = mm.quantize_to_step(
          input_section.start_time, steps_per_second, quantize_cutoff=0)
    else:
      primer_sequence = input_sequence
      input_start_step = 0

    if primer_sequence.notes:
      last_end_time = max(n.end_time for n in primer_sequence.notes)
    else:
      last_end_time = 0

    if last_end_time > generate_section.start_time:
      raise mm.SequenceGeneratorError(
          'Got GenerateSection request for section that is before or equal to '
          'the end of the NoteSequence. This model can only extend sequences. '
          'Requested start time: %s, Final note end time: %s' %
          (generate_section.start_time, last_end_time))

    # Quantize the priming sequence.
    quantized_primer_sequence = mm.quantize_note_sequence(
        primer_sequence, self.steps_per_quarter)

    extracted_seqs, _ = mm.extract_pianoroll_sequences(
        quantized_primer_sequence, start_step=input_start_step)
    assert len(extracted_seqs) <= 1

    generate_start_step = mm.quantize_to_step(
        generate_section.start_time, steps_per_second, quantize_cutoff=0)
    # Note that when quantizing end_step, we set quantize_cutoff to 1.0 so it
    # always rounds down. This avoids generating a sequence that ends at 5.0
    # seconds when the requested end time is 4.99.
    generate_end_step = mm.quantize_to_step(
        generate_section.end_time, steps_per_second, quantize_cutoff=1.0)

    if extracted_seqs and extracted_seqs[0]:
      pianoroll_seq = extracted_seqs[0]
    else:
      raise ValueError('No priming pianoroll could be extracted.')

    # Ensure that the track extends up to the step we want to start generating.
    pianoroll_seq.set_length(generate_start_step - pianoroll_seq.start_step)

    # Extract generation arguments from generator options.
    arg_types = {
        'beam_size': lambda arg: arg.int_value,
        'branch_factor': lambda arg: arg.int_value,
    }
    args = dict((name, value_fn(generator_options.args[name]))
                for name, value_fn in arg_types.items()
                if name in generator_options.args)

    total_steps = pianoroll_seq.num_steps + (
        generate_end_step - generate_start_step)

    pianoroll_seq = self._model.generate_pianoroll_sequence(
        total_steps, pianoroll_seq, **args)
    pianoroll_seq.set_length(total_steps)

    generated_sequence = pianoroll_seq.to_sequence(qpm=qpm)
    assert (generated_sequence.total_time - generate_section.end_time) <= 1e-5
    return generated_sequence
Example #7
0
    def _generate(self, input_sequence, generator_options):
        if len(generator_options.input_sections) > 1:
            raise sequence_generator.SequenceGeneratorError(
                'This model supports at most one input_sections message, but got %s'
                % len(generator_options.input_sections))
        if len(generator_options.generate_sections) != 1:
            raise sequence_generator.SequenceGeneratorError(
                'This model supports only 1 generate_sections message, but got %s'
                % len(generator_options.generate_sections))

        # This sequence will be quantized later, so it is guaranteed to have only 1
        # tempo.
        qpm = mm.DEFAULT_QUARTERS_PER_MINUTE
        if input_sequence.tempos:
            qpm = input_sequence.tempos[0].qpm

        steps_per_second = mm.steps_per_quarter_to_steps_per_second(
            self.steps_per_quarter, qpm)

        generate_section = generator_options.generate_sections[0]
        if generator_options.input_sections:
            input_section = generator_options.input_sections[0]
            primer_sequence = mm.trim_note_sequence(input_sequence,
                                                    input_section.start_time,
                                                    input_section.end_time)
            input_start_step = mm.quantize_to_step(input_section.start_time,
                                                   steps_per_second,
                                                   quantize_cutoff=0)
        else:
            primer_sequence = input_sequence
            input_start_step = 0

        if primer_sequence.notes:
            last_end_time = max(n.end_time for n in primer_sequence.notes)
        else:
            last_end_time = 0

        if last_end_time > generate_section.start_time:
            raise sequence_generator.SequenceGeneratorError(
                'Got GenerateSection request for section that is before or equal to '
                'the end of the NoteSequence. This model can only extend sequences. '
                'Requested start time: %s, Final note end time: %s' %
                (generate_section.start_time, last_end_time))

        # Quantize the priming sequence.
        quantized_primer_sequence = mm.quantize_note_sequence(
            primer_sequence, self.steps_per_quarter)

        extracted_seqs, _ = polyphony_lib.extract_polyphonic_sequences(
            quantized_primer_sequence, start_step=input_start_step)
        assert len(extracted_seqs) <= 1

        generate_start_step = mm.quantize_to_step(generate_section.start_time,
                                                  steps_per_second,
                                                  quantize_cutoff=0)
        # Note that when quantizing end_step, we set quantize_cutoff to 1.0 so it
        # always rounds down. This avoids generating a sequence that ends at 5.0
        # seconds when the requested end time is 4.99.
        generate_end_step = mm.quantize_to_step(generate_section.end_time,
                                                steps_per_second,
                                                quantize_cutoff=1.0)

        if extracted_seqs and extracted_seqs[0]:
            poly_seq = extracted_seqs[0]
        else:
            # If no track could be extracted, create an empty track that starts at the
            # requested generate_start_step. This will result in a sequence that
            # contains only the START token.
            poly_seq = polyphony_lib.PolyphonicSequence(
                steps_per_quarter=(quantized_primer_sequence.quantization_info.
                                   steps_per_quarter),
                start_step=generate_start_step)

        # Ensure that the track extends up to the step we want to start generating.
        poly_seq.set_length(generate_start_step - poly_seq.start_step)
        # Trim any trailing end events to prepare the sequence for more events to be
        # appended during generation.
        poly_seq.trim_trailing_end_events()

        # Extract generation arguments from generator options.
        arg_types = {
            'temperature': lambda arg: arg.float_value,
            'beam_size': lambda arg: arg.int_value,
            'branch_factor': lambda arg: arg.int_value,
            'steps_per_iteration': lambda arg: arg.int_value
        }
        args = dict((name, value_fn(generator_options.args[name]))
                    for name, value_fn in arg_types.items()
                    if name in generator_options.args)

        # Inject the priming sequence as melody in the output of the generator, if
        # requested.
        # This option starts with no_ so that if it is unspecified (as will be the
        # case when used with the midi interface), the default will be to inject the
        # primer.
        if not (generator_options.args['no_inject_primer_during_generation'].
                bool_value):
            melody_to_inject = copy.deepcopy(poly_seq)
            if generator_options.args['condition_on_primer'].bool_value:
                inject_start_step = poly_seq.num_steps
            else:
                # 0 steps because we'll overwrite poly_seq with a blank sequence below.
                inject_start_step = 0

            args['modify_events_callback'] = functools.partial(
                _inject_melody, melody_to_inject, inject_start_step)

        # If we don't want to condition on the priming sequence, then overwrite
        # poly_seq with a blank sequence to feed into the generator.
        if not generator_options.args['condition_on_primer'].bool_value:
            poly_seq = polyphony_lib.PolyphonicSequence(
                steps_per_quarter=(quantized_primer_sequence.quantization_info.
                                   steps_per_quarter),
                start_step=generate_start_step)
            poly_seq.trim_trailing_end_events()

        total_steps = poly_seq.num_steps + (generate_end_step -
                                            generate_start_step)

        while poly_seq.num_steps < total_steps:
            # Assume it takes ~5 rnn steps to generate one quantized step.
            # Can't know for sure until generation is finished because the number of
            # notes per quantized step is variable.
            steps_to_gen = total_steps - poly_seq.num_steps
            rnn_steps_to_gen = 5 * steps_to_gen
            tf.logging.info(
                'Need to generate %d more steps for this sequence, will try asking '
                'for %d RNN steps' % (steps_to_gen, rnn_steps_to_gen))
            poly_seq = self._model.generate_polyphonic_sequence(
                len(poly_seq) + rnn_steps_to_gen, poly_seq, **args)
        poly_seq.set_length(total_steps)

        if generator_options.args['condition_on_primer'].bool_value:
            generated_sequence = poly_seq.to_sequence(qpm=qpm)
        else:
            # Specify a base_note_sequence because the priming sequence was not
            # included in poly_seq.
            generated_sequence = poly_seq.to_sequence(
                qpm=qpm, base_note_sequence=copy.deepcopy(primer_sequence))
        assert (generated_sequence.total_time -
                generate_section.end_time) <= 1e-5
        return generated_sequence
  def _generate(self, input_sequence, generator_options):
    if len(generator_options.input_sections) > 1:
      raise mm.SequenceGeneratorException(
          'This model supports at most one input_sections message, but got %s' %
          len(generator_options.input_sections))
    if len(generator_options.generate_sections) != 1:
      raise mm.SequenceGeneratorException(
          'This model supports only 1 generate_sections message, but got %s' %
          len(generator_options.generate_sections))

    qpm = (input_sequence.tempos[0].qpm
           if input_sequence and input_sequence.tempos
           else mm.DEFAULT_QUARTERS_PER_MINUTE)

    generate_section = generator_options.generate_sections[0]
    if generator_options.input_sections:
      input_section = generator_options.input_sections[0]
      primer_sequence = mm.trim_note_sequence(
          input_sequence, input_section.start_time, input_section.end_time)
      input_start_step = self.seconds_to_steps(input_section.start_time, qpm)
    else:
      primer_sequence = input_sequence
      input_start_step = 0

    last_end_time = (max(n.end_time for n in primer_sequence.notes)
                     if primer_sequence.notes else 0)
    if last_end_time > generate_section.start_time:
      raise mm.SequenceGeneratorException(
          'Got GenerateSection request for section that is before the end of '
          'the NoteSequence. This model can only extend sequences. Requested '
          'start time: %s, Final note end time: %s' %
          (generate_section.start_time, last_end_time))

    # Quantize the priming sequence.
    quantized_sequence = mm.quantize_note_sequence(
        primer_sequence, self.steps_per_quarter)
    # Setting gap_bars to infinite ensures that the entire input will be used.
    extracted_drum_tracks, _ = mm.extract_drum_tracks(
        quantized_sequence, search_start_step=input_start_step, min_bars=0,
        gap_bars=float('inf'))
    assert len(extracted_drum_tracks) <= 1

    start_step = self.seconds_to_steps(
        generate_section.start_time, qpm)
    end_step = self.seconds_to_steps(generate_section.end_time, qpm)

    if extracted_drum_tracks and extracted_drum_tracks[0]:
      drums = extracted_drum_tracks[0]
    else:
      # If no drum track could be extracted, create an empty drum track that
      # starts 1 step before the request start_step. This will result in 1 step
      # of silence when the drum track is extended below.
      drums = mm.DrumTrack([], start_step=max(0, start_step - 1))

    # Ensure that the drum track extends up to the step we want to start
    # generating.
    drums.set_length(start_step - drums.start_step)

    # Extract generation arguments from generator options.
    arg_types = {
        'temperature': lambda arg: arg.float_value,
        'beam_size': lambda arg: arg.int_value,
        'branch_factor': lambda arg: arg.int_value,
        'steps_per_iteration': lambda arg: arg.int_value
    }
    args = dict((name, value_fn(generator_options.args[name]))
                for name, value_fn in arg_types.items()
                if name in generator_options.args)

    generated_drums = self._model.generate_drum_track(
        end_step - drums.start_step, drums, **args)
    generated_sequence = generated_drums.to_sequence(qpm=qpm)
    assert (generated_sequence.total_time - generate_section.end_time) <= 1e-5
    return generated_sequence
  def _generate(self, input_sequence, generator_options):
    if len(generator_options.input_sections) > 1:
      raise mm.SequenceGeneratorError(
          'This model supports at most one input_sections message, but got %s' %
          len(generator_options.input_sections))
    if len(generator_options.generate_sections) != 1:
      raise mm.SequenceGeneratorError(
          'This model supports only 1 generate_sections message, but got %s' %
          len(generator_options.generate_sections))

    generate_section = generator_options.generate_sections[0]
    if generator_options.input_sections:
      input_section = generator_options.input_sections[0]
      primer_sequence = mm.trim_note_sequence(
          input_sequence, input_section.start_time, input_section.end_time)
      input_start_step = mm.quantize_to_step(
          input_section.start_time, self.steps_per_second, quantize_cutoff=0.0)
    else:
      primer_sequence = input_sequence
      input_start_step = 0
    if primer_sequence.notes:
      last_end_time = max(n.end_time for n in primer_sequence.notes)
    else:
      last_end_time = 0
    if last_end_time > generate_section.start_time:
      raise mm.SequenceGeneratorError(
          'Got GenerateSection request for section that is before or equal to '
          'the end of the NoteSequence. This model can only extend sequences. '
          'Requested start time: %s, Final note end time: %s' %
          (generate_section.start_time, last_end_time))

    # Quantize the priming sequence.
    quantized_primer_sequence = mm.quantize_note_sequence_absolute(
        primer_sequence, self.steps_per_second)

    extracted_perfs, _ = mm.extract_performances(
        quantized_primer_sequence, start_step=input_start_step,
        num_velocity_bins=self.num_velocity_bins,
        note_performance=self._note_performance)
    assert len(extracted_perfs) <= 1

    generate_start_step = mm.quantize_to_step(
        generate_section.start_time, self.steps_per_second, quantize_cutoff=0.0)
    # Note that when quantizing end_step, we set quantize_cutoff to 1.0 so it
    # always rounds down. This avoids generating a sequence that ends at 5.0
    # seconds when the requested end time is 4.99.
    generate_end_step = mm.quantize_to_step(
        generate_section.end_time, self.steps_per_second, quantize_cutoff=1.0)

    if extracted_perfs and extracted_perfs[0]:
      performance = extracted_perfs[0]
    else:
      # If no track could be extracted, create an empty track that starts at the
      # requested generate_start_step.
      performance = mm.Performance(
          steps_per_second=(
              quantized_primer_sequence.quantization_info.steps_per_second),
          start_step=generate_start_step,
          num_velocity_bins=self.num_velocity_bins)

    # Ensure that the track extends up to the step we want to start generating.
    performance.set_length(generate_start_step - performance.start_step)

    # Extract generation arguments from generator options.
    arg_types = {
        'disable_conditioning': lambda arg: ast.literal_eval(arg.string_value),
        'temperature': lambda arg: arg.float_value,
        'beam_size': lambda arg: arg.int_value,
        'branch_factor': lambda arg: arg.int_value,
        'steps_per_iteration': lambda arg: arg.int_value
    }
    if self.control_signals:
      for control in self.control_signals:
        arg_types[control.name] = lambda arg: ast.literal_eval(arg.string_value)

    args = dict((name, value_fn(generator_options.args[name]))
                for name, value_fn in arg_types.items()
                if name in generator_options.args)

    # Make sure control signals are present and convert to lists if necessary.
    if self.control_signals:
      for control in self.control_signals:
        if control.name not in args:
          tf.logging.warning(
              'Control value not specified, using default: %s = %s',
              control.name, control.default_value)
          args[control.name] = [control.default_value]
        elif control.validate(args[control.name]):
          args[control.name] = [args[control.name]]
        else:
          if not isinstance(args[control.name], list) or not all(
              control.validate(value) for value in args[control.name]):
            tf.logging.fatal(
                'Invalid control value: %s = %s',
                control.name, args[control.name])

    # Make sure disable conditioning flag is present when conditioning is
    # optional and convert to list if necessary.
    if self.optional_conditioning:
      if 'disable_conditioning' not in args:
        args['disable_conditioning'] = [False]
      elif isinstance(args['disable_conditioning'], bool):
        args['disable_conditioning'] = [args['disable_conditioning']]
      else:
        if not isinstance(args['disable_conditioning'], list) or not all(
            isinstance(value, bool) for value in args['disable_conditioning']):
          tf.logging.fatal(
              'Invalid disable_conditioning value: %s',
              args['disable_conditioning'])

    total_steps = performance.num_steps + (
        generate_end_step - generate_start_step)

    if 'notes_per_second' in args:
      mean_note_density = (
          sum(args['notes_per_second']) / len(args['notes_per_second']))
    else:
      mean_note_density = DEFAULT_NOTE_DENSITY

    # Set up functions that map generation step to control signal values and
    # disable conditioning flag.
    if self.control_signals:
      control_signal_fns = []
      for control in self.control_signals:
        control_signal_fns.append(functools.partial(
            _step_to_value,
            num_steps=total_steps,
            values=args[control.name]))
        del args[control.name]
      args['control_signal_fns'] = control_signal_fns
    if self.optional_conditioning:
      args['disable_conditioning_fn'] = functools.partial(
          _step_to_value,
          num_steps=total_steps,
          values=args['disable_conditioning'])
      del args['disable_conditioning']

    if not performance:
      # Primer is empty; let's just start with silence.
      performance.set_length(min(performance.max_shift_steps, total_steps))

    while performance.num_steps < total_steps:
      # Assume the average specified (or default) note density and 4 RNN steps
      # per note. Can't know for sure until generation is finished because the
      # number of notes per quantized step is variable.
      note_density = max(1.0, mean_note_density)
      steps_to_gen = total_steps - performance.num_steps
      rnn_steps_to_gen = int(math.ceil(
          4.0 * note_density * steps_to_gen / self.steps_per_second))
      tf.logging.info(
          'Need to generate %d more steps for this sequence, will try asking '
          'for %d RNN steps' % (steps_to_gen, rnn_steps_to_gen))
      performance = self._model.generate_performance(
          len(performance) + rnn_steps_to_gen, performance, **args)

      if not self.fill_generate_section:
        # In the interest of speed just go through this loop once, which may not
        # entirely fill the generate section.
        break

    performance.set_length(total_steps)

    generated_sequence = performance.to_sequence(
        max_note_duration=self.max_note_duration)

    assert (generated_sequence.total_time - generate_section.end_time) <= 1e-5
    return generated_sequence
  def _generate(self, input_sequence, generator_options):
    if len(generator_options.input_sections) > 1:
      raise mm.SequenceGeneratorException(
          'This model supports at most one input_sections message, but got %s' %
          len(generator_options.input_sections))
    if len(generator_options.generate_sections) != 1:
      raise mm.SequenceGeneratorException(
          'This model supports only 1 generate_sections message, but got %s' %
          len(generator_options.generate_sections))

    # This sequence will be quantized later, so it is guaranteed to have only 1
    # tempo.
    qpm = mm.DEFAULT_QUARTERS_PER_MINUTE
    if input_sequence.tempos:
      qpm = input_sequence.tempos[0].qpm

    steps_per_second = mm.steps_per_quarter_to_steps_per_second(
        self.steps_per_quarter, qpm)

    generate_section = generator_options.generate_sections[0]
    if generator_options.input_sections:
      input_section = generator_options.input_sections[0]
      primer_sequence = mm.trim_note_sequence(
          input_sequence, input_section.start_time, input_section.end_time)
      input_start_step = mm.quantize_to_step(
          input_section.start_time, steps_per_second, quantize_cutoff=0)
    else:
      primer_sequence = input_sequence
      input_start_step = 0

    last_end_time = (max(n.end_time for n in primer_sequence.notes)
                     if primer_sequence.notes else 0)
    if last_end_time > generate_section.start_time:
      raise mm.SequenceGeneratorException(
          'Got GenerateSection request for section that is before or equal to '
          'the end of the NoteSequence. This model can only extend sequences. '
          'Requested start time: %s, Final note end time: %s' %
          (generate_section.start_time, last_end_time))

    # Quantize the priming sequence.
    quantized_primer_sequence = mm.quantize_note_sequence(
        primer_sequence, self.steps_per_quarter)

    extracted_seqs, _ = polyphony_lib.extract_polyphonic_sequences(
        quantized_primer_sequence, start_step=input_start_step)
    assert len(extracted_seqs) <= 1

    generate_start_step = mm.quantize_to_step(
        generate_section.start_time, steps_per_second, quantize_cutoff=0)
    # Note that when quantizing end_step, we set quantize_cutoff to 1.0 so it
    # always rounds down. This avoids generating a sequence that ends at 5.0
    # seconds when the requested end time is 4.99.
    generate_end_step = mm.quantize_to_step(
        generate_section.end_time, steps_per_second, quantize_cutoff=1.0)

    if extracted_seqs and extracted_seqs[0]:
      poly_seq = extracted_seqs[0]
    else:
      # If no track could be extracted, create an empty track that starts at the
      # requested generate_start_step. This will result in a sequence that
      # contains only the START token.
      poly_seq = polyphony_lib.PolyphonicSequence(
          steps_per_quarter=(
              quantized_primer_sequence.quantization_info.steps_per_quarter),
          start_step=generate_start_step)

    # Ensure that the track extends up to the step we want to start generating.
    poly_seq.set_length(generate_start_step - poly_seq.start_step)
    # Trim any trailing end events to prepare the sequence for more events to be
    # appended during generation.
    poly_seq.trim_trailing_end_events()

    # Extract generation arguments from generator options.
    arg_types = {
        'temperature': lambda arg: arg.float_value,
        'beam_size': lambda arg: arg.int_value,
        'branch_factor': lambda arg: arg.int_value,
        'steps_per_iteration': lambda arg: arg.int_value
    }
    args = dict((name, value_fn(generator_options.args[name]))
                for name, value_fn in arg_types.items()
                if name in generator_options.args)

    # Inject the priming sequence as melody in the output of the generator, if
    # requested.
    # This option starts with no_ so that if it is unspecified (as will be the
    # case when used with the midi interface), the default will be to inject the
    # primer.
    if not (generator_options.args[
        'no_inject_primer_during_generation'].bool_value):
      melody_to_inject = copy.deepcopy(poly_seq)
      if generator_options.args['condition_on_primer'].bool_value:
        inject_start_step = poly_seq.num_steps
      else:
        # 0 steps because we'll overwrite poly_seq with a blank sequence below.
        inject_start_step = 0

      args['modify_events_callback'] = partial(
          _inject_melody, melody_to_inject, inject_start_step)

    # If we don't want to condition on the priming sequence, then overwrite
    # poly_seq with a blank sequence to feed into the generator.
    if not generator_options.args['condition_on_primer'].bool_value:
      poly_seq = polyphony_lib.PolyphonicSequence(
          steps_per_quarter=(
              quantized_primer_sequence.quantization_info.steps_per_quarter),
          start_step=generate_start_step)
      poly_seq.trim_trailing_end_events()

    total_steps = poly_seq.num_steps + (
        generate_end_step - generate_start_step)

    while poly_seq.num_steps < total_steps:
      # Assume it takes ~5 rnn steps to generate one quantized step.
      # Can't know for sure until generation is finished because the number of
      # notes per quantized step is variable.
      steps_to_gen = total_steps - poly_seq.num_steps
      rnn_steps_to_gen = 5 * steps_to_gen
      tf.logging.info(
          'Need to generate %d more steps for this sequence, will try asking '
          'for %d RNN steps' % (steps_to_gen, rnn_steps_to_gen))
      poly_seq = self._model.generate_polyphonic_sequence(
          len(poly_seq) + rnn_steps_to_gen, poly_seq, **args)
    poly_seq.set_length(total_steps)

    if generator_options.args['condition_on_primer'].bool_value:
      generated_sequence = poly_seq.to_sequence(qpm=qpm)
    else:
      # Specify a base_note_sequence because the priming sequence was not
      # included in poly_seq.
      generated_sequence = poly_seq.to_sequence(
          qpm=qpm, base_note_sequence=copy.deepcopy(primer_sequence))
    assert (generated_sequence.total_time - generate_section.end_time) <= 1e-5
    return generated_sequence
Example #11
0
    def _generate(self, input_sequence, generator_options):
        if len(generator_options.input_sections) > 1:
            raise mm.SequenceGeneratorException(
                'This model supports at most one input_sections message, but got %s'
                % len(generator_options.input_sections))
        if len(generator_options.generate_sections) != 1:
            raise mm.SequenceGeneratorException(
                'This model supports only 1 generate_sections message, but got %s'
                % len(generator_options.generate_sections))

        generate_section = generator_options.generate_sections[0]
        if generator_options.input_sections:
            input_section = generator_options.input_sections[0]
            primer_sequence = mm.trim_note_sequence(input_sequence,
                                                    input_section.start_time,
                                                    input_section.end_time)
            input_start_step = mm.quantize_to_step(input_section.start_time,
                                                   self.steps_per_second,
                                                   quantize_cutoff=0.0)
        else:
            primer_sequence = input_sequence
            input_start_step = 0

        last_end_time = (max(
            n.end_time
            for n in primer_sequence.notes) if primer_sequence.notes else 0)
        if last_end_time > generate_section.start_time:
            raise mm.SequenceGeneratorException(
                'Got GenerateSection request for section that is before or equal to '
                'the end of the NoteSequence. This model can only extend sequences. '
                'Requested start time: %s, Final note end time: %s' %
                (generate_section.start_time, last_end_time))

        # Quantize the priming sequence.
        quantized_primer_sequence = mm.quantize_note_sequence_absolute(
            primer_sequence, self.steps_per_second)

        extracted_perfs, _ = performance_lib.extract_performances(
            quantized_primer_sequence,
            start_step=input_start_step,
            num_velocity_bins=self.num_velocity_bins)
        assert len(extracted_perfs) <= 1

        generate_start_step = mm.quantize_to_step(generate_section.start_time,
                                                  self.steps_per_second,
                                                  quantize_cutoff=0.0)
        # Note that when quantizing end_step, we set quantize_cutoff to 1.0 so it
        # always rounds down. This avoids generating a sequence that ends at 5.0
        # seconds when the requested end time is 4.99.
        generate_end_step = mm.quantize_to_step(generate_section.end_time,
                                                self.steps_per_second,
                                                quantize_cutoff=1.0)

        if extracted_perfs and extracted_perfs[0]:
            performance = extracted_perfs[0]
        else:
            # If no track could be extracted, create an empty track that starts at the
            # requested generate_start_step.
            performance = performance_lib.Performance(
                steps_per_second=(quantized_primer_sequence.quantization_info.
                                  steps_per_second),
                start_step=generate_start_step,
                num_velocity_bins=self.num_velocity_bins)

        # Ensure that the track extends up to the step we want to start generating.
        performance.set_length(generate_start_step - performance.start_step)

        # Extract generation arguments from generator options.
        arg_types = {
            'note_density': lambda arg: ast.literal_eval(arg.string_value),
            'pitch_histogram': lambda arg: ast.literal_eval(arg.string_value),
            'disable_conditioning':
            lambda arg: ast.literal_eval(arg.string_value),
            'temperature': lambda arg: arg.float_value,
            'beam_size': lambda arg: arg.int_value,
            'branch_factor': lambda arg: arg.int_value,
            'steps_per_iteration': lambda arg: arg.int_value
        }
        args = dict((name, value_fn(generator_options.args[name]))
                    for name, value_fn in arg_types.items()
                    if name in generator_options.args)

        # Make sure note density is present when conditioning on it and not present
        # otherwise.
        if not self.note_density_conditioning and 'note_density' in args:
            tf.logging.warning(
                'Not conditioning on note density, ignoring requested density.'
            )
            del args['note_density']
        if self.note_density_conditioning and 'note_density' not in args:
            tf.logging.warning(
                'Conditioning on note density but none requested, using default.'
            )
            args['note_density'] = [DEFAULT_NOTE_DENSITY]

        # Make sure pitch class histogram is present when conditioning on it and not
        # present otherwise.
        if not self.pitch_histogram_conditioning and 'pitch_histogram' in args:
            tf.logging.warning(
                'Not conditioning on pitch histogram, ignoring requested histogram.'
            )
            del args['pitch_histogram']
        if self.pitch_histogram_conditioning and 'pitch_histogram' not in args:
            tf.logging.warning(
                'Conditioning on pitch histogram but none requested, using default.'
            )
            args['pitch_histogram'] = [DEFAULT_PITCH_HISTOGRAM]

        # Make sure disable conditioning flag is present when conditioning is
        # optional and not present otherwise.
        if not self.optional_conditioning and 'disable_conditioning' in args:
            tf.logging.warning(
                'No optional conditioning, ignoring disable conditioning flag.'
            )
            del args['disable_conditioning']
        if self.optional_conditioning and 'disable_conditioning' not in args:
            args['disable_conditioning'] = [False]

        # If a single note density, pitch class histogram, or disable flag is
        # present, convert to list to simplify further processing.
        if (self.note_density_conditioning
                and not isinstance(args['note_density'], list)):
            args['note_density'] = [args['note_density']]
        if (self.pitch_histogram_conditioning
                and not isinstance(args['pitch_histogram'][0], list)):
            args['pitch_histogram'] = [args['pitch_histogram']]
        if (self.optional_conditioning
                and not isinstance(args['disable_conditioning'], list)):
            args['disable_conditioning'] = [args['disable_conditioning']]

        # Make sure each pitch class histogram sums to one.
        if self.pitch_histogram_conditioning:
            for i in range(len(args['pitch_histogram'])):
                total = sum(args['pitch_histogram'][i])
                if total > 0:
                    args['pitch_histogram'][i] = [
                        float(count) / total
                        for count in args['pitch_histogram'][i]
                    ]
                else:
                    tf.logging.warning(
                        'Pitch histogram is empty, using default.')
                    args['pitch_histogram'][i] = DEFAULT_PITCH_HISTOGRAM

        total_steps = performance.num_steps + (generate_end_step -
                                               generate_start_step)

        # Set up functions that map generation step to note density, pitch
        # histogram, and disable conditioning flag.
        mean_note_density = DEFAULT_NOTE_DENSITY
        if self.note_density_conditioning:
            args['note_density_fn'] = partial(
                _step_to_note_density,
                num_steps=total_steps,
                note_densities=args['note_density'])
            mean_note_density = sum(args['note_density']) / len(
                args['note_density'])
            del args['note_density']
        if self.pitch_histogram_conditioning:
            args['pitch_histogram_fn'] = partial(
                _step_to_pitch_histogram,
                num_steps=total_steps,
                pitch_histograms=args['pitch_histogram'])
            del args['pitch_histogram']
        if self.optional_conditioning:
            args['disable_conditioning_fn'] = partial(
                _step_to_disable_conditioning,
                num_steps=total_steps,
                disable_conditioning_flags=args['disable_conditioning'])
            del args['disable_conditioning']

        if not performance:
            # Primer is empty; let's just start with silence.
            performance.set_length(
                min(performance_lib.MAX_SHIFT_STEPS, total_steps))

        while performance.num_steps < total_steps:
            # Assume the average specified (or default) note density and 4 RNN steps
            # per note. Can't know for sure until generation is finished because the
            # number of notes per quantized step is variable.
            note_density = max(1.0, mean_note_density)
            steps_to_gen = total_steps - performance.num_steps
            rnn_steps_to_gen = int(
                math.ceil(4.0 * note_density * steps_to_gen /
                          self.steps_per_second))
            tf.logging.info(
                'Need to generate %d more steps for this sequence, will try asking '
                'for %d RNN steps' % (steps_to_gen, rnn_steps_to_gen))
            performance = self._model.generate_performance(
                len(performance) + rnn_steps_to_gen, performance, **args)

            if not self.fill_generate_section:
                # In the interest of speed just go through this loop once, which may not
                # entirely fill the generate section.
                break

        performance.set_length(total_steps)

        generated_sequence = performance.to_sequence(
            max_note_duration=self.max_note_duration)

        assert (generated_sequence.total_time -
                generate_section.end_time) <= 1e-5
        return generated_sequence
    def _primer_melody_to_event_sequence(self, input_sequence,
                                         generator_options, config):

        qpm = (input_sequence.tempos[0].qpm if input_sequence
               and input_sequence.tempos else mm.DEFAULT_QUARTERS_PER_MINUTE)
        steps_per_second = mm.steps_per_quarter_to_steps_per_second(
            self.steps_per_quarter, qpm)

        generate_section = generator_options.generate_sections[0]
        if generator_options.input_sections:
            input_section = generator_options.input_sections[0]
            primer_sequence = mm.trim_note_sequence(input_sequence,
                                                    input_section.start_time,
                                                    input_section.end_time)
            input_start_step = mm.quantize_to_step(input_section.start_time,
                                                   steps_per_second,
                                                   quantize_cutoff=0)
        else:
            primer_sequence = input_sequence
            input_start_step = 0

        last_end_time = (max(
            n.end_time
            for n in primer_sequence.notes) if primer_sequence.notes else 0)
        if last_end_time > generate_section.start_time:
            raise mm.SequenceGeneratorException(
                'Got GenerateSection request for section that is before the end of '
                'the NoteSequence. This model can only extend sequences. Requested '
                'start time: %s, Final note end time: %s' %
                (generate_section.start_time, last_end_time))

        # Quantize the priming sequence.
        quantized_sequence = mm.quantize_note_sequence(primer_sequence,
                                                       self.steps_per_quarter)
        # Setting gap_bars to infinite ensures that the entire input will be used.
        extracted_melodies, _ = mm.extract_melodies(
            quantized_sequence,
            search_start_step=input_start_step,
            min_bars=0,
            min_unique_pitches=1,
            gap_bars=float('inf'),
            ignore_polyphonic_notes=True)
        assert len(extracted_melodies) <= 1

        start_step = mm.quantize_to_step(generate_section.start_time,
                                         steps_per_second,
                                         quantize_cutoff=0)
        # Note that when quantizing end_step, we set quantize_cutoff to 1.0 so it
        # always rounds down. This avoids generating a sequence that ends at 5.0
        # seconds when the requested end time is 4.99.
        end_step = mm.quantize_to_step(generate_section.end_time,
                                       steps_per_second,
                                       quantize_cutoff=1.0)

        if extracted_melodies and extracted_melodies[0]:
            melody = extracted_melodies[0]
        else:
            # If no melody could be extracted, create an empty melody that starts 1
            # step before the request start_step. This will result in 1 step of
            # silence when the melody is extended below.
            steps_per_bar = int(
                mm.steps_per_bar_in_quantized_sequence(quantized_sequence))
            melody = mm.Melody([],
                               start_step=max(0, start_step - 1),
                               steps_per_bar=steps_per_bar,
                               steps_per_quarter=self.steps_per_quarter)

        # Ensure that the melody extends up to the step we want to start generating.
        melody.set_length(start_step - melody.start_step - 2)

        now_encoding = config.encoder_decoder._one_hot_encoding

        # Extract generation arguments from generator options.
        primer_events = self._model.primer_melody_to_events(
            end_step - melody.start_step, melody)

        for i, event in enumerate(primer_events):
            primer_events[i] = now_encoding.encode_event(event)

        return primer_events
Example #13
0
def generate(unused_argv):
    # Downloads the bundle from the magenta website
    mm.notebook_utils.download_bundle("drum_kit_rnn.mag", "bundles")
    bundle = mm.sequence_generator_bundle.read_bundle_file(
        os.path.join("bundles", "drum_kit_rnn.mag"))

    # Initialize the generator "drum_kit"
    generator_map = drums_rnn_sequence_generator.get_generator_map()
    generator = generator_map["drum_kit"](checkpoint=None, bundle=bundle)
    generator.initialize()

    # Define constants
    qpm = 120
    num_bars = 3
    seconds_per_step = 60.0 / qpm / generator.steps_per_quarter
    num_steps_per_bar = constants.DEFAULT_STEPS_PER_BAR
    seconds_per_bar = num_steps_per_bar * seconds_per_step

    # Use a priming sequence
    primer_sequence = mm.midi_io.midi_file_to_note_sequence(
        os.path.join("primers", "Jazz_Drum_Basic_1_bar.mid"))
    primer_start_time = 0
    primer_end_time = primer_start_time + seconds_per_bar

    # Calculates the generation start and end time
    generation_start_time = primer_end_time
    generation_end_time = generation_start_time + (seconds_per_bar * num_bars)
    generator_options = generator_pb2.GeneratorOptions()
    generator_options.args['temperature'].float_value = 1.1
    generator_options.generate_sections.add(start_time=generation_start_time,
                                            end_time=generation_end_time)

    # Generates on primer sequence
    sequence = generator.generate(primer_sequence, generator_options)

    # Outputs the plot
    os.makedirs("output", exist_ok=True)
    plot_file = os.path.join("output", "out.html")
    pretty_midi = mm.midi_io.note_sequence_to_pretty_midi(sequence)
    plotter = Plotter(live_reload=True)
    plotter.show(pretty_midi, plot_file)
    print(f"Generated plot file: {os.path.abspath(plot_file)}")

    # We find the proper input port for the software synth
    # (which is the output port for Magenta)
    output_ports = [
        name for name in mido.get_output_names() if args.midi_port in name
    ]
    if not output_ports:
        raise Exception(f"Cannot find proper output ports in: "
                        f"{mido.get_output_names()}")
    print(f"Playing generated MIDI in output port names: {output_ports}")

    # Start a new MIDI hub on that port (output only)
    midi_hub = MidiHub(input_midi_ports=[],
                       output_midi_ports=output_ports,
                       texture_type=None)

    # Start on a empty sequence, allowing the update of the
    # sequence for later.
    empty_sequence = music_pb2.NoteSequence()
    player = midi_hub.start_playback(empty_sequence, allow_updates=True)
    player._channel = 9

    # We want a period in seconds of 4 bars
    period = Decimal(240) / qpm
    period = period * (num_bars + 1)
    sleeper = concurrency.Sleeper()
    index = 0
    while True:
        try:
            # We get the next tick time by using the period
            # to find the absolute tick number.
            now = Decimal(time.time())
            tick_number = int(now // period)
            tick_number_next = tick_number + 1
            tick_time = tick_number * period
            tick_time_next = tick_number_next * period

            # Update the player time to the current tick time
            sequence_adjusted = music_pb2.NoteSequence()
            sequence_adjusted.CopyFrom(sequence)
            sequence_adjusted = adjust_sequence_times(sequence_adjusted,
                                                      float(tick_time))
            player.update_sequence(sequence_adjusted,
                                   start_time=float(tick_time))

            # Generate a new sequence based on the previous sequence
            index = index + 1
            generator_options = generator_pb2.GeneratorOptions()
            generator_options.args['temperature'].float_value = 1
            generation_start_time = index * period
            generation_end_time = generation_start_time + period
            generator_options.generate_sections.add(
                start_time=generation_start_time, end_time=generation_end_time)
            sequence = generator.generate(sequence, generator_options)
            sequence = trim_note_sequence(sequence, generation_start_time,
                                          generation_end_time)

            # Sleep until the next tick time
            sleeper.sleep_until(float(tick_time_next))
        except KeyboardInterrupt:
            print(f"Stopping")
            return 0
  def _generate(self, input_sequence, generator_options):
    if len(generator_options.input_sections) > 1:
      raise mm.SequenceGeneratorException(
          'This model supports at most one input_sections message, but got %s' %
          len(generator_options.input_sections))
    if len(generator_options.generate_sections) != 1:
      raise mm.SequenceGeneratorException(
          'This model supports only 1 generate_sections message, but got %s' %
          len(generator_options.generate_sections))

    generate_section = generator_options.generate_sections[0]
    if generator_options.input_sections:
      input_section = generator_options.input_sections[0]
      primer_sequence = mm.trim_note_sequence(
          input_sequence, input_section.start_time, input_section.end_time)
      input_start_step = mm.quantize_to_step(
          input_section.start_time, self.steps_per_second, quantize_cutoff=0.0)
    else:
      primer_sequence = input_sequence
      input_start_step = 0

    last_end_time = (max(n.end_time for n in primer_sequence.notes)
                     if primer_sequence.notes else 0)
    if last_end_time > generate_section.start_time:
      raise mm.SequenceGeneratorException(
          'Got GenerateSection request for section that is before or equal to '
          'the end of the NoteSequence. This model can only extend sequences. '
          'Requested start time: %s, Final note end time: %s' %
          (generate_section.start_time, last_end_time))

    # Quantize the priming sequence.
    quantized_primer_sequence = mm.quantize_note_sequence_absolute(
        primer_sequence, self.steps_per_second)

    extracted_perfs, _ = performance_lib.extract_performances(
        quantized_primer_sequence, start_step=input_start_step,
        num_velocity_bins=self.num_velocity_bins)
    assert len(extracted_perfs) <= 1

    generate_start_step = mm.quantize_to_step(
        generate_section.start_time, self.steps_per_second, quantize_cutoff=0.0)
    # Note that when quantizing end_step, we set quantize_cutoff to 1.0 so it
    # always rounds down. This avoids generating a sequence that ends at 5.0
    # seconds when the requested end time is 4.99.
    generate_end_step = mm.quantize_to_step(
        generate_section.end_time, self.steps_per_second, quantize_cutoff=1.0)

    if extracted_perfs and extracted_perfs[0]:
      performance = extracted_perfs[0]
    else:
      # If no track could be extracted, create an empty track that starts at the
      # requested generate_start_step.
      performance = performance_lib.Performance(
          steps_per_second=(
              quantized_primer_sequence.quantization_info.steps_per_second),
          start_step=generate_start_step,
          num_velocity_bins=self.num_velocity_bins)

    # Ensure that the track extends up to the step we want to start generating.
    performance.set_length(generate_start_step - performance.start_step)

    # Extract generation arguments from generator options.
    arg_types = {
        'note_density': lambda arg: ast.literal_eval(arg.string_value),
        'pitch_histogram': lambda arg: ast.literal_eval(arg.string_value),
        'disable_conditioning': lambda arg: ast.literal_eval(arg.string_value),
        'temperature': lambda arg: arg.float_value,
        'beam_size': lambda arg: arg.int_value,
        'branch_factor': lambda arg: arg.int_value,
        'steps_per_iteration': lambda arg: arg.int_value
    }
    args = dict((name, value_fn(generator_options.args[name]))
                for name, value_fn in arg_types.items()
                if name in generator_options.args)

    # Make sure note density is present when conditioning on it and not present
    # otherwise.
    if not self.note_density_conditioning and 'note_density' in args:
      tf.logging.warning(
          'Not conditioning on note density, ignoring requested density.')
      del args['note_density']
    if self.note_density_conditioning and 'note_density' not in args:
      tf.logging.warning(
          'Conditioning on note density but none requested, using default.')
      args['note_density'] = [DEFAULT_NOTE_DENSITY]

    # Make sure pitch class histogram is present when conditioning on it and not
    # present otherwise.
    if not self.pitch_histogram_conditioning and 'pitch_histogram' in args:
      tf.logging.warning(
          'Not conditioning on pitch histogram, ignoring requested histogram.')
      del args['pitch_histogram']
    if self.pitch_histogram_conditioning and 'pitch_histogram' not in args:
      tf.logging.warning(
          'Conditioning on pitch histogram but none requested, using default.')
      args['pitch_histogram'] = [DEFAULT_PITCH_HISTOGRAM]

    # Make sure disable conditioning flag is present when conditioning is
    # optional and not present otherwise.
    if not self.optional_conditioning and 'disable_conditioning' in args:
      tf.logging.warning(
          'No optional conditioning, ignoring disable conditioning flag.')
      del args['disable_conditioning']
    if self.optional_conditioning and 'disable_conditioning' not in args:
      args['disable_conditioning'] = [False]

    # If a single note density, pitch class histogram, or disable flag is
    # present, convert to list to simplify further processing.
    if (self.note_density_conditioning and
        not isinstance(args['note_density'], list)):
      args['note_density'] = [args['note_density']]
    if (self.pitch_histogram_conditioning and
        not isinstance(args['pitch_histogram'][0], list)):
      args['pitch_histogram'] = [args['pitch_histogram']]
    if (self.optional_conditioning and
        not isinstance(args['disable_conditioning'], list)):
      args['disable_conditioning'] = [args['disable_conditioning']]

    # Make sure each pitch class histogram sums to one.
    if self.pitch_histogram_conditioning:
      for i in range(len(args['pitch_histogram'])):
        total = sum(args['pitch_histogram'][i])
        if total > 0:
          args['pitch_histogram'][i] = [float(count) / total
                                        for count in args['pitch_histogram'][i]]
        else:
          tf.logging.warning('Pitch histogram is empty, using default.')
          args['pitch_histogram'][i] = DEFAULT_PITCH_HISTOGRAM

    total_steps = performance.num_steps + (
        generate_end_step - generate_start_step)

    # Set up functions that map generation step to note density, pitch
    # histogram, and disable conditioning flag.
    mean_note_density = DEFAULT_NOTE_DENSITY
    if self.note_density_conditioning:
      args['note_density_fn'] = partial(
          _step_to_note_density,
          num_steps=total_steps,
          note_densities=args['note_density'])
      mean_note_density = sum(args['note_density']) / len(args['note_density'])
      del args['note_density']
    if self.pitch_histogram_conditioning:
      args['pitch_histogram_fn'] = partial(
          _step_to_pitch_histogram,
          num_steps=total_steps,
          pitch_histograms=args['pitch_histogram'])
      del args['pitch_histogram']
    if self.optional_conditioning:
      args['disable_conditioning_fn'] = partial(
          _step_to_disable_conditioning,
          num_steps=total_steps,
          disable_conditioning_flags=args['disable_conditioning'])
      del args['disable_conditioning']

    if not performance:
      # Primer is empty; let's just start with silence.
      performance.set_length(min(performance_lib.MAX_SHIFT_STEPS, total_steps))

    while performance.num_steps < total_steps:
      # Assume the average specified (or default) note density and 4 RNN steps
      # per note. Can't know for sure until generation is finished because the
      # number of notes per quantized step is variable.
      note_density = max(1.0, mean_note_density)
      steps_to_gen = total_steps - performance.num_steps
      rnn_steps_to_gen = int(math.ceil(
          4.0 * note_density * steps_to_gen / self.steps_per_second))
      tf.logging.info(
          'Need to generate %d more steps for this sequence, will try asking '
          'for %d RNN steps' % (steps_to_gen, rnn_steps_to_gen))
      performance = self._model.generate_performance(
          len(performance) + rnn_steps_to_gen, performance, **args)

      if not self.fill_generate_section:
        # In the interest of speed just go through this loop once, which may not
        # entirely fill the generate section.
        break

    performance.set_length(total_steps)

    generated_sequence = performance.to_sequence(
        max_note_duration=self.max_note_duration)

    assert (generated_sequence.total_time - generate_section.end_time) <= 1e-5
    return generated_sequence
Example #15
0
    def _generate(self, input_sequence, generator_options):
        if len(generator_options.input_sections) > 1:
            raise mm.SequenceGeneratorException(
                'This model supports at most one input_sections message, but got %s'
                % len(generator_options.input_sections))
        if len(generator_options.generate_sections) != 1:
            raise mm.SequenceGeneratorException(
                'This model supports only 1 generate_sections message, but got %s'
                % len(generator_options.generate_sections))

        qpm = (input_sequence.tempos[0].qpm if input_sequence
               and input_sequence.tempos else mm.DEFAULT_QUARTERS_PER_MINUTE)
        steps_per_second = mm.steps_per_quarter_to_steps_per_second(
            self.steps_per_quarter, qpm)

        generate_section = generator_options.generate_sections[0]
        if generator_options.input_sections:
            input_section = generator_options.input_sections[0]
            primer_sequence = mm.trim_note_sequence(input_sequence,
                                                    input_section.start_time,
                                                    input_section.end_time)
            input_start_step = mm.quantize_to_step(input_section.start_time,
                                                   steps_per_second)
        else:
            primer_sequence = input_sequence
            input_start_step = 0

        last_end_time = (max(
            n.end_time
            for n in primer_sequence.notes) if primer_sequence.notes else 0)
        if last_end_time > generate_section.start_time:
            raise mm.SequenceGeneratorException(
                'Got GenerateSection request for section that is before the end of '
                'the NoteSequence. This model can only extend sequences. Requested '
                'start time: %s, Final note end time: %s' %
                (generate_section.start_time, last_end_time))

        # Quantize the priming sequence.
        quantized_sequence = mm.quantize_note_sequence(primer_sequence,
                                                       self.steps_per_quarter)
        # Setting gap_bars to infinite ensures that the entire input will be used.
        extracted_melodies, _ = mm.extract_melodies(
            quantized_sequence,
            search_start_step=input_start_step,
            min_bars=0,
            min_unique_pitches=1,
            gap_bars=float('inf'),
            ignore_polyphonic_notes=True)
        assert len(extracted_melodies) <= 1

        start_step = mm.quantize_to_step(generate_section.start_time,
                                         steps_per_second)
        end_step = mm.quantize_to_step(generate_section.end_time,
                                       steps_per_second)

        if extracted_melodies and extracted_melodies[0]:
            melody = extracted_melodies[0]
        else:
            # If no melody could be extracted, create an empty melody that starts 1
            # step before the request start_step. This will result in 1 step of
            # silence when the melody is extended below.
            steps_per_bar = int(
                mm.steps_per_bar_in_quantized_sequence(quantized_sequence))
            melody = mm.Melody([],
                               start_step=max(0, start_step - 1),
                               steps_per_bar=steps_per_bar,
                               steps_per_quarter=self.steps_per_quarter)

        # Ensure that the melody extends up to the step we want to start generating.
        melody.set_length(start_step - melody.start_step)

        # Extract generation arguments from generator options.
        arg_types = {
            'temperature': lambda arg: arg.float_value,
            'beam_size': lambda arg: arg.int_value,
            'branch_factor': lambda arg: arg.int_value,
            'steps_per_iteration': lambda arg: arg.int_value
        }
        args = dict((name, value_fn(generator_options.args[name]))
                    for name, value_fn in arg_types.items()
                    if name in generator_options.args)

        generated_melody = self._model.generate_melody(
            end_step - melody.start_step, melody, **args)
        generated_sequence = generated_melody.to_sequence(qpm=qpm)
        assert (generated_sequence.total_time -
                generate_section.end_time) <= 1e-5
        return generated_sequence
    def _generate(self, input_sequence, generator_options):
        if len(generator_options.input_sections) > 1:
            raise mm.SequenceGeneratorException(
                'This model supports at most one input_sections message, but got %s'
                % len(generator_options.input_sections))
        if len(generator_options.generate_sections) != 1:
            raise mm.SequenceGeneratorException(
                'This model supports only 1 generate_sections message, but got %s'
                % len(generator_options.generate_sections))

        qpm = (input_sequence.tempos[0].qpm if input_sequence
               and input_sequence.tempos else mm.DEFAULT_QUARTERS_PER_MINUTE)

        generate_section = generator_options.generate_sections[0]
        if generator_options.input_sections:
            # Use primer melody from input section only. Take backing chords from
            # beginning of input section through end of generate section.
            input_section = generator_options.input_sections[0]
            primer_sequence = mm.trim_note_sequence(input_sequence,
                                                    input_section.start_time,
                                                    input_section.end_time)
            backing_sequence = mm.trim_note_sequence(input_sequence,
                                                     input_section.start_time,
                                                     generate_section.end_time)
            input_start_step = self.seconds_to_steps(input_section.start_time,
                                                     qpm)
        else:
            # No input section. Take primer melody from the beginning of the sequence
            # up until the start of the generate section.
            primer_sequence = mm.trim_note_sequence(
                input_sequence, 0.0, generate_section.start_time)
            backing_sequence = mm.trim_note_sequence(input_sequence, 0.0,
                                                     generate_section.end_time)
            input_start_step = 0

        last_end_time = (max(
            n.end_time
            for n in primer_sequence.notes) if primer_sequence.notes else 0)
        if last_end_time >= generate_section.start_time:
            raise mm.SequenceGeneratorException(
                'Got GenerateSection request for section that is before or equal to '
                'the end of the input section. This model can only extend melodies. '
                'Requested start time: %s, Final note end time: %s' %
                (generate_section.start_time, last_end_time))

        # Quantize the priming and backing sequences.
        quantized_primer_sequence = mm.quantize_note_sequence(
            primer_sequence, self._steps_per_quarter)
        quantized_backing_sequence = mm.quantize_note_sequence(
            backing_sequence, self._steps_per_quarter)

        # Setting gap_bars to infinite ensures that the entire input will be used.
        extracted_melodies, _ = mm.extract_melodies(
            quantized_primer_sequence,
            search_start_step=input_start_step,
            min_bars=0,
            min_unique_pitches=1,
            gap_bars=float('inf'),
            ignore_polyphonic_notes=True)
        assert len(extracted_melodies) <= 1

        start_step = self.seconds_to_steps(generate_section.start_time, qpm)
        end_step = self.seconds_to_steps(generate_section.end_time, qpm)

        if extracted_melodies and extracted_melodies[0]:
            melody = extracted_melodies[0]
        else:
            # If no melody could be extracted, create an empty melody that starts 1
            # step before the request start_step. This will result in 1 step of
            # silence when the melody is extended below.
            steps_per_bar = int(
                mm.steps_per_bar_in_quantized_sequence(
                    quantized_primer_sequence))
            melody = mm.Melody([],
                               start_step=max(0, start_step - 1),
                               steps_per_bar=steps_per_bar,
                               steps_per_quarter=self.steps_per_quarter)

        extracted_chords, _ = mm.extract_chords(quantized_backing_sequence)
        chords = extracted_chords[0]

        # Make sure that chords and melody start on the same step.
        if chords.start_step < melody.start_step:
            chords.set_length(
                len(chords) - melody.start_step + chords.start_step)

        assert chords.end_step == end_step

        # Ensure that the melody extends up to the step we want to start generating.
        melody.set_length(start_step - melody.start_step)

        # Extract generation arguments from generator options.
        arg_types = {
            'temperature': lambda arg: arg.float_value,
            'beam_size': lambda arg: arg.int_value,
            'branch_factor': lambda arg: arg.int_value,
            'steps_per_iteration': lambda arg: arg.int_value
        }
        args = dict((name, value_fn(generator_options.args[name]))
                    for name, value_fn in arg_types.items()
                    if name in generator_options.args)

        generated_melody = self._model.generate_melody(melody, chords, **args)
        generated_lead_sheet = mm.LeadSheet(generated_melody, chords)
        generated_sequence = generated_lead_sheet.to_sequence(qpm=qpm)
        assert (generated_sequence.total_time -
                generate_section.end_time) <= 1e-5
        return generated_sequence
  def _generate(self, input_sequence, generator_options):
    if len(generator_options.input_sections) > 1:
      raise mm.SequenceGeneratorError(
          'This model supports at most one input_sections message, but got %s' %
          len(generator_options.input_sections))
    if len(generator_options.generate_sections) != 1:
      raise mm.SequenceGeneratorError(
          'This model supports only 1 generate_sections message, but got %s' %
          len(generator_options.generate_sections))

    if input_sequence and input_sequence.tempos:
      qpm = input_sequence.tempos[0].qpm
    else:
      qpm = mm.DEFAULT_QUARTERS_PER_MINUTE
    steps_per_second = mm.steps_per_quarter_to_steps_per_second(
        self.steps_per_quarter, qpm)

    generate_section = generator_options.generate_sections[0]
    if generator_options.input_sections:
      # Use primer melody from input section only. Take backing chords from
      # beginning of input section through end of generate section.
      input_section = generator_options.input_sections[0]
      primer_sequence = mm.trim_note_sequence(
          input_sequence, input_section.start_time, input_section.end_time)
      backing_sequence = mm.trim_note_sequence(
          input_sequence, input_section.start_time, generate_section.end_time)
      input_start_step = mm.quantize_to_step(
          input_section.start_time, steps_per_second, quantize_cutoff=0.0)
    else:
      # No input section. Take primer melody from the beginning of the sequence
      # up until the start of the generate section.
      primer_sequence = mm.trim_note_sequence(
          input_sequence, 0.0, generate_section.start_time)
      backing_sequence = mm.trim_note_sequence(
          input_sequence, 0.0, generate_section.end_time)
      input_start_step = 0

    if primer_sequence.notes:
      last_end_time = max(n.end_time for n in primer_sequence.notes)
    else:
      last_end_time = 0
    if last_end_time >= generate_section.start_time:
      raise mm.SequenceGeneratorError(
          'Got GenerateSection request for section that is before or equal to '
          'the end of the input section. This model can only extend melodies. '
          'Requested start time: %s, Final note end time: %s' %
          (generate_section.start_time, last_end_time))

    # Quantize the priming and backing sequences.
    quantized_primer_sequence = mm.quantize_note_sequence(
        primer_sequence, self.steps_per_quarter)
    quantized_backing_sequence = mm.quantize_note_sequence(
        backing_sequence, self.steps_per_quarter)

    # Setting gap_bars to infinite ensures that the entire input will be used.
    extracted_melodies, _ = mm.extract_melodies(
        quantized_primer_sequence, search_start_step=input_start_step,
        min_bars=0, min_unique_pitches=1, gap_bars=float('inf'),
        ignore_polyphonic_notes=True)
    assert len(extracted_melodies) <= 1

    start_step = mm.quantize_to_step(
        generate_section.start_time, steps_per_second, quantize_cutoff=0.0)
    # Note that when quantizing end_step, we set quantize_cutoff to 1.0 so it
    # always rounds down. This avoids generating a sequence that ends at 5.0
    # seconds when the requested end time is 4.99.
    end_step = mm.quantize_to_step(
        generate_section.end_time, steps_per_second, quantize_cutoff=1.0)

    if extracted_melodies and extracted_melodies[0]:
      melody = extracted_melodies[0]
    else:
      # If no melody could be extracted, create an empty melody that starts 1
      # step before the request start_step. This will result in 1 step of
      # silence when the melody is extended below.
      steps_per_bar = int(
          mm.steps_per_bar_in_quantized_sequence(quantized_primer_sequence))
      melody = mm.Melody([],
                         start_step=max(0, start_step - 1),
                         steps_per_bar=steps_per_bar,
                         steps_per_quarter=self.steps_per_quarter)

    extracted_chords, _ = mm.extract_chords(quantized_backing_sequence)
    chords = extracted_chords[0]

    # Make sure that chords and melody start on the same step.
    if chords.start_step < melody.start_step:
      chords.set_length(len(chords) - melody.start_step + chords.start_step)

    assert chords.end_step == end_step

    # Ensure that the melody extends up to the step we want to start generating.
    melody.set_length(start_step - melody.start_step)

    # Extract generation arguments from generator options.
    arg_types = {
        'temperature': lambda arg: arg.float_value,
        'beam_size': lambda arg: arg.int_value,
        'branch_factor': lambda arg: arg.int_value,
        'steps_per_iteration': lambda arg: arg.int_value
    }
    args = dict((name, value_fn(generator_options.args[name]))
                for name, value_fn in arg_types.items()
                if name in generator_options.args)

    generated_melody = self._model.generate_melody(melody, chords, **args)
    generated_lead_sheet = mm.LeadSheet(generated_melody, chords)
    generated_sequence = generated_lead_sheet.to_sequence(qpm=qpm)
    assert (generated_sequence.total_time - generate_section.end_time) <= 1e-5
    return generated_sequence
Example #18
0
  def _generate(self, input_sequence, generator_options):
    if len(generator_options.input_sections) > 1:
      raise mm.SequenceGeneratorException(
          'This model supports at most one input_sections message, but got %s' %
          len(generator_options.input_sections))
    if len(generator_options.generate_sections) != 1:
      raise mm.SequenceGeneratorException(
          'This model supports only 1 generate_sections message, but got %s' %
          len(generator_options.generate_sections))

    generate_section = generator_options.generate_sections[0]
    if generator_options.input_sections:
      input_section = generator_options.input_sections[0]
      primer_sequence = mm.trim_note_sequence(
          input_sequence, input_section.start_time, input_section.end_time)
      input_start_step = mm.quantize_to_step(
          input_section.start_time, self.steps_per_second, quantize_cutoff=0.0)
    else:
      primer_sequence = input_sequence
      input_start_step = 0

    last_end_time = (max(n.end_time for n in primer_sequence.notes)
                     if primer_sequence.notes else 0)
    if last_end_time > generate_section.start_time:
      raise mm.SequenceGeneratorException(
          'Got GenerateSection request for section that is before or equal to '
          'the end of the NoteSequence. This model can only extend sequences. '
          'Requested start time: %s, Final note end time: %s' %
          (generate_section.start_time, last_end_time))

    # Quantize the priming sequence.
    quantized_primer_sequence = mm.quantize_note_sequence_absolute(
        primer_sequence, self.steps_per_second)

    extracted_perfs, _ = performance_lib.extract_performances(
        quantized_primer_sequence, start_step=input_start_step,
        num_velocity_bins=self.num_velocity_bins)
    assert len(extracted_perfs) <= 1

    generate_start_step = mm.quantize_to_step(
        generate_section.start_time, self.steps_per_second, quantize_cutoff=0.0)
    # Note that when quantizing end_step, we set quantize_cutoff to 1.0 so it
    # always rounds down. This avoids generating a sequence that ends at 5.0
    # seconds when the requested end time is 4.99.
    generate_end_step = mm.quantize_to_step(
        generate_section.end_time, self.steps_per_second, quantize_cutoff=1.0)

    if extracted_perfs and extracted_perfs[0]:
      performance = extracted_perfs[0]
    else:
      # If no track could be extracted, create an empty track that starts at the
      # requested generate_start_step.
      performance = performance_lib.Performance(
          steps_per_second=(
              quantized_primer_sequence.quantization_info.steps_per_second),
          start_step=generate_start_step,
          num_velocity_bins=self.num_velocity_bins)

    # Ensure that the track extends up to the step we want to start generating.
    performance.set_length(generate_start_step - performance.start_step)

    # Extract generation arguments from generator options.
    arg_types = {
        'temperature': lambda arg: arg.float_value,
        'beam_size': lambda arg: arg.int_value,
        'branch_factor': lambda arg: arg.int_value,
        'steps_per_iteration': lambda arg: arg.int_value
    }
    args = dict((name, value_fn(generator_options.args[name]))
                for name, value_fn in arg_types.items()
                if name in generator_options.args)

    total_steps = performance.num_steps + (
        generate_end_step - generate_start_step)

    if not performance:
      # Primer is empty; let's just start with silence.
      performance.set_length(min(performance_lib.MAX_SHIFT_STEPS, total_steps))

    while performance.num_steps < total_steps:
      # Assume there's around 10 notes per second and 4 RNN steps per note.
      # Can't know for sure until generation is finished because the number of
      # notes per quantized step is variable.
      steps_to_gen = total_steps - performance.num_steps
      rnn_steps_to_gen = 40 * int(math.ceil(
          float(steps_to_gen) / performance_lib.DEFAULT_STEPS_PER_SECOND))
      tf.logging.info(
          'Need to generate %d more steps for this sequence, will try asking '
          'for %d RNN steps' % (steps_to_gen, rnn_steps_to_gen))
      performance = self._model.generate_performance(
          len(performance) + rnn_steps_to_gen, performance, **args)

      if not self.fill_generate_section:
        # In the interest of speed just go through this loop once, which may not
        # entirely fill the generate section.
        break

    performance.set_length(total_steps)

    generated_sequence = performance.to_sequence(
        max_note_duration=self.max_note_duration)

    assert (generated_sequence.total_time - generate_section.end_time) <= 1e-5
    return generated_sequence
    def _generate(self, input_sequence, generator_options):
        if len(generator_options.input_sections) > 1:
            raise sequence_generator.SequenceGeneratorError(
                'This model supports at most one input_sections message, but got %s'
                % len(generator_options.input_sections))
        if len(generator_options.generate_sections) != 1:
            raise sequence_generator.SequenceGeneratorError(
                'This model supports only 1 generate_sections message, but got %s'
                % len(generator_options.generate_sections))

        generate_section = generator_options.generate_sections[0]
        if generator_options.input_sections:
            input_section = generator_options.input_sections[0]
            primer_sequence = mm.trim_note_sequence(input_sequence,
                                                    input_section.start_time,
                                                    input_section.end_time)
            input_start_step = mm.quantize_to_step(input_section.start_time,
                                                   self.steps_per_second,
                                                   quantize_cutoff=0.0)
        else:
            primer_sequence = input_sequence
            input_start_step = 0
        if primer_sequence.notes:
            last_end_time = max(n.end_time for n in primer_sequence.notes)
        else:
            last_end_time = 0
        if last_end_time > generate_section.start_time:
            raise sequence_generator.SequenceGeneratorError(
                'Got GenerateSection request for section that is before or equal to '
                'the end of the NoteSequence. This model can only extend sequences. '
                'Requested start time: %s, Final note end time: %s' %
                (generate_section.start_time, last_end_time))

        # Quantize the priming sequence.
        quantized_primer_sequence = mm.quantize_note_sequence_absolute(
            primer_sequence, self.steps_per_second)

        extracted_perfs, _ = performance_pipeline.extract_performances(
            quantized_primer_sequence,
            start_step=input_start_step,
            num_velocity_bins=self.num_velocity_bins,
            note_performance=self._note_performance)
        assert len(extracted_perfs) <= 1

        generate_start_step = mm.quantize_to_step(generate_section.start_time,
                                                  self.steps_per_second,
                                                  quantize_cutoff=0.0)
        # Note that when quantizing end_step, we set quantize_cutoff to 1.0 so it
        # always rounds down. This avoids generating a sequence that ends at 5.0
        # seconds when the requested end time is 4.99.
        generate_end_step = mm.quantize_to_step(generate_section.end_time,
                                                self.steps_per_second,
                                                quantize_cutoff=1.0)

        if extracted_perfs and extracted_perfs[0]:
            performance = extracted_perfs[0]
        else:
            # If no track could be extracted, create an empty track that starts at the
            # requested generate_start_step.
            performance = mm.Performance(
                steps_per_second=(quantized_primer_sequence.quantization_info.
                                  steps_per_second),
                start_step=generate_start_step,
                num_velocity_bins=self.num_velocity_bins)

        # Ensure that the track extends up to the step we want to start generating.
        performance.set_length(generate_start_step - performance.start_step)

        # Extract generation arguments from generator options.
        arg_types = {
            'disable_conditioning':
            lambda arg: ast.literal_eval(arg.string_value),
            'temperature': lambda arg: arg.float_value,
            'beam_size': lambda arg: arg.int_value,
            'branch_factor': lambda arg: arg.int_value,
            'steps_per_iteration': lambda arg: arg.int_value
        }
        if self.control_signals:
            for control in self.control_signals:
                arg_types[control.name] = lambda arg: ast.literal_eval(
                    arg.string_value)

        args = dict((name, value_fn(generator_options.args[name]))
                    for name, value_fn in arg_types.items()
                    if name in generator_options.args)

        # Make sure control signals are present and convert to lists if necessary.
        if self.control_signals:
            for control in self.control_signals:
                if control.name not in args:
                    tf.logging.warning(
                        'Control value not specified, using default: %s = %s',
                        control.name, control.default_value)
                    args[control.name] = [control.default_value]
                elif control.validate(args[control.name]):
                    args[control.name] = [args[control.name]]
                else:
                    if not isinstance(args[control.name], list) or not all(
                            control.validate(value)
                            for value in args[control.name]):
                        tf.logging.fatal('Invalid control value: %s = %s',
                                         control.name, args[control.name])

        # Make sure disable conditioning flag is present when conditioning is
        # optional and convert to list if necessary.
        if self.optional_conditioning:
            if 'disable_conditioning' not in args:
                args['disable_conditioning'] = [False]
            elif isinstance(args['disable_conditioning'], bool):
                args['disable_conditioning'] = [args['disable_conditioning']]
            else:
                if not isinstance(
                        args['disable_conditioning'], list) or not all(
                            isinstance(value, bool)
                            for value in args['disable_conditioning']):
                    tf.logging.fatal('Invalid disable_conditioning value: %s',
                                     args['disable_conditioning'])

        total_steps = performance.num_steps + (generate_end_step -
                                               generate_start_step)

        if 'notes_per_second' in args:
            mean_note_density = (sum(args['notes_per_second']) /
                                 len(args['notes_per_second']))
        else:
            mean_note_density = DEFAULT_NOTE_DENSITY

        # Set up functions that map generation step to control signal values and
        # disable conditioning flag.
        if self.control_signals:
            control_signal_fns = []
            for control in self.control_signals:
                control_signal_fns.append(
                    functools.partial(_step_to_value,
                                      num_steps=total_steps,
                                      values=args[control.name]))
                del args[control.name]
            args['control_signal_fns'] = control_signal_fns
        if self.optional_conditioning:
            args['disable_conditioning_fn'] = functools.partial(
                _step_to_value,
                num_steps=total_steps,
                values=args['disable_conditioning'])
            del args['disable_conditioning']

        if not performance:
            # Primer is empty; let's just start with silence.
            performance.set_length(
                min(performance.max_shift_steps, total_steps))

        while performance.num_steps < total_steps:
            # Assume the average specified (or default) note density and 4 RNN steps
            # per note. Can't know for sure until generation is finished because the
            # number of notes per quantized step is variable.
            note_density = max(1.0, mean_note_density)
            steps_to_gen = total_steps - performance.num_steps
            rnn_steps_to_gen = int(
                math.ceil(4.0 * note_density * steps_to_gen /
                          self.steps_per_second))
            tf.logging.info(
                'Need to generate %d more steps for this sequence, will try asking '
                'for %d RNN steps' % (steps_to_gen, rnn_steps_to_gen))
            performance = self._model.generate_performance(
                len(performance) + rnn_steps_to_gen, performance, **args)

            if not self.fill_generate_section:
                # In the interest of speed just go through this loop once, which may not
                # entirely fill the generate section.
                break

        performance.set_length(total_steps)

        generated_sequence = performance.to_sequence(
            max_note_duration=self.max_note_duration)

        assert (generated_sequence.total_time -
                generate_section.end_time) <= 1e-5
        return generated_sequence
    def _generate(self, input_sequence, generator_options):
        if len(generator_options.input_sections) > 1:
            raise mm.SequenceGeneratorError(
                'This model supports at most one input_sections message, but got %s'
                % len(generator_options.input_sections))
        if len(generator_options.generate_sections) != 1:
            raise mm.SequenceGeneratorError(
                'This model supports only 1 generate_sections message, but got %s'
                % len(generator_options.generate_sections))

        # This sequence will be quantized later, so it is guaranteed to have only 1
        # tempo.
        qpm = mm.DEFAULT_QUARTERS_PER_MINUTE
        if input_sequence.tempos:
            qpm = input_sequence.tempos[0].qpm

        steps_per_second = mm.steps_per_quarter_to_steps_per_second(
            self.steps_per_quarter, qpm)

        generate_section = generator_options.generate_sections[0]
        if generator_options.input_sections:
            input_section = generator_options.input_sections[0]
            primer_sequence = mm.trim_note_sequence(input_sequence,
                                                    input_section.start_time,
                                                    input_section.end_time)
            input_start_step = mm.quantize_to_step(input_section.start_time,
                                                   steps_per_second,
                                                   quantize_cutoff=0)
        else:
            primer_sequence = input_sequence
            input_start_step = 0

        if primer_sequence.notes:
            last_end_time = max(n.end_time for n in primer_sequence.notes)
        else:
            last_end_time = 0

        if last_end_time > generate_section.start_time:
            raise mm.SequenceGeneratorError(
                'Got GenerateSection request for section that is before or equal to '
                'the end of the NoteSequence. This model can only extend sequences. '
                'Requested start time: %s, Final note end time: %s' %
                (generate_section.start_time, last_end_time))

        # Quantize the priming sequence.
        quantized_primer_sequence = mm.quantize_note_sequence(
            primer_sequence, self.steps_per_quarter)

        extracted_seqs, _ = pianoroll_pipeline.extract_pianoroll_sequences(
            quantized_primer_sequence, start_step=input_start_step)
        assert len(extracted_seqs) <= 1

        generate_start_step = mm.quantize_to_step(generate_section.start_time,
                                                  steps_per_second,
                                                  quantize_cutoff=0)
        # Note that when quantizing end_step, we set quantize_cutoff to 1.0 so it
        # always rounds down. This avoids generating a sequence that ends at 5.0
        # seconds when the requested end time is 4.99.
        generate_end_step = mm.quantize_to_step(generate_section.end_time,
                                                steps_per_second,
                                                quantize_cutoff=1.0)

        if extracted_seqs and extracted_seqs[0]:
            pianoroll_seq = extracted_seqs[0]
        else:
            raise ValueError('No priming pianoroll could be extracted.')

        # Ensure that the track extends up to the step we want to start generating.
        pianoroll_seq.set_length(generate_start_step -
                                 pianoroll_seq.start_step)

        # Extract generation arguments from generator options.
        arg_types = {
            'beam_size': lambda arg: arg.int_value,
            'branch_factor': lambda arg: arg.int_value,
        }
        args = dict((name, value_fn(generator_options.args[name]))
                    for name, value_fn in arg_types.items()
                    if name in generator_options.args)

        total_steps = pianoroll_seq.num_steps + (generate_end_step -
                                                 generate_start_step)

        pianoroll_seq = self._model.generate_pianoroll_sequence(
            total_steps, pianoroll_seq, **args)
        pianoroll_seq.set_length(total_steps)

        generated_sequence = pianoroll_seq.to_sequence(qpm=qpm)
        assert (generated_sequence.total_time -
                generate_section.end_time) <= 1e-5
        return generated_sequence
    def _generate(self, input_sequence, generator_options):
        if len(generator_options.input_sections) > 1:
            raise mm.SequenceGeneratorException(
                'This model supports at most one input_sections message, but got %s'
                % len(generator_options.input_sections))
        if len(generator_options.generate_sections) != 1:
            raise mm.SequenceGeneratorException(
                'This model supports only 1 generate_sections message, but got %s'
                % len(generator_options.generate_sections))

        qpm = (input_sequence.tempos[0].qpm if input_sequence
               and input_sequence.tempos else mm.DEFAULT_QUARTERS_PER_MINUTE)

        generate_section = generator_options.generate_sections[0]
        if generator_options.input_sections:
            input_section = generator_options.input_sections[0]
            primer_sequence = mm.trim_note_sequence(input_sequence,
                                                    input_section.start_time,
                                                    input_section.end_time)
            input_start_step = self.seconds_to_steps(input_section.start_time,
                                                     qpm)
        else:
            primer_sequence = input_sequence
            input_start_step = 0

        last_end_time = (max(
            n.end_time
            for n in primer_sequence.notes) if primer_sequence.notes else 0)
        if last_end_time > generate_section.start_time:
            raise mm.SequenceGeneratorException(
                'Got GenerateSection request for section that is before the end of '
                'the NoteSequence. This model can only extend sequences. Requested '
                'start time: %s, Final note end time: %s' %
                (generate_section.start_time, last_end_time))

        # Quantize the priming sequence.
        quantized_sequence = mm.quantize_note_sequence(primer_sequence,
                                                       self.steps_per_quarter)
        # Setting gap_bars to infinite ensures that the entire input will be used.
        extracted_drum_tracks, _ = mm.extract_drum_tracks(
            quantized_sequence,
            search_start_step=input_start_step,
            min_bars=0,
            gap_bars=float('inf'))
        assert len(extracted_drum_tracks) <= 1

        start_step = self.seconds_to_steps(generate_section.start_time, qpm)
        end_step = self.seconds_to_steps(generate_section.end_time, qpm)

        if extracted_drum_tracks and extracted_drum_tracks[0]:
            drums = extracted_drum_tracks[0]
        else:
            # If no drum track could be extracted, create an empty drum track that
            # starts 1 step before the request start_step. This will result in 1 step
            # of silence when the drum track is extended below.
            drums = mm.DrumTrack([], start_step=max(0, start_step - 1))

        # Ensure that the drum track extends up to the step we want to start
        # generating.
        drums.set_length(start_step - drums.start_step)

        # Extract generation arguments from generator options.
        arg_types = {
            'temperature': lambda arg: arg.float_value,
            'beam_size': lambda arg: arg.int_value,
            'branch_factor': lambda arg: arg.int_value,
            'steps_per_iteration': lambda arg: arg.int_value
        }
        args = dict((name, value_fn(generator_options.args[name]))
                    for name, value_fn in arg_types.items()
                    if name in generator_options.args)

        generated_drums = self._model.generate_drum_track(
            end_step - drums.start_step, drums, **args)
        generated_sequence = generated_drums.to_sequence(qpm=qpm)
        assert (generated_sequence.total_time -
                generate_section.end_time) <= 1e-5
        return generated_sequence