Пример #1
0
    def to_tensors(self, item):
        """Converts to tensors and adds hierarchical padding, if needed."""
        tensors = self._to_tensors(item)
        sampled_results = data.maybe_sample_items(list(zip(*tensors)),
                                                  self.max_tensors_per_item,
                                                  self.is_training)
        if sampled_results:
            unpadded_results = data.ConverterTensors(*zip(*sampled_results))
        else:
            unpadded_results = data.ConverterTensors()
        if not self._max_lengths:
            return unpadded_results

        # TODO(iansimon): The way control tensors are set in ConverterTensors is
        # ugly when using a hierarchical converter. Figure out how to clean this up.

        def _hierarchical_pad(input_, output, control):
            """Pad and flatten hierarchical inputs, outputs, and controls."""
            # Pad empty segments with end tokens and flatten hierarchy.
            input_ = nest.flatten(
                pad_with_element(
                    input_, self._max_lengths[:-1],
                    data.np_onehot([self.end_token], self.input_depth)))
            output = nest.flatten(
                pad_with_element(
                    output, self._max_lengths[:-1],
                    data.np_onehot([self.end_token], self.output_depth)))
            length = np.squeeze(np.array([len(x) for x in input_], np.int32))

            # Pad and concatenate flatten hierarchy.
            input_ = np.concatenate(
                [pad_with_value(x, self._max_lengths[-1], 0) for x in input_])
            output = np.concatenate(
                [pad_with_value(x, self._max_lengths[-1], 0) for x in output])

            if np.size(control):
                control = nest.flatten(
                    pad_with_element(
                        control, self._max_lengths[:-1],
                        data.np_onehot([self._control_pad_token],
                                       self.control_depth)))
                control = np.concatenate([
                    pad_with_value(x, self._max_lengths[-1], 0)
                    for x in control
                ])

            return input_, output, control, length

        padded_results = []
        for i, o, c, _ in zip(*unpadded_results):
            try:
                padded_results.append(_hierarchical_pad(i, o, c))
            except TooLongError:
                continue

        if padded_results:
            return data.ConverterTensors(*zip(*padded_results))
        else:
            return data.ConverterTensors()
Пример #2
0
  def _to_tensors_fn(self, note_sequence):
    # Performance sequences require sustain to be correctly interpreted.
    note_sequence = note_seq.apply_sustain_control_changes(note_sequence)

    if self._chord_encoding and not any(
        ta.annotation_type == CHORD_SYMBOL
        for ta in note_sequence.text_annotations):
      try:
        # Quantize just for the purpose of chord inference.
        # TODO(iansimon): Allow chord inference in unquantized sequences.
        quantized_sequence = note_seq.quantize_note_sequence(
            note_sequence, self._steps_per_quarter)
        if (note_seq.steps_per_bar_in_quantized_sequence(quantized_sequence) !=
            self._steps_per_bar):
          return data.ConverterTensors()

        # Infer chords in quantized sequence.
        note_seq.infer_chords_for_sequence(quantized_sequence)

      except (note_seq.BadTimeSignatureError,
              note_seq.NonIntegerStepsPerBarError, note_seq.NegativeTimeError,
              note_seq.ChordInferenceError):
        return data.ConverterTensors()

      # Copy inferred chords back to original sequence.
      for qta in quantized_sequence.text_annotations:
        if qta.annotation_type == CHORD_SYMBOL:
          ta = note_sequence.text_annotations.add()
          ta.annotation_type = CHORD_SYMBOL
          ta.time = qta.time
          ta.text = qta.text

    if note_sequence.tempos:
      quarters_per_minute = note_sequence.tempos[0].qpm
    else:
      quarters_per_minute = note_seq.DEFAULT_QUARTERS_PER_MINUTE
    quarters_per_bar = self._steps_per_bar / self._steps_per_quarter
    hop_size_quarters = quarters_per_bar * self._hop_size_bars
    hop_size_seconds = 60.0 * hop_size_quarters / quarters_per_minute

    # Split note sequence by bar hop size (in seconds).
    subsequences = note_seq.split_note_sequence(note_sequence, hop_size_seconds)

    if self._first_subsequence_only and len(subsequences) > 1:
      return data.ConverterTensors()

    sequence_tensors = []
    sequence_chord_tensors = []

    for subsequence in subsequences:
      # Quantize this subsequence.
      try:
        quantized_subsequence = note_seq.quantize_note_sequence(
            subsequence, self._steps_per_quarter)
        if (note_seq.steps_per_bar_in_quantized_sequence(quantized_subsequence)
            != self._steps_per_bar):
          return data.ConverterTensors()
      except (note_seq.BadTimeSignatureError,
              note_seq.NonIntegerStepsPerBarError, note_seq.NegativeTimeError):
        return data.ConverterTensors()

      # Convert the quantized subsequence to tensors.
      tensors, chord_tensors = self._quantized_subsequence_to_tensors(
          quantized_subsequence)
      if tensors:
        sequence_tensors.append(tensors)
        if self._chord_encoding:
          sequence_chord_tensors.append(chord_tensors)

    tensors = data.ConverterTensors(
        inputs=sequence_tensors, outputs=sequence_tensors,
        controls=sequence_chord_tensors)
    return hierarchical_pad_tensors(tensors, self.max_tensors_per_notesequence,
                                    self.is_training, self._max_lengths,
                                    self.end_token, self.input_depth,
                                    self.output_depth, self.control_depth,
                                    self._control_pad_token)