Пример #1
0
    def testToNoteSequence(self):
        converter = data.TrioConverter(steps_per_quarter=1,
                                       slice_bars=2,
                                       max_tensors_per_notesequence=1)

        mel_oh = data.np_onehot(self.expected_sliced_labels[3][0], 90)
        bass_oh = data.np_onehot(self.expected_sliced_labels[3][1], 90)
        drums_oh = data.np_onehot(self.expected_sliced_labels[3][2], 512)
        output_tensors = np.concatenate([mel_oh, bass_oh, drums_oh], axis=-1)

        sequences = converter.to_notesequences([output_tensors])
        self.assertEqual(1, len(sequences))

        self.assertProtoEquals(
            """
        ticks_per_quarter: 220
        tempos < qpm: 120 >
        notes <
          instrument: 0 pitch: 52 start_time: 2.0 end_time: 4.0 program: 0
          velocity: 80
        >
        notes <
          instrument: 1 pitch: 50 start_time: 1.0 end_time: 2.5 program: 33
          velocity: 80
        >
        notes <
          instrument: 9 pitch: 36 start_time: 0.0 end_time: 0.5 velocity: 80
          is_drum: True
        >
        notes <
          instrument: 9 pitch: 38 start_time: 2.0 end_time: 2.5 velocity: 80
          is_drum: True
        >
        total_time: 4.0
        """, sequences[0])
Пример #2
0
  def _hierarchical_pad(input_, output, control):
    """Pad and flatten hierarchical inputs, outputs, and controls."""
    # Pad empty segments with end tokens and flatten hierarchy.
    input_ = tf.nest.flatten(
        pad_with_element(input_, max_lengths[:-1],
                         data.np_onehot([end_token], input_depth)))
    output = tf.nest.flatten(
        pad_with_element(output, max_lengths[:-1],
                         data.np_onehot([end_token], 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, max_lengths[-1], 0) for x in input_])
    output = np.concatenate(
        [pad_with_value(x, max_lengths[-1], 0) for x in output])

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

    return input_, output, control, length
Пример #3
0
  def testToNoteSequence(self):
    converter = data.TrioConverter(
        steps_per_quarter=1, slice_bars=2, max_tensors_per_notesequence=1)

    mel_oh = data.np_onehot(self.expected_sliced_labels[3][0], 90)
    bass_oh = data.np_onehot(self.expected_sliced_labels[3][1], 90)
    drums_oh = data.np_onehot(self.expected_sliced_labels[3][2], 512)
    output_tensors = np.concatenate([mel_oh, bass_oh, drums_oh], axis=-1)

    sequences = converter.to_notesequences([output_tensors])
    self.assertEqual(1, len(sequences))

    self.assertProtoEquals(
        """
        ticks_per_quarter: 220
        tempos < qpm: 120 >
        notes <
          instrument: 0 pitch: 52 start_time: 2.0 end_time: 4.0 program: 0
          velocity: 80
        >
        notes <
          instrument: 1 pitch: 50 start_time: 1.0 end_time: 2.5 program: 33
          velocity: 80
        >
        notes <
          instrument: 9 pitch: 36 start_time: 0.0 end_time: 0.5 velocity: 80
          is_drum: True
        >
        notes <
          instrument: 9 pitch: 38 start_time: 2.0 end_time: 2.5 velocity: 80
          is_drum: True
        >
        total_time: 4.0
        """,
        sequences[0])
Пример #4
0
    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
Пример #5
0
    def testToNoteSequenceChordConditioned(self):
        converter = data.TrioConverter(
            steps_per_quarter=1,
            slice_bars=2,
            max_tensors_per_notesequence=1,
            chord_encoding=mm.MajorMinorChordOneHotEncoding())

        mel_oh = data.np_onehot(self.expected_sliced_labels[3][0], 90)
        bass_oh = data.np_onehot(self.expected_sliced_labels[3][1], 90)
        drums_oh = data.np_onehot(self.expected_sliced_labels[3][2], 512)
        chords_oh = data.np_onehot(self.expected_sliced_chord_labels[3], 25)

        output_tensors = np.concatenate([mel_oh, bass_oh, drums_oh], axis=-1)

        sequences = converter.to_notesequences([output_tensors], [chords_oh])
        self.assertEqual(1, len(sequences))

        self.assertProtoEquals(
            """
        ticks_per_quarter: 220
        tempos < qpm: 120 >
        notes <
          instrument: 0 pitch: 52 start_time: 2.0 end_time: 4.0 program: 0
          velocity: 80
        >
        notes <
          instrument: 1 pitch: 50 start_time: 1.0 end_time: 2.5 program: 33
          velocity: 80
        >
        notes <
          instrument: 9 pitch: 36 start_time: 0.0 end_time: 0.5 velocity: 80
          is_drum: True
        >
        notes <
          instrument: 9 pitch: 38 start_time: 2.0 end_time: 2.5 velocity: 80
          is_drum: True
        >
        text_annotations <
          text: 'N.C.' annotation_type: CHORD_SYMBOL
        >
        text_annotations <
          time: 2.0 text: 'C' annotation_type: CHORD_SYMBOL
        >
        total_time: 4.0
        """, sequences[0])
Пример #6
0
  def testToNoteSequenceChordConditioned(self):
    converter = data.TrioConverter(
        steps_per_quarter=1, slice_bars=2, max_tensors_per_notesequence=1,
        chord_encoding=mm.MajorMinorChordOneHotEncoding())

    mel_oh = data.np_onehot(self.expected_sliced_labels[3][0], 90)
    bass_oh = data.np_onehot(self.expected_sliced_labels[3][1], 90)
    drums_oh = data.np_onehot(self.expected_sliced_labels[3][2], 512)
    chords_oh = data.np_onehot(self.expected_sliced_chord_labels[3], 25)

    output_tensors = np.concatenate([mel_oh, bass_oh, drums_oh], axis=-1)

    sequences = converter.to_notesequences([output_tensors], [chords_oh])
    self.assertEqual(1, len(sequences))

    self.assertProtoEquals(
        """
        ticks_per_quarter: 220
        tempos < qpm: 120 >
        notes <
          instrument: 0 pitch: 52 start_time: 2.0 end_time: 4.0 program: 0
          velocity: 80
        >
        notes <
          instrument: 1 pitch: 50 start_time: 1.0 end_time: 2.5 program: 33
          velocity: 80
        >
        notes <
          instrument: 9 pitch: 36 start_time: 0.0 end_time: 0.5 velocity: 80
          is_drum: True
        >
        notes <
          instrument: 9 pitch: 38 start_time: 2.0 end_time: 2.5 velocity: 80
          is_drum: True
        >
        text_annotations <
          text: 'N.C.' annotation_type: CHORD_SYMBOL
        >
        text_annotations <
          time: 2.0 text: 'C' annotation_type: CHORD_SYMBOL
        >
        total_time: 4.0
        """,
        sequences[0])
Пример #7
0
  def _quantized_subsequence_to_tensors(self, quantized_subsequence):
    # Reject sequences with out-of-range pitches.
    if any(note.pitch < self._min_pitch or note.pitch > self._max_pitch
           for note in quantized_subsequence.notes):
      return [], []

    # Extract all instruments.
    tracks, _ = performance_pipeline.extract_performances(
        quantized_subsequence,
        max_steps_truncate=self._max_steps_truncate,
        num_velocity_bins=self._num_velocity_bins,
        split_instruments=True)

    # Reject sequences with too few instruments.
    if not (self._min_num_instruments <= len(tracks) <=
            self._max_num_instruments):
      return [], []

    # Sort tracks by program, with drums at the end.
    tracks = sorted(tracks, key=lambda t: (t.is_drum, t.program))

    chunk_size_steps = self._steps_per_bar * self._chunk_size_bars
    chunks = [[] for _ in range(self._max_num_chunks)]

    total_length = 0

    for track in tracks:
      # Make sure the track is the proper number of time steps.
      track.set_length(self._max_steps_truncate)

      # Split this track into chunks.
      def new_performance(quantized_sequence, start_step, track=track):
        steps_per_quarter = (
            self._steps_per_quarter if quantized_sequence is None else None)
        return performance_lib.MetricPerformance(
            quantized_sequence=quantized_sequence,
            steps_per_quarter=steps_per_quarter,
            start_step=start_step,
            num_velocity_bins=self._num_velocity_bins,
            program=track.program, is_drum=track.is_drum)
      track_chunks = split_performance(
          track, chunk_size_steps, new_performance, clip_tied_notes=True)

      assert len(track_chunks) == self._max_num_chunks

      track_chunk_lengths = [len(track_chunk) for track_chunk in track_chunks]
      # Each track chunk needs room for program token and end token.
      if not all(l <= self._max_events_per_instrument - 2
                 for l in track_chunk_lengths):
        return [], []
      if not all(
          note_seq.MIN_MIDI_PROGRAM <= t.program <= note_seq.MAX_MIDI_PROGRAM
          for t in track_chunks
          if not t.is_drum):
        return [], []

      total_length += sum(track_chunk_lengths)

      # Aggregate by chunk.
      for i, track_chunk in enumerate(track_chunks):
        chunks[i].append(track_chunk)

    # Reject sequences that are too short (in events).
    if total_length < self._min_total_events:
      return [], []

    num_programs = note_seq.MAX_MIDI_PROGRAM - note_seq.MIN_MIDI_PROGRAM + 1

    chunk_tensors = []
    chunk_chord_tensors = []

    for chunk_tracks in chunks:
      track_tensors = []

      for track in chunk_tracks:
        # Add a special token for program at the beginning of each track.
        track_tokens = [self._performance_encoding.num_classes + (
            num_programs if track.is_drum else track.program)]
        # Then encode the performance events.
        for event in track:
          track_tokens.append(self._performance_encoding.encode_event(event))
        # Then add the end token.
        track_tokens.append(self.end_token)

        encoded_track = data.np_onehot(
            track_tokens, self.output_depth, self.output_dtype)
        track_tensors.append(encoded_track)

      if self._chord_encoding:
        # Extract corresponding chords for each track. The chord sequences may
        # be different for different tracks even though the underlying chords
        # are the same, as the performance event times will generally be
        # different.
        try:
          track_chords = chords_lib.event_list_chords(
              quantized_subsequence, chunk_tracks)
        except chords_lib.CoincidentChordsError:
          return [], []

        track_chord_tensors = []

        try:
          # Chord encoding for all tracks is inside this try block. If any
          # track fails we need to skip the whole subsequence.

          for chords in track_chords:
            # Start with a pad token corresponding to the track program token.
            track_chord_tokens = [self._control_pad_token]
            # Then encode the chords.
            for chord in chords:
              track_chord_tokens.append(
                  self._chord_encoding.encode_event(chord))
            # Then repeat the final chord for the track end token.
            track_chord_tokens.append(track_chord_tokens[-1])

            encoded_track_chords = data.np_onehot(
                track_chord_tokens, self.control_depth, self.control_dtype)
            track_chord_tensors.append(encoded_track_chords)

        except (note_seq.ChordSymbolError, note_seq.ChordEncodingError):
          return [], []

        chunk_chord_tensors.append(track_chord_tensors)

      chunk_tensors.append(track_tensors)

    return chunk_tensors, chunk_chord_tensors
Пример #8
0
 def labels_to_inputs(self, labels, converter):
   return [data.np_onehot(l, converter.input_depth, converter.input_dtype)
           for l in labels]
Пример #9
0
 def labels_to_inputs(self, labels, converter):
     return [
         data.np_onehot(l, converter.input_depth, converter.input_dtype)
         for l in labels
     ]
Пример #10
0
  def _quantized_subsequence_to_tensors(self, quantized_subsequence):
    # Reject sequences with out-of-range pitches.
    if any(note.pitch < self._min_pitch or note.pitch > self._max_pitch
           for note in quantized_subsequence.notes):
      return [], []

    # Extract all instruments.
    tracks, _ = mm.extract_performances(
        quantized_subsequence,
        max_steps_truncate=self._max_steps_truncate,
        num_velocity_bins=self._num_velocity_bins,
        split_instruments=True)

    # Reject sequences with too few instruments.
    if not (self._min_num_instruments <= len(tracks) <=
            self._max_num_instruments):
      return [], []

    # Sort tracks by program, with drums at the end.
    tracks = sorted(tracks, key=lambda t: (t.is_drum, t.program))

    chunk_size_steps = self._steps_per_bar * self._chunk_size_bars
    chunks = [[] for _ in range(self._max_num_chunks)]

    total_length = 0

    for track in tracks:
      # Make sure the track is the proper number of time steps.
      track.set_length(self._max_steps_truncate)

      # Split this track into chunks.
      def new_performance(quantized_sequence, start_step, track=track):
        steps_per_quarter = (
            self._steps_per_quarter if quantized_sequence is None else None)
        return performance_lib.MetricPerformance(
            quantized_sequence=quantized_sequence,
            steps_per_quarter=steps_per_quarter,
            start_step=start_step,
            num_velocity_bins=self._num_velocity_bins,
            program=track.program, is_drum=track.is_drum)
      track_chunks = split_performance(
          track, chunk_size_steps, new_performance, clip_tied_notes=True)

      assert len(track_chunks) == self._max_num_chunks

      track_chunk_lengths = [len(track_chunk) for track_chunk in track_chunks]
      # Each track chunk needs room for program token and end token.
      if not all(l <= self._max_events_per_instrument - 2
                 for l in track_chunk_lengths):
        return [], []
      if not all(mm.MIN_MIDI_PROGRAM <= t.program <= mm.MAX_MIDI_PROGRAM
                 for t in track_chunks if not t.is_drum):
        return [], []

      total_length += sum(track_chunk_lengths)

      # Aggregate by chunk.
      for i, track_chunk in enumerate(track_chunks):
        chunks[i].append(track_chunk)

    # Reject sequences that are too short (in events).
    if total_length < self._min_total_events:
      return [], []

    num_programs = mm.MAX_MIDI_PROGRAM - mm.MIN_MIDI_PROGRAM + 1

    chunk_tensors = []
    chunk_chord_tensors = []

    for chunk_tracks in chunks:
      track_tensors = []

      for track in chunk_tracks:
        # Add a special token for program at the beginning of each track.
        track_tokens = [self._performance_encoding.num_classes + (
            num_programs if track.is_drum else track.program)]
        # Then encode the performance events.
        for event in track:
          track_tokens.append(self._performance_encoding.encode_event(event))
        # Then add the end token.
        track_tokens.append(self.end_token)

        encoded_track = data.np_onehot(
            track_tokens, self.output_depth, self.output_dtype)
        track_tensors.append(encoded_track)

      if self._chord_encoding:
        # Extract corresponding chords for each track. The chord sequences may
        # be different for different tracks even though the underlying chords
        # are the same, as the performance event times will generally be
        # different.
        try:
          track_chords = chords_lib.event_list_chords(
              quantized_subsequence, chunk_tracks)
        except chords_lib.CoincidentChordsError:
          return [], []

        track_chord_tensors = []

        try:
          # Chord encoding for all tracks is inside this try block. If any
          # track fails we need to skip the whole subsequence.

          for chords in track_chords:
            # Start with a pad token corresponding to the track program token.
            track_chord_tokens = [self._control_pad_token]
            # Then encode the chords.
            for chord in chords:
              track_chord_tokens.append(
                  self._chord_encoding.encode_event(chord))
            # Then repeat the final chord for the track end token.
            track_chord_tokens.append(track_chord_tokens[-1])

            encoded_track_chords = data.np_onehot(
                track_chord_tokens, self.control_depth, self.control_dtype)
            track_chord_tensors.append(encoded_track_chords)

        except (mm.ChordSymbolError, mm.ChordEncodingError):
          return [], []

        chunk_chord_tensors.append(track_chord_tensors)

      chunk_tensors.append(track_tensors)

    return chunk_tensors, chunk_chord_tensors