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 = note_seq.trim_note_sequence(
                input_sequence, input_section.start_time,
                input_section.end_time)
            input_start_step = note_seq.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 = note_seq.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 = note_seq.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 = note_seq.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 = note_seq.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
示例#2
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 = note_seq.DEFAULT_QUARTERS_PER_MINUTE
        if input_sequence.tempos:
            qpm = input_sequence.tempos[0].qpm

        steps_per_second = note_seq.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 = note_seq.trim_note_sequence(
                input_sequence, input_section.start_time,
                input_section.end_time)
            input_start_step = note_seq.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 = note_seq.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 = note_seq.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 = note_seq.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 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 = note_seq.DEFAULT_QUARTERS_PER_MINUTE
    steps_per_second = note_seq.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 = note_seq.trim_note_sequence(input_sequence,
                                                    input_section.start_time,
                                                    input_section.end_time)
      input_start_step = note_seq.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 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 = note_seq.quantize_note_sequence(
        primer_sequence, self.steps_per_quarter)
    # Setting gap_bars to infinite ensures that the entire input will be used.
    extracted_melodies, _ = melody_pipelines.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 = note_seq.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 = note_seq.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(
          note_seq.steps_per_bar_in_quantized_sequence(quantized_sequence))
      melody = note_seq.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
示例#4
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 = note_seq.DEFAULT_QUARTERS_PER_MINUTE
        if input_sequence.tempos:
            qpm = input_sequence.tempos[0].qpm

        steps_per_second = note_seq.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 = note_seq.trim_note_sequence(
                input_sequence, input_section.start_time,
                input_section.end_time)
            input_start_step = note_seq.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 = note_seq.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 = note_seq.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 = note_seq.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